diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index c8c122da4ab84..6b5bec99e6741 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -407,6 +407,19 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } + /** + * Flag to decide if authentication should ignore enrollment state. + * Defaults to false (not ignoring enrollment state) + * @param ignoreEnrollmentState + * @return This builder. + * @hide + */ + @NonNull + public Builder setIgnoreEnrollmentState(boolean ignoreEnrollmentState) { + mPromptInfo.setIgnoreEnrollmentState(ignoreEnrollmentState); + return this; + } + /** * Creates a {@link BiometricPrompt}. * diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java index 339c654f4d2f5..e6b762a64384d 100644 --- a/core/java/android/hardware/biometrics/PromptInfo.java +++ b/core/java/android/hardware/biometrics/PromptInfo.java @@ -45,6 +45,7 @@ public class PromptInfo implements Parcelable { private boolean mReceiveSystemEvents; @NonNull private List mAllowedSensorIds = new ArrayList<>(); private boolean mAllowBackgroundAuthentication; + private boolean mIgnoreEnrollmentState; public PromptInfo() { @@ -66,6 +67,7 @@ public class PromptInfo implements Parcelable { mReceiveSystemEvents = in.readBoolean(); mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader()); mAllowBackgroundAuthentication = in.readBoolean(); + mIgnoreEnrollmentState = in.readBoolean(); } public static final Creator CREATOR = new Creator() { @@ -102,6 +104,7 @@ public class PromptInfo implements Parcelable { dest.writeBoolean(mReceiveSystemEvents); dest.writeList(mAllowedSensorIds); dest.writeBoolean(mAllowBackgroundAuthentication); + dest.writeBoolean(mIgnoreEnrollmentState); } public boolean containsTestConfigurations() { @@ -192,6 +195,10 @@ public class PromptInfo implements Parcelable { mAllowBackgroundAuthentication = allow; } + public void setIgnoreEnrollmentState(boolean ignoreEnrollmentState) { + mIgnoreEnrollmentState = ignoreEnrollmentState; + } + // Getters public CharSequence getTitle() { @@ -261,4 +268,8 @@ public class PromptInfo implements Parcelable { public boolean isAllowBackgroundAuthentication() { return mAllowBackgroundAuthentication; } + + public boolean isIgnoreEnrollmentState() { + return mIgnoreEnrollmentState; + } } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index a3d595c230950..fe04e5d35784f 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -531,7 +531,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { - authenticate(crypto, cancel, callback, handler, mContext.getUserId()); + authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, mContext.getUserId(), flags); } /** @@ -541,7 +541,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, int userId) { - authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, userId); + authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, userId, 0 /* flags */); } /** @@ -550,7 +550,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, - @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId) { + @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId, + int flags) { FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED, AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE, @@ -566,6 +567,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing return; } + final boolean ignoreEnrollmentState = flags == 0 ? false : true; + if (mService != null) { try { useHandler(handler); @@ -573,7 +576,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing mCryptoObject = crypto; final long operationId = crypto != null ? crypto.getOpId() : 0; final long authId = mService.authenticate(mToken, operationId, sensorId, userId, - mServiceReceiver, mContext.getOpPackageName()); + mServiceReceiver, mContext.getOpPackageName(), ignoreEnrollmentState); if (cancel != null) { cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index de94b2fbb5b59..ba1dc6da62a64 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -52,7 +52,8 @@ interface IFingerprintService { // permission. This is effectively deprecated, since it only comes through FingerprintManager // now. A requestId is returned that can be used to cancel this operation. long authenticate(IBinder token, long operationId, int sensorId, int userId, - IFingerprintServiceReceiver receiver, String opPackageName); + IFingerprintServiceReceiver receiver, String opPackageName, + boolean shouldIgnoreEnrollmentState); // Uses the fingerprint hardware to detect for the presence of a finger, without giving details // about accept/reject/lockout. A requestId is returned that can be used to cancel this diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 85bc8f7c70a2b..106e2437c3c15 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2407,7 +2407,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } else { mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal, mFingerprintAuthenticationCallback, null /* handler */, - FingerprintManager.SENSOR_ID_ANY, userId); + FingerprintManager.SENSOR_ID_ANY, userId, 0 /* flags */); } setFingerprintRunningState(BIOMETRIC_STATE_RUNNING); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 1ee6f70ec7fc6..ff5960bc33ce3 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -472,7 +472,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); mTestableLooper.processAllMessages(); - verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt()); + verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), + anyInt()); verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt()); } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index e0775d48b42fd..f42870b4b7349 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -1381,7 +1381,8 @@ public class BiometricService extends SystemService { Slog.d(TAG, "handleAuthenticate: modality(" + preAuthStatus.first + "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo - + " requestId: " + requestId); + + " requestId: " + requestId + " promptInfo.isIgnoreEnrollmentState: " + + promptInfo.isIgnoreEnrollmentState()); if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) { // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index cd0ff10168bbf..a5a3542f49c7a 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -83,6 +83,7 @@ class PreAuthInfo { final List> ineligibleSensors; final boolean credentialAvailable; final boolean confirmationRequested; + final boolean ignoreEnrollmentState; static PreAuthInfo create(ITrustManager trustManager, DevicePolicyManager devicePolicyManager, @@ -114,7 +115,8 @@ class PreAuthInfo { @AuthenticatorStatus int status = getStatusForBiometricAuthenticator( devicePolicyManager, settingObserver, sensor, userId, opPackageName, checkDevicePolicyManager, requestedStrength, - promptInfo.getAllowedSensorIds()); + promptInfo.getAllowedSensorIds(), + promptInfo.isIgnoreEnrollmentState()); Slog.d(TAG, "Package: " + opPackageName + " Sensor ID: " + sensor.id @@ -130,7 +132,8 @@ class PreAuthInfo { } return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, - eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested); + eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested, + promptInfo.isIgnoreEnrollmentState()); } /** @@ -145,7 +148,8 @@ class PreAuthInfo { BiometricService.SettingObserver settingObserver, BiometricSensor sensor, int userId, String opPackageName, boolean checkDevicePolicyManager, int requestedStrength, - @NonNull List requestedSensorIds) { + @NonNull List requestedSensorIds, + boolean ignoreEnrollmentState) { if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) { return BIOMETRIC_NO_HARDWARE; @@ -167,7 +171,8 @@ class PreAuthInfo { return BIOMETRIC_HARDWARE_NOT_DETECTED; } - if (!sensor.impl.hasEnrolledTemplates(userId, opPackageName)) { + if (!sensor.impl.hasEnrolledTemplates(userId, opPackageName) + && !ignoreEnrollmentState) { return BIOMETRIC_NOT_ENROLLED; } @@ -238,7 +243,7 @@ class PreAuthInfo { private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List eligibleSensors, List> ineligibleSensors, boolean credentialAvailable, - boolean confirmationRequested) { + boolean confirmationRequested, boolean ignoreEnrollmentState) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; this.credentialRequested = credentialRequested; @@ -247,6 +252,7 @@ class PreAuthInfo { this.ineligibleSensors = ineligibleSensors; this.credentialAvailable = credentialAvailable; this.confirmationRequested = confirmationRequested; + this.ignoreEnrollmentState = ignoreEnrollmentState; } private Pair calculateErrorByPriority() { diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index f35bb7ffd26bf..c5d33ed7400b8 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -281,7 +281,7 @@ public class FingerprintService extends SystemService { @Override // Binder call public long authenticate(final IBinder token, final long operationId, final int sensorId, final int userId, final IFingerprintServiceReceiver receiver, - final String opPackageName) { + final String opPackageName, boolean ignoreEnrollmentState) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final int callingUserId = UserHandle.getCallingUserId(); @@ -333,7 +333,8 @@ public class FingerprintService extends SystemService { && sensorProps != null && sensorProps.isAnyUdfpsType()) { identity = Binder.clearCallingIdentity(); try { - return authenticateWithPrompt(operationId, sensorProps, userId, receiver); + return authenticateWithPrompt(operationId, sensorProps, userId, receiver, + ignoreEnrollmentState); } finally { Binder.restoreCallingIdentity(identity); } @@ -347,7 +348,8 @@ public class FingerprintService extends SystemService { final long operationId, @NonNull final FingerprintSensorPropertiesInternal props, final int userId, - final IFingerprintServiceReceiver receiver) { + final IFingerprintServiceReceiver receiver, + boolean ignoreEnrollmentState) { final Context context = getUiContext(); final Executor executor = context.getMainExecutor(); @@ -368,6 +370,7 @@ public class FingerprintService extends SystemService { }) .setAllowedSensorIds(new ArrayList<>( Collections.singletonList(props.sensorId))) + .setIgnoreEnrollmentState(ignoreEnrollmentState) .build(); final BiometricPrompt.AuthenticationCallback promptCallback =