Loading services/core/java/com/android/server/wm/ActivityRecord.java +31 −21 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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) { // 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() { Loading Loading @@ -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) { Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +8 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading services/core/java/com/android/server/wm/DisplayContent.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +78 −46 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading @@ -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. Loading @@ -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)); && mTask.isTopActivityFocusable() && (starting == null || !starting.isDescendantOf(mTask)); final PooledConsumer f = PooledLambda.obtainConsumer( EnsureActivitiesVisibleHelper::setActivityVisibilityState, this, PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity); mContiner.forAllActivities(f); f.recycle(); 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; } final boolean reallyVisible = r.shouldBeVisible( mBehindFullscreenActivity, false /* ignoringKeyguard */); private void updateActivityVisibility(ActivityRecord r) { final boolean isTop = r == mTop; if (isAboveTop(isTop)) { return; } 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 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; Loading Loading @@ -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, Loading @@ -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 */); } } } services/core/java/com/android/server/wm/KeyguardController.java +48 −10 Original line number Diff line number Diff line Loading @@ -277,6 +277,27 @@ class KeyguardController { && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); } /** * 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}). Loading Loading @@ -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; Loading @@ -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(); } } Loading @@ -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); } } Loading Loading @@ -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()); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +31 −21 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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) { // 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() { Loading Loading @@ -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) { Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +8 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. */ Loading
services/core/java/com/android/server/wm/DisplayContent.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +78 −46 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading @@ -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. Loading @@ -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)); && mTask.isTopActivityFocusable() && (starting == null || !starting.isDescendantOf(mTask)); final PooledConsumer f = PooledLambda.obtainConsumer( EnsureActivitiesVisibleHelper::setActivityVisibilityState, this, PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity); mContiner.forAllActivities(f); f.recycle(); 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; } final boolean reallyVisible = r.shouldBeVisible( mBehindFullscreenActivity, false /* ignoringKeyguard */); private void updateActivityVisibility(ActivityRecord r) { final boolean isTop = r == mTop; if (isAboveTop(isTop)) { return; } 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 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; Loading Loading @@ -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, Loading @@ -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 */); } } }
services/core/java/com/android/server/wm/KeyguardController.java +48 −10 Original line number Diff line number Diff line Loading @@ -277,6 +277,27 @@ class KeyguardController { && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); } /** * 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}). Loading Loading @@ -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; Loading @@ -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(); } } Loading @@ -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); } } Loading Loading @@ -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()); Loading