Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d095afe authored by Josh Tsuji's avatar Josh Tsuji
Browse files

[flexiglass] Tie lockscreen visibility during Gone -> LS to wakefulness state.

This fixes multiple flicker issues with screen off, canceled screen off, and unlocked camera launch (which is just a special case of canceled screen off).

A much less severe black flicker during unlocked camera launch still occurs due to an errant aodVisible=true, this will be fixed as part of b/438799387.

Fixes: 439672420
Fixes: 439671061
Test: atest WindowManagerLockscreenVisibilityInteractorTest
Flag: com.android.systemui.scene_container
Change-Id: I05bee04b7097f4bacf0ddc30588cd707077e03ca
parent 07a1a036
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@ import com.android.systemui.kosmos.collectValues
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.data.repository.HideOverlay
@@ -1106,6 +1109,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(lockscreenVisibility).isFalse()

            powerInteractor.setAsleepForTest()
            setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
            // Lockscreen remains not visible during the transition so that the unlocked app content
            // is visible under the light reveal screen off animation.
@@ -1297,6 +1301,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {

            // Lockscreen vis remains false during Gone -> LS so the unlocked app content is visible
            // during the screen off animation.
            powerInteractor.setAsleepForTest()
            setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
            assertThat(lockscreenVisibility).isFalse()

@@ -1305,6 +1310,68 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
            assertThat(lockscreenVisibility).isTrue()
        }

    @Test
    @EnableSceneContainer
    fun lockscreenVisibility_becomesVisible_ifAwakeDuringGoneLs() =
        kosmos.runTest {
            enableSingleShade()
            runCurrent()

            powerInteractor.setAwakeForTest()
            kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
            setSceneTransition(Idle(Scenes.Gone))
            sceneInteractor.changeScene(Scenes.Gone, "")

            val lockscreenVisibility by collectLastValue(underTest.lockscreenVisibility)
            assertThat(lockscreenVisibility).isFalse()

            // Lockscreen vis remains false during Gone -> LS so the unlocked app content is visible
            // during the screen off animation.
            powerInteractor.setAsleepForTest()
            setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
            assertThat(lockscreenVisibility).isFalse()

            powerInteractor.setAwakeForTest()
            runCurrent()
            assertThat(lockscreenVisibility).isTrue()

            setSceneTransition(Idle(Scenes.Lockscreen))
            sceneInteractor.changeScene(Scenes.Lockscreen, "")
            assertThat(lockscreenVisibility).isTrue()
        }

    @Test
    @EnableSceneContainer
    fun lockscreenVisibility_remainsNotVisible_ifCameraLaunch() =
        kosmos.runTest {
            enableSingleShade()
            runCurrent()

            kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
            setSceneTransition(Idle(Scenes.Gone))
            sceneInteractor.changeScene(Scenes.Gone, "")

            val lockscreenVisibility by collectLastValue(underTest.lockscreenVisibility)
            assertThat(lockscreenVisibility).isFalse()

            // Lockscreen vis remains false during Gone -> LS so the unlocked app content is visible
            // during the screen off animation.
            powerInteractor.setAsleepForTest()
            setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
            assertThat(lockscreenVisibility).isFalse()

            powerInteractor.onCameraLaunchGestureDetected()
            powerInteractor.setAwakeForTest()
            runCurrent()
            assertThat(lockscreenVisibility).isFalse()

            setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
            setSceneTransition(Idle(Scenes.Gone))
            sceneInteractor.changeScene(Scenes.Gone, "")
            assertThat(lockscreenVisibility).isFalse()
        }


    companion object {
        private val progress = MutableStateFlow(0f)

+30 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.deviceIsAsleepInState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Overlays
@@ -34,14 +35,15 @@ import com.android.systemui.statusbar.notification.domain.interactor.Notificatio
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import dagger.Lazy
import javax.inject.Inject

@SysUISingleton
class WindowManagerLockscreenVisibilityInteractor
@@ -59,6 +61,7 @@ constructor(
    deviceEntryInteractor: Lazy<DeviceEntryInteractor>,
    wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
    deviceProvisioningInteractor: Lazy<DeviceProvisioningInteractor>,
    powerInteractor: PowerInteractor,
) {
    private val defaultSurfaceBehindVisibility =
        combine(
@@ -198,6 +201,26 @@ constructor(
                .distinctUntilChanged()
        }

    /**
     * WM lockscreen visibility during Gone -> Lockscreen.
     *
     * Lockscreen only needs to remain non-visible (unlocked app content visible) in order to play
     * the screen off animation. If we become awake during the transition, that means the animation
     * was cancelled and we should hide the unlocked content so it's not visible behind the
     * lockscreen during Gone -> Lockscreen.
     *
     * This also covers the Lockdown case, where Gone -> Lockscreen starts while awake. There is no
     * lockdown animation, so we should immediately hide the unlocked content.
     *
     * We also need Lockscreen to remain non-visible at all times if the unlocked power button
     * gesture is triggered, since we'll be returning to Gone as if we never tried to lock in the
     * first place.
     */
    private val goneToLockscreenLsVisibility =
        powerInteractor.detailedWakefulness
            .distinctUntilChangedBy { it.isAwake() }
            .map { it.isAwake() && !it.powerButtonLaunchGestureTriggered }

    private val lockscreenVisibilityWithScenes: Flow<Boolean> =
        deviceProvisioningInteractor.get().isDeviceProvisioned.flatMapLatestConflated {
            isProvisioned ->
@@ -232,6 +255,11 @@ constructor(
                                        // visible.
                                        it.currentOverlays.contains(Overlays.Bouncer) ->
                                            flowOf(true)
                                        // If we're transitioning to Lockscreen from Gone, special
                                        // cases apply.
                                        it.fromScene == Scenes.Gone &&
                                            it.toScene == Scenes.Lockscreen ->
                                            goneToLockscreenLsVisibility
                                        // Otherwise, default to showing the lockscreen if the
                                        // device is not yet entered, or leaving it not showing if
                                        // the device was entered. This covers two requirements:
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.notification.domain.interactor.notificationLaunchAnimationInteractor
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
@@ -38,5 +39,6 @@ val Kosmos.windowManagerLockscreenVisibilityInteractor by
            deviceEntryInteractor = { deviceEntryInteractor },
            wakeToGoneInteractor = keyguardWakeDirectlyToGoneInteractor,
            deviceProvisioningInteractor = { deviceProvisioningInteractor },
            powerInteractor = powerInteractor,
        )
    }