Don't resume until keyguard is gone

If we try to resume top activity immediately after we remove
the sleep token and something else in the system will call
ActivityStackSupervisor#ensureActivitiesVisibleLocked(), then
the activity will be immediately stopped. This not only introduces
an extra unnecessary cycle, but also leads to other with
activities ending in a wrong state or cycling through states
indefinitely.

Bug: 73003134
Bug: 73062280
Bug: 71582913
Test: Launch an app or go to launcher, lock and unlock, observe lifecycle logs.
Change-Id: Ic0117a55e27c8a67de4ce24ca349bc842d356093
(cherry picked from commit 97f5a016e1c004de0b76915ca33fe3abe8e19f24)
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 8367916..4901192 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -65,7 +65,7 @@
     static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ_REASON = DEBUG_ALL || false;
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || true;
+    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ddba349..40021eb 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1625,20 +1625,6 @@
             // The activity may be waiting for stop, but that is no longer appropriate for it.
             mStackSupervisor.mStoppingActivities.remove(this);
             mStackSupervisor.mGoingToSleepActivities.remove(this);
-
-            // If the activity is stopped or stopping, cycle to the paused state.
-            if (state == STOPPED || state == STOPPING) {
-                // Capture reason before state change
-                final String reason = getLifecycleDescription("makeVisibleIfNeeded");
-
-                // An activity must be in the {@link PAUSING} state for the system to validate
-                // the move to {@link PAUSED}.
-                state = PAUSING;
-                service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
-                        PauseActivityItem.obtain(finishing, false /* userLeaving */,
-                                configChangeFlags, false /* dontReport */)
-                                .setDescription(reason));
-            }
         } catch (Exception e) {
             // Just skip on any failure; we'll make it visible when it next restarts.
             Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 812de88..fe10670 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1419,6 +1419,11 @@
             return false;
         }
 
+        if (prev == resuming) {
+            Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
+            return false;
+        }
+
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
         else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
         mResumedActivity = null;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f4f60c2..b98a0f79 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3342,7 +3342,11 @@
                     stack.goToSleepIfPossible(false /* shuttingDown */);
                 } else {
                     stack.awakeFromSleepingLocked();
-                    if (isFocusedStack(stack)) {
+                    if (isFocusedStack(stack)
+                            && !mKeyguardController.isKeyguardActive(display.mDisplayId)) {
+                        // If there is no keyguard on this display - resume immediately. Otherwise
+                        // we'll wait for keyguard visibility callback and resume while ensuring
+                        // activities visibility
                         resumeFocusedStackTopActivityLocked();
                     }
                 }
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 05305f3..e361a70 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -86,8 +86,16 @@
      *         display, false otherwise
      */
     boolean isKeyguardShowing(int displayId) {
-        return mKeyguardShowing && !mKeyguardGoingAway &&
-                (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
+        return isKeyguardActive(displayId) && !mKeyguardGoingAway;
+    }
+
+    /**
+     * @return true if Keyguard is showing and not occluded. We ignore whether it is going away or
+     *         not here.
+     */
+    boolean isKeyguardActive(int displayId) {
+        return mKeyguardShowing && (displayId == DEFAULT_DISPLAY ? !mOccluded
+                : displayId == mSecondaryDisplayShowing);
     }
 
     /**
@@ -114,6 +122,9 @@
                 mDismissalRequested = false;
             }
         }
+        if (!showing) {
+            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        }
         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
         updateKeyguardSleepToken();
     }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 9923fa8..d3df924 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -108,7 +108,8 @@
         assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
     }
 
-    @Test
+    // TODO: b/71582913
+    //@Test
     public void testPausingWhenVisibleFromStopped() throws Exception {
         final MutableBoolean pauseFound = new MutableBoolean(false);
         doAnswer((InvocationOnMock invocationOnMock) -> {