Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt +5 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.compose.animation.scene.MutableSceneTransitionLayoutState import com.android.compose.animation.scene.OverlayKey import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.animation.scene.observableTransitionState import com.android.systemui.scene.shared.model.SceneDataSource import kotlinx.coroutines.CoroutineScope Loading Loading @@ -103,4 +104,8 @@ class SceneTransitionLayoutDataSource( override fun instantlyHideOverlay(overlay: OverlayKey) { state.snapTo(overlays = state.currentOverlays - overlay) } override fun freezeAndAnimateToCurrentState() { (state.transitionState as? TransitionState.Transition)?.freezeAndAnimateToCurrentState() } } packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt +39 −0 Original line number Diff line number Diff line Loading @@ -1358,6 +1358,45 @@ class LockscreenSceneTransitionInteractorTest : SysuiTestCase() { ) } /** * When a transition away from the lockscreen is interrupted by an `Idle(Lockscreen)`, a * `sceneState` that was set during the transition is consumed and passed to KTF. */ @Test fun transition_from_ls_scene_sceneStateSet_then_interrupted_by_idle_on_ls() = testScope.runTest { val currentStep by collectLastValue(kosmos.realKeyguardTransitionRepository.transitions) sceneTransitions.value = ObservableTransitionState.Transition( Scenes.Lockscreen, Scenes.Gone, flowOf(Scenes.Lockscreen), progress, false, flowOf(false), ) progress.value = 0.4f assertTransition( step = currentStep!!, from = KeyguardState.LOCKSCREEN, to = KeyguardState.UNDEFINED, state = TransitionState.RUNNING, progress = 0.4f, ) val sceneState = KeyguardState.AOD underTest.onSceneAboutToChange(toScene = Scenes.Lockscreen, sceneState = sceneState) sceneTransitions.value = ObservableTransitionState.Idle(Scenes.Lockscreen) assertTransition( step = currentStep!!, from = KeyguardState.UNDEFINED, to = KeyguardState.AOD, state = TransitionState.FINISHED, progress = 1f, ) } private fun assertTransition( step: TransitionStep, from: KeyguardState? = null, Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +42 −0 Original line number Diff line number Diff line Loading @@ -757,4 +757,46 @@ class SceneInteractorTest : SysuiTestCase() { verify(processor, never()).onSceneAboutToChange(any(), any()) } @Test fun changeScene_sameScene_withFreeze() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) val processor = mock<SceneInteractor.OnSceneAboutToChangeListener>() underTest.registerSceneStateProcessor(processor) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) underTest.changeScene( toScene = Scenes.Lockscreen, loggingReason = "test", sceneState = KeyguardState.AOD, forceSettleToTargetScene = true, ) verify(processor).onSceneAboutToChange(Scenes.Lockscreen, KeyguardState.AOD) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(1) } @Test fun changeScene_sameScene_withoutFreeze() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) val processor = mock<SceneInteractor.OnSceneAboutToChangeListener>() underTest.registerSceneStateProcessor(processor) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) underTest.changeScene( toScene = Scenes.Lockscreen, loggingReason = "test", sceneState = KeyguardState.AOD, forceSettleToTargetScene = false, ) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) } } packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt +2 −0 Original line number Diff line number Diff line Loading @@ -151,5 +151,7 @@ constructor( override fun instantlyShowOverlay(overlay: OverlayKey) = Unit override fun instantlyHideOverlay(overlay: OverlayKey) = Unit override fun freezeAndAnimateToCurrentState() = Unit } } packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LockscreenSceneTransitionRepository.kt +10 −4 Original line number Diff line number Diff line Loading @@ -25,11 +25,17 @@ import kotlinx.coroutines.flow.MutableStateFlow class LockscreenSceneTransitionRepository @Inject constructor() { /** * This [KeyguardState] will indicate which sub state within KTF should be navigated to when the * next transition into the Lockscreen scene is started. It will be consumed exactly once and * after that the state will be set back to [DEFAULT_STATE]. * This [KeyguardState] will indicate which sub-state within KTF should be navigated to next. * * This can be either starting a transition to the `Lockscreen` scene or cancelling a transition * from the `Lockscreen` scene and returning back to it. * * A `null` value means that no explicit target state was set and therefore the [DEFAULT_STATE] * should be used. * * Once consumed, this state should be reset to `null`. */ val nextLockscreenTargetState: MutableStateFlow<KeyguardState> = MutableStateFlow(DEFAULT_STATE) val nextLockscreenTargetState: MutableStateFlow<KeyguardState?> = MutableStateFlow(null) companion object { val DEFAULT_STATE = KeyguardState.LOCKSCREEN Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneTransitionLayoutDataSource.kt +5 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.compose.animation.scene.MutableSceneTransitionLayoutState import com.android.compose.animation.scene.OverlayKey import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.animation.scene.observableTransitionState import com.android.systemui.scene.shared.model.SceneDataSource import kotlinx.coroutines.CoroutineScope Loading Loading @@ -103,4 +104,8 @@ class SceneTransitionLayoutDataSource( override fun instantlyHideOverlay(overlay: OverlayKey) { state.snapTo(overlays = state.currentOverlays - overlay) } override fun freezeAndAnimateToCurrentState() { (state.transitionState as? TransitionState.Transition)?.freezeAndAnimateToCurrentState() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt +39 −0 Original line number Diff line number Diff line Loading @@ -1358,6 +1358,45 @@ class LockscreenSceneTransitionInteractorTest : SysuiTestCase() { ) } /** * When a transition away from the lockscreen is interrupted by an `Idle(Lockscreen)`, a * `sceneState` that was set during the transition is consumed and passed to KTF. */ @Test fun transition_from_ls_scene_sceneStateSet_then_interrupted_by_idle_on_ls() = testScope.runTest { val currentStep by collectLastValue(kosmos.realKeyguardTransitionRepository.transitions) sceneTransitions.value = ObservableTransitionState.Transition( Scenes.Lockscreen, Scenes.Gone, flowOf(Scenes.Lockscreen), progress, false, flowOf(false), ) progress.value = 0.4f assertTransition( step = currentStep!!, from = KeyguardState.LOCKSCREEN, to = KeyguardState.UNDEFINED, state = TransitionState.RUNNING, progress = 0.4f, ) val sceneState = KeyguardState.AOD underTest.onSceneAboutToChange(toScene = Scenes.Lockscreen, sceneState = sceneState) sceneTransitions.value = ObservableTransitionState.Idle(Scenes.Lockscreen) assertTransition( step = currentStep!!, from = KeyguardState.UNDEFINED, to = KeyguardState.AOD, state = TransitionState.FINISHED, progress = 1f, ) } private fun assertTransition( step: TransitionStep, from: KeyguardState? = null, Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +42 −0 Original line number Diff line number Diff line Loading @@ -757,4 +757,46 @@ class SceneInteractorTest : SysuiTestCase() { verify(processor, never()).onSceneAboutToChange(any(), any()) } @Test fun changeScene_sameScene_withFreeze() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) val processor = mock<SceneInteractor.OnSceneAboutToChangeListener>() underTest.registerSceneStateProcessor(processor) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) underTest.changeScene( toScene = Scenes.Lockscreen, loggingReason = "test", sceneState = KeyguardState.AOD, forceSettleToTargetScene = true, ) verify(processor).onSceneAboutToChange(Scenes.Lockscreen, KeyguardState.AOD) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(1) } @Test fun changeScene_sameScene_withoutFreeze() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) val processor = mock<SceneInteractor.OnSceneAboutToChangeListener>() underTest.registerSceneStateProcessor(processor) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) underTest.changeScene( toScene = Scenes.Lockscreen, loggingReason = "test", sceneState = KeyguardState.AOD, forceSettleToTargetScene = false, ) verify(processor, never()).onSceneAboutToChange(any(), any()) assertThat(fakeSceneDataSource.freezeAndAnimateToCurrentStateCallCount).isEqualTo(0) } }
packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSceneRepository.kt +2 −0 Original line number Diff line number Diff line Loading @@ -151,5 +151,7 @@ constructor( override fun instantlyShowOverlay(overlay: OverlayKey) = Unit override fun instantlyHideOverlay(overlay: OverlayKey) = Unit override fun freezeAndAnimateToCurrentState() = Unit } }
packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LockscreenSceneTransitionRepository.kt +10 −4 Original line number Diff line number Diff line Loading @@ -25,11 +25,17 @@ import kotlinx.coroutines.flow.MutableStateFlow class LockscreenSceneTransitionRepository @Inject constructor() { /** * This [KeyguardState] will indicate which sub state within KTF should be navigated to when the * next transition into the Lockscreen scene is started. It will be consumed exactly once and * after that the state will be set back to [DEFAULT_STATE]. * This [KeyguardState] will indicate which sub-state within KTF should be navigated to next. * * This can be either starting a transition to the `Lockscreen` scene or cancelling a transition * from the `Lockscreen` scene and returning back to it. * * A `null` value means that no explicit target state was set and therefore the [DEFAULT_STATE] * should be used. * * Once consumed, this state should be reset to `null`. */ val nextLockscreenTargetState: MutableStateFlow<KeyguardState> = MutableStateFlow(DEFAULT_STATE) val nextLockscreenTargetState: MutableStateFlow<KeyguardState?> = MutableStateFlow(null) companion object { val DEFAULT_STATE = KeyguardState.LOCKSCREEN Loading