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
(cherry picked from commit 47e576c0654c64ff4eab70f9ecacd44109e149a8)
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8f39f3d..aa0c62c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1916,6 +1916,8 @@
      * @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) {
@@ -1926,6 +1928,36 @@
         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) {
@@ -2848,11 +2880,7 @@
             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 549567a..b23dcb3 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 @@
             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<ActivityRecord> activities = task.mActivities;
@@ -2114,11 +2112,7 @@
                     // 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);