Merge "Add DREAMING -> GONE when dismissible; fix WmLsVis issue with that case and others." into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
index ead151e..b069855 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
@@ -106,7 +106,7 @@
             repository.setKeyguardEnabled(true)
             runCurrent()
 
-            assertEquals(listOf(false, true, false), canWake)
+            assertEquals(listOf(false, true), canWake)
         }
 
     @Test
@@ -374,6 +374,8 @@
                     // Should be canceled by the wakeup, but there would still be an
                     // alarm in flight that should be canceled.
                     false,
+                    // True once we're actually GONE.
+                    true,
                 ),
                 canWake,
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
index df4d5ab..ea2b3cd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
@@ -206,6 +206,9 @@
     @Test
     @RequiresFlagsDisabled(Flags.FLAG_ENSURE_KEYGUARD_DOES_TRANSITION_STARTING)
     fun setSurfaceBehindVisibility_falseSetsLockscreenVisibility_without_keyguard_shell_transitions() {
+        // Show the surface behind, then hide it.
+        underTest.setLockscreenShown(true)
+        underTest.setSurfaceBehindVisibility(true)
         underTest.setSurfaceBehindVisibility(false)
         verify(activityTaskManagerService).setLockScreenShown(eq(true), any())
     }
@@ -213,6 +216,9 @@
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_ENSURE_KEYGUARD_DOES_TRANSITION_STARTING)
     fun setSurfaceBehindVisibility_falseSetsLockscreenVisibility_with_keyguard_shell_transitions() {
+        // Show the surface behind, then hide it.
+        underTest.setLockscreenShown(true)
+        underTest.setSurfaceBehindVisibility(true)
         underTest.setSurfaceBehindVisibility(false)
         verify(keyguardTransitions).startKeyguardTransition(eq(true), any())
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
index a137d6c..5b28a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
@@ -131,8 +131,18 @@
             Log.d(TAG, "ActivityTaskManagerService#keyguardGoingAway()")
             activityTaskManagerService.keyguardGoingAway(0)
             isKeyguardGoingAway = true
-        } else {
-            // Hide the surface by setting the lockscreen showing.
+        } else if (isLockscreenShowing == true) {
+            // Re-show the lockscreen if the surface was visible and we want to make it invisible,
+            // and the lockscreen is currently showing (this is the usual case of the going away
+            // animation). Re-showing the lockscreen will cancel the going away animation. If we
+            // want to hide the surface, but the lockscreen is not currently showing, do nothing and
+            // wait for lockscreenVisibility to emit if it's appropriate to show the lockscreen (it
+            // might be disabled/suppressed).
+            Log.d(
+                TAG,
+                "setLockscreenShown(true) because we're setting the surface invisible " +
+                    "and lockscreen is already showing.",
+            )
             setLockscreenShown(true)
         }
     }
@@ -153,6 +163,10 @@
         nonApps: Array<RemoteAnimationTarget>,
         finishedCallback: IRemoteAnimationFinishedCallback,
     ) {
+        // Make sure this is true - we set it true when requesting keyguardGoingAway, but there are
+        // cases where WM starts this transition on its own.
+        isKeyguardGoingAway = true
+
         // Ensure that we've started a dismiss keyguard transition. WindowManager can start the
         // going away animation on its own, if an activity launches and then requests dismissing the
         // keyguard. In this case, this is the first and only signal we'll receive to start
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt
index 8641dfa..a133f06 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt
@@ -90,6 +90,7 @@
     private val selectedUserInteractor: SelectedUserInteractor,
     keyguardEnabledInteractor: KeyguardEnabledInteractor,
     keyguardServiceLockNowInteractor: KeyguardServiceLockNowInteractor,
+    keyguardInteractor: KeyguardInteractor,
 ) {
 
     /**
@@ -106,13 +107,18 @@
             .onStart { emit(false) }
 
     /**
-     * Whether we can wake from AOD/DOZING directly to GONE, bypassing LOCKSCREEN/BOUNCER states.
+     * Whether we can wake from AOD/DOZING or DREAMING directly to GONE, bypassing
+     * LOCKSCREEN/BOUNCER states.
      *
      * This is possible in the following cases:
      * - Keyguard is disabled, either from an app request or from security being set to "None".
      * - Keyguard is suppressed, via adb locksettings.
      * - We're wake and unlocking (fingerprint auth occurred while asleep).
      * - We're allowed to ignore auth and return to GONE, due to timeouts not elapsing.
+     * - We're DREAMING and dismissible.
+     * - We're already GONE. Technically you're already awake when GONE, but this makes it easier to
+     *   reason about this state (for example, if canWakeDirectlyToGone, don't tell WM to pause the
+     *   top activity - something you should never do while GONE as well).
      */
     val canWakeDirectlyToGone =
         combine(
@@ -120,14 +126,19 @@
                 shouldSuppressKeyguard,
                 repository.biometricUnlockState,
                 repository.canIgnoreAuthAndReturnToGone,
+                transitionInteractor.currentKeyguardState,
             ) {
                 keyguardEnabled,
                 shouldSuppressKeyguard,
                 biometricUnlockState,
-                canIgnoreAuthAndReturnToGone ->
+                canIgnoreAuthAndReturnToGone,
+                currentState ->
                 (!keyguardEnabled || shouldSuppressKeyguard) ||
                     BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode) ||
-                    canIgnoreAuthAndReturnToGone
+                    canIgnoreAuthAndReturnToGone ||
+                    (currentState == KeyguardState.DREAMING &&
+                        keyguardInteractor.isKeyguardDismissible.value) ||
+                    currentState == KeyguardState.GONE
             }
             .distinctUntilChanged()
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
index 3b99bb4..184f302 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
@@ -34,7 +34,7 @@
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
-import com.android.systemui.util.kotlin.Utils.Companion.toTriple
+import com.android.systemui.util.kotlin.Utils.Companion.toQuad
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
 import dagger.Lazy
@@ -240,10 +240,11 @@
         combine(
                 transitionInteractor.currentKeyguardState,
                 wakeToGoneInteractor.canWakeDirectlyToGone,
-                ::Pair,
+                surfaceBehindVisibility,
+                ::Triple,
             )
-            .sample(transitionInteractor.startedStepWithPrecedingStep, ::toTriple)
-            .map { (currentState, canWakeDirectlyToGone, startedWithPrev) ->
+            .sample(transitionInteractor.startedStepWithPrecedingStep, ::toQuad)
+            .map { (currentState, canWakeDirectlyToGone, surfaceBehindVis, startedWithPrev) ->
                 val startedFromStep = startedWithPrev.previousValue
                 val startedStep = startedWithPrev.newValue
                 val returningToGoneAfterCancellation =
@@ -296,6 +297,11 @@
                     // we should simply tell WM that the lockscreen is no longer visible, and
                     // *not* play the going away animation or related animations.
                     false
+                } else if (!surfaceBehindVis) {
+                    // If the surface behind is not visible, then the lockscreen has to be visible
+                    // since there's nothing to show. The surface behind will never be invisible if
+                    // the lockscreen is disabled or suppressed.
+                    true
                 } else {
                     currentState != KeyguardState.GONE
                 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt
index 4aa132c..8c9163d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt
@@ -43,5 +43,6 @@
             selectedUserInteractor,
             keyguardEnabledInteractor,
             keyguardServiceLockNowInteractor,
+            keyguardInteractor,
         )
     }