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

Commit d3e5ab1f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] hide and cancel AlternateBouncer when device sleeps" into main

parents bf2fcba2 ddf24911
Loading
Loading
Loading
Loading
+52 −11
Original line number Diff line number Diff line
@@ -28,9 +28,7 @@ import com.android.compose.animation.scene.SceneKey
import com.android.internal.logging.uiEventLoggerFake
import com.android.internal.policy.IKeyguardDismissCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
@@ -357,6 +355,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            runCurrent()

            assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
            assertThat(alternateBouncerVisible).isFalse()
@@ -506,6 +505,33 @@ class SceneContainerStartableTest : SysuiTestCase() {
            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
        }

    @Test
    fun hideAlternateBouncerAndNotifyDismissCancelledWhenDeviceSleeps() =
        testScope.runTest {
            val alternateBouncerVisible by
                collectLastValue(bouncerRepository.alternateBouncerVisible)
            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
            prepareState(
                isDeviceUnlocked = false,
                initialSceneKey = Scenes.Shade,
            )
            assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
            bouncerRepository.setAlternateVisible(true)
            underTest.start()

            // run all pending dismiss succeeded/cancelled calls from setup:
            kosmos.fakeExecutor.runAllReady()

            val dismissCallback: IKeyguardDismissCallback = mock()
            kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
            powerInteractor.setAsleepForTest()
            runCurrent()
            kosmos.fakeExecutor.runAllReady()

            assertThat(alternateBouncerVisible).isFalse()
            verify(dismissCallback).onDismissCancelled()
        }

    @Test
    fun switchToLockscreenWhenDeviceSleepsLocked() =
        testScope.runTest {
@@ -1644,19 +1670,27 @@ class SceneContainerStartableTest : SysuiTestCase() {
        }

    @Test
    fun notifyKeyguardDismissCallbacks_whenUnlocking_onDismissSucceeded() =
    fun notifyKeyguardDismissCallbacks_whenUnlockingFromBouncer_onDismissSucceeded() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
            prepareState(
                authenticationMethod = AuthenticationMethodModel.Pin,
                isDeviceUnlocked = false,
                initialSceneKey = Scenes.Bouncer,
            )
            assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
            underTest.start()

            // run all pending dismiss succeeded/cancelled calls from setup:
            kosmos.fakeExecutor.runAllReady()

            val dismissCallback: IKeyguardDismissCallback = mock()
            kosmos.dismissCallbackRegistry.addCallback(dismissCallback)

            // Switch to bouncer and unlock device:
            sceneInteractor.changeScene(Scenes.Bouncer, "")
            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
            kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
            assertThat(currentScene).isEqualTo(Scenes.Gone)
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            runCurrent()
            kosmos.fakeExecutor.runAllReady()

            verify(dismissCallback).onDismissSucceeded()
@@ -1665,19 +1699,26 @@ class SceneContainerStartableTest : SysuiTestCase() {
    @Test
    fun notifyKeyguardDismissCallbacks_whenLeavingBouncer_onDismissCancelled() =
        testScope.runTest {
            val isUnlocked by collectLastValue(kosmos.deviceEntryInteractor.isUnlocked)
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            underTest.start()

            // run all pending dismiss succeeded/cancelled calls from setup:
            kosmos.fakeExecutor.runAllReady()

            val dismissCallback: IKeyguardDismissCallback = mock()
            kosmos.dismissCallbackRegistry.addCallback(dismissCallback)

            // Switch to bouncer:
            sceneInteractor.changeScene(Scenes.Bouncer, "")
            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
            runCurrent()

            // Return to lockscreen:
            // Return to lockscreen when isUnlocked=false:
            sceneInteractor.changeScene(Scenes.Lockscreen, "")
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(isUnlocked).isFalse()
            runCurrent()
            kosmos.fakeExecutor.runAllReady()

+9 −4
Original line number Diff line number Diff line
@@ -17,15 +17,16 @@

package com.android.systemui.keyguard.domain.interactor

import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.resolver.NotifShadeSceneFamilyResolver
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolver
@@ -61,6 +62,8 @@ constructor(
    deviceEntryInteractor: DeviceEntryInteractor,
    quickSettingsSceneFamilyResolver: QuickSettingsSceneFamilyResolver,
    notifShadeSceneFamilyResolver: NotifShadeSceneFamilyResolver,
    powerInteractor: PowerInteractor,
    alternateBouncerInteractor: AlternateBouncerInteractor,
) {
    val dismissAction: Flow<DismissAction> = repository.dismissAction

@@ -124,10 +127,12 @@ constructor(
                    scene = Scenes.Bouncer,
                    stateWithoutSceneContainer = PRIMARY_BOUNCER
                ),
                transitionInteractor.isFinishedIn(state = ALTERNATE_BOUNCER),
                alternateBouncerInteractor.isVisible,
                isOnShadeWhileUnlocked,
            ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked ->
                !isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked
                powerInteractor.isAsleep,
            ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked, isAsleep ->
                (!isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked) ||
                    isAsleep
            }
            .filter { it }
            .sampleFilter(dismissAction) { it !is DismissAction.None }
+26 −10
Original line number Diff line number Diff line
@@ -152,7 +152,7 @@ constructor(
            hydrateBackStack()
            resetShadeSessions()
            handleKeyguardEnabledness()
            notifyKeyguardDismissCallbacks()
            notifyKeyguardDismissCancelledCallbacks()
            refreshLockscreenEnabled()
        } else {
            sceneLogger.logFrameworkEnabled(
@@ -379,8 +379,10 @@ constructor(
                    when {
                        isAlternateBouncerVisible -> {
                            // When the device becomes unlocked when the alternate bouncer is
                            // showing, always hide the alternate bouncer...
                            // showing, always hide the alternate bouncer and notify dismiss
                            // succeeded
                            alternateBouncerInteractor.hide()
                            dismissCallbackRegistry.notifyDismissSucceeded()

                            // ... and go to Gone or stay on the current scene
                            if (
@@ -394,9 +396,11 @@ constructor(
                                null
                            }
                        }
                        isOnPrimaryBouncer ->
                        isOnPrimaryBouncer -> {
                            // When the device becomes unlocked in primary Bouncer,
                            // notify dismiss succeeded and
                            // go to previous scene or Gone.
                            dismissCallbackRegistry.notifyDismissSucceeded()
                            if (
                                previousScene.value == Scenes.Lockscreen ||
                                    !statusBarStateController.leaveOpenOnKeyguardHide()
@@ -410,6 +414,7 @@ constructor(
                                    "device was unlocked with primary bouncer showing," +
                                        " from sceneKey=$prevScene"
                            }
                        }
                        isOnLockscreen ->
                            // The lockscreen should be dismissed automatically in 2 scenarios:
                            // 1. When face auth bypass is enabled and authentication happens while
@@ -468,6 +473,9 @@ constructor(
        applicationScope.launch {
            powerInteractor.isAsleep.collect { isAsleep ->
                if (isAsleep) {
                    alternateBouncerInteractor.hide()
                    dismissCallbackRegistry.notifyDismissCancelled()

                    switchToScene(
                        targetSceneKey = Scenes.Lockscreen,
                        loggingReason = "device is starting to sleep",
@@ -771,13 +779,21 @@ constructor(
        }
    }

    private fun notifyKeyguardDismissCallbacks() {
    private fun notifyKeyguardDismissCancelledCallbacks() {
        applicationScope.launch {
            sceneInteractor.currentScene.pairwise().collect { (from, to) ->
            combine(
                    deviceEntryInteractor.isUnlocked,
                    sceneInteractor.currentScene.pairwise(),
                ) { isUnlocked, (from, to) ->
                    when {
                    from != Scenes.Bouncer -> Unit
                    to == Scenes.Gone -> dismissCallbackRegistry.notifyDismissSucceeded()
                    else -> dismissCallbackRegistry.notifyDismissCancelled()
                        from != Scenes.Bouncer -> false
                        to != Scenes.Gone && !isUnlocked -> true
                        else -> false
                    }
                }
                .collect { notifyKeyguardDismissCancelled ->
                    if (notifyKeyguardDismissCancelled) {
                        dismissCallbackRegistry.notifyDismissCancelled()
                    }
                }
        }
+3 −1
Original line number Diff line number Diff line
@@ -545,6 +545,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb

    @VisibleForTesting
    void consumeFromAlternateBouncerTransitionSteps(TransitionStep step) {
        SceneContainerFlag.assertInLegacyMode();
        hideAlternateBouncer(false);
    }

@@ -554,6 +555,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
     */
    @VisibleForTesting
    void consumeKeyguardAuthenticatedBiometricsHandled(Unit handled) {
        SceneContainerFlag.assertInLegacyMode();
        if (mAlternateBouncerInteractor.isVisibleState()) {
            hideAlternateBouncer(false);
        }
@@ -981,7 +983,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
            } else {
                showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
            }
            if (hideBouncerWhenShowing) {
            if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing) {
                hideAlternateBouncer(true);
            }
            mKeyguardUpdateManager.sendKeyguardReset();
+33 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
@@ -29,6 +30,10 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.scene.data.repository.Idle
import com.android.systemui.scene.data.repository.Transition
import com.android.systemui.scene.data.repository.setSceneTransition
@@ -82,6 +87,8 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
                deviceEntryInteractor = kosmos.deviceEntryInteractor,
                quickSettingsSceneFamilyResolver = kosmos.quickSettingsSceneFamilyResolver,
                notifShadeSceneFamilyResolver = kosmos.notifShadeSceneFamilyResolver,
                powerInteractor = kosmos.powerInteractor,
                alternateBouncerInteractor = kosmos.alternateBouncerInteractor,
            )
    }

@@ -233,6 +240,32 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
            assertThat(resetDismissAction).isNull()
        }

    @Test
    fun resetDismissAction_onBouncer_OnAsleep() =
        testScope.runTest {
            kosmos.setSceneTransition(Idle(Scenes.Bouncer))
            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                AuthenticationMethodModel.None
            )
            val resetDismissAction by collectLastValue(underTest.resetDismissAction)
            keyguardRepository.setDismissAction(
                DismissAction.RunAfterKeyguardGone(
                    dismissAction = {},
                    onCancelAction = {},
                    message = "message",
                    willAnimateOnLockscreen = true,
                )
            )
            assertThat(resetDismissAction).isNull()
            kosmos.fakePowerRepository.updateWakefulness(
                rawState = WakefulnessState.ASLEEP,
                lastWakeReason = WakeSleepReason.POWER_BUTTON,
                lastSleepReason = WakeSleepReason.TIMEOUT,
                powerButtonLaunchGestureTriggered = false,
            )
            assertThat(resetDismissAction).isEqualTo(Unit)
        }

    @Test
    fun setDismissAction_callsCancelRunnableOnPreviousDismissAction() =
        testScope.runTest {
Loading