From 47e576c0654c64ff4eab70f9ecacd44109e149a8 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Mon, 28 Jan 2019 10:26:23 -0800 Subject: [PATCH] Bring more visibility logic from stack to activity. There has been a discrepancy between the condition of pushing configuration to apps in ActivityRecord#ensureActivityConfiguration() and WindowManagerService#relayoutWindow(). This CL tries to remove the discrepancy for most activities (with an exception on activity behind a modal activity in the same stack), by changing relevant logic in ActivityRecord. This effectively fixes b/123127858 (Home page layout issue after exiting a landscape app), but still leaves a question to answer. The root cause of that issue is someone calls startRecentsActivity() to launch Nexus launcher activity and uses mLaunchTaskBehind to promote visibility. In WMS#relayoutWindow() it pushes configuration if mLaunchTaskBehind is true (by setting visibility into AppWindowToken), but ActivityRecord#ensureActivityConfiguration() doesn't consider it visible before this CL. After startRecentActivity() Nexus launcher activity schedules a relayout and receives a landscape configuration because the game is still in the foreground in the relayout pass. Later when it's really brought to foreground ActivityRecord won't push a new configuration to it because ActivityRecord still thinks the last reported configuration is the portrait one. Thus a wrong landscape config stayed. This CL lets ActivityRecord#ensureActivityConfiguration() consider mLaunchTaskBehind and pushes the landscape config, which gives it a chance to fix it when really bringing home to front. Bug: 123127858 Test: Manual test. go/wm-smoke. Change-Id: Iff6ee724a98113921d843344bba322c8b2a55f54 --- .../com/android/server/wm/ActivityRecord.java | 38 ++++++++++++++++--- .../com/android/server/wm/ActivityStack.java | 8 +--- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b7c35c0831740..e52cd7f78db2e 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1895,6 +1895,8 @@ final class ActivityRecord extends ConfigurationContainer { * @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) { @@ -1905,6 +1907,36 @@ final class ActivityRecord extends ConfigurationContainer { return !behindFullscreenActivity || mLaunchTaskBehind; } + boolean shouldBeVisible(boolean behindFullscreenActivity) { + // Check whether activity should be visible without Keyguard influence + visibleIgnoringKeyguard = shouldBeVisibleIgnoringKeyguard(behindFullscreenActivity); + + final ActivityStack stack = getActivityStack(); + if (stack == null) { + return false; + } + + // Whether this activity is the top activity of this stack. + final boolean isTop = this == stack.getTopActivity(); + // Exclude the case where this is the top activity in a pinned stack. + final boolean isTopNotPinnedStack = stack.isAttached() + && stack.getDisplay().isTopNotPinnedStack(stack); + // Now check whether it's really visible depending on Keyguard state. + return stack.checkKeyguardVisibility(this, + visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); + } + + boolean shouldBeVisible() { + final ActivityStack stack = getActivityStack(); + if (stack == null) { + return false; + } + + // TODO: Use real value of behindFullscreenActivity calculated using the same logic in + // ActivityStack#ensureActivitiesVisibleLocked(). + return shouldBeVisible(!stack.shouldBeVisible(null /* starting */)); + } + void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) { // This activity is not currently visible, but is running. Tell it to become visible. if (mState == RESUMED || this == starting) { @@ -2827,11 +2859,7 @@ final class ActivityRecord extends ConfigurationContainer { return true; } - // TODO: We should add ActivityRecord.shouldBeVisible() that checks if the activity should - // be visible based on the stack, task, and lockscreen state and use that here instead. The - // method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked(). - // Skip updating configuration for activity is a stack that shouldn't be visible. - if (!stack.shouldBeVisible(null /* starting */)) { + if (!shouldBeVisible()) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check invisible stack: " + this); return true; diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index c97e4e8a9bc0f..732309c6fc566 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2095,8 +2095,6 @@ class ActivityStack extends ConfigurationContainer { final boolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; - final boolean isTopNotPinnedStack = - isAttached() && getDisplay().isTopNotPinnedStack(this); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList activities = task.mActivities; @@ -2114,11 +2112,7 @@ class ActivityStack extends ConfigurationContainer { // Check whether activity should be visible without Keyguard influence final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard( behindFullscreenActivity); - r.visibleIgnoringKeyguard = visibleIgnoringKeyguard; - - // Now check whether it's really visible depending on Keyguard state. - final boolean reallyVisible = checkKeyguardVisibility(r, - visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); + final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity); if (visibleIgnoringKeyguard) { behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible, behindFullscreenActivity, r);