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

Commit 96cb7e01 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Changes to the bouncer scene when becomes non-interactive.

When the device becomes uninteractive, a change to the lockscreen scene
happens. This fixes an edge case where, despite the previous CL in this
chain, it's possible to switch to the bouncer scene in AOD mode if the
flinging up from the lockscreen to the bouncer scene happens right while
the transition into AOD occurs.

Fix: 330474509
Test: unit test added
Test: manually verified that what worked previously (fling up quickly
while entering AOD) doesn't work anymore - even if the bouncer scene
shows up, it goes away and we end up on the lockscreen scene in AOD.
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT

Change-Id: I53ea810d6a825121f7e5496027d26705f7b3b00f
parent 242261a5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -291,6 +291,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
                occlusionInteractor = kosmos.sceneContainerOcclusionInteractor,
                faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor,
                deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor,
                shadeInteractor = kosmos.shadeInteractor,
            )
        startable.start()

+33 −0
Original line number Diff line number Diff line
@@ -48,14 +48,17 @@ import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
import com.android.systemui.power.data.repository.fakePowerRepository
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.PowerInteractorFactory
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
@@ -140,6 +143,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
                occlusionInteractor = kosmos.sceneContainerOcclusionInteractor,
                faceUnlockInteractor = kosmos.deviceEntryFaceAuthInteractor,
                deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor,
                shadeInteractor = kosmos.shadeInteractor,
            )
    }

@@ -1127,6 +1131,33 @@ class SceneContainerStartableTest : SysuiTestCase() {
            assertThat(kosmos.fakeDeviceEntryFaceAuthRepository.isAuthRunning.value).isTrue()
        }

    @Test
    fun switchToLockscreen_whenShadeBecomesNotTouchable() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            val isShadeTouchable by collectLastValue(kosmos.shadeInteractor.isShadeTouchable)
            val transitionStateFlow = prepareState()
            underTest.start()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            // Flung to bouncer, 90% of the way there:
            transitionStateFlow.value =
                ObservableTransitionState.Transition(
                    fromScene = Scenes.Lockscreen,
                    toScene = Scenes.Bouncer,
                    progress = flowOf(0.9f),
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(false),
                )
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

            kosmos.fakePowerRepository.updateWakefulness(WakefulnessState.ASLEEP)
            runCurrent()
            assertThat(isShadeTouchable).isFalse()

            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
        }

    private fun TestScope.emulateSceneTransition(
        transitionStateFlow: MutableStateFlow<ObservableTransitionState>,
        toScene: SceneKey,
@@ -1166,6 +1197,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
        isLockscreenEnabled: Boolean = true,
        startsAwake: Boolean = true,
        isDeviceProvisioned: Boolean = true,
        isInteractive: Boolean = true,
    ): MutableStateFlow<ObservableTransitionState> {
        if (authenticationMethod?.isSecure == true) {
            assert(isLockscreenEnabled) {
@@ -1205,6 +1237,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
        } else {
            powerInteractor.setAsleepForTest()
        }
        kosmos.fakePowerRepository.setInteractive(isInteractive)

        kosmos.fakeDeviceProvisioningRepository.setDeviceProvisioned(isDeviceProvisioned)

+33 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -103,6 +104,7 @@ constructor(
    private val headsUpInteractor: HeadsUpNotificationInteractor,
    private val occlusionInteractor: SceneContainerOcclusionInteractor,
    private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor,
    private val shadeInteractor: ShadeInteractor,
) : CoreStartable {

    override fun start() {
@@ -185,6 +187,14 @@ constructor(

    /** Switches between scenes based on ever-changing application state. */
    private fun automaticallySwitchScenes() {
        handleBouncerImeVisibility()
        handleSimUnlock()
        handleDeviceUnlockStatus()
        handlePowerState()
        handleShadeTouchability()
    }

    private fun handleBouncerImeVisibility() {
        applicationScope.launch {
            // TODO (b/308001302): Move this to a bouncer specific interactor.
            bouncerInteractor.onImeHiddenByUser.collectLatest {
@@ -196,6 +206,9 @@ constructor(
                }
            }
        }
    }

    private fun handleSimUnlock() {
        applicationScope.launch {
            simBouncerInteractor
                .get()
@@ -229,6 +242,9 @@ constructor(
                    }
                }
        }
    }

    private fun handleDeviceUnlockStatus() {
        applicationScope.launch {
            deviceUnlockedInteractor.deviceUnlockStatus
                .mapNotNull { deviceUnlockStatus ->
@@ -288,7 +304,9 @@ constructor(
                    )
                }
        }
    }

    private fun handlePowerState() {
        applicationScope.launch {
            powerInteractor.isAsleep.collect { isAsleep ->
                if (isAsleep) {
@@ -317,7 +335,7 @@ constructor(
                    ) {
                        switchToScene(
                            targetSceneKey = Scenes.Bouncer,
                            loggingReason = "device is starting to wake up with a locked sim"
                            loggingReason = "device is starting to wake up with a locked sim",
                        )
                    }
                }
@@ -325,6 +343,20 @@ constructor(
        }
    }

    private fun handleShadeTouchability() {
        applicationScope.launch {
            shadeInteractor.isShadeTouchable
                .distinctUntilChanged()
                .filter { !it }
                .collect {
                    switchToScene(
                        targetSceneKey = Scenes.Lockscreen,
                        loggingReason = "device became non-interactive",
                    )
                }
        }
    }

    /** Keeps [SysUiState] up-to-date */
    private fun hydrateSystemUiState() {
        applicationScope.launch {