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

Commit ac52529e authored by Hao Dong's avatar Hao Dong Committed by Automerger Merge Worker
Browse files

Merge "Cancel sensors for lockouts on BP." into udc-d1-dev am: 860e862c

parents c892dc23 860e862c
Loading
Loading
Loading
Loading
+34 −3
Original line number Diff line number Diff line
@@ -21,7 +21,10 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE;
import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE;

import static com.android.server.biometrics.BiometricSensor.STATE_CANCELING;
import static com.android.server.biometrics.BiometricSensor.STATE_UNKNOWN;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE;
@@ -439,6 +442,13 @@ public final class AuthSession implements IBinder.DeathRecipient {
            return false;
        }

        final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
                || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
        if (errorLockout) {
            cancelAllSensors(sensor -> Utils.isAtLeastStrength(sensorIdToStrength(sensorId),
                    sensor.getCurrentStrength()));
        }

        mErrorEscrow = error;
        mVendorCodeEscrow = vendorCode;

@@ -477,8 +487,6 @@ public final class AuthSession implements IBinder.DeathRecipient {

            case STATE_AUTH_STARTED:
            case STATE_AUTH_STARTED_UI_SHOWING: {
                final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
                        || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
                if (isAllowDeviceCredential() && errorLockout) {
                    // SystemUI handles transition from biometric to device credential.
                    mState = STATE_SHOWING_DEVICE_CREDENTIAL;
@@ -675,7 +683,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
    }

    private boolean pauseSensorIfSupported(int sensorId) {
        if (sensorIdToModality(sensorId) == TYPE_FACE) {
        boolean isSensorCancelling = sensorIdToState(sensorId) == STATE_CANCELING;
        // If the sensor is locked out, canceling sensors operation is handled in onErrorReceived()
        if (sensorIdToModality(sensorId) == TYPE_FACE && !isSensorCancelling) {
            cancelAllSensors(sensor -> sensor.id == sensorId);
            return true;
        }
@@ -948,6 +958,27 @@ public final class AuthSession implements IBinder.DeathRecipient {
        return TYPE_NONE;
    }

    private @BiometricSensor.SensorState int sensorIdToState(int sensorId) {
        for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
            if (sensorId == sensor.id) {
                return sensor.getSensorState();
            }
        }
        Slog.e(TAG, "Unknown sensor: " + sensorId);
        return STATE_UNKNOWN;
    }

    @BiometricManager.Authenticators.Types
    private int sensorIdToStrength(int sensorId) {
        for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
            if (sensorId == sensor.id) {
                return sensor.getCurrentStrength();
            }
        }
        Slog.e(TAG, "Unknown sensor: " + sensorId);
        return BIOMETRIC_CONVENIENCE;
    }

    private String getAcquiredMessageForSensor(int sensorId, int acquiredInfo, int vendorCode) {
        final @Modality int modality = sensorIdToModality(sensorId);
        switch (modality) {
+36 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGAT
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING;
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -48,6 +49,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.ComponentInfoInternal;
@@ -210,6 +212,40 @@ public class AuthSessionTest {
        }
    }

    @Test
    public void testOnErrorReceived_lockoutError() throws RemoteException {
        setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR);
        setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
                mock(IBiometricAuthenticator.class));
        final AuthSession session = createAuthSession(mSensors,
                false /* checkDevicePolicyManager */,
                Authenticators.BIOMETRIC_STRONG,
                TEST_REQUEST_ID,
                0 /* operationId */,
                0 /* userId */);
        session.goToInitialState();
        for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
            assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
            session.onCookieReceived(
                    session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
        }
        assertTrue(session.allCookiesReceived());
        assertEquals(STATE_AUTH_STARTED, session.getState());

        // Either of strong sensor's lockout should cancel both sensors.
        final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
        session.onErrorReceived(0, cookie1, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 0);
        for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
            assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState());
        }
        assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());

        // If the sensor is STATE_CANCELING, delayed onAuthenticationRejected() shouldn't change the
        // session state to STATE_AUTH_PAUSED.
        session.onAuthenticationRejected(1);
        assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());
    }

    @Test
    public void testCancelReducesAppetiteForCookies() throws Exception {
        setupFace(0 /* id */, false /* confirmationAlwaysRequired */,