summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alejandro Nijamkin <nijamkin@google.com> 2024-09-11 09:13:40 -0700
committer Alejandro Nijamkin <nijamkin@google.com> 2024-09-11 11:02:14 -0700
commit43ba03fddffdddb87b2f6c6a900ccf9be137b712 (patch)
tree57197ced983fc31a374c18b5f9a7564117428031
parent79e3576e2d345f56637856d28f47053fcdf88f4b (diff)
[flexiglass] isDeviceEntered also checks back stack
isDeviceEntered should always reflect whether the user has "passed the lockscreen". Up until this point, this has only happened if the user visited the Gone scene. This CL changes that for cases when the lockscreen is "passed" by the user but without yet visiting the Gone scene. For example, in the case of unlocking while looking at the Shade scene (when clicking a notification that requires unlocking to continue). In cases like the one above, the current scene is Bouncer and the back stack is (top to bottom): [Shade, Lockscreen]. This CL contains two main changes: 1. Replace the Lockscreen at the bottom of the back stack with Gone, when unlocking in this case 2. Make DeviceEntryInteractor.isDeviceEntered watch the bottom of the back stack for a Lockscreen -> Gone swap in addition to the classic visiting of the Gone or Lockscreen scenes as it did before Bug: 359530769 Test: unit test added for the new case Test: existing unit and integration tests modified to better model what's going on and make them pass Test: manually verified no harm done (a) normal unlock with pattern bouncer + re-lock + visiting all scenes in both locked and unlocked states (b) locked -> shade -> notification click -> unlock via alternate bouncer / fingerprint (c) locked -> shade -> notification click -> dismiss alternate bouncer -> bouncer -> unlock via bouncer (d) double tap power to bring up camera app while locked -> click on gallery button -> unlock via alternate bouncer / primary bouncer Flag: com.android.systemui.scene_container Change-Id: I9e8b6a34afd574352d01f25819b71e1702af3d15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt41
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt49
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt22
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt184
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt48
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt3
9 files changed, 233 insertions, 180 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index 3253edfb5fca..d90d58b8d25c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.deviceentry.domain.interactor
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
@@ -42,11 +43,16 @@ import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -66,10 +72,14 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
private val trustRepository by lazy { kosmos.fakeTrustRepository }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
+ private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor }
+ private val sceneContainerStartable by lazy { kosmos.sceneContainerStartable }
+ private val sysuiStatusBarStateController by lazy { kosmos.sysuiStatusBarStateController }
private lateinit var underTest: DeviceEntryInteractor
@Before
fun setUp() {
+ sceneContainerStartable.start()
underTest = kosmos.deviceEntryInteractor
}
@@ -423,8 +433,37 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
assertThat(isUnlocked).isTrue()
}
- private fun switchToScene(sceneKey: SceneKey) {
+ @Test
+ fun isDeviceEntered_unlockedWhileOnShade_emitsTrue() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ assertThat(isDeviceEntered).isFalse()
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ // Navigate to shade and bouncer:
+ switchToScene(Scenes.Shade)
+ assertThat(currentScene).isEqualTo(Scenes.Shade)
+ // Simulating a "leave it open when the keyguard is hidden" which means the bouncer will
+ // be
+ // shown and successful authentication should take the user back to where they are, the
+ // shade scene.
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
+ switchToScene(Scenes.Bouncer)
+ assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+
+ assertThat(isDeviceEntered).isFalse()
+ // Authenticate with PIN to unlock and dismiss the lockscreen:
+ authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
+ runCurrent()
+
+ assertThat(isDeviceEntered).isTrue()
+ }
+
+ private fun TestScope.switchToScene(sceneKey: SceneKey) {
sceneInteractor.changeScene(sceneKey, "reason")
+ sceneInteractor.setTransitionState(flowOf(ObservableTransitionState.Idle(sceneKey)))
+ runCurrent()
}
private suspend fun givenCanShowAlternateBouncer() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 2d42c4247ab7..a0cafcbd5ad1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -161,9 +161,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- kosmos.emulateUserDrivenTransition(
- to = upDestinationSceneKey,
- )
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
kosmos.fakeSceneDataSource.pause()
kosmos.enterPin()
@@ -226,16 +224,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
assertThat(homeScene).isEqualTo(Scenes.Gone)
- kosmos.emulateUserDrivenTransition(
- to = homeScene,
- )
+ kosmos.emulateUserDrivenTransition(to = homeScene)
}
@Test
fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
testScope.runTest {
kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
kosmos.wakeUpDevice()
@@ -246,7 +242,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
testScope.runTest {
kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
kosmos.wakeUpDevice()
@@ -302,7 +298,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
testScope.runTest {
kosmos.unlockDevice()
kosmos.assertCurrentScene(Scenes.Gone)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
// Pretend like the timeout elapsed and now lock the device.
@@ -318,9 +314,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- kosmos.emulateUserDrivenTransition(
- to = upDestinationSceneKey,
- )
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
kosmos.fakeSceneDataSource.pause()
kosmos.dismissIme()
@@ -388,7 +382,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
kosmos.emulatePendingTransitionProgress(expectedVisible = true)
kosmos.enterSimPin(
authMethodAfterSimUnlock = AuthenticationMethodModel.None,
- enableLockscreen = false
+ enableLockscreen = false,
)
kosmos.assertCurrentScene(Scenes.Gone)
@@ -434,7 +428,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
/** Updates the current authentication method and related states in the data layer. */
private fun Kosmos.setAuthMethod(
authMethod: AuthenticationMethodModel,
- enableLockscreen: Boolean = true
+ enableLockscreen: Boolean = true,
) {
if (authMethod.isSecure) {
assert(enableLockscreen) {
@@ -538,24 +532,27 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
kosmos.fakeSceneDataSource.pause()
sceneInteractor.changeScene(to, "reason")
- emulatePendingTransitionProgress(
- expectedVisible = to != Scenes.Gone,
- )
+ emulatePendingTransitionProgress(expectedVisible = to != Scenes.Gone)
}
/**
- * Locks the device immediately (without delay).
+ * Locks the device.
*
* Asserts the device to be lockable (e.g. that the current authentication is secure).
*
- * Not to be confused with [putDeviceToSleep], which may also instantly lock the device.
+ * Internally emulates a power button press that puts the device to sleep, followed by another
+ * power button press that wakes up the device but is then expected to be in the locked state.
*/
private suspend fun Kosmos.lockDevice() {
val authMethod = authenticationInteractor.getAuthenticationMethod()
assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!")
.that(authMethod.isSecure)
.isTrue()
- sceneInteractor.changeScene(Scenes.Lockscreen, "")
+
+ powerInteractor.setAsleepForTest()
+ testScope.runCurrent()
+
+ powerInteractor.setAwakeForTest()
testScope.runCurrent()
}
@@ -569,9 +566,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fakeSceneDataSource.pause()
enterPin()
- emulatePendingTransitionProgress(
- expectedVisible = false,
- )
+ emulatePendingTransitionProgress(expectedVisible = false)
}
/**
@@ -645,9 +640,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
}
/** Changes device wakefulness state from awake to asleep, going through intermediary states. */
- private suspend fun Kosmos.putDeviceToSleep(
- instantlyLockDevice: Boolean = true,
- ) {
+ private suspend fun Kosmos.putDeviceToSleep() {
val wakefulnessModel = powerInteractor.detailedWakefulness.value
assertWithMessage("Cannot put device to sleep as it's already asleep!")
.that(wakefulnessModel.isAwake())
@@ -655,10 +648,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
powerInteractor.setAsleepForTest()
testScope.runCurrent()
-
- if (instantlyLockDevice) {
- lockDevice()
- }
}
/** Emulates the dismissal of the IME (soft keyboard). */
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
index 1f3454de14d7..405cfd38d49a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
@@ -28,6 +28,8 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
@@ -173,12 +175,32 @@ class SceneBackInteractorTest : SysuiTestCase() {
)
}
+ @Test
+ @EnableSceneContainer
+ fun updateBackStack() =
+ testScope.runTest {
+ underTest.onSceneChange(from = Scenes.Lockscreen, to = Scenes.Shade)
+ underTest.onSceneChange(from = Scenes.Shade, to = Scenes.QuickSettings)
+ underTest.onSceneChange(from = Scenes.QuickSettings, to = Scenes.Bouncer)
+ assertThat(underTest.backStack.value.asIterable().toList())
+ .isEqualTo(listOf(Scenes.QuickSettings, Scenes.Shade, Scenes.Lockscreen))
+
+ underTest.updateBackStack { stack ->
+ // Reverse the stack, just to see if it can be done:
+ sceneStackOf(*stack.asIterable().reversed().toTypedArray())
+ }
+
+ assertThat(underTest.backStack.value.asIterable().toList())
+ .isEqualTo(listOf(Scenes.Lockscreen, Scenes.Shade, Scenes.QuickSettings))
+ }
+
private suspend fun TestScope.assertRoute(vararg route: RouteNode) {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val backScene by collectLastValue(underTest.backScene)
route.forEachIndexed { index, node ->
sceneInteractor.changeScene(node.changeSceneTo, "")
+ runCurrent()
assertWithMessage("node at index $index currentScene mismatch")
.that(currentScene)
.isEqualTo(node.changeSceneTo)
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 d1804608d130..763a1a943bf8 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
@@ -33,7 +33,9 @@ import com.android.internal.policy.IKeyguardDismissCallback
import com.android.keyguard.AuthInteractionProperties
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
@@ -82,7 +84,9 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.data.repository.Transition
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
@@ -131,6 +135,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private val testScope = kosmos.testScope
private val deviceEntryHapticsInteractor by lazy { kosmos.deviceEntryHapticsInteractor }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
+ private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor }
private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
@@ -237,17 +242,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun hydrateVisibility_basedOnOcclusion() =
testScope.runTest {
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Lockscreen)
underTest.start()
assertThat(isVisible).isTrue()
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
assertThat(isVisible).isFalse()
@@ -259,10 +261,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun hydrateVisibility_basedOnAlternateBouncer() =
testScope.runTest {
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Lockscreen)
underTest.start()
assertThat(isVisible).isTrue()
@@ -270,7 +269,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
// WHEN the device is occluded,
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
// THEN scenes are not visible
assertThat(isVisible).isFalse()
@@ -393,6 +392,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked_whenLeaveOpenShade() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val backStack by collectLastValue(sceneBackInteractor.backStack)
kosmos.sysuiStatusBarStateController.leaveOpen = true // leave shade open
val transitionState =
@@ -414,12 +414,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
runCurrent()
assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
+ assertThat(backStack?.asIterable()?.last()).isEqualTo(Scenes.Lockscreen)
kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
SuccessFingerprintAuthenticationStatus(0, true)
)
assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
+ assertThat(backStack?.asIterable()?.last()).isEqualTo(Scenes.Gone)
}
@Test
@@ -478,10 +480,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun stayOnLockscreenWhenDeviceUnlocksWithBypassOff() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isBypassEnabled = false,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isBypassEnabled = false, initialSceneKey = Scenes.Lockscreen)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
underTest.start()
@@ -520,10 +519,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToGoneWhenDeviceIsUnlockedAndUserIsOnBouncerWithBypassDisabled() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isBypassEnabled = false,
- initialSceneKey = Scenes.Bouncer,
- )
+ prepareState(isBypassEnabled = false, initialSceneKey = Scenes.Bouncer)
assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
underTest.start()
@@ -539,10 +535,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val alternateBouncerVisible by
collectLastValue(bouncerRepository.alternateBouncerVisible)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
bouncerRepository.setAlternateVisible(true)
underTest.start()
@@ -564,10 +557,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToLockscreenWhenDeviceSleepsLocked() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
underTest.start()
powerInteractor.setAsleepForTest()
@@ -583,10 +573,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val currentTransitionInfo by
collectLastValue(kosmos.keyguardTransitionRepository.currentTransitionInfoInternal)
val transitionState =
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
kosmos.keyguardRepository.setAodAvailable(true)
runCurrent()
assertThat(asleepState).isEqualTo(KeyguardState.AOD)
@@ -615,10 +602,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val currentTransitionInfo by
collectLastValue(kosmos.keyguardTransitionRepository.currentTransitionInfoInternal)
val transitionState =
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
kosmos.keyguardRepository.setAodAvailable(false)
runCurrent()
assertThat(asleepState).isEqualTo(KeyguardState.DOZING)
@@ -1078,16 +1062,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateSystemUiState_onLockscreen_basedOnOcclusion() =
testScope.runTest {
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
runCurrent()
clearInvocations(sysUiState)
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
runCurrent()
assertThat(
@@ -1210,7 +1192,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
initialSceneKey = Scenes.Lockscreen,
authenticationMethod = AuthenticationMethodModel.Pin,
isDeviceUnlocked = false,
- startsAwake = false
+ startsAwake = false,
)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
underTest.start()
@@ -1228,11 +1210,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun collectFalsingSignals_onSuccessfulUnlock() =
testScope.runTest {
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- authenticationMethod = AuthenticationMethodModel.Pin,
- isDeviceUnlocked = false,
- )
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+
+ val transitionStateFlow =
+ prepareState(
+ initialSceneKey = Scenes.Lockscreen,
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ isDeviceUnlocked = false,
+ )
underTest.start()
runCurrent()
verify(falsingCollector, never()).onSuccessfulUnlock()
@@ -1247,36 +1232,46 @@ class SceneContainerStartableTest : SysuiTestCase() {
)
.forEach { sceneKey ->
sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
runCurrent()
verify(falsingCollector, never()).onSuccessfulUnlock()
}
// Changing to the Gone scene should report a successful unlock.
- kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
- SuccessFingerprintAuthenticationStatus(0, true)
- )
+ kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
runCurrent()
- sceneInteractor.changeScene(Scenes.Gone, "reason")
+ // Make sure that the startable changed the scene to Gone because the device unlocked.
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ // Make the transition state match the current state
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
runCurrent()
verify(falsingCollector).onSuccessfulUnlock()
// Move around scenes without changing back to Lockscreen, shouldn't report another
// unlock.
- listOf(
- Scenes.Shade,
- Scenes.QuickSettings,
- Scenes.Shade,
- Scenes.Gone,
- )
- .forEach { sceneKey ->
- sceneInteractor.changeScene(sceneKey, "reason")
- runCurrent()
- verify(falsingCollector, times(1)).onSuccessfulUnlock()
- }
-
- // Changing to the Lockscreen scene shouldn't report a successful unlock.
- sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ listOf(Scenes.Shade, Scenes.QuickSettings, Scenes.Shade, Scenes.Gone).forEach { sceneKey
+ ->
+ sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
+ runCurrent()
+ verify(falsingCollector, times(1)).onSuccessfulUnlock()
+ }
+
+ // Putting the device to sleep to lock it again, which shouldn't report another
+ // successful unlock.
+ kosmos.powerInteractor.setAsleepForTest()
+ runCurrent()
+ // Verify that the startable changed the scene to Lockscreen because the device locked
+ // following the sleep.
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ // Make the transition state match the current state
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
+ // Wake up the device again before continuing with the test.
+ kosmos.powerInteractor.setAwakeForTest()
runCurrent()
+ // Verify that the current scene is still the Lockscreen scene, now that the device is
+ // still locked.
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
verify(falsingCollector, times(1)).onSuccessfulUnlock()
// Move around scenes without unlocking.
@@ -1289,12 +1284,17 @@ class SceneContainerStartableTest : SysuiTestCase() {
)
.forEach { sceneKey ->
sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
runCurrent()
verify(falsingCollector, times(1)).onSuccessfulUnlock()
}
- // Changing to the Gone scene should report a second successful unlock.
- sceneInteractor.changeScene(Scenes.Gone, "reason")
+ kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
+ runCurrent()
+ // Make sure that the startable changed the scene to Gone because the device unlocked.
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ // Make the transition state match the current scene.
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
runCurrent()
verify(falsingCollector, times(2)).onSuccessfulUnlock()
}
@@ -1608,7 +1608,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
runCurrent()
verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(true)
@@ -1623,10 +1623,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateInteractionState_whileLocked() =
testScope.runTest {
- val transitionStateFlow =
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- )
+ val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
runCurrent()
verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
@@ -1643,10 +1640,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
},
verifyAfterTransition = {
verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- false,
- )
+ .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false)
},
)
@@ -1661,11 +1655,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean())
},
verifyAfterTransition = {
- verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- true,
- )
+ verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
},
)
@@ -1681,10 +1671,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
},
verifyAfterTransition = {
verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- false,
- )
+ .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false)
},
)
@@ -1699,11 +1686,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean())
},
verifyAfterTransition = {
- verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- true,
- )
+ verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
},
)
@@ -1881,9 +1864,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val transitionStateFlow =
- prepareState(
- authenticationMethod = AuthenticationMethodModel.None,
- )
+ prepareState(authenticationMethod = AuthenticationMethodModel.None)
underTest.start()
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
// Swipe to Gone, more than halfway
@@ -1949,9 +1930,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToGone_whenKeyguardBecomesDisabled_whenOnShadeScene() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(initialSceneKey = Scenes.Shade)
assertThat(currentScene).isEqualTo(Scenes.Shade)
underTest.start()
@@ -1981,10 +1960,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun doesNotSwitchToGone_whenKeyguardBecomesDisabled_whenDeviceEntered() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Gone,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Gone)
assertThat(currentScene).isEqualTo(Scenes.Gone)
assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isTrue()
underTest.start()
@@ -2097,10 +2073,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun refreshLockscreenEnabled() =
testScope.runTest {
val transitionState =
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Gone,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Gone)
underTest.start()
val isLockscreenEnabled by
collectLastValue(kosmos.deviceEntryInteractor.isLockscreenEnabled)
@@ -2174,10 +2147,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
runCurrent()
verifyDuringTransition?.invoke()
- transitionStateFlow.value =
- ObservableTransitionState.Idle(
- currentScene = toScene,
- )
+ transitionStateFlow.value = ObservableTransitionState.Idle(currentScene = toScene)
runCurrent()
verifyAfterTransition?.invoke()
}
@@ -2262,7 +2232,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private fun TestScope.allowHapticsOnSfps(
isPowerButtonDown: Boolean = false,
- lastPowerPress: Long = 10000
+ lastPowerPress: Long = 10000,
) {
kosmos.fakeKeyEventRepository.setPowerButtonDown(isPowerButtonDown)
@@ -2287,7 +2257,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private fun TestScope.setupBiometricAuth(
hasSfps: Boolean = false,
hasUdfps: Boolean = false,
- hasFace: Boolean = false
+ hasFace: Boolean = false,
) {
if (hasSfps) {
setFingerprintSensorType(FingerprintSensorType.POWER_BUTTON)
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 7018f9dc8556..dbd7f0739f6c 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,8 +24,11 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -34,6 +37,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@@ -59,6 +63,7 @@ constructor(
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ sceneBackInteractor: SceneBackInteractor,
) {
/**
* Whether the device is unlocked.
@@ -86,19 +91,40 @@ constructor(
* Note: This does not imply that the lockscreen is visible or not.
*/
val isDeviceEntered: StateFlow<Boolean> =
- sceneInteractor.currentScene
- .filter { currentScene ->
- currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
- }
- .mapLatestConflated { scene ->
- if (scene == Scenes.Gone) {
- // Make sure device unlock status is definitely unlocked before we consider the
- // device "entered".
- deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
- true
- } else {
- false
- }
+ combine(
+ // This flow emits true when the currentScene switches to Gone for the first time
+ // after having been on Lockscreen.
+ sceneInteractor.currentScene
+ .filter { currentScene ->
+ currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
+ }
+ .mapLatestConflated { scene ->
+ if (scene == Scenes.Gone) {
+ // Make sure device unlock status is definitely unlocked before we
+ // consider the device "entered".
+ deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
+ true
+ } else {
+ false
+ }
+ },
+ // This flow emits true only if the bottom of the navigation back stack has been
+ // switched from Lockscreen to Gone. In other words, only if the device was unlocked
+ // while visiting at least one scene "above" the Lockscreen scene.
+ sceneBackInteractor.backStack
+ // The bottom of the back stack, which is Lockscreen, Gone, or null if empty.
+ .map { it.asIterable().lastOrNull() }
+ // Filter out cases where the stack changes but the bottom remains unchanged.
+ .distinctUntilChanged()
+ // Detect changes of the bottom of the stack, start with null, so the first
+ // update emits a value and the logic doesn't need to wait for a second value
+ // before emitting something.
+ .pairwise(initialValue = null)
+ // Replacing a bottom of the stack that was Lockscreen with Gone constitutes a
+ // "device entered" event.
+ .map { (from, to) -> from == Scenes.Lockscreen && to == Scenes.Gone },
+ ) { enteredDirectly, enteredOnBackStack ->
+ enteredOnBackStack || enteredDirectly
}
.stateIn(
scope = applicationScope,
@@ -129,7 +155,7 @@ constructor(
},
isLockscreenEnabled,
deviceUnlockedInteractor.deviceUnlockStatus,
- isDeviceEntered
+ isDeviceEntered,
) { isNoneAuthMethod, isLockscreenEnabled, deviceUnlockStatus, isDeviceEntered ->
val isSwipeAuthMethod = isNoneAuthMethod && isLockscreenEnabled
(isSwipeAuthMethod ||
@@ -155,9 +181,7 @@ constructor(
* canceled
*/
@JvmOverloads
- fun attemptDeviceEntry(
- callback: IKeyguardDismissCallback? = null,
- ) {
+ fun attemptDeviceEntry(callback: IKeyguardDismissCallback? = null) {
callback?.let { dismissCallbackRegistry.addCallback(it) }
// TODO (b/307768356),
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
index 2d40845df802..afb72f03b28d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
@@ -71,6 +71,12 @@ constructor(
logger.logSceneBackStack(backStack.value.asIterable())
}
+ /** Applies the given [transform] to the back stack. */
+ fun updateBackStack(transform: (SceneStack) -> SceneStack) {
+ _backStack.update { stack -> transform(stack) }
+ logger.logSceneBackStack(backStack.value.asIterable())
+ }
+
private fun stackOperation(from: SceneKey, to: SceneKey, stack: SceneStack): StackOperation? {
val fromDistance =
checkNotNull(sceneContainerConfig.navigationDistances[from]) {
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 98907b037d85..20c5142c6197 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
@@ -45,7 +45,6 @@ import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor
import com.android.systemui.model.SceneContainerPlugin
import com.android.systemui.model.SysUiState
@@ -55,6 +54,7 @@ import com.android.systemui.plugins.FalsingManager.FalsingBeliefListener
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -118,7 +118,6 @@ constructor(
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
private val bouncerInteractor: BouncerInteractor,
private val keyguardInteractor: KeyguardInteractor,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val sysUiState: SysUiState,
@DisplayId private val displayId: Int,
private val sceneLogger: SceneLogger,
@@ -205,7 +204,7 @@ constructor(
is ObservableTransitionState.Transition -> state.fromContent
}.let { it == Scenes.Shade || it == Scenes.QuickSettings }
}
- .distinctUntilChanged()
+ .distinctUntilChanged(),
) { inBackStack, isCurrentScene ->
inBackStack || isCurrentScene
}
@@ -248,8 +247,7 @@ constructor(
visibilityForTransitionState,
isHeadsUpOrAnimatingAway,
invisibleDueToOcclusion,
- isAlternateBouncerVisible,
- ->
+ isAlternateBouncerVisible ->
when {
isHeadsUpOrAnimatingAway -> true to "showing a HUN"
isAlternateBouncerVisible -> true to "showing alternate bouncer"
@@ -322,7 +320,7 @@ constructor(
switchToScene(
// TODO(b/336581871): add sceneState?
targetSceneKey = Scenes.Bouncer,
- loggingReason = "Need to authenticate locked SIM card."
+ loggingReason = "Need to authenticate locked SIM card.",
)
}
unlockStatus.isUnlocked &&
@@ -332,7 +330,7 @@ constructor(
targetSceneKey = Scenes.Gone,
loggingReason =
"All SIM cards unlocked and device already unlocked and " +
- "lockscreen doesn't require a swipe to dismiss."
+ "lockscreen doesn't require a swipe to dismiss.",
)
}
else -> {
@@ -341,7 +339,7 @@ constructor(
targetSceneKey = Scenes.Lockscreen,
loggingReason =
"All SIM cards unlocked and device still locked" +
- " or lockscreen still requires a swipe to dismiss."
+ " or lockscreen still requires a swipe to dismiss.",
)
}
}
@@ -363,10 +361,7 @@ constructor(
when (val transitionState = sceneInteractor.transitionState.value) {
is ObservableTransitionState.Idle -> setOf(transitionState.currentScene)
is ObservableTransitionState.Transition ->
- setOf(
- transitionState.fromContent,
- transitionState.toContent,
- )
+ setOf(transitionState.fromContent, transitionState.toContent)
}
val isOnLockscreen = renderedScenes.contains(Scenes.Lockscreen)
val isAlternateBouncerVisible = alternateBouncerInteractor.isVisibleState()
@@ -423,7 +418,20 @@ constructor(
" didn't need to be left open"
} else {
val prevScene = previousScene.value
- (prevScene ?: Scenes.Gone) to
+ val targetScene = prevScene ?: Scenes.Gone
+ if (targetScene != Scenes.Gone) {
+ 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."
+ }
+ list[list.size - 1] = Scenes.Gone
+ sceneStackOf(*list.toTypedArray())
+ }
+ }
+ targetScene to
"device was unlocked with primary bouncer showing," +
" from sceneKey=$prevScene"
}
@@ -451,10 +459,7 @@ constructor(
}
}
.collect { (targetSceneKey, loggingReason) ->
- switchToScene(
- targetSceneKey = targetSceneKey,
- loggingReason = loggingReason,
- )
+ switchToScene(targetSceneKey = targetSceneKey, loggingReason = loggingReason)
}
}
}
@@ -812,7 +817,7 @@ constructor(
private fun switchToScene(
targetSceneKey: SceneKey,
loggingReason: String,
- sceneState: Any? = null
+ sceneState: Any? = null,
) {
sceneInteractor.changeScene(
toScene = targetSceneKey,
@@ -831,10 +836,9 @@ constructor(
private fun notifyKeyguardDismissCancelledCallbacks() {
applicationScope.launch {
- combine(
- deviceEntryInteractor.isUnlocked,
- sceneInteractor.currentScene.pairwise(),
- ) { isUnlocked, (from, to) ->
+ combine(deviceEntryInteractor.isUnlocked, sceneInteractor.currentScene.pairwise()) {
+ isUnlocked,
+ (from, to) ->
when {
from != Scenes.Bouncer -> false
to != Scenes.Gone && !isUnlocked -> true
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
index 13116e7fd46f..096022ce1507 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
@@ -22,6 +22,7 @@ import com.android.systemui.deviceentry.data.repository.deviceEntryRepository
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -36,5 +37,6 @@ val Kosmos.deviceEntryInteractor by
deviceUnlockedInteractor = deviceUnlockedInteractor,
alternateBouncerInteractor = alternateBouncerInteractor,
dismissCallbackRegistry = dismissCallbackRegistry,
+ sceneBackInteractor = sceneBackInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 9a5698cfb8ca..4228c3c0b110 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -32,13 +32,11 @@ import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.windowManagerLockscreenVisibilityInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
-import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
@@ -62,7 +60,6 @@ val Kosmos.sceneContainerStartable by Fixture {
deviceUnlockedInteractor = deviceUnlockedInteractor,
bouncerInteractor = bouncerInteractor,
keyguardInteractor = keyguardInteractor,
- keyguardTransitionInteractor = keyguardTransitionInteractor,
sysUiState = sysUiState,
displayId = displayTracker.defaultDisplayId,
sceneLogger = sceneLogger,