diff options
8 files changed, 142 insertions, 167 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index a8fe16b12e1b..9f707262db3a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -83,25 +83,6 @@ class CommunalSceneStartableTest : SysuiTestCase() { } @Test - fun deviceDreaming_forceBlankScene() = - with(kosmos) { - testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) - - communalInteractor.onSceneChanged(CommunalSceneKey.Communal) - assertThat(scene).isEqualTo(CommunalSceneKey.Communal) - - fakeKeyguardTransitionRepository.sendTransitionSteps( - from = KeyguardState.GLANCEABLE_HUB, - to = KeyguardState.DREAMING, - testScope = this - ) - - assertThat(scene).isEqualTo(CommunalSceneKey.Blank) - } - } - - @Test fun deviceDocked_forceCommunalScene() = with(kosmos) { testScope.runTest { @@ -115,13 +96,6 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope = this ) assertThat(scene).isEqualTo(CommunalSceneKey.Communal) - - fakeKeyguardTransitionRepository.sendTransitionSteps( - from = KeyguardState.GLANCEABLE_HUB, - to = KeyguardState.DREAMING, - testScope = this - ) - assertThat(scene).isEqualTo(CommunalSceneKey.Blank) } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index f7ba5a44f4c9..8397372e0735 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -88,7 +88,6 @@ constructor( val docked = dockManager.isDocked return when { - to == KeyguardState.DREAMING -> CommunalSceneKey.Blank docked && to == KeyguardState.LOCKSCREEN && from != KeyguardState.GLANCEABLE_HUB -> { CommunalSceneKey.Communal } 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 c6594ef317d6..acfa107cc1f1 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 @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.communalHub import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -64,12 +65,13 @@ constructor( private fun listenForDreamingToGlanceableHub() { if (!communalHub()) return - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForDreamingToGlanceableHub", - transitionOwnerName = TAG, - fromState = KeyguardState.DREAMING, - toState = KeyguardState.GLANCEABLE_HUB, - ) + scope.launch("$TAG#listenForDreamingToGlanceableHub", mainDispatcher) { + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.DREAMING, + toState = KeyguardState.GLANCEABLE_HUB, + ) + } } fun startToLockscreenTransition() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index fbf195eb0952..786c3c6697d9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -27,13 +27,16 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled import com.android.systemui.power.domain.interactor.PowerInteractor -import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleMultiple +import com.android.systemui.util.kotlin.BooleanFlowOperators.and +import com.android.systemui.util.kotlin.BooleanFlowOperators.not import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @SysUISingleton class FromGlanceableHubTransitionInteractor @@ -58,13 +61,12 @@ constructor( if (!Flags.communalHub()) { return } - listenForHubToLockscreen() + listenForHubToLockscreenOrDreaming() listenForHubToDozing() listenForHubToPrimaryBouncer() listenForHubToAlternateBouncer() listenForHubToOccluded() listenForHubToGone() - listenForHubToDreaming() } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { @@ -82,13 +84,24 @@ constructor( * Listens for the glanceable hub transition to lock screen and directly drives the keyguard * transition. */ - private fun listenForHubToLockscreen() { - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForHubToLockscreen", - transitionOwnerName = TAG, - fromState = KeyguardState.GLANCEABLE_HUB, - toState = KeyguardState.LOCKSCREEN, - ) + private fun listenForHubToLockscreenOrDreaming() { + scope.launch("$TAG#listenForGlanceableHubToLockscreenOrDream") { + keyguardInteractor.isDreaming.collectLatest { dreaming -> + withContext(mainDispatcher) { + val toState = + if (dreaming) { + KeyguardState.DREAMING + } else { + KeyguardState.LOCKSCREEN + } + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.GLANCEABLE_HUB, + toState = toState, + ) + } + } + } } private fun listenForHubToPrimaryBouncer() { @@ -137,31 +150,15 @@ constructor( } } - private fun listenForHubToDreaming() { - val invalidFromStates = setOf(KeyguardState.AOD, KeyguardState.DOZING) - scope.launch("$TAG#listenForHubToDreaming") { - keyguardInteractor.isAbleToDream - .sampleMultiple(startedKeyguardTransitionStep, finishedKeyguardState) - .collect { (isAbleToDream, lastStartedTransition, finishedKeyguardState) -> - val isOnHub = finishedKeyguardState == KeyguardState.GLANCEABLE_HUB - val isTransitionInterruptible = - lastStartedTransition.to == KeyguardState.GLANCEABLE_HUB && - !invalidFromStates.contains(lastStartedTransition.from) - if (isAbleToDream && (isOnHub || isTransitionInterruptible)) { - startTransitionTo(KeyguardState.DREAMING) - } - } - } - } - private fun listenForHubToOccluded() { scope.launch { - keyguardInteractor.isKeyguardOccluded.sample(startedKeyguardState, ::Pair).collect { - (isOccluded, keyguardState) -> - if (isOccluded && keyguardState == fromState) { - startTransitionTo(KeyguardState.OCCLUDED) + and(keyguardInteractor.isKeyguardOccluded, not(keyguardInteractor.isDreaming)) + .sample(startedKeyguardState, ::Pair) + .collect { (isOccludedAndNotDreaming, keyguardState) -> + if (isOccludedAndNotDreaming && keyguardState == fromState) { + startTransitionTo(KeyguardState.OCCLUDED) + } } - } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index 40b2c638823d..7263ae96b3a8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -360,13 +360,13 @@ constructor( if (!com.android.systemui.Flags.communalHub()) { return } - - glanceableHubTransitions.listenForGlanceableHubTransition( - transitionName = "listenForLockscreenToGlanceableHub", - transitionOwnerName = TAG, - fromState = KeyguardState.LOCKSCREEN, - toState = KeyguardState.GLANCEABLE_HUB, - ) + scope.launch(mainDispatcher) { + glanceableHubTransitions.listenForGlanceableHubTransition( + transitionOwnerName = TAG, + fromState = KeyguardState.LOCKSCREEN, + toState = KeyguardState.GLANCEABLE_HUB, + ) + } } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt index 809c0aee9882..6cb1eb493db3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt @@ -18,11 +18,9 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators -import com.android.app.tracing.coroutines.launch import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalTransitionProgress import com.android.systemui.communal.shared.model.CommunalSceneKey -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState @@ -32,13 +30,11 @@ import com.android.systemui.util.kotlin.sample import java.util.UUID import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOn class GlanceableHubTransitions @Inject constructor( - @Application private val scope: CoroutineScope, @Background private val bgDispatcher: CoroutineDispatcher, private val transitionInteractor: KeyguardTransitionInteractor, private val transitionRepository: KeyguardTransitionRepository, @@ -52,105 +48,101 @@ constructor( * externally. The progress is used for both transitions caused by user touch input or by * programmatic changes. */ - fun listenForGlanceableHubTransition( - transitionName: String, + suspend fun listenForGlanceableHubTransition( transitionOwnerName: String, fromState: KeyguardState, toState: KeyguardState, ) { val toScene = - if (toState == KeyguardState.GLANCEABLE_HUB) { - CommunalSceneKey.Communal - } else { + if (fromState == KeyguardState.GLANCEABLE_HUB) { CommunalSceneKey.Blank + } else { + CommunalSceneKey.Communal } var transitionId: UUID? = null - scope.launch("$transitionOwnerName#$transitionName") { - communalInteractor - .transitionProgressToScene(toScene) - .sample( - transitionInteractor.startedKeyguardTransitionStep.flowOn(bgDispatcher), - ::Pair - ) - .collect { pair -> - val (transitionProgress, lastStartedStep) = pair - val id = transitionId - if (id == null) { - // No transition started. - if ( - transitionProgress is CommunalTransitionProgress.Transition && - lastStartedStep.to == fromState - ) { - transitionId = - transitionRepository.startTransition( - TransitionInfo( - ownerName = transitionOwnerName, - from = fromState, - to = toState, - animator = null, // transition will be manually controlled - ) + communalInteractor + .transitionProgressToScene(toScene) + .sample( + transitionInteractor.startedKeyguardTransitionStep.flowOn(bgDispatcher), + ::Pair, + ) + .collect { (transitionProgress, lastStartedStep) -> + val id = transitionId + if (id == null) { + // No transition started. + if ( + transitionProgress is CommunalTransitionProgress.Transition && + lastStartedStep.to == fromState + ) { + transitionId = + transitionRepository.startTransition( + TransitionInfo( + ownerName = transitionOwnerName, + from = fromState, + to = toState, + animator = null, // transition will be manually controlled ) - } - } else { - if (lastStartedStep.to != toState) { - return@collect - } - // An existing `id` means a transition is started, and calls to - // `updateTransition` will control it until FINISHED or CANCELED - val nextState: TransitionState - val progressFraction: Float - when (transitionProgress) { - is CommunalTransitionProgress.Idle -> { - if (transitionProgress.scene == toScene) { - nextState = TransitionState.FINISHED - progressFraction = 1f - } else { - nextState = TransitionState.CANCELED - progressFraction = 0f - } - } - is CommunalTransitionProgress.Transition -> { - nextState = TransitionState.RUNNING - progressFraction = transitionProgress.progress - } - is CommunalTransitionProgress.OtherTransition -> { - // Shouldn't happen but if another transition starts during the - // current one, mark the current one as canceled. + ) + } + } else { + if (lastStartedStep.to != toState) { + return@collect + } + // An existing `id` means a transition is started, and calls to + // `updateTransition` will control it until FINISHED or CANCELED + val nextState: TransitionState + val progressFraction: Float + when (transitionProgress) { + is CommunalTransitionProgress.Idle -> { + if (transitionProgress.scene == toScene) { + nextState = TransitionState.FINISHED + progressFraction = 1f + } else { nextState = TransitionState.CANCELED progressFraction = 0f } } - transitionRepository.updateTransition( - id, - progressFraction, - nextState, - ) - - if ( - nextState == TransitionState.CANCELED || - nextState == TransitionState.FINISHED - ) { - transitionId = null + is CommunalTransitionProgress.Transition -> { + nextState = TransitionState.RUNNING + progressFraction = transitionProgress.progress } + is CommunalTransitionProgress.OtherTransition -> { + // Shouldn't happen but if another transition starts during the + // current one, mark the current one as canceled. + nextState = TransitionState.CANCELED + progressFraction = 0f + } + } + transitionRepository.updateTransition( + id, + progressFraction, + nextState, + ) - // If canceled, just put the state back. - if (nextState == TransitionState.CANCELED) { - transitionRepository.startTransition( - TransitionInfo( - ownerName = transitionOwnerName, - from = toState, - to = fromState, - animator = - ValueAnimator().apply { - interpolator = Interpolators.LINEAR - duration = 0 - } - ) + if ( + nextState == TransitionState.CANCELED || + nextState == TransitionState.FINISHED + ) { + transitionId = null + } + + // If canceled, just put the state back. + if (nextState == TransitionState.CANCELED) { + transitionRepository.startTransition( + TransitionInfo( + ownerName = transitionOwnerName, + from = toState, + to = fromState, + animator = + ValueAnimator().apply { + interpolator = Interpolators.LINEAR + duration = 0 + } ) - } + ) } } - } + } } } 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 abd42387cc2e..69cd173f4253 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 @@ -129,7 +129,6 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { val glanceableHubTransitions = GlanceableHubTransitions( - scope = testScope, bgDispatcher = kosmos.testDispatcher, transitionInteractor = transitionInteractor, transitionRepository = transitionRepository, @@ -1812,26 +1811,40 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { @Test fun glanceableHubToDreaming() = testScope.runTest { - // GIVEN a device that is not dreaming or dozing - keyguardRepository.setDreamingWithOverlay(false) + // GIVEN that we are dreaming and not dozing + keyguardRepository.setDreaming(true) keyguardRepository.setDozeTransitionModel( DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH) ) runCurrent() // GIVEN a prior transition has run to GLANCEABLE_HUB - runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + runTransitionAndSetWakefulness(KeyguardState.DREAMING, KeyguardState.GLANCEABLE_HUB) + runCurrent() - // WHEN the device begins to dream - keyguardRepository.setDreamingWithOverlay(true) - advanceTimeBy(100L) + // WHEN a transition away from glanceable hub starts + val currentScene = CommunalSceneKey.Communal + val targetScene = CommunalSceneKey.Blank + + val transitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Transition( + fromScene = currentScene, + toScene = targetScene, + progress = flowOf(0f, 0.1f), + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + ) + communalInteractor.setTransitionState(transitionState) + runCurrent() assertThat(transitionRepository) .startedTransition( ownerName = FromGlanceableHubTransitionInteractor::class.simpleName, from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.DREAMING, - animatorAssertion = { it.isNotNull() }, + animatorAssertion = { it.isNull() }, // transition should be manually animated ) coroutineContext.cancelChildren() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt index 55885bf58acc..5dd50731c58a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt @@ -19,13 +19,11 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher val Kosmos.glanceableHubTransitions by Kosmos.Fixture { GlanceableHubTransitions( - scope = applicationCoroutineScope, bgDispatcher = testDispatcher, transitionRepository = keyguardTransitionRepository, transitionInteractor = keyguardTransitionInteractor, |