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

Commit 84a5b7ba authored by Grace Cheng's avatar Grace Cheng
Browse files

Cleanup device unlock logic in secure lock device

Creates separate device unlock source SecureLockDeviceTwoFactorAuth and reduce duplication in DeviceUnlockedInteractor

Flag: android.security.secure_lock_device
Test: atest DeviceUnlockedInteractorTest
Bug: 401645997
Change-Id: Ice062c9913e823ce0967cb1c6ff428ebccdf181b
parent 11854639
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -867,7 +867,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() {
            // Assert device is now unlocked, deviceUnlockSource updates to face
            assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
            assertThat(deviceUnlockStatus?.deviceUnlockSource)
                .isEqualTo(DeviceUnlockSource.FaceWithoutBypass)
                .isEqualTo(DeviceUnlockSource.SecureLockDeviceTwoFactorAuth)
        }

    private fun TestScope.unlockDevice() {
+1 −3
Original line number Diff line number Diff line
@@ -2957,11 +2957,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
            kosmos.secureLockDeviceInteractor.onReadyToDismissBiometricAuth()
            runCurrent()

            assertThat(isSecureLockDeviceEnabled).isTrue()
            assertThat(isFullyUnlockedAndReadyToDismiss).isTrue()
            assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
            assertThat(deviceUnlockStatus?.deviceUnlockSource)
                .isEqualTo(DeviceUnlockSource.FaceWithoutBypass)
                .isEqualTo(DeviceUnlockSource.SecureLockDeviceTwoFactorAuth)
            assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
            assertThat(currentOverlays).doesNotContain(Overlays.Bouncer)
        }
+30 −44
Original line number Diff line number Diff line
@@ -42,9 +42,6 @@ import com.android.systemui.scene.domain.SceneFrameworkTableLog
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.securelockdevice.domain.interactor.SecureLockDeviceInteractor
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import dagger.Lazy
import javax.inject.Inject
@@ -191,41 +188,28 @@ constructor(
        }

    /** Indicates when a device has been unlocked from successful authentication on the bouncer. */
    private val onUnlockFromBouncer =
        authenticationInteractor.onAuthenticationResult
            .filter { it }
            .sampleFilter(isSecureLockDeviceEnabled) {
                /**
                 * When secure lock device is active, the device is not considered unlocked after
                 * successful bouncer auth. Secure Lock Device requires two-factor authentication:
                 * primary auth on the bouncer, followed by strong biometric authentication on the
                 * bouncer, in order to unlock and enter the device.
                 */
                !it
            }
    private val onUnlockFromBouncer = authenticationInteractor.onAuthenticationResult.filter { it }

    private val deviceUnlockSource =
        /**
         * When secure lock device is active, the device is not considered unlocked after successful
         * bouncer auth. Secure Lock Device requires two-factor authentication: primary auth on the
         * bouncer, followed by strong biometric authentication on the bouncer, in order to unlock
         * and enter the device.
         */
        isSecureLockDeviceEnabled.flatMapLatest { isSecureLockDeviceEnabled ->
            if (isSecureLockDeviceEnabled) {
                isFullyUnlockedAndReadyToDismissInSecureLockDevice
                    .filter { it }
                    .map { DeviceUnlockSource.SecureLockDeviceTwoFactorAuth }
            } else {
                merge(
            combine(
                    fingerprintAuthInteractor.fingerprintSuccess,
                    isFullyUnlockedAndReadyToDismissInSecureLockDevice,
                    ::Pair,
                )
                .sample(isSecureLockDeviceEnabled, ::toTriple)
                .filter { (_, readyToDismissInSecureLockDevice, isSecureLockDeviceEnabled) ->
                    !isSecureLockDeviceEnabled || readyToDismissInSecureLockDevice
                }
                .map { DeviceUnlockSource.Fingerprint },
            combine(
                    faceAuthInteractor.isAuthenticated.filter { it },
                    isFullyUnlockedAndReadyToDismissInSecureLockDevice,
                    ::Pair,
                )
                .sample(isSecureLockDeviceEnabled, ::toTriple)
                .filter { (_, readyToDismissInSecureLockDevice, isSecureLockDeviceEnabled) ->
                    !isSecureLockDeviceEnabled || readyToDismissInSecureLockDevice
                }
                .map { (_, _, _) ->
                    fingerprintAuthInteractor.fingerprintSuccess.map {
                        DeviceUnlockSource.Fingerprint
                    },
                    faceAuthInteractor.isAuthenticated
                        .filter { it }
                        .map {
                            if (deviceEntryBypassInteractor.isBypassEnabled.value) {
                                DeviceUnlockSource.FaceWithBypass
                            } else {
@@ -235,6 +219,8 @@ constructor(
                    trustInteractor.isTrusted.filter { it }.map { DeviceUnlockSource.TrustAgent },
                    onUnlockFromBouncer.map { DeviceUnlockSource.BouncerInput },
                )
            }
        }

    /**
     * Whether the device is unlocked or not, along with the information about the authentication
+6 −0
Original line number Diff line number Diff line
@@ -25,8 +25,14 @@ package com.android.systemui.deviceentry.shared.model
sealed class DeviceUnlockSource(val dismissesLockscreen: Boolean) {

    data object Fingerprint : DeviceUnlockSource(true)

    data object FaceWithBypass : DeviceUnlockSource(dismissesLockscreen = true)

    data object FaceWithoutBypass : DeviceUnlockSource(dismissesLockscreen = false)

    data object TrustAgent : DeviceUnlockSource(dismissesLockscreen = false)

    data object BouncerInput : DeviceUnlockSource(dismissesLockscreen = true)

    data object SecureLockDeviceTwoFactorAuth : DeviceUnlockSource(dismissesLockscreen = true)
}