diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index 81a58286aab75..8715d1f550697 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -56,9 +57,14 @@ constructor( private fun listenForDreamingToLockscreen() { scope.launch { - // Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which - // otherwise would have gone through OCCLUDED first - keyguardInteractor.isAbleToDream + // Dependending on the dream, either dream state or occluded change will change first, + // so listen for both + combine(keyguardInteractor.isAbleToDream, keyguardInteractor.isKeyguardOccluded) { + isAbleToDream, + isKeyguardOccluded -> + isAbleToDream && isKeyguardOccluded + } + .distinctUntilChanged() .sample( combine( keyguardInteractor.dozeTransitionModel, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 702f376350927..d29e7ed082ceb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -149,7 +149,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun `DREAMING to LOCKSCREEN`() = + fun `DREAMING to LOCKSCREEN - dreaming state changes first`() = testScope.runTest { // GIVEN a device is dreaming and occluded keyguardRepository.setDreamingWithOverlay(true) @@ -179,9 +179,59 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { ) // AND dreaming has stopped keyguardRepository.setDreamingWithOverlay(false) + advanceUntilIdle() + // AND then occluded has stopped + keyguardRepository.setKeyguardOccluded(false) + advanceUntilIdle() + + val info = + withArgCaptor { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to BOUNCER should occur + assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.DREAMING) + assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `DREAMING to LOCKSCREEN - occluded state changes first`() = + testScope.runTest { + // GIVEN a device is dreaming and occluded + keyguardRepository.setDreamingWithOverlay(true) + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + // GIVEN a prior transition has run to DREAMING + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.DREAMING, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // WHEN doze is complete + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH) + ) // AND occluded has stopped keyguardRepository.setKeyguardOccluded(false) advanceUntilIdle() + // AND then dreaming has stopped + keyguardRepository.setDreamingWithOverlay(false) + advanceUntilIdle() val info = withArgCaptor {