Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +68 −9 Original line number Diff line number Diff line Loading @@ -2532,6 +2532,64 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(isAlternateBouncerVisible).isFalse() } @Test fun replacesLockscreenSceneOnBackStack_whenFaceUnlocked_fromShade_noAlternateBouncer() = testScope.runTest { val transitionState = prepareState( isDeviceUnlocked = false, initialSceneKey = Scenes.Lockscreen, authenticationMethod = AuthenticationMethodModel.Pin, ) underTest.start() val isUnlocked by collectLastValue( kosmos.deviceUnlockedInteractor.deviceUnlockStatus.map { it.isUnlocked } ) val currentScene by collectLastValue(sceneInteractor.currentScene) val backStack by collectLastValue(sceneBackInteractor.backStack) val isAlternateBouncerVisible by collectLastValue(kosmos.alternateBouncerInteractor.isVisible) assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Change to shade. sceneInteractor.changeScene(Scenes.Shade, "") transitionState.value = ObservableTransitionState.Idle(Scenes.Shade) runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Show the alternate bouncer. kosmos.alternateBouncerInteractor.forceShow() kosmos.sysuiStatusBarStateController.leaveOpen = true // leave shade open runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isTrue() // Simulate race condition by hiding the alternate bouncer *before* the face unlock: kosmos.alternateBouncerInteractor.hide() runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Trigger a face unlock. updateFaceAuthStatus(isSuccess = true) runCurrent() assertThat(isUnlocked).isTrue() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Gone) assertThat(isAlternateBouncerVisible).isFalse() } private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, Loading Loading @@ -2768,15 +2826,16 @@ class SceneContainerStartableTest : SysuiTestCase() { } private fun updateFaceAuthStatus(isSuccess: Boolean) { with(kosmos.fakeDeviceEntryFaceAuthRepository) { isAuthenticated.value = isSuccess setAuthenticationStatus( if (isSuccess) { kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus( SuccessFaceAuthenticationStatus( successResult = Mockito.mock(FaceManager.AuthenticationResult::class.java) ) ) } else { kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus( FailedFaceAuthenticationStatus() } ) } } Loading packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +16 −9 Original line number Diff line number Diff line Loading @@ -430,8 +430,13 @@ constructor( "mechanism: ${deviceUnlockStatus.deviceUnlockSource}" else -> null } // Not on lockscreen or bouncer, so remain in the current scene. else -> null // Not on lockscreen or bouncer, so remain in the current scene but since // unlocked, replace the Lockscreen scene from the bottom of the navigation // back stack with the Gone scene. else -> { replaceLockscreenSceneOnBackStack() null } } } .collect { (targetSceneKey, loggingReason) -> Loading @@ -440,17 +445,19 @@ constructor( } } /** If the [Scenes.Lockscreen] is on the backstack, replaces it with [Scenes.Gone]. */ /** * If the [Scenes.Lockscreen] is on the bottom of the navigation backstack, replaces it with * [Scenes.Gone]. */ private fun replaceLockscreenSceneOnBackStack() { sceneBackInteractor.updateBackStack { stack -> val list = stack.asIterable().toMutableList() check(list.last() == Scenes.Lockscreen) { "The bottommost/last SceneKey of the back stack isn't" + " the Lockscreen scene like expected. The back" + " stack is $stack." } if (list.lastOrNull() == Scenes.Lockscreen) { list[list.size - 1] = Scenes.Gone sceneStackOf(*list.toTypedArray()) } else { stack } } } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +68 −9 Original line number Diff line number Diff line Loading @@ -2532,6 +2532,64 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(isAlternateBouncerVisible).isFalse() } @Test fun replacesLockscreenSceneOnBackStack_whenFaceUnlocked_fromShade_noAlternateBouncer() = testScope.runTest { val transitionState = prepareState( isDeviceUnlocked = false, initialSceneKey = Scenes.Lockscreen, authenticationMethod = AuthenticationMethodModel.Pin, ) underTest.start() val isUnlocked by collectLastValue( kosmos.deviceUnlockedInteractor.deviceUnlockStatus.map { it.isUnlocked } ) val currentScene by collectLastValue(sceneInteractor.currentScene) val backStack by collectLastValue(sceneBackInteractor.backStack) val isAlternateBouncerVisible by collectLastValue(kosmos.alternateBouncerInteractor.isVisible) assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Change to shade. sceneInteractor.changeScene(Scenes.Shade, "") transitionState.value = ObservableTransitionState.Idle(Scenes.Shade) runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Show the alternate bouncer. kosmos.alternateBouncerInteractor.forceShow() kosmos.sysuiStatusBarStateController.leaveOpen = true // leave shade open runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isTrue() // Simulate race condition by hiding the alternate bouncer *before* the face unlock: kosmos.alternateBouncerInteractor.hide() runCurrent() assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Lockscreen) assertThat(isAlternateBouncerVisible).isFalse() // Trigger a face unlock. updateFaceAuthStatus(isSuccess = true) runCurrent() assertThat(isUnlocked).isTrue() assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(backStack?.asIterable()?.first()).isEqualTo(Scenes.Gone) assertThat(isAlternateBouncerVisible).isFalse() } private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, Loading Loading @@ -2768,15 +2826,16 @@ class SceneContainerStartableTest : SysuiTestCase() { } private fun updateFaceAuthStatus(isSuccess: Boolean) { with(kosmos.fakeDeviceEntryFaceAuthRepository) { isAuthenticated.value = isSuccess setAuthenticationStatus( if (isSuccess) { kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus( SuccessFaceAuthenticationStatus( successResult = Mockito.mock(FaceManager.AuthenticationResult::class.java) ) ) } else { kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus( FailedFaceAuthenticationStatus() } ) } } Loading
packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +16 −9 Original line number Diff line number Diff line Loading @@ -430,8 +430,13 @@ constructor( "mechanism: ${deviceUnlockStatus.deviceUnlockSource}" else -> null } // Not on lockscreen or bouncer, so remain in the current scene. else -> null // Not on lockscreen or bouncer, so remain in the current scene but since // unlocked, replace the Lockscreen scene from the bottom of the navigation // back stack with the Gone scene. else -> { replaceLockscreenSceneOnBackStack() null } } } .collect { (targetSceneKey, loggingReason) -> Loading @@ -440,17 +445,19 @@ constructor( } } /** If the [Scenes.Lockscreen] is on the backstack, replaces it with [Scenes.Gone]. */ /** * If the [Scenes.Lockscreen] is on the bottom of the navigation backstack, replaces it with * [Scenes.Gone]. */ private fun replaceLockscreenSceneOnBackStack() { sceneBackInteractor.updateBackStack { stack -> val list = stack.asIterable().toMutableList() check(list.last() == Scenes.Lockscreen) { "The bottommost/last SceneKey of the back stack isn't" + " the Lockscreen scene like expected. The back" + " stack is $stack." } if (list.lastOrNull() == Scenes.Lockscreen) { list[list.size - 1] = Scenes.Gone sceneStackOf(*list.toTypedArray()) } else { stack } } } Loading