Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +38 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ @file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalCoroutinesApi::class) @file:OptIn(ExperimentalCoroutinesApi::class) package com.android.systemui.scene.domain.startable Loading Loading @@ -395,6 +395,7 @@ class SceneContainerStartableTest : SysuiTestCase() { ) assertThat(currentSceneKey).isEqualTo(Scenes.Gone) underTest.start() runCurrent() kosmos.fakePowerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, Loading Loading @@ -1284,6 +1285,42 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Lockscreen) } @Test fun switchToGone_whenSurfaceBehindLockscreenVisibleMidTransition() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene) val transitionStateFlow = prepareState( authenticationMethod = AuthenticationMethodModel.None, ) underTest.start() assertThat(currentScene).isEqualTo(Scenes.Lockscreen) // Swipe to Gone, more than halfway transitionStateFlow.value = ObservableTransitionState.Transition( fromScene = Scenes.Lockscreen, toScene = Scenes.Gone, currentScene = flowOf(Scenes.Gone), progress = flowOf(0.51f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(true), ) runCurrent() // Lift finger transitionStateFlow.value = ObservableTransitionState.Transition( fromScene = Scenes.Lockscreen, toScene = Scenes.Gone, currentScene = flowOf(Scenes.Gone), progress = flowOf(0.51f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(false), ) runCurrent() assertThat(currentScene).isEqualTo(Scenes.Gone) } @Test fun switchToGone_extendUnlock() = testScope.runTest { Loading packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt +12 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.keyguard.domain.interactor.TrustInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.util.kotlin.Quad import com.android.systemui.utils.coroutines.flow.mapLatestConflated import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading Loading @@ -96,7 +98,16 @@ constructor( .filter { currentScene -> currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen } .map { it == Scenes.Gone } .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 } } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, Loading packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +23 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor import com.android.systemui.model.SceneContainerPlugin import com.android.systemui.model.SysUiState import com.android.systemui.model.updateFlags Loading Loading @@ -81,6 +82,7 @@ import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading Loading @@ -120,6 +122,7 @@ constructor( private val uiEventLogger: UiEventLogger, private val sceneBackInteractor: SceneBackInteractor, private val shadeSessionStorage: SessionStorage, private val windowMgrLockscreenVisInteractor: WindowManagerLockscreenVisibilityInteractor, ) : CoreStartable { private val centralSurfaces: CentralSurfaces? get() = centralSurfacesOptLazy.get().getOrNull() Loading Loading @@ -227,6 +230,25 @@ constructor( handleDeviceUnlockStatus() handlePowerState() handleShadeTouchability() handleSurfaceBehindKeyguardVisibility() } private fun handleSurfaceBehindKeyguardVisibility() { applicationScope.launch { sceneInteractor.currentScene.collectLatest { currentScene -> if (currentScene == Scenes.Lockscreen) { // Wait for surface to become visible windowMgrLockscreenVisInteractor.surfaceBehindVisibility.first { it } // Make sure the device is actually unlocked before force-changing the scene deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked } // Override the current transition, if any, by forcing the scene to Gone sceneInteractor.changeScene( toScene = Scenes.Gone, loggingReason = "surface behind keyguard is visible", ) } } } } private fun handleBouncerImeVisibility() { Loading Loading @@ -329,8 +351,7 @@ constructor( Scenes.Gone to "device was unlocked in Bouncer scene" } else { val prevScene = previousScene.value (prevScene ?: Scenes.Gone) to (prevScene ?: Scenes.Gone) to "device was unlocked in Bouncer scene, from sceneKey=$prevScene" } isOnLockscreen -> Loading packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInt import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.keyguard.domain.interactor.keyguardInteractor 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 Loading Loading @@ -67,5 +68,6 @@ val Kosmos.sceneContainerStartable by Fixture { uiEventLogger = uiEventLogger, sceneBackInteractor = sceneBackInteractor, shadeSessionStorage = shadeSessionStorage, windowMgrLockscreenVisInteractor = windowManagerLockscreenVisibilityInteractor, ) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +38 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ @file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalCoroutinesApi::class) @file:OptIn(ExperimentalCoroutinesApi::class) package com.android.systemui.scene.domain.startable Loading Loading @@ -395,6 +395,7 @@ class SceneContainerStartableTest : SysuiTestCase() { ) assertThat(currentSceneKey).isEqualTo(Scenes.Gone) underTest.start() runCurrent() kosmos.fakePowerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, Loading Loading @@ -1284,6 +1285,42 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Lockscreen) } @Test fun switchToGone_whenSurfaceBehindLockscreenVisibleMidTransition() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene) val transitionStateFlow = prepareState( authenticationMethod = AuthenticationMethodModel.None, ) underTest.start() assertThat(currentScene).isEqualTo(Scenes.Lockscreen) // Swipe to Gone, more than halfway transitionStateFlow.value = ObservableTransitionState.Transition( fromScene = Scenes.Lockscreen, toScene = Scenes.Gone, currentScene = flowOf(Scenes.Gone), progress = flowOf(0.51f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(true), ) runCurrent() // Lift finger transitionStateFlow.value = ObservableTransitionState.Transition( fromScene = Scenes.Lockscreen, toScene = Scenes.Gone, currentScene = flowOf(Scenes.Gone), progress = flowOf(0.51f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(false), ) runCurrent() assertThat(currentScene).isEqualTo(Scenes.Gone) } @Test fun switchToGone_extendUnlock() = testScope.runTest { Loading
packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt +12 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.systemui.keyguard.domain.interactor.TrustInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.util.kotlin.Quad import com.android.systemui.utils.coroutines.flow.mapLatestConflated import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading Loading @@ -96,7 +98,16 @@ constructor( .filter { currentScene -> currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen } .map { it == Scenes.Gone } .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 } } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, Loading
packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +23 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor import com.android.systemui.model.SceneContainerPlugin import com.android.systemui.model.SysUiState import com.android.systemui.model.updateFlags Loading Loading @@ -81,6 +82,7 @@ import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading Loading @@ -120,6 +122,7 @@ constructor( private val uiEventLogger: UiEventLogger, private val sceneBackInteractor: SceneBackInteractor, private val shadeSessionStorage: SessionStorage, private val windowMgrLockscreenVisInteractor: WindowManagerLockscreenVisibilityInteractor, ) : CoreStartable { private val centralSurfaces: CentralSurfaces? get() = centralSurfacesOptLazy.get().getOrNull() Loading Loading @@ -227,6 +230,25 @@ constructor( handleDeviceUnlockStatus() handlePowerState() handleShadeTouchability() handleSurfaceBehindKeyguardVisibility() } private fun handleSurfaceBehindKeyguardVisibility() { applicationScope.launch { sceneInteractor.currentScene.collectLatest { currentScene -> if (currentScene == Scenes.Lockscreen) { // Wait for surface to become visible windowMgrLockscreenVisInteractor.surfaceBehindVisibility.first { it } // Make sure the device is actually unlocked before force-changing the scene deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked } // Override the current transition, if any, by forcing the scene to Gone sceneInteractor.changeScene( toScene = Scenes.Gone, loggingReason = "surface behind keyguard is visible", ) } } } } private fun handleBouncerImeVisibility() { Loading Loading @@ -329,8 +351,7 @@ constructor( Scenes.Gone to "device was unlocked in Bouncer scene" } else { val prevScene = previousScene.value (prevScene ?: Scenes.Gone) to (prevScene ?: Scenes.Gone) to "device was unlocked in Bouncer scene, from sceneKey=$prevScene" } isOnLockscreen -> Loading
packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInt import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.keyguard.domain.interactor.keyguardInteractor 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 Loading Loading @@ -67,5 +68,6 @@ val Kosmos.sceneContainerStartable by Fixture { uiEventLogger = uiEventLogger, sceneBackInteractor = sceneBackInteractor, shadeSessionStorage = shadeSessionStorage, windowMgrLockscreenVisInteractor = windowManagerLockscreenVisibilityInteractor, ) }