diff options
4 files changed, 246 insertions, 176 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt index 077927dfe0a2..5bf77ae9b23c 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt @@ -233,6 +233,12 @@ sealed interface ObservableTransitionState { (to == null || this.toContent == to) } + fun isTransitioningSets(from: Set<ContentKey>? = null, to: Set<ContentKey>? = null): Boolean { + return this is Transition && + (from == null || from.contains(this.fromContent)) && + (to == null || to.contains(this.toContent)) + } + /** Whether we are transitioning from [content] to [other], or from [other] to [content]. */ fun isTransitioningBetween(content: ContentKey, other: ContentKey): Boolean { return isTransitioning(from = content, to = other) || diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt index 6e16705b0739..7f313564e35a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt @@ -34,6 +34,8 @@ import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticati import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.data.repository.Idle +import com.android.systemui.scene.data.repository.Transition import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.data.repository.setSceneTransition import com.android.systemui.scene.domain.interactor.sceneInteractor @@ -115,9 +117,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { assertEquals( listOf( - false, // We should start with the surface invisible on LOCKSCREEN. + false // We should start with the surface invisible on LOCKSCREEN. ), - values + values, ) val lockscreenSpecificSurfaceVisibility = true @@ -134,13 +136,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // We started a transition from LOCKSCREEN, we should be using the value emitted by the // lockscreenSurfaceVisibilityFlow. - assertEquals( - listOf( - false, - lockscreenSpecificSurfaceVisibility, - ), - values - ) + assertEquals(listOf(false, lockscreenSpecificSurfaceVisibility), values) // Go back to LOCKSCREEN, since we won't emit 'true' twice in a row. transitionRepository.sendTransitionStep( @@ -166,7 +162,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { lockscreenSpecificSurfaceVisibility, false, // FINISHED (LOCKSCREEN) ), - values + values, ) val bouncerSpecificVisibility = true @@ -191,7 +187,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { false, bouncerSpecificVisibility, ), - values + values, ) } @@ -362,20 +358,14 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { kosmos.sceneInteractor.changeScene(Scenes.Gone, "") assertThat(currentScene).isEqualTo(Scenes.Gone) - listOf( - Scenes.Shade, - Scenes.QuickSettings, - Scenes.Shade, - Scenes.Gone, - ) - .forEach { scene -> - kosmos.setSceneTransition(ObservableTransitionState.Idle(scene)) - kosmos.sceneInteractor.changeScene(scene, "") - assertThat(currentScene).isEqualTo(scene) - assertWithMessage("Unexpected visibility for scene \"${scene.debugName}\"") - .that(isSurfaceBehindVisible) - .isTrue() - } + listOf(Scenes.Shade, Scenes.QuickSettings, Scenes.Shade, Scenes.Gone).forEach { scene -> + kosmos.setSceneTransition(ObservableTransitionState.Idle(scene)) + kosmos.sceneInteractor.changeScene(scene, "") + assertThat(currentScene).isEqualTo(scene) + assertWithMessage("Unexpected visibility for scene \"${scene.debugName}\"") + .that(isSurfaceBehindVisible) + .isTrue() + } } @Test @@ -386,19 +376,14 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) - listOf( - Scenes.Shade, - Scenes.QuickSettings, - Scenes.Shade, - Scenes.Lockscreen, - ) - .forEach { scene -> - kosmos.setSceneTransition(ObservableTransitionState.Idle(scene)) - kosmos.sceneInteractor.changeScene(scene, "") - assertWithMessage("Unexpected visibility for scene \"${scene.debugName}\"") - .that(isSurfaceBehindVisible) - .isFalse() - } + listOf(Scenes.Shade, Scenes.QuickSettings, Scenes.Shade, Scenes.Lockscreen).forEach { + scene -> + kosmos.setSceneTransition(ObservableTransitionState.Idle(scene)) + kosmos.sceneInteractor.changeScene(scene, "") + assertWithMessage("Unexpected visibility for scene \"${scene.debugName}\"") + .that(isSurfaceBehindVisible) + .isFalse() + } } @Test @@ -427,9 +412,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { assertEquals( listOf( - false, // Not using the animation when we're just sitting on LOCKSCREEN. + false // Not using the animation when we're just sitting on LOCKSCREEN. ), - values + values, ) surfaceBehindIsAnimatingFlow.emit(true) @@ -437,7 +422,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE, - testScope + testScope, ) runCurrent() @@ -446,7 +431,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { false, true, // Still true when we're FINISHED -> GONE, since we're still animating. ), - values + values, ) surfaceBehindIsAnimatingFlow.emit(false) @@ -458,7 +443,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // False once the animation ends. ), - values + values, ) } @@ -488,9 +473,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { assertEquals( listOf( - false, // Not using the animation when we're just sitting on LOCKSCREEN. + false // Not using the animation when we're just sitting on LOCKSCREEN. ), - values + values, ) surfaceBehindIsAnimatingFlow.emit(true) @@ -509,7 +494,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { false, true, // We're happily animating while transitioning to gone. ), - values + values, ) // Oh no, we're still surfaceBehindAnimating=true, but no longer transitioning to GONE. @@ -536,7 +521,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // Despite the animator still running, this should be false. ), - values + values, ) surfaceBehindIsAnimatingFlow.emit(false) @@ -548,7 +533,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // The animator ending should have no effect. ), - values + values, ) } @@ -579,10 +564,10 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { assertEquals( listOf( - true, // Unsurprisingly, we should start with the lockscreen visible on + true // Unsurprisingly, we should start with the lockscreen visible on // LOCKSCREEN. ), - values + values, ) transitionRepository.sendTransitionStep( @@ -596,9 +581,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { assertEquals( listOf( - true, // Lockscreen remains visible while we're transitioning to GONE. + true // Lockscreen remains visible while we're transitioning to GONE. ), - values + values, ) transitionRepository.sendTransitionStep( @@ -615,7 +600,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // Once we're fully GONE, the lockscreen should not be visible. ), - values + values, ) } @@ -628,7 +613,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE, - testScope + testScope, ) runCurrent() @@ -640,7 +625,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Then, false, since we finish in GONE. false, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -665,7 +650,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Should remain false as we transition from GONE. false, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -693,7 +678,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // visibility of the from state (LS). true, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -706,14 +691,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { runCurrent() - assertEquals( - listOf( - true, - false, - true, - ), - values - ) + assertEquals(listOf(true, false, true), values) } /** @@ -730,7 +708,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE, - testScope + testScope, ) runCurrent() @@ -740,7 +718,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Not visible since we're GONE. false, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -803,7 +781,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // STARTED to GONE after a CANCELED from GONE. false, ), - values + values, ) transitionRepository.sendTransitionSteps( @@ -820,7 +798,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // visible again once we're finished in LOCKSCREEN. true, ), - values + values, ) } @@ -833,7 +811,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE, - testScope + testScope, ) runCurrent() @@ -843,7 +821,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Not visible when finished in GONE. false, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -869,7 +847,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { // Still not visible during GONE -> AOD. false, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -886,9 +864,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // Visible now that we're FINISHED in AOD. - true + true, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -914,9 +892,9 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { true, false, // Remains visible from AOD during transition. - true + true, ), - values + values, ) transitionRepository.sendTransitionStep( @@ -934,15 +912,15 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { false, true, // Until we're finished in GONE again. - false + false, ), - values + values, ) } @Test @EnableSceneContainer - fun lockscreenVisibility() = + fun lockscreenVisibilityWithScenes() = testScope.runTest { val isDeviceUnlocked by collectLastValue( @@ -956,32 +934,69 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { val lockscreenVisibility by collectLastValue(underTest.value.lockscreenVisibility) assertThat(lockscreenVisibility).isTrue() + kosmos.setSceneTransition(Idle(Scenes.Shade)) + kosmos.sceneInteractor.changeScene(Scenes.Shade, "") + assertThat(currentScene).isEqualTo(Scenes.Shade) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Transition(from = Scenes.Shade, to = Scenes.QuickSettings)) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Idle(Scenes.QuickSettings)) + kosmos.sceneInteractor.changeScene(Scenes.QuickSettings, "") + assertThat(currentScene).isEqualTo(Scenes.QuickSettings) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Transition(from = Scenes.QuickSettings, to = Scenes.Shade)) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Idle(Scenes.Shade)) + kosmos.sceneInteractor.changeScene(Scenes.Shade, "") + assertThat(currentScene).isEqualTo(Scenes.Shade) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Idle(Scenes.Bouncer)) kosmos.sceneInteractor.changeScene(Scenes.Bouncer, "") assertThat(currentScene).isEqualTo(Scenes.Bouncer) assertThat(lockscreenVisibility).isTrue() + kosmos.setSceneTransition(Transition(from = Scenes.Bouncer, to = Scenes.Gone)) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Idle(Scenes.Gone)) kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) assertThat(isDeviceUnlocked).isTrue() kosmos.sceneInteractor.changeScene(Scenes.Gone, "") assertThat(currentScene).isEqualTo(Scenes.Gone) assertThat(lockscreenVisibility).isFalse() + kosmos.setSceneTransition(Idle(Scenes.Shade)) kosmos.sceneInteractor.changeScene(Scenes.Shade, "") assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(lockscreenVisibility).isFalse() + kosmos.setSceneTransition(Transition(from = Scenes.Shade, to = Scenes.QuickSettings)) + assertThat(lockscreenVisibility).isFalse() + + kosmos.setSceneTransition(Idle(Scenes.QuickSettings)) kosmos.sceneInteractor.changeScene(Scenes.QuickSettings, "") assertThat(currentScene).isEqualTo(Scenes.QuickSettings) assertThat(lockscreenVisibility).isFalse() + kosmos.setSceneTransition(Idle(Scenes.Shade)) kosmos.sceneInteractor.changeScene(Scenes.Shade, "") assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(lockscreenVisibility).isFalse() + kosmos.setSceneTransition(Idle(Scenes.Gone)) kosmos.sceneInteractor.changeScene(Scenes.Gone, "") assertThat(currentScene).isEqualTo(Scenes.Gone) assertThat(lockscreenVisibility).isFalse() + kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen)) + assertThat(lockscreenVisibility).isFalse() + + kosmos.setSceneTransition(Idle(Scenes.Lockscreen)) kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "") assertThat(currentScene).isEqualTo(Scenes.Lockscreen) assertThat(lockscreenVisibility).isTrue() @@ -1037,7 +1052,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { flowOf(Scenes.Lockscreen), progress, false, - flowOf(false) + flowOf(false), ) private val goneToLs = @@ -1047,7 +1062,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { flowOf(Scenes.Lockscreen), progress, false, - flowOf(false) + flowOf(false), ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt index a1f606740cd9..d648c25ced8b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt @@ -18,7 +18,8 @@ package com.android.systemui.keyguard.domain.interactor -import com.android.compose.animation.scene.ObservableTransitionState +import com.android.compose.animation.scene.ObservableTransitionState.Idle +import com.android.compose.animation.scene.ObservableTransitionState.Transition import com.android.systemui.Flags.transitionRaceCondition import com.android.systemui.dagger.SysUISingleton import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor @@ -30,6 +31,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.device import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor import com.android.systemui.util.kotlin.Utils.Companion.toTriple @@ -110,11 +112,8 @@ constructor( } .distinctUntilChanged() - private val isDeviceEntered: Flow<Boolean> by lazy { - deviceEntryInteractor.get().isDeviceEntered - } - - private val isDeviceNotEntered: Flow<Boolean> by lazy { isDeviceEntered.map { !it } } + private val isDeviceEntered by lazy { deviceEntryInteractor.get().isDeviceEntered } + private val isDeviceNotEntered by lazy { isDeviceEntered.map { !it } } /** * Surface visibility, which is either determined by the default visibility when not @@ -124,32 +123,24 @@ constructor( @OptIn(ExperimentalCoroutinesApi::class) val surfaceBehindVisibility: Flow<Boolean> = if (SceneContainerFlag.isEnabled) { - sceneInteractor.get().transitionState.flatMapLatestConflated { transitionState -> - when (transitionState) { - is ObservableTransitionState.Transition -> - when { - transitionState.fromContent == Scenes.Lockscreen && - transitionState.toContent == Scenes.Gone -> - sceneInteractor - .get() - .isTransitionUserInputOngoing - .flatMapLatestConflated { isUserInputOngoing -> - if (isUserInputOngoing) { - isDeviceEntered - } else { - flowOf(true) - } - } - transitionState.fromContent == Scenes.Bouncer && - transitionState.toContent == Scenes.Gone -> - transitionState.progress.map { progress -> - progress > - FromPrimaryBouncerTransitionInteractor - .TO_GONE_SURFACE_BEHIND_VISIBLE_THRESHOLD - } - else -> isDeviceEntered + sceneInteractor.get().transitionState.flatMapLatestConflated { state -> + when { + state.isTransitioning(from = Scenes.Lockscreen, to = Scenes.Gone) -> + (state as Transition).isUserInputOngoing.flatMapLatestConflated { + isUserInputOngoing -> + if (isUserInputOngoing) { + isDeviceEntered + } else { + flowOf(true) + } + } + state.isTransitioning(from = Scenes.Bouncer, to = Scenes.Gone) -> + (state as Transition).progress.map { progress -> + progress > + FromPrimaryBouncerTransitionInteractor + .TO_GONE_SURFACE_BEHIND_VISIBLE_THRESHOLD } - is ObservableTransitionState.Idle -> isDeviceEntered + else -> isDeviceEntered } } } else { @@ -219,6 +210,123 @@ constructor( } /** + * Scenes that are part of the keyguard and are shown when the device is locked or when the + * keyguard still needs to be dismissed. + */ + private val keyguardScenes = setOf(Scenes.Lockscreen, Scenes.Bouncer, Scenes.Communal) + + /** + * Scenes that don't belong in the keyguard family and cannot show when the device is locked or + * when the keyguard still needs to be dismissed. + */ + private val nonKeyguardScenes = setOf(Scenes.Gone) + + /** + * Scenes that can show regardless of device lock or keyguard dismissal states. Other sources of + * state need to be consulted to know whether the device has been entered or not. + */ + private val keyguardAgnosticScenes = + setOf( + Scenes.Shade, + Scenes.QuickSettings, + Overlays.NotificationsShade, + Overlays.QuickSettingsShade, + ) + + private val lockscreenVisibilityWithScenes = + combine( + sceneInteractor.get().transitionState.flatMapLatestConflated { + when (it) { + is Idle -> { + when (it.currentScene) { + in keyguardScenes -> flowOf(true) + in nonKeyguardScenes -> flowOf(false) + in keyguardAgnosticScenes -> isDeviceNotEntered + else -> + throw IllegalStateException("Unknown scene: ${it.currentScene}") + } + } + is Transition -> { + when { + it.isTransitioningSets(from = keyguardScenes) -> flowOf(true) + it.isTransitioningSets(from = nonKeyguardScenes) -> flowOf(false) + it.isTransitioningSets(from = keyguardAgnosticScenes) -> + isDeviceNotEntered + else -> + throw IllegalStateException("Unknown scene: ${it.fromContent}") + } + } + } + }, + wakeToGoneInteractor.canWakeDirectlyToGone, + ::Pair, + ) + .map { (lockscreenVisibilityByTransitionState, canWakeDirectlyToGone) -> + lockscreenVisibilityByTransitionState && !canWakeDirectlyToGone + } + + private val lockscreenVisibilityLegacy = + combine( + transitionInteractor.currentKeyguardState, + wakeToGoneInteractor.canWakeDirectlyToGone, + ::Pair, + ) + .sample(transitionInteractor.startedStepWithPrecedingStep, ::toTriple) + .map { (currentState, canWakeDirectlyToGone, startedWithPrev) -> + val startedFromStep = startedWithPrev.previousValue + val startedStep = startedWithPrev.newValue + val returningToGoneAfterCancellation = + startedStep.to == KeyguardState.GONE && + startedFromStep.transitionState == TransitionState.CANCELED && + startedFromStep.from == KeyguardState.GONE + + val transitionInfo = + if (transitionRaceCondition()) { + transitionRepository.currentTransitionInfo + } else { + transitionRepository.currentTransitionInfoInternal.value + } + val wakingDirectlyToGone = + deviceIsAsleepInState(transitionInfo.from) && + transitionInfo.to == KeyguardState.GONE + + if (returningToGoneAfterCancellation || wakingDirectlyToGone) { + // GONE -> AOD/DOZING (cancel) -> GONE is the camera launch transition, + // which means we never want to show the lockscreen throughout the + // transition. Same for waking directly to gone, due to the lockscreen being + // disabled or because the device was woken back up before the lock timeout + // duration elapsed. + false + } else if (canWakeDirectlyToGone) { + // Never show the lockscreen if we can wake directly to GONE. This means + // that the lock timeout has not yet elapsed, or the keyguard is disabled. + // In either case, we don't show the activity lock screen until one of those + // conditions changes. + false + } else if ( + currentState == KeyguardState.DREAMING && + deviceEntryInteractor.get().isUnlocked.value + ) { + // Dreams dismiss keyguard and return to GONE if they can. + false + } else if ( + startedWithPrev.newValue.from == KeyguardState.OCCLUDED && + startedWithPrev.newValue.to == KeyguardState.GONE + ) { + // OCCLUDED -> GONE directly, without transiting a *_BOUNCER state, occurs + // when an app uses intent flags to launch over an insecure keyguard without + // dismissing it, and then manually requests keyguard dismissal while + // OCCLUDED. This transition is not user-visible; the device unlocks in the + // background and the app remains on top, while we're now GONE. In this case + // we should simply tell WM that the lockscreen is no longer visible, and + // *not* play the going away animation or related animations. + false + } else { + currentState != KeyguardState.GONE + } + } + + /** * Whether the lockscreen is visible, from the Window Manager (WM) perspective. * * Note: This may briefly be true even if the lockscreen UI has animated out (alpha = 0f), as we @@ -227,69 +335,11 @@ constructor( */ val lockscreenVisibility: Flow<Boolean> = if (SceneContainerFlag.isEnabled) { - isDeviceNotEntered - } else { - combine( - transitionInteractor.currentKeyguardState, - wakeToGoneInteractor.canWakeDirectlyToGone, - ::Pair, - ) - .sample(transitionInteractor.startedStepWithPrecedingStep, ::toTriple) - .map { (currentState, canWakeDirectlyToGone, startedWithPrev) -> - val startedFromStep = startedWithPrev.previousValue - val startedStep = startedWithPrev.newValue - val returningToGoneAfterCancellation = - startedStep.to == KeyguardState.GONE && - startedFromStep.transitionState == TransitionState.CANCELED && - startedFromStep.from == KeyguardState.GONE - - val transitionInfo = - if (transitionRaceCondition()) { - transitionRepository.currentTransitionInfo - } else { - transitionRepository.currentTransitionInfoInternal.value - } - val wakingDirectlyToGone = - deviceIsAsleepInState(transitionInfo.from) && - transitionInfo.to == KeyguardState.GONE - - if (returningToGoneAfterCancellation || wakingDirectlyToGone) { - // GONE -> AOD/DOZING (cancel) -> GONE is the camera launch transition, - // which means we never want to show the lockscreen throughout the - // transition. Same for waking directly to gone, due to the lockscreen being - // disabled or because the device was woken back up before the lock timeout - // duration elapsed. - false - } else if (canWakeDirectlyToGone) { - // Never show the lockscreen if we can wake directly to GONE. This means - // that the lock timeout has not yet elapsed, or the keyguard is disabled. - // In either case, we don't show the activity lock screen until one of those - // conditions changes. - false - } else if ( - currentState == KeyguardState.DREAMING && - deviceEntryInteractor.get().isUnlocked.value - ) { - // Dreams dismiss keyguard and return to GONE if they can. - false - } else if ( - startedWithPrev.newValue.from == KeyguardState.OCCLUDED && - startedWithPrev.newValue.to == KeyguardState.GONE - ) { - // OCCLUDED -> GONE directly, without transiting a *_BOUNCER state, occurs - // when an app uses intent flags to launch over an insecure keyguard without - // dismissing it, and then manually requests keyguard dismissal while - // OCCLUDED. This transition is not user-visible; the device unlocks in the - // background and the app remains on top, while we're now GONE. In this case - // we should simply tell WM that the lockscreen is no longer visible, and - // *not* play the going away animation or related animations. - false - } else { - currentState != KeyguardState.GONE - } - } - .distinctUntilChanged() - } + lockscreenVisibilityWithScenes + } else { + lockscreenVisibilityLegacy + } + .distinctUntilChanged() /** * Whether always-on-display (AOD) is visible when the lockscreen is visible, from window diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index f3c6190d2f7b..1fbe8e2f21e5 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -213,7 +213,6 @@ constructor( /** Updates the visibility of the scene container. */ private fun hydrateVisibility() { applicationScope.launch { - // TODO(b/296114544): Combine with some global hun state to make it visible! deviceProvisioningInteractor.isDeviceProvisioned .flatMapLatest { isAllowedToBeVisible -> if (isAllowedToBeVisible) { |