diff options
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 e79587776412..ad281247a719 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() { @@ -7537,10 +7549,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 c96509e5ef51..4db121b6ea33 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -35,6 +35,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; @@ -5271,6 +5272,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 ee9886b4a98f..d149db6b676f 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1983,10 +1983,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 bc607bf4175a..c4ca4cd637e3 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; @@ -5664,21 +5663,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 */ @@ -5712,64 +5719,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 2791234031da..89a34cfc77f3 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 f4f172d8e5b5..58d994c6cae3 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()); } } |