diff options
| author | 2020-08-18 09:59:15 +0800 | |
|---|---|---|
| committer | 2020-09-10 12:49:06 +0800 | |
| commit | bba6bedfa9a9705e86ff9f1f9afead7ea50bec07 (patch) | |
| tree | 8e15b9a3a98b95527cdb6fde44aa594e46f7eecb | |
| parent | 401dc73af47c422a067c862d0a2c191a8cd8934b (diff) | |
Submit visibility to the activities after the sleep state stable
ActivityRecord#shouldBeVisible can be affected by sleep status.
So in the original ensureActivityVisibility sequence:
beginActivityVisibilityUpdate
ensureActivityVisibility =>
ActivityRecord#shouldBeVisible =>
commit visiblity to the activity if changed
endActivityVisibilityUpdate
KeyguardController#visibilitiesUpdated
Then if the occluding state has changed, execute above sequence again,
which could change the visibility again, so previous loop become
useless. Sometimes the loop cause issue like b/161036653.
An idea is to let KeyguardController to handle
TopActivityOccludesKeyguard and TopDismissingKeyguardActivity together
to update display sleep state. And only commit the visibility to
activities after sleep status is stable.
In this CL the ensureActivityVisibility sequence become
beginActivityVisibilityUpdate
ensureActivityVisibility =>
ActivityRecord#updateVisibilityStatus
endActivityVisibilityUpdate
KeyguardController#visibilitiesUpdated
if occluding state has changed, execute ensureActivityVisibility again.
Then after all sleep status has changed, commit the visibility to
activity.
Bug: 163993448
Test: atest ActivityVisibilityTests KeyguardTests KeyguardLockedTests
KeyguardTransitionTests AppConfigurationTests ReplaceWindowTests
Test: atest ActivityRecordTests RecentTasksTest ActivityStackTests
DisplayContentTests
Change-Id: Ifa69ce5cc8069966c6bf2b23bad56e4b2bd286ba
13 files changed, 237 insertions, 148 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 6df46ed2532b..8410e175eadd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4628,18 +4628,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this); } - /** @return {@code true} if this activity should be made visible. */ - boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) { + 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); if (ignoringKeyguard) { return visibleIgnoringKeyguard; } + return shouldBeVisibleUnchecked(); + } + + boolean shouldBeVisibleUnchecked() { final Task stack = getRootTask(); - if (stack == null) { + if (stack == null || !visibleIgnoringKeyguard) { return false; } @@ -4652,26 +4660,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } - // Check if the activity is on a sleeping display, and if it can turn it ON. - if (mDisplayContent.isSleeping()) { - final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn() - || canShowWhenLocked() || containsDismissKeyguardWindow(); - if (!canTurnScreenOn) { - return false; - } + // Check if the activity is on a sleeping display + // TODO b/163993448 mSetToSleep is required when restarting an existing activity, try to + // remove it if possible. + if (mSetToSleep && mDisplayContent.isSleeping()) { + return false; } + 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 == stack.getTopNonFinishingActivity(); - final boolean isTopNotPinnedStack = stack.isAttached() - && stack.getDisplayArea().isTopNotFinishNotPinnedStack(stack); - final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this, - visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); - - return visibleIgnoringDisplayStatus; + final boolean isTop = this == task.getTopNonFinishingActivity(); + final boolean isTopNotPinnedStack = task.isAttached() + && task.getDisplayArea().isTopNotFinishNotPinnedStack(task); + task.updateKeyguardVisibility(this, isTop && isTopNotPinnedStack); } boolean shouldBeVisible() { @@ -7538,10 +7550,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } final Task stack = getRootTask(); - return stack != null - && !stack.inMultiWindowMode() - && stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, - stack.topRunningActivity() == this /* isTop */); + return stack != null && !stack.inMultiWindowMode() + && mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this); } void setTurnScreenOn(boolean turnScreenOn) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 9df192b76f9a..5196416e2cd3 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -759,8 +759,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { false /* markFrozenIfConfigChanged */, true /* deferResume */); } - if (r.getRootTask().checkKeyguardVisibility(r, true /* shouldBeVisible */, - true /* isTop */) && r.allowMoveToFront()) { + if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) { // We only set the visibility to true if the activity is not being launched in // background, and is allowed to be visible based on keyguard state. This avoids // setting this into motion in window manager that is later cancelled due to later @@ -2298,11 +2297,15 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } /** Ends a batch of visibility updates. */ - void endActivityVisibilityUpdate() { - mVisibilityTransactionDepth--; - if (mVisibilityTransactionDepth == 0) { + 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); } + mVisibilityTransactionDepth--; } /** Returns {@code true} if the caller is on the path to update visibility. */ diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8ccbd1166a44..9d5db1eba9e9 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -36,6 +36,7 @@ import static android.os.Build.VERSION_CODES.N; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Display.INVALID_DISPLAY; @@ -5293,6 +5294,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mSingleTaskInstance = true; } + /** + * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. + */ + boolean canShowWithInsecureKeyguard() { + final int flags = mDisplay.getFlags(); + return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; + } + /** Returns true if the display can only contain one task */ boolean isSingleTaskInstance() { return mSingleTaskInstance; diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index e2c07491db01..251c01469c6a 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -22,12 +22,9 @@ import static com.android.server.wm.Task.TAG_VISIBILITY; import android.annotation.Nullable; import android.util.Slog; -import com.android.internal.util.function.pooled.PooledConsumer; -import com.android.internal.util.function.pooled.PooledLambda; - /** Helper class to ensure activities are in the right visible state for a container. */ class EnsureActivitiesVisibleHelper { - private final Task mContiner; + private final Task mTask; private ActivityRecord mTop; private ActivityRecord mStarting; private boolean mAboveTop; @@ -38,11 +35,11 @@ class EnsureActivitiesVisibleHelper { private boolean mNotifyClients; EnsureActivitiesVisibleHelper(Task container) { - mContiner = container; + mTask = container; } /** - * Update all attributes except {@link mContiner} to use in subsequent calculations. + * Update all attributes except {@link mTask} to use in subsequent calculations. * * @param starting The activity that is being started * @param configChanges Parts of the configuration that changed for this activity for evaluating @@ -54,11 +51,11 @@ class EnsureActivitiesVisibleHelper { void reset(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { mStarting = starting; - mTop = mContiner.topRunningActivity(); + mTop = mTask.topRunningActivity(); // If the top activity is not fullscreen, then we need to make sure any activities under it // are now visible. mAboveTop = mTop != null; - mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting); + mContainerShouldBeVisible = mTask.shouldBeVisible(mStarting); mBehindFullscreenActivity = !mContainerShouldBeVisible; mConfigChanges = configChanges; mPreserveWindows = preserveWindows; @@ -66,7 +63,26 @@ class EnsureActivitiesVisibleHelper { } /** - * Ensure visibility with an option to also update the configuration of visible activities. + * 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. * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean) * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) * @param starting The top most activity in the task. @@ -79,54 +95,84 @@ class EnsureActivitiesVisibleHelper { * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc * be sent to the clients. */ - void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows, - boolean notifyClients) { + void processCommit(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { reset(starting, configChanges, preserveWindows, notifyClients); - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop - + " configChanges=0x" + Integer.toHexString(configChanges)); + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processCommit behind " + mTop); + } if (mTop != null) { - mContiner.checkTranslucentActivityWaiting(mTop); + mTask.checkTranslucentActivityWaiting(mTop); } // We should not resume activities that being launched behind because these // activities are actually behind other fullscreen activities, but still required // to be visible (such as performing Recents animation). final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind - && mContiner.isTopActivityFocusable() - && (starting == null || !starting.isDescendantOf(mContiner)); - - final PooledConsumer f = PooledLambda.obtainConsumer( - EnsureActivitiesVisibleHelper::setActivityVisibilityState, this, - PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity); - mContiner.forAllActivities(f); - f.recycle(); + && mTask.isTopActivityFocusable() + && (starting == null || !starting.isDescendantOf(mTask)); + + mTask.forAllActivities(a -> { + commitActivityVisibility(a, starting, resumeTopActivity); + }); } - private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, - final boolean resumeTopActivity) { - final boolean isTop = r == mTop; + private boolean isAboveTop(boolean isTop) { if (mAboveTop && !isTop) { - return; + return true; } mAboveTop = false; + return false; + } + + private void updateActivityVisibility(ActivityRecord r) { + final boolean isTop = r == mTop; + if (isAboveTop(isTop)) { + return; + } - final boolean reallyVisible = r.shouldBeVisible( - mBehindFullscreenActivity, false /* ignoringKeyguard */); + r.updateVisibility(mBehindFullscreenActivity); // Check whether activity should be visible without Keyguard influence if (r.visibleIgnoringKeyguard) { if (r.occludesParent()) { // At this point, nothing else needs to be shown in this task. - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r - + " stackVisible=" + mContainerShouldBeVisible - + " behindFullscreen=" + mBehindFullscreenActivity); + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r + + " stackVisible=" + mContainerShouldBeVisible + + " behindFullscreen=" + mBehindFullscreenActivity); + } mBehindFullscreenActivity = true; } else { mBehindFullscreenActivity = false; } } + 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; @@ -170,20 +216,6 @@ class EnsureActivitiesVisibleHelper { + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); r.makeInvisible(); } - - final int windowingMode = mContiner.getWindowingMode(); - if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome() - && r.isRootOfTask()) { - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner - + " 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, @@ -207,7 +239,7 @@ class EnsureActivitiesVisibleHelper { r.setVisibility(true); } if (r != starting) { - mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */); + mTask.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */); } } } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 69e8c57a489c..bad28ba333ba 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -278,6 +278,27 @@ class KeyguardController { } /** + * Checks whether {@param r} should be visible depending on Keyguard state. + * + * @return true if {@param r} is visible taken Keyguard state into account, false otherwise + */ + boolean checkKeyguardVisibility(ActivityRecord r) { + if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) { + return true; + } + + 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()); + } else if (isKeyguardLocked()) { + return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked()); + } else { + return true; + } + } + + /** * Makes sure to update lockscreen occluded/dismiss state if needed after completing all * visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}). */ @@ -442,6 +463,7 @@ class KeyguardController { private final int mDisplayId; private boolean mOccluded; private ActivityRecord mDismissingKeyguardActivity; + private ActivityRecord mTopTurnScreenOnActivity; private boolean mRequestDismissKeyguard; private final ActivityTaskManagerService mService; private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; @@ -455,30 +477,38 @@ class KeyguardController { void onRemoved() { mDismissingKeyguardActivity = null; + mTopTurnScreenOnActivity = null; mSleepTokenAcquirer.release(mDisplayId); } void visibilitiesUpdated(KeyguardController controller, DisplayContent display) { final boolean lastOccluded = mOccluded; final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity; + final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity; mRequestDismissKeyguard = false; mOccluded = false; 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 (stack.getTopDismissingKeyguardActivity() != null) { - mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity(); + if (topDismissing != null) { + mDismissingKeyguardActivity = topDismissing; + } + if (topTurnScreenOn != null) { + mTopTurnScreenOnActivity = topTurnScreenOn; } // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display. - if (mDisplayId != DEFAULT_DISPLAY) { - mOccluded |= stack.canShowWithInsecureKeyguard() + if (mDisplayId != DEFAULT_DISPLAY && stack.mDisplayContent != null) { + mOccluded |= stack.mDisplayContent.canShowWithInsecureKeyguard() && controller.canDismissKeyguard(); } } @@ -488,14 +518,20 @@ class KeyguardController { .getDisplayPolicy().isShowingDreamLw(); } - if (lastOccluded != mOccluded) { - controller.handleOccludedChanged(mDisplayId); - } - if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded + mRequestDismissKeyguard = lastDismissActivity != mDismissingKeyguardActivity + && !mOccluded && mDismissingKeyguardActivity != null && controller.mWindowManager.isKeyguardSecure( - controller.mService.getCurrentUserId())) { - mRequestDismissKeyguard = true; + controller.mService.getCurrentUserId()); + + if (mTopTurnScreenOnActivity != null + && mTopTurnScreenOnActivity != lastTurnScreenOnActivity + && !mService.mWindowManager.mPowerManager.isInteractive()) { + controller.mStackSupervisor.wakeUp("handleTurnScreenOn"); + } + + if (lastOccluded != mOccluded) { + controller.handleOccludedChanged(mDisplayId); } } @@ -525,6 +561,8 @@ class KeyguardController { sb.append(" Occluded=").append(mOccluded) .append(" DismissingKeyguardActivity=") .append(mDismissingKeyguardActivity) + .append(" TurnScreenOnActivity=") + .append(mTopTurnScreenOnActivity) .append(" at display=") .append(mDisplayId); pw.println(sb.toString()); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 6539e1325ec1..fca89ac68c39 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1982,10 +1982,22 @@ class RootWindowContainer extends WindowContainer<DisplayContent> notifyClients); } } finally { - mStackSupervisor.endActivityVisibilityUpdate(); + 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); + } + }); + } + boolean switchUser(int userId, UserState uss) { final Task topFocusedStack = getTopDisplayFocusedStack(); final int focusStackId = topFocusedStack != null diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index c35d73282442..a541192885fe 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -61,7 +61,6 @@ import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.INVALID_DISPLAY; import static android.view.SurfaceControl.METADATA_TASK_ID; import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; @@ -197,7 +196,6 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import android.view.Display; import android.view.DisplayInfo; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; @@ -600,6 +598,7 @@ class Task extends WindowContainer<WindowContainer> { private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; + private ActivityRecord mTopTurnScreenOnActivity; private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1; @@ -5663,21 +5662,29 @@ class Task extends WindowContainer<WindowContainer> { boolean preserveWindows, boolean notifyClients) { mTopActivityOccludesKeyguard = false; mTopDismissingKeyguardActivity = null; + mTopTurnScreenOnActivity = null; mStackSupervisor.beginActivityVisibilityUpdate(); try { - mEnsureActivitiesVisibleHelper.process( - starting, configChanges, preserveWindows, notifyClients); + mEnsureActivitiesVisibleHelper.processUpdate(starting); if (mTranslucentActivityWaiting != null && mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { - // Nothing is getting drawn or everything was already visible, don't wait for timeout. + // Nothing is getting drawn or everything was already visible, don't wait for + // timeout. notifyActivityDrawnLocked(null); } } finally { - mStackSupervisor.endActivityVisibilityUpdate(); + mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows, + notifyClients); } } + void commitActivitiesVisible(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { + mEnsureActivitiesVisibleHelper.processCommit(starting, configChanges, preserveWindows, + notifyClients); + } + /** * @return true if the top visible activity wants to occlude the Keyguard, false otherwise */ @@ -5711,64 +5718,34 @@ class Task extends WindowContainer<WindowContainer> { } /** - * Checks whether {@param r} should be visible depending on Keyguard state and updates - * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if - * necessary. - * - * @return true if {@param r} is visible taken Keyguard state into account, false otherwise + * @return the top most visible activity that wants to turn screen on */ - boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) { - int displayId = getDisplayId(); - if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY; + ActivityRecord getTopTurnScreenOnActivity() { + return mTopTurnScreenOnActivity; + } - final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController() - .isKeyguardOrAodShowing(displayId); - final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked(); + /** + * Updates {@link #mTopActivityOccludesKeyguard}, {@link #mTopTurnScreenOnActivity} and + * {@link #mTopDismissingKeyguardActivity} if this task could be visible. + * + */ + void updateKeyguardVisibility(ActivityRecord r, boolean isTop) { final boolean showWhenLocked = r.canShowWhenLocked(); final boolean dismissKeyguard = r.containsDismissKeyguardWindow(); - if (shouldBeVisible) { - if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { - mTopDismissingKeyguardActivity = 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. - if (isTop) { - mTopActivityOccludesKeyguard |= showWhenLocked; - } - - final boolean canShowWithKeyguard = canShowWithInsecureKeyguard() - && mStackSupervisor.getKeyguardController().canDismissKeyguard(); - if (canShowWithKeyguard) { - return true; - } - } - if (keyguardOrAodShowing) { - // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard - // right away and AOD isn't visible. - return shouldBeVisible && mStackSupervisor.getKeyguardController() - .canShowActivityWhileKeyguardShowing(r, dismissKeyguard); - } else if (keyguardLocked) { - return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded( - dismissKeyguard, showWhenLocked); - } else { - return shouldBeVisible; + final boolean turnScreenOn = r.canTurnScreenOn(); + if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { + mTopDismissingKeyguardActivity = r; } - } - /** - * Check if the display to which this stack is attached has - * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. - */ - boolean canShowWithInsecureKeyguard() { - final DisplayContent displayContent = mDisplayContent; - if (displayContent == null) { - throw new IllegalStateException("Stack is not attached to any display, stackId=" - + getRootTaskId()); + if (turnScreenOn && mTopTurnScreenOnActivity == null) { + mTopTurnScreenOnActivity = r; } - final int flags = displayContent.mDisplay.getFlags(); - return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; + // Only the top activity may control occluded, as we can't occlude the Keyguard if the + // top app doesn't want to occlude it. + if (isTop) { + mTopActivityOccludesKeyguard |= showWhenLocked; + } } void checkTranslucentActivityWaiting(ActivityRecord top) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 6550167683a0..2b32e40f7332 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -1779,7 +1779,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { notifyClients); } } finally { - mAtmService.mStackSupervisor.endActivityVisibilityUpdate(); + mAtmService.mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, + preserveWindows, notifyClients); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 09375db01888..89a0c7c4885e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -73,7 +73,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; @@ -1671,8 +1670,6 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testCanTurnScreenOn() { mStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - doReturn(true).when(mStack).checkKeyguardVisibility( - same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean()); doReturn(true).when(mActivity).getTurnScreenOnFlag(); assertTrue(mActivity.canTurnScreenOn()); @@ -1681,8 +1678,6 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testFreeformWindowCantTurnScreenOn() { mStack.setWindowingMode(WINDOWING_MODE_FREEFORM); - doReturn(true).when(mStack).checkKeyguardVisibility( - same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean()); doReturn(true).when(mActivity).getTurnScreenOnFlag(); assertFalse(mActivity.canTurnScreenOn()); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 4951658bbd78..a60f93a3b14a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -1410,7 +1410,7 @@ public class ActivityStackTests extends WindowTestsBase { new ActivityBuilder(mAtm).setTask(mTask).build(); new ActivityBuilder(mAtm).setTask(mTask).build(); doReturn(false).when(nonTopVisibleActivity).attachedToProcess(); - doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean()); + doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleUnchecked(); doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(), anyBoolean()); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 7f904265de15..32896791d915 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -823,7 +823,14 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent newDisplay = createNewDisplay(); final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin"); + final Task stack = mDisplayContent.getTopStack(); + final ActivityRecord activity = stack.topRunningActivity(); + doReturn(true).when(activity).shouldBeVisibleUnchecked(); + final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1"); + final Task stack1 = newDisplay.getTopStack(); + final ActivityRecord activity1 = stack1.topRunningActivity(); + doReturn(true).when(activity1).shouldBeVisibleUnchecked(); appWin.setHasSurface(true); appWin1.setHasSurface(true); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 253fbae4579b..5231fd7ba956 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -44,6 +44,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -291,7 +292,8 @@ public class RecentTasksTest extends WindowTestsBase { mRecentTasks.add(mTasks.get(1)); invocation.callRealMethod(); return null; - }).when(mSupervisor).endActivityVisibilityUpdate(); + }).when(mSupervisor).endActivityVisibilityUpdate(any(), anyInt(), anyBoolean(), + anyBoolean()); mTaskContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */, false /* notifyClients */); diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index eb7d9c2d3c32..6a29c5b5424a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -534,11 +534,14 @@ public class SystemServicesTestRule implements TestRule { doNothing().when(this).scheduleIdleTimeout(any()); // unit test version does not handle launch wake lock doNothing().when(this).acquireLaunchWakelock(); - doReturn(mock(KeyguardController.class)).when(this).getKeyguardController(); mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class); initialize(); + + final KeyguardController controller = getKeyguardController(); + spyOn(controller); + doReturn(true).when(controller).checkKeyguardVisibility(any()); } } |