summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ale Nijamkin <nijamkin@google.com> 2025-03-19 16:10:54 -0700
committer Ale Nijamkin <nijamkin@google.com> 2025-03-19 16:10:54 -0700
commit2bcc948cb94e9b0fffba895fb9f0bdaaef44a72e (patch)
tree4bc5b9c9d38d9f40c950e3139a7d9b9a2813ca87
parent502a5b56b5eb3de345e8f0b8f4c7161fab2a465f (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
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt77
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt27
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)
}
}
}