Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19b2eb5e authored by Wei Sheng Shih's avatar Wei Sheng Shih Committed by Android (Google) Code Review
Browse files

Merge "Only update keyguard status from top focusable visible task."

parents abd78597 556a113a
Loading
Loading
Loading
Loading
+5 −22
Original line number Diff line number Diff line
@@ -2700,7 +2700,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                // activities be updated, they may be seen by users.
                ensureVisibility = true;
            } else if (mStackSupervisor.getKeyguardController().isKeyguardLocked()
                    && stack.topActivityOccludesKeyguard()) {
                    && mStackSupervisor.getKeyguardController().topActivityOccludesKeyguard(this)) {
                // Ensure activity visibilities and update lockscreen occluded/dismiss state when
                // finishing the top activity that occluded keyguard. So that, the
                // ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below
@@ -4631,15 +4631,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
    }

    private void updateVisibleIgnoringKeyguard(boolean behindFullscreenActivity) {
        // Check whether activity should be visible without Keyguard influence
        visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
                && okToShowLocked();
    }

    /** @return {@code true} if this activity should be made visible. */
    private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
        updateVisibleIgnoringKeyguard(behindFullscreenActivity);
        updateVisibilityIgnoringKeyguard(behindFullscreenActivity);

        if (ignoringKeyguard) {
            return visibleIgnoringKeyguard;
@@ -4673,20 +4667,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
    }

    void updateVisibility(boolean behindFullscreenActivity) {
        updateVisibleIgnoringKeyguard(behindFullscreenActivity);
        final Task task = getRootTask();
        if (task == null || !visibleIgnoringKeyguard) {
            return;
        }
        // Now check whether it's really visible depending on Keyguard state, and update
        // {@link ActivityStack} internal states.
        // Inform the method if this activity is the top activity of this stack, but exclude the
        // case where this is the top activity in a pinned stack.
        final boolean isTop = this == task.getTopNonFinishingActivity();
        final boolean isTopNotPinnedStack = task.isAttached()
                && task.getDisplayArea().isTopNotFinishNotPinnedStack(task);
        task.updateKeyguardVisibility(this, isTop && isTopNotPinnedStack);
    void updateVisibilityIgnoringKeyguard(boolean behindFullscreenActivity) {
        visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
                && okToShowLocked();
    }

    boolean shouldBeVisible() {
+4 −8
Original line number Diff line number Diff line
@@ -2304,18 +2304,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    /** Starts a batch of visibility updates. */
    void beginActivityVisibilityUpdate() {
        if (mVisibilityTransactionDepth == 0) {
            getKeyguardController().updateVisibility();
        }
        mVisibilityTransactionDepth++;
    }

    /** Ends a batch of visibility updates. */
    void endActivityVisibilityUpdate(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        if (mVisibilityTransactionDepth == 1) {
            getKeyguardController().visibilitiesUpdated();
            // commit visibility to activities
            mRootWindowContainer.commitActivitiesVisible(starting, configChanges, preserveWindows,
                    notifyClients);
        }
    void endActivityVisibilityUpdate() {
        mVisibilityTransactionDepth--;
    }

+47 −70
Original line number Diff line number Diff line
@@ -63,26 +63,8 @@ class EnsureActivitiesVisibleHelper {
    }

    /**
     * Update visibility to activities.
     * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @param starting The top most activity in the task.
     *                 The activity is either starting or resuming.
     *                 Caller should ensure starting activity is visible.
     *
     */
    void processUpdate(@Nullable ActivityRecord starting) {
        reset(starting, 0 /* configChanges */, false /* preserveWindows */,
                false /* notifyClients */);
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processUpdate behind " + mTop);
        }

        mTask.forAllActivities(this::updateActivityVisibility);
    }

    /**
     * Commit visibility with an option to also update the configuration of visible activities.
     * Update and commit visibility with an option to also update the configuration of visible
     * activities.
     * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @param starting The top most activity in the task.
@@ -95,12 +77,13 @@ class EnsureActivitiesVisibleHelper {
     * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc
     *                      be sent to the clients.
     */
    void processCommit(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
    void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
        reset(starting, configChanges, preserveWindows, notifyClients);

        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processCommit behind " + mTop);
            Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop
                    + " configChanges=0x" + Integer.toHexString(configChanges));
        }
        if (mTop != null) {
            mTask.checkTranslucentActivityWaiting(mTop);
@@ -114,25 +97,20 @@ class EnsureActivitiesVisibleHelper {
                && (starting == null || !starting.isDescendantOf(mTask));

        mTask.forAllActivities(a -> {
            commitActivityVisibility(a, starting, resumeTopActivity);
            setActivityVisibilityState(a, starting, resumeTopActivity);
        });
    }

    private boolean isAboveTop(boolean isTop) {
        if (mAboveTop && !isTop) {
            return true;
        }
        mAboveTop = false;
        return false;
    }

    private void updateActivityVisibility(ActivityRecord r) {
    private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
        final boolean isTop = r == mTop;
        if (isAboveTop(isTop)) {
        if (mAboveTop && !isTop) {
            return;
        }
        mAboveTop = false;

        r.updateVisibility(mBehindFullscreenActivity);
        r.updateVisibilityIgnoringKeyguard(mBehindFullscreenActivity);
        final boolean reallyVisible = r.shouldBeVisibleUnchecked();

        // Check whether activity should be visible without Keyguard influence
        if (r.visibleIgnoringKeyguard) {
@@ -149,36 +127,14 @@ class EnsureActivitiesVisibleHelper {
            }
        }

        if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Home task: at " + mTask
                        + " stackShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity);
            }
            // No other task in the home stack should be visible behind the home activity.
            // Home activities is usually a translucent activity with the wallpaper behind
            // them. However, when they don't have the wallpaper behind them, we want to
            // show activities in the next application stack behind them vs. another
            // task in the home stack like recents.
            mBehindFullscreenActivity = true;
        }
    }

    private void commitActivityVisibility(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
        final boolean isTop = r == mTop;
        if (isAboveTop(isTop)) {
            return;
        }

        final boolean reallyVisible = r.shouldBeVisibleUnchecked();

        if (reallyVisible) {
            if (r.finishing) {
                return;
            }
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Make visible? " + r
                        + " finishing=" + r.finishing + " state=" + r.getState());
            }
            // First: if this is not the current activity being started, make
            // sure it matches the current configuration.
            if (r != mStarting && mNotifyClients) {
@@ -191,8 +147,9 @@ class EnsureActivitiesVisibleHelper {
                        resumeTopActivity && isTop, r);
            } else if (r.mVisibleRequested) {
                // If this activity is already visible, then there is nothing to do here.
                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                        "Skipping: already visible at " + r);
                if (DEBUG_VISIBILITY) {
                    Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r);
                }

                if (r.mClientVisibilityDeferred && mNotifyClients) {
                    r.makeActiveIfNeeded(r.mClientVisibilityDeferred ? null : starting);
@@ -209,13 +166,29 @@ class EnsureActivitiesVisibleHelper {
            // Aggregate current change flags.
            mConfigChanges |= r.configChangeFlags;
        } else {
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Make invisible? " + r
                        + " finishing=" + r.finishing + " state=" + r.getState()
                        + " stackShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity
                        + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
            }
            r.makeInvisible();
        }

        if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Home task: at " + mTask
                        + " stackShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity);
            }
            // No other task in the home stack should be visible behind the home activity.
            // Home activities is usually a translucent activity with the wallpaper behind
            // them. However, when they don't have the wallpaper behind them, we want to
            // show activities in the next application stack behind them vs. another
            // task in the home stack like recents.
            mBehindFullscreenActivity = true;
        }
    }

    private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
@@ -230,12 +203,16 @@ class EnsureActivitiesVisibleHelper {

        // This activity needs to be visible, but isn't even running...
        // get it started and resume if no other stack in this stack is resumed.
        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
        }
        if (r != starting) {
            r.startFreezingScreenLocked(configChanges);
        }
        if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
            }
            r.setVisibility(true);
        }
        if (r != starting) {
+80 −52
Original line number Diff line number Diff line
@@ -124,6 +124,14 @@ class KeyguardController {
        return mKeyguardShowing && !mKeyguardGoingAway;
    }

    /**
     *
     * @return true if the activity is controlling keyguard state.
     */
    boolean topActivityOccludesKeyguard(ActivityRecord r) {
        return getDisplayState(r.getDisplayId()).mTopOccludesActivity == r;
    }

    /**
     * @return {@code true} if the keyguard is going away, {@code false} otherwise.
     */
@@ -258,15 +266,14 @@ class KeyguardController {
     * @return True if we may show an activity while Keyguard is showing because we are in the
     *         process of dismissing it anyways, false otherwise.
     */
    boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {

    boolean canShowActivityWhileKeyguardShowing(ActivityRecord r) {
        // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
        // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
        // Keyguard.
        return dismissKeyguard && canDismissKeyguard() && !mAodShowing
        return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !mAodShowing
                && (mDismissalRequested
                || (r.canShowWhenLocked()
                        && getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r));
                        && getDisplayState(r.getDisplayId()).mDismissingKeyguardActivity != r));
    }

    /**
@@ -290,7 +297,7 @@ class KeyguardController {
        if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) {
            // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
            // right away and AOD isn't visible.
            return canShowActivityWhileKeyguardShowing(r, r.containsDismissKeyguardWindow());
            return canShowActivityWhileKeyguardShowing(r);
        } else if (isKeyguardLocked()) {
            return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked());
        } else {
@@ -299,16 +306,17 @@ class KeyguardController {
    }

    /**
     * Makes sure to update lockscreen occluded/dismiss state if needed after completing all
     * visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}).
     * Makes sure to update lockscreen occluded/dismiss/turnScreenOn state if needed before
     * completing set all visibility
     * ({@link ActivityStackSupervisor#beginActivityVisibilityUpdate}).
     */
    void visibilitiesUpdated() {
    void updateVisibility() {
        boolean requestDismissKeyguard = false;
        for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
             displayNdx >= 0; displayNdx--) {
            final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
            final KeyguardDisplayState state = getDisplay(display.mDisplayId);
            state.visibilitiesUpdated(this, display);
            final KeyguardDisplayState state = getDisplayState(display.mDisplayId);
            state.updateVisibility(this, display);
            requestDismissKeyguard |= state.mRequestDismissKeyguard;
        }

@@ -340,7 +348,6 @@ class KeyguardController {
                                false /* alwaysKeepCurrent */, 0 /* flags */,
                                true /* forceOverride */);
                updateKeyguardSleepToken(DEFAULT_DISPLAY);
                mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                mWindowManager.executeAppTransition();
            } finally {
                mService.continueWindowLayout();
@@ -370,13 +377,12 @@ class KeyguardController {
                && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
            dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
                    0 /* flags */, true /* forceOverride */);
            mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
            mWindowManager.executeAppTransition();
        }
    }

    private boolean isDisplayOccluded(int displayId) {
        return getDisplay(displayId).mOccluded;
    boolean isDisplayOccluded(int displayId) {
        return getDisplayState(displayId).mOccluded;
    }

    /**
@@ -433,7 +439,7 @@ class KeyguardController {
    }

    private void updateKeyguardSleepToken(int displayId) {
        final KeyguardDisplayState state = getDisplay(displayId);
        final KeyguardDisplayState state = getDisplayState(displayId);
        if (isKeyguardUnoccludedOrAodShowing(displayId)) {
            state.mSleepTokenAcquirer.acquire(displayId);
        } else if (!isKeyguardUnoccludedOrAodShowing(displayId)) {
@@ -441,7 +447,7 @@ class KeyguardController {
        }
    }

    private KeyguardDisplayState getDisplay(int displayId) {
    private KeyguardDisplayState getDisplayState(int displayId) {
        KeyguardDisplayState state = mDisplayStates.get(displayId);
        if (state == null) {
            state = new KeyguardDisplayState(mService, displayId, mSleepTokenAcquirer);
@@ -462,8 +468,11 @@ class KeyguardController {
    private static class KeyguardDisplayState {
        private final int mDisplayId;
        private boolean mOccluded;

        private ActivityRecord mTopOccludesActivity;
        private ActivityRecord mDismissingKeyguardActivity;
        private ActivityRecord mTopTurnScreenOnActivity;

        private boolean mRequestDismissKeyguard;
        private final ActivityTaskManagerService mService;
        private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
@@ -476,58 +485,77 @@ class KeyguardController {
        }

        void onRemoved() {
            mTopOccludesActivity = null;
            mDismissingKeyguardActivity = null;
            mTopTurnScreenOnActivity = null;
            mSleepTokenAcquirer.release(mDisplayId);
        }

        void visibilitiesUpdated(KeyguardController controller, DisplayContent display) {
        /**
         * Updates {@link #mOccluded}, {@link #mTopTurnScreenOnActivity} and
         * {@link #mDismissingKeyguardActivity} if the top task could be visible.
         */
        void updateVisibility(KeyguardController controller, DisplayContent display) {
            final boolean lastOccluded = mOccluded;
            final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;

            final ActivityRecord lastDismissKeyguardActivity = mDismissingKeyguardActivity;
            final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity;

            mRequestDismissKeyguard = false;
            mOccluded = false;

            mTopOccludesActivity = null;
            mDismissingKeyguardActivity = null;
            mTopTurnScreenOnActivity = null;

            // only top + focusable + visible task can control occluding.
            final Task stack = getStackForControllingOccluding(display);
            if (stack != null) {
                final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
                final ActivityRecord topTurnScreenOn = stack.getTopTurnScreenOnActivity();
                mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
                        && stack.topRunningActivity() == topDismissing
                        && controller.canShowWhileOccluded(
                                true /* dismissKeyguard */,
                                false /* showWhenLocked */));
                if (topDismissing != null) {
                    mDismissingKeyguardActivity = topDismissing;
            boolean occludedByActivity = false;
            final Task task = getRootTaskForControllingOccluding(display);
            if (task != null) {
                final ActivityRecord r = task.getTopNonFinishingActivity();
                if (r != null) {
                    final boolean showWhenLocked = r.canShowWhenLocked();
                    if (r.containsDismissKeyguardWindow()) {
                        mDismissingKeyguardActivity = r;
                    }
                    if (r.getTurnScreenOnFlag()
                            && r.currentLaunchCanTurnScreenOn()) {
                        mTopTurnScreenOnActivity = r;
                    }
                if (topTurnScreenOn != null) {
                    mTopTurnScreenOnActivity = topTurnScreenOn;

                    if (showWhenLocked) {
                        mTopOccludesActivity = r;
                    }

                    // Only the top activity may control occluded, as we can't occlude the Keyguard
                    // if the top app doesn't want to occlude it.
                    occludedByActivity = showWhenLocked || (mDismissingKeyguardActivity != null
                            && task.topRunningActivity() == mDismissingKeyguardActivity
                            && controller.canShowWhileOccluded(
                                    true /* dismissKeyguard */, false /* showWhenLocked */));
                    // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
                if (mDisplayId != DEFAULT_DISPLAY && stack.mDisplayContent != null) {
                    mOccluded |= stack.mDisplayContent.canShowWithInsecureKeyguard()
                    if (mDisplayId != DEFAULT_DISPLAY && task.mDisplayContent != null) {
                        occludedByActivity |=
                                task.mDisplayContent.canShowWithInsecureKeyguard()
                                && controller.canDismissKeyguard();
                    }
                }
            // TODO(b/123372519): isShowingDream can only works on default display.
            if (mDisplayId == DEFAULT_DISPLAY) {
                mOccluded |= mService.mRootWindowContainer.getDefaultDisplay()
                        .getDisplayPolicy().isShowingDreamLw();
            }

            mRequestDismissKeyguard = lastDismissActivity != mDismissingKeyguardActivity
            // TODO(b/123372519): isShowingDream can only works on default display.
            mOccluded = occludedByActivity || (mDisplayId == DEFAULT_DISPLAY
                    && mService.mRootWindowContainer.getDefaultDisplay()
                    .getDisplayPolicy().isShowingDreamLw());
            mRequestDismissKeyguard = lastDismissKeyguardActivity != mDismissingKeyguardActivity
                    && !mOccluded
                    && mDismissingKeyguardActivity != null
                    && controller.mWindowManager.isKeyguardSecure(
                    controller.mService.getCurrentUserId());

            if (mTopTurnScreenOnActivity != null
                    && mTopTurnScreenOnActivity != lastTurnScreenOnActivity
                    && !mService.mWindowManager.mPowerManager.isInteractive()) {
            if (mTopTurnScreenOnActivity != lastTurnScreenOnActivity
                    && mTopTurnScreenOnActivity != null
                    && !mService.mWindowManager.mPowerManager.isInteractive()
                    && (mRequestDismissKeyguard || occludedByActivity)) {
                controller.mStackSupervisor.wakeUp("handleTurnScreenOn");
                mTopOccludesActivity.setCurrentLaunchCanTurnScreenOn(false);
            }

            if (lastOccluded != mOccluded) {
@@ -542,13 +570,13 @@ class KeyguardController {
         * occlusion state.
         */
        @Nullable
        private Task getStackForControllingOccluding(DisplayContent display) {
        private Task getRootTaskForControllingOccluding(DisplayContent display) {
            return display.getItemFromTaskDisplayAreas(taskDisplayArea -> {
                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
                    final Task stack = taskDisplayArea.getStackAt(sNdx);
                    if (stack != null && stack.isFocusableAndVisible()
                            && !stack.inPinnedWindowingMode()) {
                        return stack;
                    final Task task = taskDisplayArea.getStackAt(sNdx);
                    if (task != null && task.isFocusableAndVisible()
                            && !task.inPinnedWindowingMode()) {
                        return task;
                    }
                }
                return null;
+1 −13
Original line number Diff line number Diff line
@@ -2003,20 +2003,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                        notifyClients);
            }
        } finally {
            mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows,
                    notifyClients);
        }
    }

    void commitActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        forAllTaskDisplayAreas(taskDisplayArea -> {
            for (int stackNdx = taskDisplayArea.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
                final Task task = taskDisplayArea.getStackAt(stackNdx);
                task.commitActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            mStackSupervisor.endActivityVisibilityUpdate();
        }
        });
    }

    boolean switchUser(int userId, UserState uss) {
Loading