Support direct DOZING->PRIMARY_BOUNCER

This can happen after boot, or if the auth is locked out.

Fixes: 327718578
Test: atest KeyguardTransitionScenariosTest
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint
TEAMFOOD

Change-Id: Ie71e752f0224aa239ba1350d50996ce4b510949a
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 617982f..dbd5e26 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -93,14 +93,22 @@
                     startedKeyguardTransitionStep,
                     keyguardInteractor.isKeyguardOccluded,
                     keyguardInteractor.biometricUnlockState,
+                    keyguardInteractor.primaryBouncerShowing,
                 )
-                .collect { (_, isKeyguardShowing, lastStartedStep, occluded, biometricUnlockState)
-                    ->
+                .collect {
+                    (
+                        _,
+                        isKeyguardShowing,
+                        lastStartedStep,
+                        occluded,
+                        biometricUnlockState,
+                        primaryBouncerShowing) ->
                     if (
                         lastStartedStep.to == KeyguardState.AOD &&
                             !occluded &&
                             !isWakeAndUnlock(biometricUnlockState) &&
-                            isKeyguardShowing
+                            isKeyguardShowing &&
+                            !primaryBouncerShowing
                     ) {
                         val modeOnCanceled =
                             if (lastStartedStep.from == KeyguardState.LOCKSCREEN) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index baa865d..8591fe7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -31,6 +31,8 @@
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.debounce
 import kotlinx.coroutines.launch
 
@@ -59,6 +61,14 @@
         listenForTransitionToCamera(scope, keyguardInteractor)
     }
 
+    private val canDismissLockScreen: Flow<Boolean> =
+        combine(
+            keyguardInteractor.isKeyguardShowing,
+            keyguardInteractor.isKeyguardDismissible,
+        ) { isKeyguardShowing, isKeyguardDismissible ->
+            isKeyguardDismissible && !isKeyguardShowing
+        }
+
     private fun listenForDozingToAny() {
         scope.launch {
             powerInteractor.isAwake
@@ -68,8 +78,8 @@
                     startedKeyguardTransitionStep,
                     keyguardInteractor.isKeyguardOccluded,
                     communalInteractor.isIdleOnCommunal,
-                    keyguardInteractor.isKeyguardShowing,
-                    keyguardInteractor.isKeyguardDismissible,
+                    canDismissLockScreen,
+                    keyguardInteractor.primaryBouncerShowing,
                 )
                 .collect {
                     (
@@ -78,16 +88,18 @@
                         lastStartedTransition,
                         occluded,
                         isIdleOnCommunal,
-                        isKeyguardShowing,
-                        isKeyguardDismissible) ->
+                        canDismissLockScreen,
+                        primaryBouncerShowing) ->
                     if (!(isAwake && lastStartedTransition.to == KeyguardState.DOZING)) {
                         return@collect
                     }
                     startTransitionTo(
                         if (isWakeAndUnlock(biometricUnlockState)) {
                             KeyguardState.GONE
-                        } else if (isKeyguardDismissible && !isKeyguardShowing) {
+                        } else if (canDismissLockScreen) {
                             KeyguardState.GONE
+                        } else if (primaryBouncerShowing) {
+                            KeyguardState.PRIMARY_BOUNCER
                         } else if (occluded) {
                             KeyguardState.OCCLUDED
                         } else if (isIdleOnCommunal) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index eae0467..c65a9ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -654,6 +654,30 @@
             coroutineContext.cancelChildren()
         }
 
+    @Test
+    fun dozingToPrimaryBouncer() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to DOZING
+            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.DOZING)
+            runCurrent()
+
+            // WHEN awaked by a request to show the primary bouncer, as can happen if SPFS is
+            // touched after boot
+            powerInteractor.setAwakeForTest()
+            bouncerRepository.setPrimaryShow(true)
+            advanceTimeBy(60L)
+
+            assertThat(transitionRepository)
+                .startedTransition(
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    from = KeyguardState.DOZING,
+                    ownerName = "FromDozingTransitionInteractor",
+                    animatorAssertion = { it.isNotNull() }
+                )
+
+            coroutineContext.cancelChildren()
+        }
+
     /** This handles security method NONE and screen off with lock timeout */
     @Test
     fun dozingToGoneWithKeyguardNotShowing() =