Transitions - Legacy dream -> lockscreen flicker

It briefly shows lockscreen content before hiding and fading in
nicely. This is due to the possible ordering of occlusion/dreaming
events so make sure to start the transition as soon as either changes.

Fixes: 267600416
Test: atest KeyguardTransitionScenariosTest

Change-Id: I337d0189af72e052b805a213d0faa8f6b528811d
This commit is contained in:
Matt Pietal
2023-02-02 12:50:41 +00:00
parent 02cdf72ad3
commit 5b85373d3e
2 changed files with 60 additions and 4 deletions

View File

@@ -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,

View File

@@ -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<TransitionInfo> {
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<TransitionInfo> {