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

Commit 9ec777c0 authored by Matt Pietal's avatar Matt Pietal
Browse files

Listen for additional AOD->* transitions

AOD->OCCLUDED logic was not quite right, as it waited for the doze
machine finish. In some cases, the transition to AOD is interrupted,
such as when hitting the power button while unlocked and receiving a
phone call.

AOD->PRIMARY_BOUNCER was never mapped. This does happen when the user
is locked out of biometrics, but attempts to use it anyways.

Fixes: 317464126
Test: atest KeyguardTransitionScenariosTest
Flag: N/A
Change-Id: Iec50306252941a90c822a1b27dfef70a9857b1d1
parent fdaf4101
Loading
Loading
Loading
Loading
+43 −12
Original line number Diff line number Diff line
@@ -54,12 +54,33 @@ constructor(
    ) {

    override fun start() {
        listenForAodToLockscreenOrOccluded()
        listenForAodToLockscreen()
        listenForAodToPrimaryBouncer()
        listenForAodToGone()
        listenForAodToOccluded()
        listenForTransitionToCamera(scope, keyguardInteractor)
    }

    private fun listenForAodToLockscreenOrOccluded() {
    /**
     * There are cases where the transition to AOD begins but never completes, such as tapping power
     * during an incoming phone call when unlocked. In this case, GONE->AOD should be interrupted to
     * run AOD->OCCLUDED.
     */
    private fun listenForAodToOccluded() {
        scope.launch {
            keyguardInteractor.isKeyguardOccluded.sample(startedKeyguardState, ::Pair).collect {
                (isOccluded, startedKeyguardState) ->
                if (isOccluded && startedKeyguardState == KeyguardState.AOD) {
                    startTransitionTo(
                        toState = KeyguardState.OCCLUDED,
                        modeOnCanceled = TransitionModeOnCanceled.RESET
                    )
                }
            }
        }
    }

    private fun listenForAodToLockscreen() {
        scope.launch {
            keyguardInteractor
                .dozeTransitionTo(DozeStateModel.FINISH)
@@ -72,20 +93,15 @@ constructor(
                    ::toTriple
                )
                .collect { (_, lastStartedStep, occluded) ->
                    if (lastStartedStep.to == KeyguardState.AOD) {
                        val toState =
                            if (occluded) KeyguardState.OCCLUDED else KeyguardState.LOCKSCREEN
                    if (lastStartedStep.to == KeyguardState.AOD && !occluded) {
                        val modeOnCanceled =
                            if (
                                toState == KeyguardState.LOCKSCREEN &&
                                    lastStartedStep.from == KeyguardState.LOCKSCREEN
                            ) {
                            if (lastStartedStep.from == KeyguardState.LOCKSCREEN) {
                                TransitionModeOnCanceled.REVERSE
                            } else {
                                TransitionModeOnCanceled.LAST_VALUE
                            }
                        startTransitionTo(
                            toState = toState,
                            toState = KeyguardState.LOCKSCREEN,
                            modeOnCanceled = modeOnCanceled,
                        )
                    }
@@ -93,11 +109,26 @@ constructor(
        }
    }

    /**
     * If there is a biometric lockout and FPS is tapped while on AOD, it should go directly to the
     * PRIMARY_BOUNCER.
     */
    private fun listenForAodToPrimaryBouncer() {
        scope.launch {
            keyguardInteractor.primaryBouncerShowing
                .sample(startedKeyguardTransitionStep, ::Pair)
                .collect { (isBouncerShowing, lastStartedTransitionStep) ->
                    if (isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.AOD) {
                        startTransitionTo(KeyguardState.PRIMARY_BOUNCER)
                    }
                }
        }
    }

    private fun listenForAodToGone() {
        scope.launch {
            keyguardInteractor.biometricUnlockState.sample(finishedKeyguardState, ::Pair).collect {
                pair ->
                val (biometricUnlockState, keyguardState) = pair
                (biometricUnlockState, keyguardState) ->
                if (keyguardState == KeyguardState.AOD && isWakeAndUnlock(biometricUnlockState)) {
                    startTransitionTo(KeyguardState.GONE)
                }
+25 −7
Original line number Diff line number Diff line
@@ -1342,14 +1342,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.AOD)
            runCurrent()

            // WHEN the keyguard is occluded and aod ends
            // WHEN the keyguard is occluded
            keyguardRepository.setKeyguardOccluded(true)
            keyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(
                    from = DozeStateModel.DOZE_AOD,
                    to = DozeStateModel.FINISH,
                )
            )
            runCurrent()

            val info =
@@ -1365,6 +1359,30 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
            coroutineContext.cancelChildren()
        }

    @Test
    fun aodToPrimaryBouncer() =
        testScope.runTest {
            // GIVEN a prior transition has run to AOD
            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.AOD)
            runCurrent()

            // WHEN the primary bouncer is set to show
            bouncerRepository.setPrimaryShow(true)
            runCurrent()

            val info =
                withArgCaptor<TransitionInfo> {
                    verify(transitionRepository).startTransition(capture())
                }
            // THEN a transition to OCCLUDED should occur
            assertThat(info.ownerName).isEqualTo("FromAodTransitionInteractor")
            assertThat(info.from).isEqualTo(KeyguardState.AOD)
            assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
            assertThat(info.animator).isNotNull()

            coroutineContext.cancelChildren()
        }

    @Test
    fun lockscreenToOccluded_fromCameraGesture() =
        testScope.runTest {