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

Commit 860e862c authored by Hao Dong's avatar Hao Dong Committed by Android (Google) Code Review
Browse files

Merge "Cancel sensors for lockouts on BP." into udc-d1-dev

parents 9437d3c0 710bd6cb
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 */,