diff options
9 files changed, 110 insertions, 56 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt index e7aaddd94695..857b9f82f8bc 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGoneTransitionViewModelTest.kt @@ -68,9 +68,7 @@ class LockscreenToGoneTransitionViewModelTest : SysuiTestCase() { repository.sendTransitionStep(step(0f)) assertThat(alpha).isEqualTo(0.5f) - repository.sendTransitionStep(step(0.25f)) - assertThat(alpha).isEqualTo(0.25f) - + // Before the halfway point, it will have reached zero repository.sendTransitionStep(step(.5f)) assertThat(alpha).isEqualTo(0f) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index 53a8e5dbda32..5256bb956bc4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -720,6 +720,59 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + fun alphaDoesNotUpdateWhileGoneTransitionIsRunning() = + testScope.runTest { + val viewState = ViewStateAccessor() + val alpha by collectLastValue(underTest.keyguardAlpha(viewState)) + + showLockscreen() + // GONE transition gets to 90% complete + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + transitionState = TransitionState.STARTED, + value = 0f, + ) + ) + runCurrent() + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + transitionState = TransitionState.RUNNING, + value = 0.9f, + ) + ) + runCurrent() + + // At this point, alpha should be zero + assertThat(alpha).isEqualTo(0f) + + // An attempt to override by the shade should be ignored + shadeRepository.setQsExpansion(0.5f) + assertThat(alpha).isEqualTo(0f) + } + + @Test + fun alphaWhenGoneIsSetToOne() = + testScope.runTest { + val viewState = ViewStateAccessor() + val alpha by collectLastValue(underTest.keyguardAlpha(viewState)) + + showLockscreen() + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GONE, + testScope + ) + keyguardRepository.setStatusBarState(StatusBarState.SHADE) + + assertThat(alpha).isEqualTo(1f) + } + + @Test fun shadeCollapseFadeIn() = testScope.runTest { val fadeIn by collectValues(underTest.shadeCollapseFadeIn) 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 12b27eb195fb..2649d4347495 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 @@ -289,7 +289,10 @@ constructor( .collect { pair -> val (isKeyguardGoingAway, lastStartedStep) = pair if (isKeyguardGoingAway && lastStartedStep.to == KeyguardState.LOCKSCREEN) { - startTransitionTo(KeyguardState.GONE) + startTransitionTo( + KeyguardState.GONE, + modeOnCanceled = TransitionModeOnCanceled.RESET, + ) } } } @@ -303,20 +306,6 @@ constructor( startTransitionTo(KeyguardState.GONE) } } - - return - } - - scope.launch { - keyguardInteractor.isKeyguardGoingAway - .sample(startedKeyguardTransitionStep, ::Pair) - .collect { pair -> - KeyguardWmStateRefactor.assertInLegacyMode() - val (isKeyguardGoingAway, lastStartedStep) = pair - if (isKeyguardGoingAway && lastStartedStep.to == KeyguardState.LOCKSCREEN) { - startTransitionTo(KeyguardState.GONE) - } - } } } @@ -413,7 +402,7 @@ constructor( val TO_OCCLUDED_DURATION = 450.milliseconds val TO_AOD_DURATION = 500.milliseconds val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION - val TO_GONE_DURATION = DEFAULT_DURATION + val TO_GONE_DURATION = 633.milliseconds val TO_GLANCEABLE_HUB_DURATION = 1.seconds } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt index c40902871388..cbbb82039329 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt @@ -30,8 +30,6 @@ import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.map /** * Breaks down AOD->LOCKSCREEN transition into discrete steps for corresponding views to consume. @@ -53,6 +51,8 @@ constructor( to = KeyguardState.LOCKSCREEN, ) + private var isShadeExpanded = false + /** * Begin the transition from wherever the y-translation value is currently. This helps ensure a * smooth transition if a transition in canceled. @@ -77,22 +77,21 @@ constructor( } val notificationAlpha: Flow<Float> = - combine( - shadeInteractor.shadeExpansion.map { it > 0f }, - shadeInteractor.qsExpansion.map { it > 0f }, - transitionAnimation.sharedFlow( - duration = 500.milliseconds, - onStep = { it }, - onCancel = { 1f }, - ), - ) { isShadeExpanded, isQsExpanded, alpha -> - if (isShadeExpanded || isQsExpanded) { - // One example of this happening is dragging a notification while pulsing on AOD - 1f - } else { - alpha - } - } + transitionAnimation.sharedFlow( + duration = 500.milliseconds, + onStart = { + isShadeExpanded = + shadeInteractor.shadeExpansion.value > 0f || + shadeInteractor.qsExpansion.value > 0f + }, + onStep = { + if (isShadeExpanded) { + 1f + } else { + it + } + }, + ) val shortcutsAlpha: Flow<Float> = transitionAnimation.sharedFlow( diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt index bc60c838b703..cde45f2060e5 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt @@ -66,7 +66,7 @@ interface BaseShadeInteractor { val isAnyExpanded: StateFlow<Boolean> /** The amount [0-1] that the shade has been opened. */ - val shadeExpansion: Flow<Float> + val shadeExpansion: StateFlow<Float> /** * The amount [0-1] QS has been opened. Normal shade with notifications (QQS) visible will diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt index e9bb4c623013..5fbd2cfaec79 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt @@ -29,7 +29,7 @@ class ShadeInteractorEmptyImpl @Inject constructor() : ShadeInteractor { private val inactiveFlowBoolean = MutableStateFlow(false) private val inactiveFlowFloat = MutableStateFlow(0f) override val isShadeEnabled: StateFlow<Boolean> = inactiveFlowBoolean - override val shadeExpansion: Flow<Float> = inactiveFlowFloat + override val shadeExpansion: StateFlow<Float> = inactiveFlowFloat override val qsExpansion: StateFlow<Float> = inactiveFlowFloat override val isQsExpanded: StateFlow<Boolean> = inactiveFlowBoolean override val isQsBypassingShade: Flow<Boolean> = inactiveFlowBoolean diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt index 421a76163346..ac881b5bfa97 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt @@ -50,7 +50,7 @@ constructor( * The amount [0-1] that the shade has been opened. Uses stateIn to avoid redundant calculations * in downstream flows. */ - override val shadeExpansion: Flow<Float> = + override val shadeExpansion: StateFlow<Float> = combine( repository.lockscreenShadeExpansion, keyguardRepository.statusBarState, diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt index 7785eda4bd6a..7f35f17954c4 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt @@ -49,7 +49,9 @@ constructor( sharedNotificationContainerInteractor: SharedNotificationContainerInteractor, shadeRepository: ShadeRepository, ) : BaseShadeInteractor { - override val shadeExpansion: Flow<Float> = sceneBasedExpansion(sceneInteractor, Scenes.Shade) + override val shadeExpansion: StateFlow<Float> = + sceneBasedExpansion(sceneInteractor, Scenes.Shade) + .stateIn(scope, SharingStarted.Eagerly, 0f) private val sceneBasedQsExpansion = sceneBasedExpansion(sceneInteractor, Scenes.QuickSettings) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index ab6c14892eea..d112edb9772c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -35,7 +35,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED -import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED +import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel @@ -366,21 +366,34 @@ constructor( } } } - .onStart { emit(0f) } + .onStart { emit(1f) } .dumpWhileCollecting("alphaForShadeAndQsExpansion") - private val alphaWhenGoneAndShadeState: Flow<Float> = - combineTransform( - keyguardTransitionInteractor.transitions - .map { step -> step.to == GONE && step.transitionState == FINISHED } - .distinctUntilChanged(), - keyguardInteractor.statusBarState, - ) { isGoneTransitionFinished, statusBarState -> - if (isGoneTransitionFinished && statusBarState == SHADE) { - emit(1f) + private val isGoneTransitionRunning: Flow<Boolean> = + flow { + while (currentCoroutineContext().isActive) { + emit(false) + // Ensure start where GONE is inactive + keyguardTransitionInteractor.transitionValue(GONE).first { it == 0f } + // Wait for a GONE transition to begin + keyguardTransitionInteractor.transitionStepsToState(GONE).first { + it.value > 0f && it.transitionState == RUNNING + } + emit(true) + // Now await the signal that SHADE state has been reached or the GONE transition + // was reversed. Until SHADE state has been replaced and merged with GONE, it is + // the only source of when it is considered safe to reset alpha to 1f for HUNs. + combine( + keyguardInteractor.statusBarState, + // Emit -1f on start to make sure the flow runs + keyguardTransitionInteractor.transitionValue(GONE).onStart { emit(-1f) } + ) { statusBarState, goneValue -> + statusBarState == SHADE || goneValue == 0f + } + .first { it } } } - .dumpWhileCollecting("alphaWhenGoneAndShadeState") + .dumpWhileCollecting("goneTransitionInProgress") fun keyguardAlpha(viewState: ViewStateAccessor): Flow<Float> { // All transition view models are mututally exclusive, and safe to merge @@ -407,12 +420,11 @@ constructor( return merge( alphaTransitions, - // Sends a final alpha value of 1f when truly gone, to make sure HUNs appear - alphaWhenGoneAndShadeState, // These remaining cases handle alpha changes within an existing state, such as // shade expansion or swipe to dismiss combineTransform( isOnLockscreenWithoutShade, + isGoneTransitionRunning, shadeCollapseFadeIn, alphaForShadeAndQsExpansion, keyguardInteractor.dismissAlpha.dumpWhileCollecting( @@ -420,6 +432,7 @@ constructor( ), ) { isOnLockscreenWithoutShade, + isGoneTransitionRunning, shadeCollapseFadeIn, alphaForShadeAndQsExpansion, dismissAlpha -> @@ -427,7 +440,7 @@ constructor( if (!shadeCollapseFadeIn && dismissAlpha != null) { emit(dismissAlpha) } - } else { + } else if (!isGoneTransitionRunning) { emit(alphaForShadeAndQsExpansion) } }, |