summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt177
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt238
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt1
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) {