diff options
| author | 2025-03-19 16:10:54 -0700 | |
|---|---|---|
| committer | 2025-03-19 16:10:54 -0700 | |
| commit | 2bcc948cb94e9b0fffba895fb9f0bdaaef44a72e (patch) | |
| tree | 4bc5b9c9d38d9f40c950e3139a7d9b9a2813ca87 | |
| parent | 502a5b56b5eb3de345e8f0b8f4c7161fab2a465f (diff) | |
[flexiglass] Sleep, unlock state, and auth method logic changes
1. No longer change scenes if the device becomes unlocked while
asleep; stay on the lockscreen; we especially don't want to go from
bouncer to gone while asleep
2. If the auth method changes to a non-secure one, hide the bouncer overlay
Bug: 404470548
Test: unit tests added
Test: manually verified that unlocking the device while its asleep
doesn't move to the gone scene (used adb to change the auth method to a
non-secure one while the device was asleep and observed the
SceneFramework logcat tag to see what scene changes are started in
response)
Test: manually verified that changing the auth method to a non-secure
one while the device is awake and on the bouncer scene correctly hides
the bouncer and returns to the lockscreen scene (using the same method
as above)
Flag: com.android.systemui.scene_container
Change-Id: I7ecc74824adf25b5c05116de783417eb3fa7c85f
2 files changed, 102 insertions, 2 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index 6d4fffdefb1b..00710dc037fa 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.scene.domain.startable import android.app.StatusBarManager @@ -121,6 +123,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.settings.data.repository.userAwareSecureSettingsRepository import com.google.android.msdl.data.model.MSDLToken import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -2608,6 +2611,75 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + fun handleDeviceUnlockStatus_returnsToLsFromBouncer_whenGoesToSleep() = + testScope.runTest { + val authMethod by collectLastValue(kosmos.authenticationInteractor.authenticationMethod) + val isUnlocked by + collectLastValue( + kosmos.deviceUnlockedInteractor.deviceUnlockStatus.map { it.isUnlocked } + ) + val currentScene by collectLastValue(sceneInteractor.currentScene) + val currentOverlays by collectLastValue(sceneInteractor.currentOverlays) + val isAwake by collectLastValue(powerInteractor.isAwake) + prepareState( + isDeviceUnlocked = false, + initialSceneKey = Scenes.Lockscreen, + authenticationMethod = AuthenticationMethodModel.Pin, + startsAwake = true, + ) + underTest.start() + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin) + assertThat(isUnlocked).isFalse() + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).doesNotContain(Overlays.Bouncer) + assertThat(isAwake).isTrue() + + sceneInteractor.showOverlay(Overlays.Bouncer, "") + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin) + assertThat(isUnlocked).isFalse() + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).contains(Overlays.Bouncer) + assertThat(isAwake).isTrue() + + powerInteractor.setAsleepForTest() + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin) + assertThat(isUnlocked).isFalse() + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).doesNotContain(Overlays.Bouncer) + assertThat(isAwake).isFalse() + } + + @Test + fun hidesBouncer_whenAuthMethodChangesToNonSecure() = + testScope.runTest { + val authMethod by collectLastValue(kosmos.authenticationInteractor.authenticationMethod) + val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) + val currentOverlays by collectLastValue(kosmos.sceneInteractor.currentOverlays) + prepareState( + authenticationMethod = AuthenticationMethodModel.Password, + initialSceneKey = Scenes.Lockscreen, + ) + underTest.start() + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Password) + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).doesNotContain(Overlays.Bouncer) + + sceneInteractor.showOverlay(Overlays.Bouncer, "") + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Password) + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).contains(Overlays.Bouncer) + + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.None + ) + runCurrent() + + assertThat(authMethod).isEqualTo(AuthenticationMethodModel.None) + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + assertThat(currentOverlays).doesNotContain(Overlays.Bouncer) + } + + @Test fun replacesLockscreenSceneOnBackStack_whenFaceUnlocked_fromShade_noAlternateBouncer() = testScope.runTest { val transitionState = @@ -2898,7 +2970,10 @@ class SceneContainerStartableTest : SysuiTestCase() { sceneInteractor.changeScene(it, "prepareState, initialSceneKey isn't null") } for (overlay in initialOverlays) { - sceneInteractor.showOverlay(overlay, "prepareState, initialOverlays isn't empty") + sceneInteractor.instantlyShowOverlay( + overlay, + "prepareState, initialOverlays isn't empty", + ) } if (startsAwake) { powerInteractor.setAwakeForTest() diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index 06fc8610c97b..daaa2db54775 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -332,6 +332,7 @@ constructor( /** Switches between scenes based on ever-changing application state. */ private fun automaticallySwitchScenes() { handleBouncerImeVisibility() + handleBouncerHiding() handleSimUnlock() handleDeviceUnlockStatus() handlePowerState() @@ -352,6 +353,24 @@ constructor( } } + private fun handleBouncerHiding() { + applicationScope.launch { + repeatWhen( + condition = + authenticationInteractor + .get() + .authenticationMethod + .map { !it.isSecure } + .distinctUntilChanged() + ) { + sceneInteractor.hideOverlay( + overlay = Overlays.Bouncer, + loggingReason = "Authentication method changed to a non-secure one.", + ) + } + } + } + private fun handleSimUnlock() { applicationScope.launch { simBouncerInteractor @@ -434,6 +453,12 @@ constructor( } } + if (powerInteractor.detailedWakefulness.value.isAsleep()) { + // The logic below is for when the device becomes unlocked. That must be a + // no-op if the device is not awake. + return@mapNotNull null + } + if ( isOnPrimaryBouncer && deviceUnlockStatus.deviceUnlockSource == DeviceUnlockSource.TrustAgent @@ -833,7 +858,7 @@ constructor( } .collect { val loggingReason = "Falsing detected." - switchToScene(Scenes.Lockscreen, loggingReason) + switchToScene(targetSceneKey = Scenes.Lockscreen, loggingReason = loggingReason) } } } |