Move device unlock initiation to DeviceEntryInteractor

Scene transitions from bouncer are managed by DeviceEntryInteractor instead of the BouncerInteractor

Bug: 310005730
Test: all affected unit tests
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT

Change-Id: Ia3beab0f183eec06289f15f75c91a67a51087b7e
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index f091558..07359d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -60,10 +60,10 @@
 import com.android.systemui.biometrics.AuthRippleController;
 import com.android.systemui.biometrics.UdfpsController;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
@@ -127,7 +127,7 @@
     @NonNull private final KeyguardTransitionInteractor mTransitionInteractor;
     @NonNull private final KeyguardInteractor mKeyguardInteractor;
     @NonNull private final View.AccessibilityDelegate mAccessibilityDelegate;
-    @NonNull private final Lazy<BouncerInteractor> mBouncerInteractor;
+    @NonNull private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractor;
     @NonNull private final SceneContainerFlags mSceneContainerFlags;
 
     // Tracks the velocity of a touch to help filter out the touches that move too fast.
@@ -205,7 +205,7 @@
             @NonNull FeatureFlags featureFlags,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             Context context,
-            Lazy<BouncerInteractor> bouncerInteractor,
+            Lazy<DeviceEntryInteractor> deviceEntryInteractor,
             SceneContainerFlags sceneContainerFlags
     ) {
         mStatusBarStateController = statusBarStateController;
@@ -232,7 +232,7 @@
         dumpManager.registerDumpable(TAG, this);
         mResources = resources;
         mContext = context;
-        mBouncerInteractor = bouncerInteractor;
+        mDeviceEntryInteractor = deviceEntryInteractor;
         mSceneContainerFlags = sceneContainerFlags;
 
         mAccessibilityDelegate = new View.AccessibilityDelegate() {
@@ -747,7 +747,7 @@
         vibrateOnLongPress();
 
         if (mSceneContainerFlags.isEnabled()) {
-            mBouncerInteractor.get().showOrUnlockDevice(null);
+            mDeviceEntryInteractor.get().attemptDeviceEntry();
         } else {
             mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index e8b16db..14cbf76 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -45,7 +45,9 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
@@ -68,6 +70,12 @@
     val isAutoConfirmFeatureEnabled: StateFlow<Boolean>
 
     /**
+     * Emits the result whenever a PIN/Pattern/Password security challenge is attempted by the user
+     * in order to unlock the device.
+     */
+    val authenticationChallengeResult: SharedFlow<Boolean>
+
+    /**
      * The exact length a PIN should be for us to enable PIN length hinting.
      *
      * A PIN that's shorter or longer than this is not eligible for the UI to render hints showing
@@ -164,6 +172,7 @@
             initialValue = false,
             getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled,
         )
+    override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = 6
 
@@ -224,6 +233,7 @@
             } else {
                 lockPatternUtils.reportFailedPasswordAttempt(selectedUserId)
             }
+            authenticationChallengeResult.emit(isSuccessful)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 22b44d5..321293f 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.authentication.domain.interactor
 
-import com.android.app.tracing.TraceUtils.Companion.async
 import com.android.app.tracing.TraceUtils.Companion.withContext
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
@@ -40,6 +39,7 @@
 import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
@@ -47,7 +47,6 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /**
  * Hosts application business logic related to user authentication.
@@ -143,6 +142,13 @@
     /** Whether the pattern should be visible for the currently-selected user. */
     val isPatternVisible: StateFlow<Boolean> = repository.isPatternVisible
 
+    /**
+     * Emits the outcome (successful or unsuccessful) whenever a PIN/Pattern/Password security
+     * challenge is attempted by the user in order to unlock the device.
+     */
+    val authenticationChallengeResult: SharedFlow<Boolean> =
+        repository.authenticationChallengeResult
+
     private var throttlingCountdownJob: Job? = null
 
     init {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index b9a913e..94f1c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.classifier.domain.interactor.FalsingInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.res.R
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.flag.SceneContainerFlags
@@ -51,7 +50,6 @@
     @Application private val applicationScope: CoroutineScope,
     @Application private val applicationContext: Context,
     private val repository: BouncerRepository,
-    private val deviceEntryInteractor: DeviceEntryInteractor,
     private val authenticationInteractor: AuthenticationInteractor,
     private val sceneInteractor: SceneInteractor,
     flags: SceneContainerFlags,
@@ -142,32 +140,6 @@
     }
 
     /**
-     * Either shows the bouncer or unlocks the device, if the bouncer doesn't need to be shown.
-     *
-     * @param message An optional message to show to the user in the bouncer.
-     */
-    fun showOrUnlockDevice(
-        message: String? = null,
-    ) {
-        applicationScope.launch {
-            if (deviceEntryInteractor.isAuthenticationRequired()) {
-                repository.setMessage(
-                    message ?: promptMessage(authenticationInteractor.getAuthenticationMethod())
-                )
-                sceneInteractor.changeScene(
-                    scene = SceneModel(SceneKey.Bouncer),
-                    loggingReason = "request to unlock device while authentication required",
-                )
-            } else {
-                sceneInteractor.changeScene(
-                    scene = SceneModel(SceneKey.Gone),
-                    loggingReason = "request to unlock device while authentication isn't required",
-                )
-            }
-        }
-    }
-
-    /**
      * Resets the user-facing message back to the default according to the current authentication
      * method.
      */
@@ -212,17 +184,11 @@
         return applicationScope
             .async {
                 val authResult = authenticationInteractor.authenticate(input, tryAutoConfirm)
-                when (authResult) {
-                    // Authentication succeeded.
-                    AuthenticationResult.SUCCEEDED ->
-                        sceneInteractor.changeScene(
-                            scene = SceneModel(SceneKey.Gone),
-                            loggingReason = "successful authentication",
-                        )
-                    // Authentication failed.
-                    AuthenticationResult.FAILED -> showErrorMessage()
-                    // Authentication skipped.
-                    AuthenticationResult.SKIPPED -> if (!tryAutoConfirm) showErrorMessage()
+                if (
+                    authResult == AuthenticationResult.FAILED ||
+                        (authResult == AuthenticationResult.SKIPPED && !tryAutoConfirm)
+                ) {
+                    showErrorMessage()
                 }
                 authResult
             }
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
index 1e29e1f..64fd2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.deviceentry.data.repository
 
+import android.util.Log
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -15,9 +16,12 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.withContext
 
@@ -40,6 +44,9 @@
      */
     suspend fun isInsecureLockscreenEnabled(): Boolean
 
+    /** Report successful authentication for device entry. */
+    fun reportSuccessfulAuthentication()
+
     /**
      * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
      * dismissed once the authentication challenge is completed.
@@ -67,7 +74,9 @@
     keyguardStateController: KeyguardStateController,
 ) : DeviceEntryRepository {
 
-    override val isUnlocked =
+    private val _isUnlocked = MutableStateFlow(false)
+
+    private val isUnlockedReportedByLegacyKeyguard =
         conflatedCallbackFlow {
                 val callback =
                     object : KeyguardStateController.Callback {
@@ -99,12 +108,15 @@
                 awaitClose { keyguardStateController.removeCallback(callback) }
             }
             .distinctUntilChanged()
+            .onEach { _isUnlocked.value = it }
             .stateIn(
                 applicationScope,
                 SharingStarted.Eagerly,
                 initialValue = false,
             )
 
+    override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
+
     override suspend fun isInsecureLockscreenEnabled(): Boolean {
         return withContext(backgroundDispatcher) {
             val selectedUserId = userRepository.getSelectedUserInfo().id
@@ -112,6 +124,11 @@
         }
     }
 
+    override fun reportSuccessfulAuthentication() {
+        Log.d(TAG, "Successful authentication reported.")
+        _isUnlocked.value = true
+    }
+
     override val isBypassEnabled: StateFlow<Boolean> =
         conflatedCallbackFlow {
                 val listener =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index e872d13..2f9087b 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -24,16 +24,20 @@
 import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.TrustRepository
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.shared.model.SceneModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
 
 /**
  * Hosts application business logic related to device entry.
@@ -48,9 +52,10 @@
     @Application private val applicationScope: CoroutineScope,
     repository: DeviceEntryRepository,
     private val authenticationInteractor: AuthenticationInteractor,
-    sceneInteractor: SceneInteractor,
+    private val sceneInteractor: SceneInteractor,
     deviceEntryFaceAuthRepository: DeviceEntryFaceAuthRepository,
     trustRepository: TrustRepository,
+    flags: SceneContainerFlags,
 ) {
     /**
      * Whether the device is unlocked.
@@ -125,6 +130,32 @@
             )
 
     /**
+     * Attempt to enter the device and dismiss the lockscreen. If authentication is required to
+     * unlock the device it will transition to bouncer.
+     */
+    fun attemptDeviceEntry() {
+        // TODO (b/307768356),
+        //       1. Check if the device is already authenticated by trust agent/passive biometrics
+        //       2. show SPFS/UDFPS bouncer if it is available AlternateBouncerInteractor.show
+        //       3. For face auth only setups trigger face auth, delay transitioning to bouncer for
+        //          a small amount of time.
+        //       4. Transition to bouncer scene
+        applicationScope.launch {
+            if (isAuthenticationRequired()) {
+                sceneInteractor.changeScene(
+                    scene = SceneModel(SceneKey.Bouncer),
+                    loggingReason = "request to unlock device while authentication required",
+                )
+            } else {
+                sceneInteractor.changeScene(
+                    scene = SceneModel(SceneKey.Gone),
+                    loggingReason = "request to unlock device while authentication isn't required",
+                )
+            }
+        }
+    }
+
+    /**
      * Returns `true` if the device currently requires authentication before entry is granted;
      * `false` if the device can be entered without authenticating first.
      */
@@ -139,4 +170,16 @@
      * lock screen.
      */
     val isBypassEnabled: StateFlow<Boolean> = repository.isBypassEnabled
+
+    init {
+        if (flags.isEnabled()) {
+            applicationScope.launch {
+                authenticationInteractor.authenticationChallengeResult.collectLatest { successful ->
+                    if (successful) {
+                        repository.reportSuccessfulAuthentication()
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index 9edd2c6..5993cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.qs.ui.viewmodel
 
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
 import javax.inject.Inject
 
@@ -26,11 +26,9 @@
 class QuickSettingsSceneViewModel
 @Inject
 constructor(
-    private val bouncerInteractor: BouncerInteractor,
+    private val deviceEntryInteractor: DeviceEntryInteractor,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
 ) {
     /** Notifies that some content in quick settings was clicked. */
-    fun onContentClicked() {
-        bouncerInteractor.showOrUnlockDevice()
-    }
+    fun onContentClicked() = deviceEntryInteractor.attemptDeviceEntry()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index 9c5a201..20b9ede 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.shade.ui.viewmodel
 
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
@@ -34,8 +33,7 @@
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    deviceEntryInteractor: DeviceEntryInteractor,
-    private val bouncerInteractor: BouncerInteractor,
+    private val deviceEntryInteractor: DeviceEntryInteractor,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
 ) {
     /** The key of the scene we should switch to when swiping up. */
@@ -60,9 +58,7 @@
             )
 
     /** Notifies that some content in the shade was clicked. */
-    fun onContentClicked() {
-        bouncerInteractor.showOrUnlockDevice()
-    }
+    fun onContentClicked() = deviceEntryInteractor.attemptDeviceEntry()
 
     private fun upDestinationSceneKey(
         isUnlocked: Boolean,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 1d4f2cb..d2f45ae 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -42,8 +42,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.biometrics.AuthRippleController;
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
 import com.android.systemui.doze.util.BurnInHelperKt;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlags;
@@ -78,7 +78,7 @@
     protected MockitoSession mStaticMockSession;
 
     protected final SceneTestUtils mSceneTestUtils = new SceneTestUtils(this);
-    protected @Mock BouncerInteractor mBouncerInteractor;
+    protected @Mock DeviceEntryInteractor mDeviceEntryInteractor;
     protected @Mock LockIconView mLockIconView;
     protected @Mock AnimatedStateListDrawable mIconDrawable;
     protected @Mock Context mContext;
@@ -176,7 +176,7 @@
                 mFeatureFlags,
                 mPrimaryBouncerInteractor,
                 mContext,
-                () -> mBouncerInteractor,
+                () -> mDeviceEntryInteractor,
                 mSceneTestUtils.getSceneContainerFlags()
         );
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index adcec10..93a5393 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -381,7 +381,7 @@
 
         // THEN show primary bouncer via keyguard view controller, not scene container
         verify(mKeyguardViewController).showPrimaryBouncer(anyBoolean());
-        verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor, never()).attemptDeviceEntry();
     }
 
     @Test
@@ -395,7 +395,7 @@
 
         // THEN show primary bouncer
         verify(mKeyguardViewController, never()).showPrimaryBouncer(anyBoolean());
-        verify(mBouncerInteractor).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor).attemptDeviceEntry();
     }
 
     @Test
@@ -408,6 +408,7 @@
         mUnderTest.onLongPress();
 
         // THEN don't show primary bouncer
-        verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor, never()).attemptDeviceEntry();
+        verify(mKeyguardViewController, never()).showPrimaryBouncer(anyBoolean());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 0c06808..bdb2eea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -127,6 +127,22 @@
             assertThat(values.last()).isTrue()
         }
 
+    @Test
+    fun reportAuthenticationAttempt_emitsAuthenticationChallengeResult() =
+        testScope.runTest {
+            val authenticationChallengeResults by
+                collectValues(underTest.authenticationChallengeResult)
+
+            runCurrent()
+            underTest.reportAuthenticationAttempt(true)
+            runCurrent()
+            underTest.reportAuthenticationAttempt(false)
+            runCurrent()
+            underTest.reportAuthenticationAttempt(true)
+
+            assertThat(authenticationChallengeResults).isEqualTo(listOf(true, false, true))
+        }
+
     private fun setSecurityModeAndDispatchBroadcast(
         securityMode: KeyguardSecurityModel.SecurityMode,
     ) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 103f2b8..ed059b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -211,7 +211,7 @@
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNullAndHasNoEffect() =
+    fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isThrottled by collectLastValue(underTest.isThrottled)
@@ -234,7 +234,7 @@
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalseAndDoesNotUnlockDevice() =
+    fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalse() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
@@ -250,12 +250,10 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.FAILED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalseAndDoesNotUnlockDevice() =
+    fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalse() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
@@ -271,12 +269,10 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.FAILED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrueAndUnlocksDevice() =
+    fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrue() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
@@ -292,12 +288,10 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isTrue()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
@@ -321,7 +315,7 @@
         }
 
     @Test
-    fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNull() =
         testScope.runTest {
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
@@ -334,12 +328,10 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withoutCorrectPassword_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withoutCorrectPassword_returnsNull() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(
                 DataLayerAuthenticationMethodModel.Password
@@ -347,40 +339,29 @@
 
             assertThat(underTest.authenticate("password".toList(), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
     fun throttling() =
         testScope.runTest {
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
             val throttling by collectLastValue(underTest.throttling)
             val isThrottled by collectLastValue(underTest.isThrottled)
             utils.authenticationRepository.setAuthenticationMethod(
                 DataLayerAuthenticationMethodModel.Pin
             )
             underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
-            assertThat(isUnlocked).isTrue()
-            assertThat(isThrottled).isFalse()
-            assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
-
-            utils.deviceEntryRepository.setUnlocked(false)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
 
             // Make many wrong attempts, but just shy of what's needed to get throttled:
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1) {
                 underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-                assertThat(isUnlocked).isFalse()
                 assertThat(isThrottled).isFalse()
                 assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
             }
 
             // Make one more wrong attempt, leading to throttling:
             underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isTrue()
             assertThat(throttling)
                 .isEqualTo(
@@ -394,7 +375,6 @@
             // Correct PIN, but throttled, so doesn't attempt it:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isTrue()
             assertThat(throttling)
                 .isEqualTo(
@@ -427,7 +407,6 @@
 
             // Move the clock forward one more second, to completely finish the throttling period:
             advanceTimeBy(1000)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isFalse()
             assertThat(throttling)
                 .isEqualTo(
@@ -441,7 +420,6 @@
             // Correct PIN and no longer throttled so unlocks successfully:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(isUnlocked).isTrue()
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 5775396..8a7c362 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -43,20 +43,15 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class BouncerInteractorTest : SysuiTestCase() {
+class
+BouncerInteractorTest : SysuiTestCase() {
 
     private val utils = SceneTestUtils(this)
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
-        )
     private val underTest =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -79,11 +74,6 @@
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
-
             underTest.clearMessage()
             assertThat(message).isEmpty()
 
@@ -94,7 +84,6 @@
             assertThat(underTest.authenticate(listOf(9, 8, 7)))
                 .isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PIN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
@@ -102,37 +91,25 @@
             // Correct input.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
     fun pinAuthMethod_tryAutoConfirm_withAutoConfirmPin() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val message by collectLastValue(underTest.message)
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
             utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
             assertThat(isAutoConfirmEnabled).isTrue()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
-            underTest.clearMessage()
 
             // Incomplete input.
             assertThat(underTest.authenticate(listOf(1, 2), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Wrong 6-digit pin
             assertThat(underTest.authenticate(listOf(1, 2, 3, 5, 5, 6), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.FAILED)
-            assertThat(message).isEqualTo(MESSAGE_WRONG_PIN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Correct input.
             assertThat(
@@ -142,7 +119,6 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
@@ -153,16 +129,11 @@
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            underTest.clearMessage()
 
             // Incomplete input.
             assertThat(underTest.authenticate(listOf(1, 2), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Correct input.
             assertThat(
@@ -173,25 +144,16 @@
                 )
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun passwordAuthMethod() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
             utils.authenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Password
             )
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
-
-            underTest.clearMessage()
-            assertThat(message).isEmpty()
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -200,7 +162,6 @@
             assertThat(underTest.authenticate("alohamora".toList()))
                 .isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -208,7 +169,6 @@
             // Correct input.
             assertThat(underTest.authenticate("password".toList()))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
@@ -220,14 +180,6 @@
                 AuthenticationMethodModel.Pattern
             )
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
-
-            underTest.clearMessage()
-            assertThat(message).isEmpty()
-
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
 
@@ -243,7 +195,6 @@
             assertThat(wrongPattern.size).isAtLeast(utils.authenticationRepository.minPatternLength)
             assertThat(underTest.authenticate(wrongPattern)).isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -257,7 +208,6 @@
             assertThat(underTest.authenticate(tooShortPattern))
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -265,51 +215,6 @@
             // Correct input.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.PATTERN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.deviceEntryRepository.setUnlocked(true)
-            runCurrent()
-
-            underTest.showOrUnlockDevice()
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
-            utils.deviceEntryRepository.setUnlocked(false)
-
-            underTest.showOrUnlockDevice()
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_customMessageShown() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val message by collectLastValue(underTest.message)
-            utils.authenticationRepository.setAuthenticationMethod(
-                AuthenticationMethodModel.Password
-            )
-            runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-
-            val customMessage = "Hello there!"
-            underTest.showOrUnlockDevice(customMessage)
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(customMessage)
         }
 
     @Test
@@ -320,13 +225,8 @@
             val message by collectLastValue(underTest.message)
             val currentScene by collectLastValue(sceneInteractor.desiredScene)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            runCurrent()
-            underTest.showOrUnlockDevice()
-            runCurrent()
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { times ->
                 // Wrong PIN.
                 assertThat(underTest.authenticate(listOf(6, 7, 8, 9)))
@@ -355,7 +255,6 @@
             // Correct PIN, but throttled, so doesn't change away from the bouncer scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
             assertTryAgainMessage(
                 message,
                 FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds
@@ -381,12 +280,10 @@
                             FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
                     )
                 )
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
 
             // Correct PIN and no longer throttled so changes to the Gone scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Gone)
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index 8e1f5ac..db64ba2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -39,18 +39,12 @@
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
-        )
     private val underTest =
         PinBouncerViewModel(
             applicationContext = context,
             viewModelScope = testScope.backgroundScope,
             interactor =
                 utils.bouncerInteractor(
-                    deviceEntryInteractor = deviceEntryInteractor,
                     authenticationInteractor = authenticationInteractor,
                     sceneInteractor = sceneInteractor,
                 ),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index 6357a1a..382e284 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -48,14 +48,8 @@
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val actionButtonInteractor = utils.bouncerActionButtonInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = utils.sceneInteractor(),
         )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 390742031..23eba82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -46,14 +46,8 @@
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -110,19 +104,19 @@
     @Test
     fun onAuthenticateKeyPressed_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPasswordBouncer()
 
             underTest.onPasswordInputChanged("password")
             underTest.onAuthenticateKeyPressed()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
     fun onAuthenticateKeyPressed_whenWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             lockDeviceAndOpenPasswordBouncer()
@@ -132,13 +126,11 @@
 
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun onAuthenticateKeyPressed_whenEmpty() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             utils.authenticationRepository.setAuthenticationMethod(
@@ -147,7 +139,6 @@
             utils.deviceEntryRepository.setUnlocked(false)
             sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
             underTest.onShown()
             // Enter nothing.
 
@@ -155,13 +146,13 @@
 
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(ENTER_YOUR_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun onAuthenticateKeyPressed_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             lockDeviceAndOpenPasswordBouncer()
@@ -171,7 +162,7 @@
             underTest.onAuthenticateKeyPressed()
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct password:
             underTest.onPasswordInputChanged("password")
@@ -179,7 +170,7 @@
 
             underTest.onAuthenticateKeyPressed()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 47db4f8..b106d55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -49,14 +49,8 @@
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -120,7 +114,8 @@
     @Test
     fun onDragEnd_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val selectedDots by collectLastValue(underTest.selectedDots)
             val currentDot by collectLastValue(underTest.currentDot)
             lockDeviceAndOpenPatternBouncer()
@@ -150,7 +145,7 @@
 
             underTest.onDragEnd()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
@@ -344,7 +339,8 @@
     @Test
     fun onDragEnd_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val selectedDots by collectLastValue(underTest.selectedDots)
             val currentDot by collectLastValue(underTest.currentDot)
@@ -356,14 +352,14 @@
             assertThat(selectedDots).isEmpty()
             assertThat(currentDot).isNull()
             assertThat(message?.text).isEqualTo(WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct pattern:
             CORRECT_PATTERN.forEach(::dragToCoordinate)
 
             underTest.onDragEnd()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     private fun dragOverCoordinates(vararg coordinatesDragged: Point) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index e07c0b8..69f855d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -48,14 +48,8 @@
     private val testScope = utils.testScope
     private val sceneInteractor = utils.sceneInteractor()
     private val authenticationInteractor = utils.authenticationInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -181,7 +175,8 @@
     @Test
     fun onAuthenticateButtonClicked_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -190,7 +185,7 @@
 
             underTest.onAuthenticateButtonClicked()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
@@ -217,7 +212,8 @@
     @Test
     fun onAuthenticateButtonClicked_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
             lockDeviceAndOpenPinBouncer()
@@ -230,7 +226,7 @@
             underTest.onAuthenticateButtonClicked()
             assertThat(message?.text).ignoringCase().isEqualTo(WRONG_PIN)
             assertThat(pin).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct PIN:
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -240,21 +236,22 @@
 
             underTest.onAuthenticateButtonClicked()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
     fun onAutoConfirm_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
                 underTest.onPinButtonClicked(digit)
             }
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
index 2c80035..0eb8982 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
@@ -96,6 +96,17 @@
         }
 
     @Test
+    fun reportSuccessfulAuthentication_shouldUpdateIsUnlocked() =
+        testScope.runTest {
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            assertThat(isUnlocked).isFalse()
+
+            underTest.reportSuccessfulAuthentication()
+
+            assertThat(isUnlocked).isTrue()
+        }
+
+    @Test
     fun isBypassEnabled_disabledInController() =
         testScope.runTest {
             whenever(keyguardBypassController.isBypassEnabled).thenAnswer { false }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index aebadc5..81251d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -278,12 +278,68 @@
         }
 
     @Test
+    fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+            utils.deviceEntryRepository.setUnlocked(true)
+            runCurrent()
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
+    @Test
+    fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
+    @Test
+    fun showOrUnlockDevice_authMethodSwipe_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
+    @Test
     fun isBypassEnabled_disabledInRepository_false() =
         testScope.runTest {
             utils.deviceEntryRepository.setBypassEnabled(false)
             assertThat(underTest.isBypassEnabled.value).isFalse()
         }
 
+    @Test
+    fun successfulAuthenticationChallengeAttempt_updatedIsUnlockedState() =
+        testScope.runTest {
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            assertThat(isUnlocked).isFalse()
+
+            utils.authenticationRepository.reportAuthenticationAttempt(true)
+
+            assertThat(isUnlocked).isTrue()
+        }
+
     private fun switchToScene(sceneKey: SceneKey) {
         sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index a9f8239..2f93c73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -90,13 +90,8 @@
 
         underTest =
             QuickSettingsSceneViewModel(
-                bouncerInteractor =
-                    utils.bouncerInteractor(
-                        deviceEntryInteractor =
-                            utils.deviceEntryInteractor(
-                                authenticationInteractor = authenticationInteractor,
-                                sceneInteractor = sceneInteractor,
-                            ),
+                deviceEntryInteractor =
+                    utils.deviceEntryInteractor(
                         authenticationInteractor = authenticationInteractor,
                         sceneInteractor = sceneInteractor,
                     ),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index e84d274..790f5fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -135,7 +135,6 @@
 
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -234,7 +233,6 @@
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                bouncerInteractor = bouncerInteractor,
                 shadeHeaderViewModel = shadeHeaderViewModel,
             )
 
@@ -648,6 +646,9 @@
 
         emulateUserDrivenTransition(SceneKey.Bouncer)
         enterPin()
+        // This repository state is not changed by the AuthInteractor, it relies on
+        // KeyguardStateController.
+        utils.deviceEntryRepository.setUnlocked(true)
         emulateUiSceneTransition(
             expectedVisible = false,
         )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 589f9ae..2de927a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -96,12 +96,6 @@
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                bouncerInteractor =
-                    utils.bouncerInteractor(
-                        deviceEntryInteractor = deviceEntryInteractor,
-                        authenticationInteractor = authenticationInteractor,
-                        sceneInteractor = sceneInteractor,
-                    ),
                 shadeHeaderViewModel = shadeHeaderViewModel,
             )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index 81c5d9c..1ec1939 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -25,11 +25,11 @@
 import com.android.systemui.authentication.shared.model.AuthenticationResultModel
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -37,13 +37,13 @@
 import kotlinx.coroutines.test.currentTime
 
 class FakeAuthenticationRepository(
-    private val deviceEntryRepository: FakeDeviceEntryRepository,
     private val currentTime: () -> Long,
 ) : AuthenticationRepository {
 
     private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false)
     override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
         _isAutoConfirmFeatureEnabled.asStateFlow()
+    override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = HINTING_PIN_LENGTH
 
@@ -80,7 +80,7 @@
 
     override suspend fun reportAuthenticationAttempt(isSuccessful: Boolean) {
         failedAttemptCount = if (isSuccessful) 0 else failedAttemptCount + 1
-        deviceEntryRepository.setUnlocked(isSuccessful)
+        authenticationChallengeResult.emit(isSuccessful)
     }
 
     override suspend fun getPinLength(): Int {
@@ -216,9 +216,8 @@
     @Provides
     @SysUISingleton
     fun provideFake(
-        deviceEntryRepository: FakeDeviceEntryRepository,
         scope: TestScope,
-    ) = FakeAuthenticationRepository(deviceEntryRepository, currentTime = { scope.currentTime })
+    ) = FakeAuthenticationRepository(currentTime = { scope.currentTime })
 
     @Module
     interface Bindings {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
index f029348..5ae210b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
@@ -39,6 +39,10 @@
         return isInsecureLockscreenEnabled
     }
 
+    override fun reportSuccessfulAuthentication() {
+        _isUnlocked.value = true
+    }
+
     fun setUnlocked(isUnlocked: Boolean) {
         _isUnlocked.value = isUnlocked
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 36ec18f..6afca15 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -110,7 +110,6 @@
     val deviceEntryRepository: FakeDeviceEntryRepository by lazy { FakeDeviceEntryRepository() }
     val authenticationRepository: FakeAuthenticationRepository by lazy {
         FakeAuthenticationRepository(
-            deviceEntryRepository = deviceEntryRepository,
             currentTime = { testScope.currentTime },
         )
     }
@@ -181,6 +180,7 @@
             sceneInteractor = sceneInteractor,
             deviceEntryFaceAuthRepository = faceAuthRepository,
             trustRepository = trustRepository,
+            flags = FakeSceneContainerFlags(enabled = true)
         )
     }
 
@@ -221,7 +221,6 @@
     }
 
     fun bouncerInteractor(
-        deviceEntryInteractor: DeviceEntryInteractor,
         authenticationInteractor: AuthenticationInteractor,
         sceneInteractor: SceneInteractor,
     ): BouncerInteractor {
@@ -229,7 +228,6 @@
             applicationScope = applicationScope(),
             applicationContext = context,
             repository = BouncerRepository(featureFlags),
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
             flags = sceneContainerFlags,