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

Commit 266a2217 authored by Chandru S's avatar Chandru S Committed by Android (Google) Code Review
Browse files

Merge "Trigger face auth whenever user switching has completed." into udc-qpr-dev

parents 54a63492 5d9a9f73
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -109,6 +109,18 @@ interface DeviceEntryFaceAuthRepository {
    /** Set whether face authentication should be locked out or not */
    fun lockoutFaceAuth()

    /**
     * Cancel current face authentication and prevent it from running until [resumeFaceAuth] is
     * invoked.
     */
    fun pauseFaceAuth()

    /**
     * Allow face auth paused using [pauseFaceAuth] to run again. The next invocation to
     * [authenticate] will run as long as other gating conditions don't stop it from running.
     */
    fun resumeFaceAuth()

    /**
     * Trigger face authentication.
     *
@@ -186,6 +198,15 @@ constructor(
    override val isAuthRunning: StateFlow<Boolean>
        get() = _isAuthRunning

    private val faceAuthPaused = MutableStateFlow(false)
    override fun pauseFaceAuth() {
        faceAuthPaused.value = true
    }

    override fun resumeFaceAuth() {
        faceAuthPaused.value = false
    }

    private val keyguardSessionId: InstanceId?
        get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)

@@ -329,11 +350,7 @@ constructor(
                    "isFaceAuthenticationEnabled",
                    tableLogBuffer
                ),
                logAndObserve(
                    userRepository.userSwitchingInProgress.isFalse(),
                    "userSwitchingNotInProgress",
                    tableLogBuffer
                ),
                logAndObserve(faceAuthPaused.isFalse(), "faceAuthIsNotPaused", tableLogBuffer),
                logAndObserve(
                    keyguardRepository.isKeyguardGoingAway.isFalse(),
                    "keyguardNotGoingAway",
@@ -454,7 +471,6 @@ constructor(
        }

    private fun handleFaceCancellationError() {
        cancelNotReceivedHandlerJob?.cancel()
        applicationScope.launch {
            faceAuthRequestedWhileCancellation?.let {
                faceAuthLogger.launchingQueuedFaceAuthRequest(it)
@@ -483,6 +499,7 @@ constructor(
    }

    private fun onFaceAuthRequestCompleted() {
        cancelNotReceivedHandlerJob?.cancel()
        cancellationInProgress = false
        _isAuthRunning.value = false
        authCancellationSignal = null
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ class NoopDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceA
        get() = emptyFlow()

    override fun lockoutFaceAuth() = Unit
    override fun pauseFaceAuth() = Unit

    override fun resumeFaceAuth() = Unit

    /**
     * Trigger face authentication.
+24 −2
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * Encapsulates business logic related face authentication being triggered for device entry from
@@ -69,6 +71,7 @@ constructor(
    private val faceAuthenticationLogger: FaceAuthenticationLogger,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
    private val userRepository: UserRepository,
) : CoreStartable, KeyguardFaceAuthInteractor {

    private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf()
@@ -128,6 +131,23 @@ constructor(
                }
            }
            .launchIn(applicationScope)

        // User switching should stop face auth and then when it is complete we should trigger face
        // auth so that the switched user can unlock the device with face auth.
        userRepository.userSwitchingInProgress
            .pairwise(false)
            .onEach { (wasSwitching, isSwitching) ->
                if (!wasSwitching && isSwitching) {
                    repository.pauseFaceAuth()
                } else if (wasSwitching && !isSwitching) {
                    repository.resumeFaceAuth()
                    runFaceAuth(
                        FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING,
                        fallbackToDetect = true
                    )
                }
            }
            .launchIn(applicationScope)
    }

    override fun onSwipeUpOnBouncer() {
@@ -199,10 +219,12 @@ constructor(
            } else {
                faceAuthenticationStatusOverride.value = null
                applicationScope.launch {
                    withContext(mainDispatcher) {
                        faceAuthenticationLogger.authRequested(uiEvent)
                        repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect)
                    }
                }
            }
        } else {
            faceAuthenticationLogger.ignoredFaceAuthTrigger(
                uiEvent,
+4 −6
Original line number Diff line number Diff line
@@ -541,10 +541,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
        }

    @Test
    fun authenticateDoesNotRunIfUserIsCurrentlySwitching() =
        testScope.runTest {
            testGatingCheckForFaceAuth { fakeUserRepository.setUserSwitching(true) }
        }
    fun authenticateDoesNotRunIfFaceAuthIsCurrentlyPaused() =
        testScope.runTest { testGatingCheckForFaceAuth { underTest.pauseFaceAuth() } }

    @Test
    fun authenticateDoesNotRunIfKeyguardIsNotShowing() =
@@ -840,7 +838,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {

    @Test
    fun detectDoesNotRunWhenUserSwitchingInProgress() =
        testScope.runTest { testGatingCheckForDetect { fakeUserRepository.setUserSwitching(true) } }
        testScope.runTest { testGatingCheckForDetect { underTest.pauseFaceAuth() } }

    @Test
    fun detectDoesNotRunWhenKeyguardGoingAway() =
@@ -1130,7 +1128,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
            .addLockoutResetCallback(faceLockoutResetCallback.capture())
        biometricSettingsRepository.setFaceEnrolled(true)
        biometricSettingsRepository.setIsFaceAuthEnabled(true)
        fakeUserRepository.setUserSwitching(false)
        underTest.resumeFaceAuth()
        trustRepository.setCurrentUserTrusted(false)
        keyguardRepository.setKeyguardGoingAway(false)
        keyguardRepository.setWakefulnessModel(
+37 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -74,6 +75,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
    private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
    private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    private lateinit var faceAuthRepository: FakeDeviceEntryFaceAuthRepository
    private lateinit var fakeUserRepository: FakeUserRepository
    private lateinit var fakeDeviceEntryFingerprintAuthRepository:
        FakeDeviceEntryFingerprintAuthRepository

@@ -98,6 +100,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
                .keyguardTransitionInteractor

        fakeDeviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
        fakeUserRepository = FakeUserRepository()
        underTest =
            SystemUIKeyguardFaceAuthInteractor(
                mContext,
@@ -131,7 +134,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
                featureFlags,
                FaceAuthenticationLogger(logcatLogBuffer("faceAuthBuffer")),
                keyguardUpdateMonitor,
                fakeDeviceEntryFingerprintAuthRepository
                fakeDeviceEntryFingerprintAuthRepository,
                fakeUserRepository,
            )
    }

@@ -211,6 +215,38 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
                )
        }

    @Test
    fun faceAuthIsPausedWhenUserSwitchingIsInProgress() =
        testScope.runTest {
            underTest.start()

            fakeUserRepository.setUserSwitching(false)
            runCurrent()
            fakeUserRepository.setUserSwitching(true)
            runCurrent()

            assertThat(faceAuthRepository.isFaceAuthPaused()).isTrue()
        }

    @Test
    fun faceAuthIsUnpausedWhenUserSwitchingIsInComplete() =
        testScope.runTest {
            underTest.start()

            // previously running
            fakeUserRepository.setUserSwitching(true)
            runCurrent()
            fakeUserRepository.setUserSwitching(false)
            runCurrent()

            assertThat(faceAuthRepository.isFaceAuthPaused()).isFalse()

            runCurrent()
            assertThat(faceAuthRepository.runningAuthRequest.value!!.first)
                .isEqualTo(FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING)
            assertThat(faceAuthRepository.runningAuthRequest.value!!.second).isEqualTo(true)
        }

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