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

Commit 3d6fe892 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Switch scenes when keyguard enabledness changes

1 - When the keyguard becomes disabled, switches to the Gone scene (if not
  in lockdown mode)
2 - When the keyguard becomes enabled again, switches to the Lockscreen
  scene (if it was previously hidden when disabled)
3 - If the auth method becomes insecure, forgets the bit set in (1)

Fix: 348644111
Test: added unit tests
Flag: com.android.systemui.scene_container
Change-Id: If34fce812477654feac1066c839262455c38c61e
parent 4afe405e
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -175,13 +175,13 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)

            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
            assertThat(backScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(backScene).isNull()
            assertThat(destinations)
                .isEqualTo(
                    mapOf(
                        Back to UserActionResult(Scenes.Lockscreen),
                        Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Lockscreen),
                        Back to UserActionResult(Scenes.Shade),
                        Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
                        Swipe(
                            fromSource = Edge.Bottom,
                            direction = SwipeDirection.Up,
+112 −9
Original line number Diff line number Diff line
@@ -36,12 +36,15 @@ import com.android.systemui.classifier.falsingCollector
import com.android.systemui.classifier.falsingManager
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
@@ -1339,6 +1342,111 @@ class SceneContainerStartableTest : SysuiTestCase() {
            assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
        }

    @Test
    fun switchToGone_whenKeyguardBecomesDisabled() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            underTest.start()

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()

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

    @Test
    fun switchToGone_whenKeyguardBecomesDisabled_whenOnShadeScene() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState(
                initialSceneKey = Scenes.Shade,
            )
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            underTest.start()

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()

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

    @Test
    fun doesNotSwitchToGone_whenKeyguardBecomesDisabled_whenInLockdownMode() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            underTest.start()

            kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
            kosmos.fakeBiometricSettingsRepository.setIsUserInLockdown(true)
            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()

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

    @Test
    fun doesNotSwitchToGone_whenKeyguardBecomesDisabled_whenDeviceEntered() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState(
                isDeviceUnlocked = true,
                initialSceneKey = Scenes.Gone,
            )
            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isTrue()
            underTest.start()
            sceneInteractor.changeScene(Scenes.Shade, "")
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isTrue()

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()

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

    @Test
    fun switchToLockscreen_whenKeyguardBecomesEnabled_afterHidingWhenDisabled() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            underTest.start()
            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Gone)

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(true)
            runCurrent()

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

    @Test
    fun doesNotSwitchToLockscreen_whenKeyguardBecomesEnabled_ifAuthMethodBecameInsecure() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            prepareState()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            underTest.start()
            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(false)
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Gone)
            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                AuthenticationMethodModel.None
            )
            runCurrent()

            kosmos.keyguardEnabledInteractor.notifyKeyguardEnabled(true)
            runCurrent()

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

    private fun TestScope.emulateSceneTransition(
        transitionStateFlow: MutableStateFlow<ObservableTransitionState>,
        toScene: SceneKey,
@@ -1381,16 +1489,11 @@ class SceneContainerStartableTest : SysuiTestCase() {
        isDeviceProvisioned: Boolean = true,
        isInteractive: Boolean = true,
    ): MutableStateFlow<ObservableTransitionState> {
        if (authenticationMethod?.isSecure == true) {
            assert(isLockscreenEnabled) {
                "Lockscreen cannot be disabled while having a secure authentication method"
            }
        if (isDeviceUnlocked) {
            kosmos.deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
        }
        }

        check(initialSceneKey != Scenes.Gone || isDeviceUnlocked) {
            "Cannot start on the Gone scene and have the device be locked at the same time."
+24 −0
Original line number Diff line number Diff line
@@ -211,6 +211,9 @@ constructor(
            }
        }

    /** Whether the device is in lockdown mode, where bouncer input is required to unlock. */
    val isInLockdown: Flow<Boolean> = deviceEntryRestrictionReason.map { it.isInLockdown() }

    /**
     * Attempt to enter the device and dismiss the lockscreen. If authentication is required to
     * unlock the device it will transition to bouncer.
@@ -259,6 +262,27 @@ constructor(
        return repository.isLockscreenEnabled()
    }

    fun DeviceEntryRestrictionReason?.isInLockdown(): Boolean {
        return when (this) {
            DeviceEntryRestrictionReason.UserLockdown -> true
            DeviceEntryRestrictionReason.PolicyLockdown -> true

            // Add individual enum value instead of using "else" so new reasons are guaranteed
            // to be added here at compile-time.
            null -> false
            DeviceEntryRestrictionReason.DeviceNotUnlockedSinceReboot -> false
            DeviceEntryRestrictionReason.BouncerLockedOut -> false
            DeviceEntryRestrictionReason.AdaptiveAuthRequest -> false
            DeviceEntryRestrictionReason.NonStrongBiometricsSecurityTimeout -> false
            DeviceEntryRestrictionReason.TrustAgentDisabled -> false
            DeviceEntryRestrictionReason.StrongBiometricsLockedOut -> false
            DeviceEntryRestrictionReason.SecurityTimeout -> false
            DeviceEntryRestrictionReason.DeviceNotUnlockedSinceMainlineUpdate -> false
            DeviceEntryRestrictionReason.UnattendedUpdate -> false
            DeviceEntryRestrictionReason.NonStrongFaceLockedOut -> false
        }
    }

    /**
     * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
     * dismissed once the authentication challenge is completed. For example, completing a biometric
+22 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
@@ -293,6 +294,15 @@ interface KeyguardRepository {

    /** Sets whether the keyguard is enabled (see [isKeyguardEnabled]). */
    fun setKeyguardEnabled(enabled: Boolean)

    /** @see isShowKeyguardWhenReenabled */
    fun setShowKeyguardWhenReenabled(isShowKeyguardWhenReenabled: Boolean)

    /**
     * Returns `true` if the keyguard should be re-shown once it becomes re-enabled again; `false`
     * otherwise.
     */
    fun isShowKeyguardWhenReenabled(): Boolean
}

/** Encapsulates application state for the keyguard. */
@@ -474,6 +484,8 @@ constructor(
    private val _isDozing = MutableStateFlow(statusBarStateController.isDozing)
    override val isDozing: StateFlow<Boolean> = _isDozing.asStateFlow()

    private var isShowKeyguardWhenReenabled: Boolean = false

    override fun setIsDozing(isDozing: Boolean) {
        _isDozing.value = isDozing
    }
@@ -692,6 +704,16 @@ constructor(
        _isKeyguardEnabled.value = enabled
    }

    override fun setShowKeyguardWhenReenabled(isShowKeyguardWhenReenabled: Boolean) {
        SceneContainerFlag.assertInNewMode()
        this.isShowKeyguardWhenReenabled = isShowKeyguardWhenReenabled
    }

    override fun isShowKeyguardWhenReenabled(): Boolean {
        SceneContainerFlag.assertInNewMode()
        return isShowKeyguardWhenReenabled
    }

    private fun statusBarStateIntToObject(value: Int): StatusBarState {
        return when (value) {
            0 -> StatusBarState.SHADE
+15 −13
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ constructor(
                    }
            }

            if (!SceneContainerFlag.isEnabled) {
                scope.launch {
                    keyguardRepository.isKeyguardEnabled
                        .filterRelevantKeyguardStateAnd { enabled -> enabled }
@@ -113,6 +114,7 @@ constructor(
                            )
                        }
                }
            }
        } else {
            scope.launch("$TAG#listenForGoneToLockscreenOrHub") {
                keyguardInteractor.isKeyguardShowing
Loading