diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 0d9570697dbfd..eeee062769d01 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4439,34 +4439,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A removeStartingWindow(); } - void notifyUnknownVisibilityLaunched() { - + /** + * Suppress transition until the new activity becomes ready, otherwise the keyguard can appear + * for a short amount of time before the new process with the new activity had the ability to + * set its showWhenLocked flags. + */ + void notifyUnknownVisibilityLaunchedForKeyguardTransition() { // No display activities never add a window, so there is no point in waiting them for // relayout. - if (!noDisplay && getDisplayContent() != null) { - getDisplayContent().mUnknownAppVisibilityController.notifyLaunched(this); - } - } - - /** - * @return true if the input activity should be made visible, ignoring any effect Keyguard - * might have on the visibility - * - * TODO(b/123540470): Combine this method and {@link #shouldBeVisible(boolean)}. - * - * @see {@link ActivityStack#checkKeyguardVisibility} - */ - boolean shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity) { - if (!okToShowLocked()) { - return false; + if (noDisplay || !mStackSupervisor.getKeyguardController().isKeyguardLocked()) { + return; } - return !behindFullscreenActivity || mLaunchTaskBehind; + mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this); } - boolean shouldBeVisible(boolean behindFullscreenActivity) { + /** @return {@code true} if this activity should be made visible. */ + boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) { // Check whether activity should be visible without Keyguard influence - visibleIgnoringKeyguard = shouldBeVisibleIgnoringKeyguard(behindFullscreenActivity); + visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind) + && okToShowLocked(); + + if (ignoringKeyguard) { + return visibleIgnoringKeyguard; + } final ActivityStack stack = getActivityStack(); if (stack == null) { @@ -4495,9 +4491,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } - // TODO: Use real value of behindFullscreenActivity calculated using the same logic in - // ActivityStack#ensureActivitiesVisibleLocked(). - return shouldBeVisible(!stack.shouldBeVisible(null /* starting */)); + final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity( + this, null /* handleBehindFullscreenActivity */); + return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */); } void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) { @@ -5538,12 +5534,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - void removeOrphanedStartingWindow(boolean behindFullscreenActivity) { - if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) { + /** + * If any activities below the top running one are in the INITIALIZING state and they have a + * starting window displayed then remove that starting window. It is possible that the activity + * in this state will never resumed in which case that starting window will be orphaned. + *
+ * It should only be called if this activity is behind other fullscreen activity.
+ */
+ void cancelInitializing() {
+ if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
+ // Remove orphaned starting window.
if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
mStartingWindowState = STARTING_WINDOW_REMOVED;
removeStartingWindow();
}
+ if (isState(INITIALIZING) && !shouldBeVisible(
+ true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
+ // Remove the unknown visibility record because an invisible activity shouldn't block
+ // the keyguard transition.
+ mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
+ }
}
void postWindowRemoveStartingWindowCleanup(WindowState win) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a2353a0226310..8e3995bfd8724 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -162,6 +162,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Consumer;
/**
* State and management of a single stack of activities.
@@ -2118,14 +2119,21 @@ class ActivityStack extends ConfigurationContainer {
}
aboveTop = false;
+ final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity,
+ false /* ignoringKeyguard */);
// Check whether activity should be visible without Keyguard influence
- final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
- behindFullscreenActivity);
- final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity);
- if (visibleIgnoringKeyguard) {
- behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible,
- behindFullscreenActivity, r);
+ 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=" + stackShouldBeVisible
+ + " behindFullscreen=" + behindFullscreenActivity);
+ behindFullscreenActivity = true;
+ } else {
+ behindFullscreenActivity = false;
+ }
}
+
if (reallyVisible) {
if (r.finishing) {
continue;
@@ -2338,18 +2346,6 @@ class ActivityStack extends ConfigurationContainer {
return false;
}
- private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity,
- ActivityRecord r) {
- if (r.occludesParent()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // At this point, nothing else needs to be shown in this task.
- behindFullscreenActivity = true;
- }
- return behindFullscreenActivity;
- }
-
void convertActivityToTranslucent(ActivityRecord r) {
mTranslucentActivityWaiting = r;
mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -2400,14 +2396,22 @@ class ActivityStack extends ConfigurationContainer {
}
}
- /** If any activities below the top running one are in the INITIALIZING state and they have a
- * starting window displayed then remove that starting window. It is possible that the activity
- * in this state will never resumed in which case that starting window will be orphaned. */
+ /** @see ActivityRecord#cancelInitializing() */
void cancelInitializingActivities() {
- final ActivityRecord topActivity = topRunningActivityLocked();
- boolean aboveTop = true;
// We don't want to clear starting window for activities that aren't behind fullscreen
// activities as we need to display their starting window until they are done initializing.
+ checkBehindFullscreenActivity(null /* toCheck */, ActivityRecord::cancelInitializing);
+ }
+
+ /**
+ * If an activity {@param toCheck} is given, this method returns {@code true} if the activity
+ * is occluded by any fullscreen activity. If there is no {@param toCheck} and the handling
+ * function {@param handleBehindFullscreenActivity} is given, this method will pass all occluded
+ * activities to the function.
+ */
+ boolean checkBehindFullscreenActivity(ActivityRecord toCheck,
+ Consumer