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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23622472

Change-Id: Iffaa26b1c7d750f310a90cd7ba2e597548c4528e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hao Dong
2023-06-09 00:00:15 +00:00
committed by Automerger Merge Worker
2 changed files with 70 additions and 3 deletions

View File

@@ -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) {

View File

@@ -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 */,