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

Commit b5ea48a0 authored by Beverly's avatar Beverly
Browse files

Don't filter face failures in the face repository

Instead, filter the message later (KeyguardIndicationController,
BiometricMessageInteractor).

The face failure status still needs to be sent to play the face
failure haptic.

Test: atest KeyguardIndicationControllerTest
Fixes: 282876070
Flag: None
Change-Id: I4c11ec4809e1133b9f726d31ec9847bee0669fcb
parent be0aeae3
Loading
Loading
Loading
Loading
+0 −26
Original line number Diff line number Diff line
@@ -1052,32 +1052,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
            biometricSettingsRepository.setIsFaceAuthCurrentlyAllowed(true)
            faceAuthenticateIsCalled()
        }
    @Test
    fun authFailedCallAfterAuthLockedOutErrorShouldBeIgnored() =
        testScope.runTest {
            initCollectors()
            allPreconditionsToRunFaceAuthAreTrue()
            runCurrent()
            assertThat(canFaceAuthRun()).isTrue()

            underTest.requestAuthenticate(FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED, false)
            runCurrent()

            faceAuthenticateIsCalled()
            authenticationCallback.value.onAuthenticationError(
                FACE_ERROR_LOCKOUT_PERMANENT,
                "Too many attempts, face not available"
            )

            val lockoutError = authStatus() as ErrorFaceAuthenticationStatus
            assertThat(lockedOut()).isTrue()
            assertThat(lockoutError.isLockoutError()).isTrue()

            authenticationCallback.value.onAuthenticationFailed()
            runCurrent()

            assertThat(authStatus()).isEqualTo(lockoutError)
        }

    private suspend fun TestScope.testGatingCheckForFaceAuth(
        gatingCheckModifier: suspend () -> Unit
+6 −6
Original line number Diff line number Diff line
@@ -62,6 +62,10 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
import com.google.errorprone.annotations.CompileTimeConstant
import java.io.PrintWriter
import java.util.Arrays
import java.util.stream.Collectors
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@@ -83,10 +87,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.PrintWriter
import java.util.Arrays
import java.util.stream.Collectors
import javax.inject.Inject

/**
 * API to run face authentication and detection for device entry / on keyguard (as opposed to the
@@ -431,11 +431,11 @@ constructor(
            override fun onAuthenticationFailed() {
                _isAuthenticated.value = false
                faceAuthLogger.authenticationFailed()
                _authenticationStatus.value = FailedFaceAuthenticationStatus()
                if (!_isLockedOut.value) {
                    // onAuthenticationError gets invoked before onAuthenticationFailed when the
                    // last auth attempt locks out face authentication.
                    // Skip updating the authentication status in such a scenario.
                    _authenticationStatus.value = FailedFaceAuthenticationStatus()
                    // Skip onFaceAuthRequestCompleted in such a scenario.
                    onFaceAuthRequestCompleted()
                }
            }
+7 −0
Original line number Diff line number Diff line
@@ -1228,6 +1228,13 @@ public class KeyguardIndicationController {
                    && msgId != BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
            final boolean faceAuthFailed = biometricSourceType == FACE
                    && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
            if (faceAuthFailed && mFaceLockedOutThisAuthSession) {
                mKeyguardLogger.logBiometricMessage(
                        "skipped showing faceAuthFailed message due to lockout",
                        msgId,
                        helpString);
                return;
            }
            final boolean fpAuthFailed = biometricSourceType == FINGERPRINT
                    && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed
            final boolean isUnlockWithFingerprintPossible = canUnlockWithFingerprint();
+16 −1
Original line number Diff line number Diff line
@@ -91,6 +91,21 @@ import java.util.Set;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class KeyguardIndicationControllerTest extends KeyguardIndicationControllerBaseTest {
    @Test
    public void afterFaceLockout_skipShowingFaceNotRecognized() {
        createController();
        onFaceLockoutError("lockout");
        verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE, "lockout");
        clearInvocations(mRotateTextViewController);

        // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED (face fail)
        mKeyguardUpdateMonitorCallback.onBiometricHelp(
                BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
                "Face not recognized",
                BiometricSourceType.FACE);
        verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); // no updated message
    }

    @Test
    public void createController_setIndicationAreaAgain_destroysPreviousRotateTextViewController() {
        // GIVEN a controller with a mocked rotate text view controlller
@@ -1242,7 +1257,7 @@ public class KeyguardIndicationControllerTest extends KeyguardIndicationControll
    public void onBiometricFailed_resetFaceHelpMessageDeferral() {
        createController();

        // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED
        // WHEN face sends an onBiometricAuthFailed
        mKeyguardUpdateMonitorCallback.onBiometricAuthFailed(BiometricSourceType.FACE);

        // THEN face help message deferral is reset