Loading services/core/java/com/android/server/wm/ActivityRecord.java +5 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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() { Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +4 −8 Original line number Diff line number Diff line Loading @@ -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--; } Loading services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +47 −70 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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); Loading @@ -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) { Loading @@ -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) { Loading @@ -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); Loading @@ -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, Loading @@ -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) { Loading services/core/java/com/android/server/wm/KeyguardController.java +80 −52 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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)); } /** Loading @@ -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 { Loading @@ -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; } Loading Loading @@ -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(); Loading Loading @@ -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; } /** Loading Loading @@ -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)) { Loading @@ -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); Loading @@ -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; Loading @@ -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) { Loading @@ -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; Loading services/core/java/com/android/server/wm/RootWindowContainer.java +1 −13 Original line number Diff line number Diff line Loading @@ -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 Loading
services/core/java/com/android/server/wm/ActivityRecord.java +5 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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() { Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +4 −8 Original line number Diff line number Diff line Loading @@ -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--; } Loading
services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +47 −70 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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); Loading @@ -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) { Loading @@ -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) { Loading @@ -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); Loading @@ -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, Loading @@ -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) { Loading
services/core/java/com/android/server/wm/KeyguardController.java +80 −52 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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)); } /** Loading @@ -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 { Loading @@ -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; } Loading Loading @@ -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(); Loading Loading @@ -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; } /** Loading Loading @@ -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)) { Loading @@ -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); Loading @@ -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; Loading @@ -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) { Loading @@ -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; Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +1 −13 Original line number Diff line number Diff line Loading @@ -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