summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl3
-rw-r--r--core/java/android/hardware/face/FaceManager.java52
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl22
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java33
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java24
-rw-r--r--services/core/java/com/android/server/biometrics/PreAuthInfo.java39
-rw-r--r--services/core/java/com/android/server/biometrics/Utils.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java22
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java40
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java116
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java49
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/EnrollClient.java19
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java24
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java54
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java20
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/RemovalClient.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java18
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java33
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java27
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java84
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceInternalCleanupClient.java35
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java15
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java15
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java78
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceRevokeChallengeClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java218
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java94
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintGenerateChallengeClient.java14
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalCleanupClient.java34
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRevokeChallengeClient.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java126
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java84
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricServiceBaseTest.java7
46 files changed, 915 insertions, 687 deletions
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
index 4a46972cd200..8eb22dabbf3c 100644
--- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -50,6 +50,9 @@ interface IBiometricAuthenticator {
// Determine if a user has at least one enrolled face
boolean hasEnrolledTemplates(int userId, String opPackageName);
+ // Return the LockoutTracker status for the specified user
+ int getLockoutModeForUser(int userId);
+
// Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
void resetLockout(int userId, in byte [] hardwareAuthToken);
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 9876de11a2bb..58cb1e135350 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -165,7 +165,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*
* @param crypto object associated with the call or null if none required.
* @param cancel an object that can be used to cancel authentication
- * @param flags optional flags; should be 0
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
* @throws IllegalArgumentException if the crypto operation is not supported or is not backed
@@ -177,8 +176,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
- authenticate(crypto, cancel, flags, callback, handler, mContext.getUserId());
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
+ authenticate(crypto, cancel, callback, handler, mContext.getUserId());
}
/**
@@ -202,7 +201,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*
* @param crypto object associated with the call or null if none required.
* @param cancel an object that can be used to cancel authentication
- * @param flags optional flags; should be 0
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
* @param userId userId to authenticate for
@@ -214,8 +212,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler,
- int userId) {
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -237,7 +234,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
mService.authenticate(mToken, operationId, userId, mServiceReceiver,
- flags, mContext.getOpPackageName());
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception while authenticating: ", e);
if (callback != null) {
@@ -260,9 +257,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @see FaceManager#enroll(int, byte[], CancellationSignal, EnrollmentCallback, int[], Surface)
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void enroll(int userId, byte[] token, CancellationSignal cancel,
+ public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures) {
- enroll(userId, token, cancel, callback, disabledFeatures, null /* surface */);
+ enroll(userId, hardwareAuthToken, cancel, callback, disabledFeatures, null /* surface */);
}
/**
@@ -277,7 +274,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @param token a unique token provided by a recent creation or verification of device
* credentials (e.g. pin, pattern or password).
* @param cancel an object that can be used to cancel enrollment
- * @param flags optional flags
* @param userId the user to whom this face will belong to
* @param callback an object to receive enrollment events
* @param surface optional camera preview surface for a single-camera device. Must be null if
@@ -285,7 +281,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void enroll(int userId, byte[] token, CancellationSignal cancel,
+ public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface surface) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -304,7 +300,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enroll");
- mService.enroll(userId, mToken, token, mServiceReceiver,
+ mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver,
mContext.getOpPackageName(), disabledFeatures, surface);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
@@ -329,15 +325,15 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
- * @param token a unique token provided by a recent creation or verification of device
- * credentials (e.g. pin, pattern or password).
+ * @param hardwareAuthToken a unique token provided by a recent creation or verification of
+ * device credentials (e.g. pin, pattern or password).
* @param cancel an object that can be used to cancel enrollment
* @param userId the user to whom this face will belong to
* @param callback an object to receive enrollment events
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void enrollRemotely(int userId, byte[] token, CancellationSignal cancel,
+ public void enrollRemotely(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -356,7 +352,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enrollRemotely");
- mService.enrollRemotely(userId, mToken, token, mServiceReceiver,
+ mService.enrollRemotely(userId, mToken, hardwareAuthToken, mServiceReceiver,
mContext.getOpPackageName(), disabledFeatures);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enrollRemotely: ", e);
@@ -444,13 +440,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void setFeature(int userId, int feature, boolean enabled, byte[] token,
+ public void setFeature(int userId, int feature, boolean enabled, byte[] hardwareAuthToken,
SetFeatureCallback callback) {
if (mService != null) {
try {
mSetFeatureCallback = callback;
- mService.setFeature(userId, feature, enabled, token, mServiceReceiver,
- mContext.getOpPackageName());
+ mService.setFeature(mToken, userId, feature, enabled, hardwareAuthToken,
+ mServiceReceiver, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -465,22 +461,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
if (mService != null) {
try {
mGetFeatureCallback = callback;
- mService.getFeature(userId, feature, mServiceReceiver, mContext.getOpPackageName());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Pokes the the driver to have it start looking for faces again.
- * @hide
- */
- @RequiresPermission(MANAGE_BIOMETRIC)
- public void userActivity() {
- if (mService != null) {
- try {
- mService.userActivity();
+ mService.getFeature(mToken, userId, feature, mServiceReceiver,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 8dbaf2115fe5..f4122fe7c625 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -28,8 +28,8 @@ import android.view.Surface;
*/
interface IFaceService {
// Authenticate the given sessionId with a face
- void authenticate(IBinder token, long operationId, int userid,
- IFaceServiceReceiver receiver, int flags, String opPackageName);
+ void authenticate(IBinder token, long operationId, int userid, IFaceServiceReceiver receiver,
+ String opPackageName);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -51,11 +51,11 @@ interface IFaceService {
int callingUid, int callingPid, int callingUserId);
// Start face enrollment
- void enroll(int userId, IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
+ void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
String opPackageName, in int [] disabledFeatures, in Surface surface);
// Start remote face enrollment
- void enrollRemotely(int userId, IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
+ void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
String opPackageName, in int [] disabledFeatures);
// Cancel enrollment in progress
@@ -80,21 +80,23 @@ interface IFaceService {
// Determine if a user has at least one enrolled face
boolean hasEnrolledFaces(int userId, String opPackageName);
+ // Return the LockoutTracker status for the specified user
+ int getLockoutModeForUser(int userId);
+
// Gets the authenticator ID for face
long getAuthenticatorId(int callingUserId);
// Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
- void resetLockout(int userId, in byte [] token);
+ void resetLockout(int userId, in byte [] hardwareAuthToken);
// Add a callback which gets notified when the face lockout period expired.
void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback);
- void setFeature(int userId, int feature, boolean enabled, in byte [] token,
- IFaceServiceReceiver receiver, String opPackageName);
+ void setFeature(IBinder token, int userId, int feature, boolean enabled,
+ in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, String opPackageName);
- void getFeature(int userId, int feature, IFaceServiceReceiver receiver, String opPackageName);
-
- void userActivity();
+ void getFeature(IBinder token, int userId, int feature, IFaceServiceReceiver receiver,
+ String opPackageName);
// Give FaceService its ID. See AuthService.java
void initializeConfiguration(int sensorId);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 4787984cdf41..abe63d65102c 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -277,7 +277,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Callback structure provided to {@link FingerprintManager#enroll(byte[], CancellationSignal,
- * int, int, EnrollmentCallback)} must provide an implementation of this for listening to
+ * int, EnrollmentCallback)} must provide an implementation of this for listening to
* fingerprint events.
*
* @hide
@@ -387,7 +387,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, flags, callback, handler, mContext.getUserId());
+ authenticate(crypto, cancel, callback, handler, mContext.getUserId());
}
/**
@@ -403,18 +403,18 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
/**
- * Defaults to {@link FingerprintManager#authenticate(CryptoObject, CancellationSignal, int,
+ * Defaults to {@link FingerprintManager#authenticate(CryptoObject, CancellationSignal,
* AuthenticationCallback, Handler, int, Surface)} with {@code surface} set to null.
*
- * @see FingerprintManager#authenticate(CryptoObject, CancellationSignal, int,
+ * @see FingerprintManager#authenticate(CryptoObject, CancellationSignal,
* AuthenticationCallback, Handler, int, Surface)
*
* @hide
*/
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
- authenticate(crypto, cancel, flags, callback, handler, userId, null /* surface */);
+ @NonNull AuthenticationCallback callback, Handler handler, int userId) {
+ authenticate(crypto, cancel, callback, handler, userId, null /* surface */);
}
/**
@@ -428,7 +428,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, Handler handler, int userId,
+ @NonNull AuthenticationCallback callback, Handler handler, int userId,
@Nullable Surface surface) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
@@ -449,7 +449,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
- mService.authenticate(mToken, operationId, userId, mServiceReceiver, flags,
+ mService.authenticate(mToken, operationId, userId, mServiceReceiver,
mContext.getOpPackageName(), surface);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception while authenticating: ", e);
@@ -463,18 +463,18 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
/**
- * Defaults to {@link FingerprintManager#enroll(byte[], CancellationSignal, int, int,
+ * Defaults to {@link FingerprintManager#enroll(byte[], CancellationSignal, int,
* EnrollmentCallback, Surface)} with {@code surface} set to null.
*
- * @see FingerprintManager#enroll(byte[], CancellationSignal, int, int, EnrollmentCallback,
+ * @see FingerprintManager#enroll(byte[], CancellationSignal, int, EnrollmentCallback,
* Surface)
*
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
- public void enroll(byte [] token, CancellationSignal cancel, int flags,
- int userId, EnrollmentCallback callback) {
- enroll(token, cancel, flags, userId, callback, null /* surface */);
+ public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId,
+ EnrollmentCallback callback) {
+ enroll(hardwareAuthToken, cancel, userId, callback, null /* surface */);
}
/**
@@ -488,14 +488,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
* @param token a unique token provided by a recent creation or verification of device
* credentials (e.g. pin, pattern or password).
* @param cancel an object that can be used to cancel enrollment
- * @param flags optional flags
* @param userId the user to whom this fingerprint will belong to
* @param callback an object to receive enrollment events
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
- public void enroll(byte [] token, CancellationSignal cancel, int flags,
- int userId, EnrollmentCallback callback, @Nullable Surface surface) {
+ public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId,
+ EnrollmentCallback callback, @Nullable Surface surface) {
if (userId == UserHandle.USER_CURRENT) {
userId = getCurrentUserId();
}
@@ -515,7 +514,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
if (mService != null) {
try {
mEnrollmentCallback = callback;
- mService.enroll(mToken, token, userId, mServiceReceiver, flags,
+ mService.enroll(mToken, hardwareAuthToken, userId, mServiceReceiver,
mContext.getOpPackageName(), surface);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 7e251fd24e94..5adba7595ef9 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -33,8 +33,7 @@ interface IFingerprintService {
// USE_FINGERPRINT/USE_BIOMETRIC permission. This is effectively deprecated, since it only comes
// through FingerprintManager now.
void authenticate(IBinder token, long operationId, int userId,
- IFingerprintServiceReceiver receiver, int flags, String opPackageName,
- in Surface surface);
+ IFingerprintServiceReceiver receiver, String opPackageName, in Surface surface);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -57,8 +56,8 @@ interface IFingerprintService {
int callingUid, int callingPid, int callingUserId);
// Start fingerprint enrollment
- void enroll(IBinder token, in byte [] cryptoToken, int userId, IFingerprintServiceReceiver receiver,
- int flags, String opPackageName, in Surface surface);
+ void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver,
+ String opPackageName, in Surface surface);
// Cancel enrollment in progress
void cancelEnrollment(IBinder token);
@@ -85,11 +84,14 @@ interface IFingerprintService {
// Determine if a user has at least one enrolled fingerprint
boolean hasEnrolledFingerprints(int userId, String opPackageName);
+ // Return the LockoutTracker status for the specified user
+ int getLockoutModeForUser(int userId);
+
// Gets the authenticator ID for fingerprint
long getAuthenticatorId(int callingUserId);
// Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
- void resetLockout(int userId, in byte [] cryptoToken);
+ void resetLockout(int userId, in byte [] hardwareAuthToken);
// Add a callback which gets notified when the fingerprint lockout period expired.
void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b39eaf3f3324..e45cfe27b33f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2047,8 +2047,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
- mFpm.authenticate(null, mFingerprintCancelSignal, 0, mFingerprintAuthenticationCallback,
- null, userId);
+ mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
+ mFingerprintAuthenticationCallback, null /* handler */, userId);
setFingerprintRunningState(BIOMETRIC_STATE_RUNNING);
}
}
@@ -2065,8 +2065,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mFaceCancelSignal.cancel();
}
mFaceCancelSignal = new CancellationSignal();
- mFaceManager.authenticate(null, mFaceCancelSignal, 0,
- mFaceAuthenticationCallback, null, userId);
+ mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
+ mFaceAuthenticationCallback, null /* handler */, userId);
setFaceRunningState(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 9e056cf16ec7..c36bb0472240 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -423,7 +423,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFaceManager).isHardwareDetected();
verify(mFaceManager).hasEnrolledTemplates(anyInt());
}
@@ -433,7 +433,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -443,7 +443,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -455,7 +455,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -478,14 +478,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp();
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
// Stop scanning when bouncer becomes visible
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true /* showingBouncer */);
mTestableLooper.processAllMessages();
clearInvocations(mFaceManager);
mKeyguardUpdateMonitor.requestFaceAuth();
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -493,7 +493,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardOccluded(true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -505,7 +505,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -515,7 +515,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -526,7 +526,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -537,7 +537,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);
mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
- verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -549,7 +549,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any());
}
@Test
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index 7a4f70a72252..08a617134221 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -32,6 +32,9 @@ import android.os.RemoteException;
import android.util.Pair;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.biometrics.sensors.LockoutTracker;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -54,6 +57,8 @@ class PreAuthInfo {
static final int BIOMETRIC_NOT_ENROLLED = 7;
static final int BIOMETRIC_NOT_ENABLED_FOR_APPS = 8;
static final int CREDENTIAL_NOT_ENROLLED = 9;
+ static final int BIOMETRIC_LOCKOUT_TIMED = 10;
+ static final int BIOMETRIC_LOCKOUT_PERMANENT = 11;
@IntDef({AUTHENTICATOR_OK,
BIOMETRIC_NO_HARDWARE,
BIOMETRIC_DISABLED_BY_DEVICE_POLICY,
@@ -62,7 +67,9 @@ class PreAuthInfo {
BIOMETRIC_HARDWARE_NOT_DETECTED,
BIOMETRIC_NOT_ENROLLED,
BIOMETRIC_NOT_ENABLED_FOR_APPS,
- CREDENTIAL_NOT_ENROLLED})
+ CREDENTIAL_NOT_ENROLLED,
+ BIOMETRIC_LOCKOUT_TIMED,
+ BIOMETRIC_LOCKOUT_PERMANENT})
@Retention(RetentionPolicy.SOURCE)
@interface AuthenticatorStatus {}
@@ -73,7 +80,7 @@ class PreAuthInfo {
// Sensors that can be used for this request (e.g. strong enough, enrolled, enabled).
final List<BiometricSensor> eligibleSensors;
// Sensors that cannot be used for this request. Pair<BiometricSensor, AuthenticatorStatus>
- private final List<Pair<BiometricSensor, Integer>> mIneligibleSensors;
+ final List<Pair<BiometricSensor, Integer>> ineligibleSensors;
final boolean credentialAvailable;
final boolean confirmationRequested;
@@ -156,6 +163,14 @@ class PreAuthInfo {
if (!sensor.impl.hasEnrolledTemplates(userId, opPackageName)) {
return BIOMETRIC_NOT_ENROLLED;
}
+
+ final @LockoutTracker.LockoutMode int lockoutMode =
+ sensor.impl.getLockoutModeForUser(userId);
+ if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) {
+ return BIOMETRIC_LOCKOUT_TIMED;
+ } else if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) {
+ return BIOMETRIC_LOCKOUT_PERMANENT;
+ }
} catch (RemoteException e) {
return BIOMETRIC_HARDWARE_NOT_DETECTED;
}
@@ -232,7 +247,7 @@ class PreAuthInfo {
this.credentialRequested = credentialRequested;
this.eligibleSensors = eligibleSensors;
- this.mIneligibleSensors = ineligibleSensors;
+ this.ineligibleSensors = ineligibleSensors;
this.credentialAvailable = credentialAvailable;
this.confirmationRequested = confirmationRequested;
}
@@ -258,9 +273,9 @@ class PreAuthInfo {
}
} else {
// Pick the first sensor error if it exists
- if (!mIneligibleSensors.isEmpty()) {
- modality |= mIneligibleSensors.get(0).first.modality;
- status = mIneligibleSensors.get(0).second;
+ if (!ineligibleSensors.isEmpty()) {
+ modality |= ineligibleSensors.get(0).first.modality;
+ status = ineligibleSensors.get(0).second;
} else {
modality |= TYPE_CREDENTIAL;
status = CREDENTIAL_NOT_ENROLLED;
@@ -274,9 +289,9 @@ class PreAuthInfo {
}
} else {
// Pick the first sensor error if it exists
- if (!mIneligibleSensors.isEmpty()) {
- modality |= mIneligibleSensors.get(0).first.modality;
- status = mIneligibleSensors.get(0).second;
+ if (!ineligibleSensors.isEmpty()) {
+ modality |= ineligibleSensors.get(0).first.modality;
+ status = ineligibleSensors.get(0).second;
} else {
modality |= TYPE_NONE;
status = BIOMETRIC_NO_HARDWARE;
@@ -293,7 +308,7 @@ class PreAuthInfo {
}
Slog.d(TAG, "getCanAuthenticateInternal Modality: " + modality
- + " AuthenticatorSatus: " + status);
+ + " AuthenticatorStatus: " + status);
return new Pair<>(modality, status);
}
@@ -325,6 +340,8 @@ class PreAuthInfo {
case BIOMETRIC_HARDWARE_NOT_DETECTED:
case BIOMETRIC_NOT_ENROLLED:
case CREDENTIAL_NOT_ENROLLED:
+ case BIOMETRIC_LOCKOUT_TIMED:
+ case BIOMETRIC_LOCKOUT_PERMANENT:
break;
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
@@ -379,7 +396,7 @@ class PreAuthInfo {
string.append("}");
string.append("\nIneligible:{");
- for (Pair<BiometricSensor, Integer> ineligible : mIneligibleSensors) {
+ for (Pair<BiometricSensor, Integer> ineligible : ineligibleSensors) {
string.append(ineligible.first).append(":").append(ineligible.second).append(" ");
}
string.append("}");
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 0d4d5893e9b1..6be457474630 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -23,6 +23,8 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_DISABLED_BY_DE
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_HARDWARE_NOT_DETECTED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE;
+import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_PERMANENT;
+import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_TIMED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENABLED_FOR_APPS;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE;
@@ -235,6 +237,10 @@ public class Utils {
case BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
break;
+ case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
+ case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
+ biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS;
+ break;
default:
Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
@@ -289,6 +295,12 @@ public class Utils {
case CREDENTIAL_NOT_ENROLLED:
return BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL;
+ case BIOMETRIC_LOCKOUT_TIMED:
+ return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
+
+ case BIOMETRIC_LOCKOUT_PERMANENT:
+ return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
case BIOMETRIC_HARDWARE_NOT_DETECTED:
case BIOMETRIC_NOT_ENABLED_FOR_APPS:
diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
index 92fc33e86a6f..466465e0a3f5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -32,7 +32,7 @@ import android.util.Slog;
* Abstract {@link ClientMonitor} subclass that operations eligible/interested in acquisition
* messages should extend.
*/
-public abstract class AcquisitionClient extends ClientMonitor
+public abstract class AcquisitionClient<T> extends ClientMonitor<T>
implements ErrorConsumer, Cancellable {
private static final String TAG = "Biometrics/AcquisitionClient";
@@ -47,18 +47,28 @@ public abstract class AcquisitionClient extends ClientMonitor
private final VibrationEffect mSuccessVibrationEffect;
private final VibrationEffect mErrorVibrationEffect;
- AcquisitionClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- boolean restricted, @NonNull String owner, int cookie, int sensorId, int statsModality,
+ AcquisitionClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull String owner, int cookie, int sensorId, int statsModality,
int statsAction, int statsClient) {
- super(finishCallback, context, token, listener, userId, restricted, owner, cookie, sensorId,
- statsModality, statsAction, statsClient);
+ super(context, token, listener, userId, owner, cookie, sensorId, statsModality, statsAction,
+ statsClient);
mPowerManager = context.getSystemService(PowerManager.class);
mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
}
@Override
+ public void unableToStart() {
+ try {
+ getListener().onError(getSensorId(), getCookie(),
+ BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send error", e);
+ }
+ }
+
+ @Override
public void onError(int errorCode, int vendorCode) {
logOnError(getContext(), errorCode, vendorCode, getTargetUserId());
try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index e4e7715daed1..a9cefbaf8ac0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -22,6 +22,7 @@ import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
@@ -33,7 +34,7 @@ import java.util.ArrayList;
/**
* A class to keep track of the authentication state for a given client.
*/
-public abstract class AuthenticationClient extends AcquisitionClient {
+public abstract class AuthenticationClient<T> extends AcquisitionClient<T> {
private static final String TAG = "Biometrics/AuthenticationClient";
@@ -42,26 +43,29 @@ public abstract class AuthenticationClient extends AcquisitionClient {
private final IActivityTaskManager mActivityTaskManager;
private final TaskStackListener mTaskStackListener;
private final LockoutTracker mLockoutTracker;
+ private final boolean mIsRestricted;
protected final long mOperationId;
private long mStartTimeMs;
private boolean mAlreadyCancelled;
- public AuthenticationClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- int targetUserId, long operationId, boolean restricted, @NonNull String owner,
- int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
- int statsModality, int statsClient, @NonNull TaskStackListener taskStackListener,
- @NonNull LockoutTracker lockoutTracker) {
- super(finishCallback, context, token, listener, targetUserId, restricted, owner, cookie,
- sensorId, statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
+ protected boolean mAuthAttempted;
+
+ public AuthenticationClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
+ boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
+ int sensorId, boolean isStrongBiometric, int statsModality, int statsClient,
+ @NonNull TaskStackListener taskStackListener, @NonNull LockoutTracker lockoutTracker) {
+ super(context, token, listener, targetUserId, owner, cookie, sensorId,
+ statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;
mActivityTaskManager = ActivityTaskManager.getService();
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
+ mIsRestricted = restricted;
}
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
@@ -144,7 +148,7 @@ public abstract class AuthenticationClient extends AcquisitionClient {
// Explicitly have if/else here to make it super obvious in case the code is
// touched in the future.
- if (!getIsRestricted()) {
+ if (!mIsRestricted) {
listener.onAuthenticationSucceeded(getSensorId(), identifier, byteToken,
getTargetUserId(), mIsStrongBiometric);
} else {
@@ -183,7 +187,20 @@ public abstract class AuthenticationClient extends AcquisitionClient {
* Start authentication
*/
@Override
- public void start() {
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
+ final @LockoutTracker.LockoutMode int lockoutMode =
+ mLockoutTracker.getLockoutModeForUser(getTargetUserId());
+ if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
+ Slog.v(TAG, "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
+ int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
+ ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
+ : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+ onError(errorCode, 0 /* vendorCode */);
+ return;
+ }
+
try {
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
} catch (RemoteException e) {
@@ -193,6 +210,7 @@ public abstract class AuthenticationClient extends AcquisitionClient {
if (DEBUG) Slog.w(TAG, "Requesting auth for " + getOwnerString());
mStartTimeMs = System.currentTimeMillis();
+ mAuthAttempted = true;
startHalOperation();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java
index 4c24d1a61e45..a784b4b57eea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java
@@ -71,7 +71,7 @@ import java.util.Map;
*
* @hide
*/
-public abstract class BiometricServiceBase extends SystemService
+public abstract class BiometricServiceBase<T> extends SystemService
implements IHwBinder.DeathRecipient {
protected static final boolean DEBUG = true;
@@ -83,7 +83,6 @@ public abstract class BiometricServiceBase extends SystemService
private final String mKeyguardPackage;
protected final IActivityTaskManager mActivityTaskManager;
private final PowerManager mPowerManager;
- private final UserManager mUserManager;
protected final BiometricTaskStackListener mTaskStackListener =
new BiometricTaskStackListener();
private final ResetClientStateRunnable mResetClientState = new ResetClientStateRunnable();
@@ -120,7 +119,7 @@ public abstract class BiometricServiceBase extends SystemService
if (!hasEnrolledBiometrics(userId)) {
Slog.d(getTag(), "Last biometric removed for user: " + userId
+ ", updating active group");
- updateActiveGroup(userId, null);
+ updateActiveGroup(userId);
}
}
@@ -128,8 +127,8 @@ public abstract class BiometricServiceBase extends SystemService
};
private IBiometricService mBiometricService;
- private ClientMonitor mCurrentClient;
- private ClientMonitor mPendingClient;
+ private ClientMonitor<T> mCurrentClient;
+ private ClientMonitor<T> mPendingClient;
private PerformanceTracker mPerformanceTracker;
private int mSensorId;
protected int mCurrentUserId = UserHandle.USER_NULL;
@@ -140,6 +139,11 @@ public abstract class BiometricServiceBase extends SystemService
protected abstract String getTag();
/**
+ * @return a fresh reference to the biometric HAL
+ */
+ protected abstract T getDaemon();
+
+ /**
* @return the biometric utilities for a specific implementation.
*/
protected abstract BiometricUtils getBiometricUtils();
@@ -153,9 +157,8 @@ public abstract class BiometricServiceBase extends SystemService
/**
* Notifies the HAL that the user has changed.
* @param userId
- * @param clientPackage
*/
- protected abstract void updateActiveGroup(int userId, String clientPackage);
+ protected abstract void updateActiveGroup(int userId);
/**
* @param userId
@@ -253,7 +256,7 @@ public abstract class BiometricServiceBase extends SystemService
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
statsModality(), BiometricsProtoEnums.ISSUE_CANCEL_TIMED_OUT);
- ClientMonitor newClient = mPendingClient;
+ ClientMonitor<T> newClient = mPendingClient;
mCurrentClient = null;
mPendingClient = null;
startClient(newClient, false);
@@ -339,7 +342,6 @@ public abstract class BiometricServiceBase extends SystemService
mAppOps = context.getSystemService(AppOpsManager.class);
mActivityTaskManager = ActivityTaskManager.getService();
mPowerManager = mContext.getSystemService(PowerManager.class);
- mUserManager = UserManager.get(mContext);
mPerformanceTracker = PerformanceTracker.getInstanceForSensorId(getSensorId());
}
@@ -456,7 +458,7 @@ public abstract class BiometricServiceBase extends SystemService
// When enrollment finishes, update this group's authenticator id, as the HAL has
// already generated a new authenticator id when the new biometric is enrolled.
if (identifier instanceof Fingerprint) {
- updateActiveGroup(((Fingerprint)identifier).getGroupId(), null);
+ updateActiveGroup(((Fingerprint)identifier).getGroupId());
}
}
}
@@ -520,7 +522,7 @@ public abstract class BiometricServiceBase extends SystemService
* Calls from the Manager. These are still on the calling binder's thread.
*/
- protected void enrollInternal(EnrollClient client, int userId) {
+ protected void enrollInternal(EnrollClient<T> client, int userId) {
if (hasReachedEnrollmentLimit(userId)) {
return;
}
@@ -546,26 +548,26 @@ public abstract class BiometricServiceBase extends SystemService
});
}
- protected void generateChallengeInternal(GenerateChallengeClient client) {
+ protected void generateChallengeInternal(GenerateChallengeClient<T> client) {
mHandler.post(() -> {
startClient(client, true /* initiatedByClient */);
});
}
- protected void revokeChallengeInternal(RevokeChallengeClient client) {
+ protected void revokeChallengeInternal(RevokeChallengeClient<T> client) {
mHandler.post(() -> {
startClient(client, true /* initiatedByClient */);
});
}
- protected void authenticateInternal(AuthenticationClient client, String opPackageName) {
+ protected void authenticateInternal(AuthenticationClient<T> client, String opPackageName) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
authenticateInternal(client, opPackageName, callingUid, callingPid, callingUserId);
}
- protected void authenticateInternal(AuthenticationClient client,
+ protected void authenticateInternal(AuthenticationClient<T> client,
String opPackageName, int callingUid, int callingPid, int callingUserId) {
if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
callingUserId)) {
@@ -622,13 +624,13 @@ public abstract class BiometricServiceBase extends SystemService
});
}
- protected void removeInternal(RemovalClient client) {
+ protected void removeInternal(RemovalClient<T> client) {
mHandler.post(() -> {
startClient(client, true /* initiatedByClient */);
});
}
- protected void cleanupInternal(InternalCleanupClient client) {
+ protected void cleanupInternal(InternalCleanupClient<T> client) {
mHandler.post(() -> {
if (DEBUG) {
Slog.v(getTag(), "Cleaning up templates for user("
@@ -639,18 +641,9 @@ public abstract class BiometricServiceBase extends SystemService
}
// Should be done on a handler thread - not on the Binder's thread.
- private void startAuthentication(AuthenticationClient client, String opPackageName) {
+ private void startAuthentication(AuthenticationClient<T> client, String opPackageName) {
if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")");
- @LockoutTracker.LockoutMode int lockoutMode = getLockoutMode(client.getTargetUserId());
- if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
- Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
- int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
- ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
- : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
- client.onError(errorCode, 0 /* vendorCode */);
- return;
- }
startClient(client, true /* initiatedByClient */);
}
@@ -751,7 +744,7 @@ public abstract class BiometricServiceBase extends SystemService
* @param initiatedByClient true for authenticate, remove and enroll
*/
@VisibleForTesting
- void startClient(ClientMonitor newClient, boolean initiatedByClient) {
+ protected void startClient(ClientMonitor<T> newClient, boolean initiatedByClient) {
ClientMonitor currentClient = mCurrentClient;
if (currentClient != null) {
if (DEBUG) Slog.v(getTag(), "request stop current client " +
@@ -811,7 +804,7 @@ public abstract class BiometricServiceBase extends SystemService
return;
}
- if (DEBUG) Slog.v(getTag(), "starting client "
+ if (DEBUG) Slog.v(getTag(), "Starting client "
+ mCurrentClient.getClass().getSimpleName()
+ "(" + mCurrentClient.getOwnerString() + ")"
+ " targetUserId: " + mCurrentClient.getTargetUserId()
@@ -823,7 +816,16 @@ public abstract class BiometricServiceBase extends SystemService
return;
}
- mCurrentClient.start();
+ final T daemon = getDaemon();
+ if (daemon == null) {
+ Slog.e(getTag(), "Daemon null, unable to start: "
+ + mCurrentClient.getClass().getSimpleName());
+ mCurrentClient.unableToStart();
+ mCurrentClient = null;
+ return;
+ }
+
+ mCurrentClient.start(daemon, mClientFinishCallback);
notifyClientActiveCallbacks(true);
}
@@ -855,9 +857,9 @@ public abstract class BiometricServiceBase extends SystemService
long t = System.currentTimeMillis();
mAuthenticatorIds.clear();
for (UserInfo user : UserManager.get(getContext()).getUsers(true /* excludeDying */)) {
- int userId = getUserOrWorkProfileId(null, user.id);
+ int userId = user.id;
if (!mAuthenticatorIds.containsKey(userId)) {
- updateActiveGroup(userId, null);
+ updateActiveGroup(userId);
}
}
@@ -867,17 +869,6 @@ public abstract class BiometricServiceBase extends SystemService
}
}
- /**
- * @param clientPackage the package of the caller
- * @return the profile id
- */
- protected int getUserOrWorkProfileId(String clientPackage, int userId) {
- if (!isKeyguard(clientPackage) && isWorkProfile(userId)) {
- return userId;
- }
- return getEffectiveUserId(userId);
- }
-
protected boolean isRestricted() {
// Only give privileged apps (like Settings) access to biometric info
final boolean restricted = !hasPermission(getManageBiometricPermission());
@@ -920,8 +911,7 @@ public abstract class BiometricServiceBase extends SystemService
* @return authenticator id for the calling user
*/
protected long getAuthenticatorId(int callingUserId) {
- final int userId = getUserOrWorkProfileId(null /* clientPackage */, callingUserId);
- return mAuthenticatorIds.getOrDefault(userId, 0L);
+ return mAuthenticatorIds.getOrDefault(callingUserId, 0L);
}
/**
@@ -937,7 +927,7 @@ public abstract class BiometricServiceBase extends SystemService
if (getCurrentClient() instanceof InternalCleanupClient) {
Slog.w(getTag(), "User switched while performing cleanup");
}
- updateActiveGroup(userId, null);
+ updateActiveGroup(userId);
doTemplateCleanupForUser(userId);
}
@@ -947,41 +937,12 @@ public abstract class BiometricServiceBase extends SystemService
}
}
- /**
- * @param userId
- * @return true if this is a work profile
- */
- private boolean isWorkProfile(int userId) {
- UserInfo userInfo = null;
- final long token = Binder.clearCallingIdentity();
- try {
- userInfo = mUserManager.getUserInfo(userId);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- return userInfo != null && userInfo.isManagedProfile();
- }
-
-
- private int getEffectiveUserId(int userId) {
- UserManager um = UserManager.get(mContext);
- if (um != null) {
- final long callingIdentity = Binder.clearCallingIdentity();
- userId = um.getCredentialOwnerProfile(userId);
- Binder.restoreCallingIdentity(callingIdentity);
- } else {
- Slog.e(getTag(), "Unable to acquire UserManager");
- }
- return userId;
- }
-
-
private void listenForUserSwitches() {
try {
ActivityManager.getService().registerUserSwitchObserver(
new SynchronousUserSwitchObserver() {
@Override
- public void onUserSwitching(int newUserId) throws RemoteException {
+ public void onUserSwitching(int newUserId) {
mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
.sendToTarget();
}
@@ -991,8 +952,7 @@ public abstract class BiometricServiceBase extends SystemService
}
}
- private void removeLockoutResetCallback(
- LockoutResetMonitor monitor) {
+ private void removeLockoutResetCallback(LockoutResetMonitor monitor) {
mLockoutMonitors.remove(monitor);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
index ea1fde919a5f..5a2d63d667db 100644
--- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
@@ -31,7 +31,7 @@ import java.util.NoSuchElementException;
* the current client. Subclasses are responsible for coordinating the interaction with
* the biometric's HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
*/
-public abstract class ClientMonitor extends LoggableMonitor implements IBinder.DeathRecipient {
+public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinder.DeathRecipient {
private static final String TAG = "Biometrics/ClientMonitor";
protected static final boolean DEBUG = BiometricServiceBase.DEBUG;
@@ -51,31 +51,26 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
void onClientFinished(ClientMonitor clientMonitor);
}
- protected final FinishCallback mFinishCallback;
-
- private final Context mContext;
+ @NonNull private final Context mContext;
private final int mTargetUserId;
- // True if client does not have MANAGE_FINGERPRINT permission
- private final boolean mIsRestricted;
- private final String mOwner;
+ @NonNull private final String mOwner;
private final int mSensorId; // sensorId as configured by the framework
- private IBinder mToken;
- private ClientMonitorCallbackConverter mListener;
+ @Nullable private IBinder mToken;
+ @Nullable private ClientMonitorCallbackConverter mListener;
// Currently only used for authentication client. The cookie generated by BiometricService
// is never 0.
private final int mCookie;
boolean mAlreadyDone;
+ @NonNull protected T mDaemon;
+ @NonNull protected FinishCallback mFinishCallback;
+
/**
- * @param finishCallback used to notify the ClientMonitor's holder when its lifecycle has
- * completed and can be removed from the scheduler
* @param context system_server context
* @param token a unique token for the client
* @param listener recipient of related events (e.g. authentication)
* @param userId target user id for operation
- * @param restricted whether or not client has the MANAGE_* permission
- * permission
* @param owner name of the client that owns this
* @param cookie BiometricPrompt authentication cookie (to be moved into a subclass soon)
* @param sensorId ID of the sensor that the operation should be requested of
@@ -83,17 +78,15 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants
*/
- public ClientMonitor(@NonNull FinishCallback finishCallback, @NonNull Context context,
- IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- boolean restricted, @NonNull String owner, int cookie, int sensorId, int statsModality,
- int statsAction, int statsClient) {
+ public ClientMonitor(@NonNull Context context, @Nullable IBinder token,
+ @Nullable ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
+ int cookie, int sensorId, int statsModality, int statsAction,
+ int statsClient) {
super(statsModality, statsAction, statsClient);
- mFinishCallback = finishCallback;
mContext = context;
mToken = token;
mListener = listener;
mTargetUserId = userId;
- mIsRestricted = restricted;
mOwner = owner;
mCookie = cookie;
mSensorId = sensorId;
@@ -112,10 +105,22 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
}
/**
+ * Invoked if the scheduler is unable to start the ClientMonitor (for example the HAL is null).
+ * If such a problem is detected, the scheduler will not invoke
+ * {@link #start(Object, FinishCallback)}.
+ */
+ public abstract void unableToStart();
+
+ /**
* Starts the ClientMonitor's lifecycle. Invokes {@link #startHalOperation()} when internal book
* keeping is complete.
+ * @param daemon reference to the HAL
+ * @param finishCallback invoked when the operation is complete (succeeds, fails, etc)
*/
- public abstract void start();
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ mDaemon = daemon;
+ mFinishCallback = finishCallback;
+ }
/**
* Starts the HAL operation specific to the ClientMonitor subclass.
@@ -174,10 +179,6 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
return mListener;
}
- public final boolean getIsRestricted() {
- return mIsRestricted;
- }
-
public final int getTargetUserId() {
return mTargetUserId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
index f4863f59db4d..ad14531a9001 100644
--- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
@@ -126,4 +126,17 @@ public final class ClientMonitorCallbackConverter {
mFingerprintServiceReceiver.onChallengeGenerated(challenge);
}
}
+
+ public void onFeatureSet(boolean success, int feature) throws RemoteException {
+ if (mFaceServiceReceiver != null) {
+ mFaceServiceReceiver.onFeatureSet(success, feature);
+ }
+ }
+
+ public void onFeatureGet(boolean success, int feature, boolean value)
+ throws RemoteException {
+ if (mFaceServiceReceiver != null) {
+ mFaceServiceReceiver.onFeatureGet(success, feature, value);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
index 4c9f68f89a94..6637ede62b80 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
@@ -29,7 +29,7 @@ import java.util.Arrays;
/**
* A class to keep track of the enrollment state for a given client.
*/
-public abstract class EnrollClient extends AcquisitionClient {
+public abstract class EnrollClient<T> extends AcquisitionClient<T> {
private static final String TAG = "Biometrics/EnrollClient";
@@ -41,14 +41,13 @@ public abstract class EnrollClient extends AcquisitionClient {
private long mEnrollmentStartTimeMs;
private boolean mAlreadyCancelled;
- public EnrollClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull byte[] hardwareAuthToken, boolean restricted, String owner,
- @NonNull BiometricUtils utils, int timeoutSec, int statsModality, int sensorId,
+ public EnrollClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
+ int timeoutSec, int statsModality, int sensorId,
boolean shouldVibrate) {
- super(finishCallback, context, token, listener, userId, restricted, owner, 0 /* cookie */,
- sensorId, statsModality, BiometricsProtoEnums.ACTION_ENROLL,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ super(context, token, listener, userId, owner, 0 /* cookie */, sensorId, statsModality,
+ BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricUtils = utils;
mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
mTimeoutSec = timeoutSec;
@@ -88,7 +87,9 @@ public abstract class EnrollClient extends AcquisitionClient {
}
@Override
- public void start() {
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
mEnrollmentStartTimeMs = System.currentTimeMillis();
startHalOperation();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
index 98e83daceb6e..12584cfa7af3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
@@ -16,27 +16,39 @@
package com.android.server.biometrics.sensors;
+import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
-public abstract class GenerateChallengeClient extends ClientMonitor {
+public abstract class GenerateChallengeClient<T> extends ClientMonitor<T> {
private static final String TAG = "GenerateChallengeClient";
protected long mChallenge;
- public GenerateChallengeClient(FinishCallback finishCallback, Context context, IBinder token,
+ public GenerateChallengeClient(Context context, IBinder token,
ClientMonitorCallbackConverter listener, String owner, int sensorId) {
- super(finishCallback, context, token, listener, 0 /* userId */, false /* restricted */,
- owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ super(context, token, listener, 0 /* userId */, owner, 0 /* cookie */, sensorId,
+ BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN);
}
@Override
- public void start() {
+ public void unableToStart() {
+ try {
+ getListener().onChallengeGenerated(0L);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send error", e);
+ }
+ }
+
+ @Override
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
startHalOperation();
try {
getListener().onChallengeGenerated(mChallenge);
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index e2e96e3f80d1..f3ade65d6748 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -37,8 +37,8 @@ import java.util.List;
* 2) The HAL and Framework are not in sync, and
* {@link #onRemoved(BiometricAuthenticator.Identifier, int)} returns true/
*/
-public abstract class InternalCleanupClient extends ClientMonitor implements EnumerateConsumer,
- RemovalConsumer {
+public abstract class InternalCleanupClient<T> extends ClientMonitor<T>
+ implements EnumerateConsumer, RemovalConsumer {
private static final String TAG = "Biometrics/InternalCleanupClient";
@@ -58,17 +58,17 @@ public abstract class InternalCleanupClient extends ClientMonitor implements Enu
private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
private final BiometricUtils mBiometricUtils;
private final List<? extends BiometricAuthenticator.Identifier> mEnrolledList;
- private ClientMonitor mCurrentTask;
+ private ClientMonitor<T> mCurrentTask;
private final FinishCallback mEnumerateFinishCallback = clientMonitor -> {
final List<BiometricAuthenticator.Identifier> unknownHALTemplates =
- ((InternalEnumerateClient) mCurrentTask).getUnknownHALTemplates();
+ ((InternalEnumerateClient<T>) mCurrentTask).getUnknownHALTemplates();
if (!unknownHALTemplates.isEmpty()) {
Slog.w(TAG, "Adding " + unknownHALTemplates.size() + " templates for deletion");
}
- for (int i = 0; i < unknownHALTemplates.size(); i++) {
- mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplates.get(i),
+ for (BiometricAuthenticator.Identifier unknownHALTemplate : unknownHALTemplates) {
+ mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplate,
mCurrentTask.getTargetUserId()));
}
@@ -85,22 +85,20 @@ public abstract class InternalCleanupClient extends ClientMonitor implements Enu
mFinishCallback.onClientFinished(this);
};
- protected abstract InternalEnumerateClient getEnumerateClient(FinishCallback finishCallback,
- Context context, IBinder token, int userId, boolean restricted, String owner,
+ protected abstract InternalEnumerateClient<T> getEnumerateClient(Context context, IBinder token,
+ int userId, String owner,
List<? extends BiometricAuthenticator.Identifier> enrolledList, BiometricUtils utils,
- int sensorId, int statsModality);
+ int sensorId);
- protected abstract RemovalClient getRemovalClient(FinishCallback finishCallback,
- Context context, IBinder token, int biometricId, int userId, boolean restricted,
- String owner, BiometricUtils utils, int sensorId, int statsModality);
+ protected abstract RemovalClient<T> getRemovalClient(Context context, IBinder token,
+ int biometricId, int userId, String owner, BiometricUtils utils, int sensorId);
- protected InternalCleanupClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, int userId, boolean restricted,
+ protected InternalCleanupClient(@NonNull Context context, int userId,
@NonNull String owner, int sensorId, int statsModality,
@NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
@NonNull BiometricUtils utils) {
- super(finishCallback, context, null /* token */, null /* ClientMonitorCallbackConverter */,
- userId, restricted, owner, 0 /* cookie */, sensorId, statsModality,
+ super(context, null /* token */, null /* ClientMonitorCallbackConverter */,
+ userId, owner, 0 /* cookie */, sensorId, statsModality,
BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricUtils = utils;
mEnrolledList = enrolledList;
@@ -109,22 +107,28 @@ public abstract class InternalCleanupClient extends ClientMonitor implements Enu
private void startCleanupUnknownHalTemplates() {
UserTemplate template = mUnknownHALTemplates.get(0);
mUnknownHALTemplates.remove(template);
- mCurrentTask = getRemovalClient(mRemoveFinishCallback, getContext(), getToken(),
- template.mIdentifier.getBiometricId(), template.mUserId, getIsRestricted(),
- getContext().getPackageName(), mBiometricUtils, getSensorId(), mStatsModality);
+ mCurrentTask = getRemovalClient(getContext(), getToken(),
+ template.mIdentifier.getBiometricId(), template.mUserId,
+ getContext().getPackageName(), mBiometricUtils, getSensorId());
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
mStatsModality,
BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
- mCurrentTask.start();
+ mCurrentTask.start(mDaemon, mRemoveFinishCallback);
}
@Override
- public void start() {
+ public void unableToStart() {
+ // nothing to do here
+ }
+
+ @Override
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
// Start enumeration. Removal will start if necessary, when enumeration is completed.
- mCurrentTask = getEnumerateClient(mEnumerateFinishCallback, getContext(), getToken(),
- getTargetUserId(), getIsRestricted(), getOwnerString(), mEnrolledList,
- mBiometricUtils, getSensorId(), mStatsModality);
- mCurrentTask.start();
+ mCurrentTask = getEnumerateClient(getContext(), getToken(), getTargetUserId(),
+ getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId());
+ mCurrentTask.start(daemon, mEnumerateFinishCallback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index 6764b2111ad3..9ce271c656c8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -31,7 +31,8 @@ import java.util.List;
/**
* Internal class to help clean up unknown templates in the HAL and Framework
*/
-public abstract class InternalEnumerateClient extends ClientMonitor implements EnumerateConsumer {
+public abstract class InternalEnumerateClient<T> extends ClientMonitor<T>
+ implements EnumerateConsumer {
private static final String TAG = "Biometrics/InternalEnumerateClient";
@@ -42,16 +43,14 @@ public abstract class InternalEnumerateClient extends ClientMonitor implements E
// List of templates to remove from the HAL
private List<BiometricAuthenticator.Identifier> mUnknownHALTemplates = new ArrayList<>();
- protected InternalEnumerateClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBinder token, int userId, boolean restricted,
+ protected InternalEnumerateClient(@NonNull Context context, @NonNull IBinder token, int userId,
@NonNull String owner,
@NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
@NonNull BiometricUtils utils, int sensorId, int statsModality) {
// Internal enumerate does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
- super(finishCallback, context, token, null /* ClientMonitorCallbackConverter */, userId,
- restricted, owner, 0 /* cookie */, sensorId, statsModality,
- BiometricsProtoEnums.ACTION_ENUMERATE,
+ super(context, token, null /* ClientMonitorCallbackConverter */, userId, owner,
+ 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN);
mEnrolledList = enrolledList;
mUtils = utils;
@@ -68,7 +67,14 @@ public abstract class InternalEnumerateClient extends ClientMonitor implements E
}
@Override
- public void start() {
+ public void unableToStart() {
+ // Nothing to do here
+ }
+
+ @Override
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
// The biometric template ids will be removed when we get confirmation from the HAL
startHalOperation();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index 661f7fcd6c47..b734516322e4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -27,26 +27,31 @@ import android.util.Slog;
/**
* A class to keep track of the remove state for a given client.
*/
-public abstract class RemovalClient extends ClientMonitor implements RemovalConsumer {
+public abstract class RemovalClient<T> extends ClientMonitor<T> implements RemovalConsumer {
private static final String TAG = "Biometrics/RemovalClient";
protected final int mBiometricId;
private final BiometricUtils mBiometricUtils;
- public RemovalClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- int biometricId, int userId, boolean restricted, @NonNull String owner,
- @NonNull BiometricUtils utils, int sensorId, int statsModality) {
- super(finishCallback, context, token, listener, userId, restricted, owner, 0 /* cookie */,
- sensorId, statsModality, BiometricsProtoEnums.ACTION_REMOVE,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ public RemovalClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
+ @NonNull String owner, @NonNull BiometricUtils utils, int sensorId, int statsModality) {
+ super(context, token, listener, userId, owner, 0 /* cookie */, sensorId, statsModality,
+ BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricId = biometricId;
mBiometricUtils = utils;
}
@Override
- public void start() {
+ public void unableToStart() {
+ // Nothing to do here
+ }
+
+ @Override
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
// The biometric template ids will be removed when we get confirmation from the HAL
startHalOperation();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
index 024ff576d230..e00396b054e6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
@@ -16,22 +16,28 @@
package com.android.server.biometrics.sensors;
+import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
-public abstract class RevokeChallengeClient extends ClientMonitor {
+public abstract class RevokeChallengeClient<T> extends ClientMonitor<T> {
- public RevokeChallengeClient(FinishCallback finishCallback, Context context, IBinder token,
- String owner, int sensorId) {
- super(finishCallback, context, token, null /* listener */, 0 /* userId */,
- false /* restricted */, owner, 0 /* cookie */, sensorId,
+ public RevokeChallengeClient(Context context, IBinder token, String owner, int sensorId) {
+ super(context, token, null /* listener */, 0 /* userId */, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN);
}
@Override
- public void start() {
+ public void unableToStart() {
+ // Nothing to do here
+ }
+
+ @Override
+ public void start(@NonNull T daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
startHalOperation();
mFinishCallback.onClientFinished(this);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java
index 82bef34469fe..a54357e922d2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticationClient.java
@@ -48,11 +48,10 @@ import java.util.ArrayList;
* Face-specific authentication client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-class FaceAuthenticationClient extends AuthenticationClient {
+class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
private static final String TAG = "FaceAuthenticationClient";
- private final IBiometricsFace mDaemon;
private final NotificationManager mNotificationManager;
private final UsageStats mUsageStats;
@@ -62,23 +61,17 @@ class FaceAuthenticationClient extends AuthenticationClient {
private final int[] mKeyguardIgnoreListVendor;
private int mLastAcquire;
- // We need to track this state since it's possible for applications to request for
- // authentication while the device is already locked out. In that case, the client is created
- // but not started yet. The user shouldn't receive the error haptics in this case.
- private boolean mStarted;
- FaceAuthenticationClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFace daemon, @NonNull IBinder token,
+ FaceAuthenticationClient(@NonNull Context context, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats) {
- super(finishCallback, context, token, listener, targetUserId, operationId, restricted,
+ super(context, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, taskStackListener,
lockoutTracker);
- mDaemon = daemon;
mNotificationManager = context.getSystemService(NotificationManager.class);
mUsageStats = usageStats;
@@ -94,18 +87,6 @@ class FaceAuthenticationClient extends AuthenticationClient {
}
@Override
- public void start() {
- mStarted = true;
- super.start();
- }
-
- @Override
- public void cancel() {
- mStarted = false;
- super.cancel();
- }
-
- @Override
protected void startHalOperation() {
try {
mDaemon.authenticate(mOperationId);
@@ -139,10 +120,6 @@ class FaceAuthenticationClient extends AuthenticationClient {
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
- if (authenticated) {
- mStarted = false;
- }
-
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -176,7 +153,9 @@ class FaceAuthenticationClient extends AuthenticationClient {
}
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
- if (mStarted) {
+ if (mAuthAttempted) {
+ // Only vibrate if auth was attempted. If the user was already locked out prior
+ // to starting authentication, do not vibrate.
vibrateError();
}
break;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index a39c4b974cdd..33244b8e61a8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -23,6 +23,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import com.android.server.biometrics.SensorConfig;
+import com.android.server.biometrics.sensors.LockoutTracker;
/**
* Shim that converts IFaceService into a common reusable IBiometricAuthenticator interface.
@@ -68,6 +69,12 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
}
@Override
+ public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId)
+ throws RemoteException {
+ return mFaceService.getLockoutModeForUser(userId);
+ }
+
+ @Override
public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException {
mFaceService.resetLockout(userId, hardwareAuthToken);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java
index ee8aa171bdbc..b63b39e3cf6c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceEnrollClient.java
@@ -16,8 +16,11 @@
package com.android.server.biometrics.sensors.face;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricFaceConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.Status;
import android.hardware.face.FaceManager;
@@ -39,24 +42,22 @@ import java.util.Arrays;
* Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-public class FaceEnrollClient extends EnrollClient {
+public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
private static final String TAG = "FaceEnrollClient";
- private final IBiometricsFace mDaemon;
- private final int[] mDisabledFeatures;
- private final NativeHandle mSurfaceHandle;
- private final int[] mEnrollIgnoreList;
- private final int[] mEnrollIgnoreListVendor;
+ @NonNull private final int[] mDisabledFeatures;
+ @Nullable private final NativeHandle mSurfaceHandle;
+ @NonNull private final int[] mEnrollIgnoreList;
+ @NonNull private final int[] mEnrollIgnoreListVendor;
- FaceEnrollClient(FinishCallback finishCallback, Context context, IBiometricsFace daemon,
- IBinder token, ClientMonitorCallbackConverter listener, int userId,
- byte[] hardwareAuthToken, boolean restricted, String owner, BiometricUtils utils,
- int[] disabledFeatures, int timeoutSec, int statsModality, NativeHandle surfaceHandle,
+ FaceEnrollClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
+ @NonNull int[] disabledFeatures, int timeoutSec, @Nullable NativeHandle surfaceHandle,
int sensorId) {
- super(finishCallback, context, token, listener, userId, hardwareAuthToken, restricted,
- owner, utils, timeoutSec, statsModality, sensorId, false /* shouldVibrate */);
- mDaemon = daemon;
+ super(context, token, listener, userId, hardwareAuthToken, owner, utils, timeoutSec,
+ BiometricsProtoEnums.MODALITY_FACE, sensorId, false /* shouldVibrate */);
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
mSurfaceHandle = surfaceHandle;
mEnrollIgnoreList = getContext().getResources()
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
index 7d10c59bf828..72188a516d65 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
@@ -31,18 +31,14 @@ import com.android.server.biometrics.sensors.GenerateChallengeClient;
* {@link android.hardware.biometrics.face.V1_0} and {@link android.hardware.biometrics.face.V1_1}
* HIDL interfaces.
*/
-public class FaceGenerateChallengeClient extends GenerateChallengeClient {
+public class FaceGenerateChallengeClient extends GenerateChallengeClient<IBiometricsFace> {
private static final String TAG = "FaceGenerateChallengeClient";
private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
- private final IBiometricsFace mDaemon;
-
- FaceGenerateChallengeClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFace daemon, @NonNull IBinder token,
+ FaceGenerateChallengeClient(@NonNull Context context, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, @NonNull String owner, int sensorId) {
- super(finishCallback, context, token, listener, owner, sensorId);
- mDaemon = daemon;
+ super(context, token, listener, owner, sensorId);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java
new file mode 100644
index 000000000000..227d817e31ff
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.face.V1_0.IBiometricsFace;
+import android.hardware.biometrics.face.V1_0.OptionalBool;
+import android.hardware.biometrics.face.V1_0.Status;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+/**
+ * Face-specific getFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
+ * and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
+ */
+public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
+
+ private static final String TAG = "FaceGetFeatureClient";
+
+ private final int mFeature;
+ private final int mFaceId;
+
+ FaceGetFeatureClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
+ int sensorId, int feature, int faceId) {
+ super(context, token, listener, userId, owner, 0 /* cookie */, sensorId,
+ BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN);
+ mFeature = feature;
+ mFaceId = faceId;
+
+ }
+
+ @Override
+ public void unableToStart() {
+ try {
+ getListener().onFeatureGet(false /* success */, mFeature, false /* value */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send error", e);
+ }
+ }
+
+ @Override
+ public void start(@NonNull IBiometricsFace daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+ startHalOperation();
+ }
+
+ @Override
+ protected void startHalOperation() {
+ try {
+ final OptionalBool result = mDaemon.getFeature(mFeature, mFaceId);
+ getListener().onFeatureGet(result.status == Status.OK, mFeature, result.value);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to getFeature", e);
+ }
+ mFinishCallback.onClientFinished(this);
+ }
+
+ @Override
+ protected void stopHalOperation() {
+ // Not supported for GetFeature
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalCleanupClient.java
index 2b4c4c8c0fe1..388baa226dee 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalCleanupClient.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.face;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.os.IBinder;
@@ -34,36 +35,30 @@ import java.util.List;
* {@link android.hardware.biometrics.face.V1_0} and {@link android.hardware.biometrics.face.V1_1}
* HIDL interfaces.
*/
-class FaceInternalCleanupClient extends InternalCleanupClient {
- private final IBiometricsFace mDaemon;
+class FaceInternalCleanupClient extends InternalCleanupClient<IBiometricsFace> {
- FaceInternalCleanupClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFace daemon, int userId, boolean restricted, String owner,
- int sensorId, int statsModality,
- @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
+ FaceInternalCleanupClient(@NonNull Context context, int userId, @NonNull String owner,
+ int sensorId, @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
@NonNull BiometricUtils utils) {
- super(finishCallback, context, userId, restricted, owner, sensorId, statsModality,
- enrolledList, utils);
- mDaemon = daemon;
+ super(context, userId, owner, sensorId, BiometricsProtoEnums.MODALITY_FACE, enrolledList,
+ utils);
}
@Override
- protected InternalEnumerateClient getEnumerateClient(FinishCallback finishCallback,
- Context context, IBinder token, int userId, boolean restricted, String owner,
+ protected InternalEnumerateClient<IBiometricsFace> getEnumerateClient(Context context,
+ IBinder token, int userId, String owner,
List<? extends BiometricAuthenticator.Identifier> enrolledList,
- BiometricUtils utils, int sensorId, int statsModality) {
- return new FaceInternalEnumerateClient(finishCallback, context, mDaemon, token, userId,
- restricted, owner, enrolledList, utils, sensorId, statsModality);
+ BiometricUtils utils, int sensorId) {
+ return new FaceInternalEnumerateClient(context, token, userId, owner, enrolledList, utils,
+ sensorId);
}
@Override
- protected RemovalClient getRemovalClient(FinishCallback finishCallback, Context context,
- IBinder token, int biometricId, int userId, boolean restricted, String owner,
- BiometricUtils utils, int sensorId, int statsModality) {
+ protected RemovalClient<IBiometricsFace> getRemovalClient(Context context, IBinder token,
+ int biometricId, int userId, String owner, BiometricUtils utils, int sensorId) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
- return new FaceRemovalClient(finishCallback, context, mDaemon, token,
- null /* ClientMonitorCallbackConverter */, biometricId, userId, restricted,
- owner, utils, sensorId, statsModality);
+ return new FaceRemovalClient(context, token, null /* ClientMonitorCallbackConverter */,
+ biometricId, userId, owner, utils, sensorId);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java
index 1b4597c5f2cd..c6749c5713d9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceInternalEnumerateClient.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.face;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.os.IBinder;
import android.os.RemoteException;
@@ -34,19 +35,15 @@ import java.util.List;
* {@link android.hardware.biometrics.face.V1_0} and {@link android.hardware.biometrics.face.V1_1}
* HIDL interfaces.
*/
-class FaceInternalEnumerateClient extends InternalEnumerateClient {
+class FaceInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFace> {
private static final String TAG = "FaceInternalEnumerateClient";
- private final IBiometricsFace mDaemon;
-
- FaceInternalEnumerateClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFace daemon, @NonNull IBinder token, int userId, boolean restricted,
+ FaceInternalEnumerateClient(@NonNull Context context, @NonNull IBinder token, int userId,
@NonNull String owner,
@NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
- @NonNull BiometricUtils utils, int sensorId, int statsModality) {
- super(finishCallback, context, token, userId, restricted, owner, enrolledList, utils,
- sensorId, statsModality);
- mDaemon = daemon;
+ @NonNull BiometricUtils utils, int sensorId) {
+ super(context, token, userId, owner, enrolledList, utils, sensorId,
+ BiometricsProtoEnums.MODALITY_FACE);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java
index 2c1939744543..b0ee9810a49b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceRemovalClient.java
@@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.face;
import android.annotation.NonNull;
import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.os.IBinder;
import android.os.RemoteException;
@@ -31,18 +32,14 @@ import com.android.server.biometrics.sensors.RemovalClient;
* Face-specific removal client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-class FaceRemovalClient extends RemovalClient {
+class FaceRemovalClient extends RemovalClient<IBiometricsFace> {
private static final String TAG = "FaceRemovalClient";
- private final IBiometricsFace mDaemon;
- FaceRemovalClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFace daemon, @NonNull IBinder token,
+ FaceRemovalClient(@NonNull Context context, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
- boolean restricted, @NonNull String owner, @NonNull BiometricUtils utils, int sensorId,
- int statsModality) {
- super(finishCallback, context, token, listener, biometricId, userId, restricted, owner,
- utils, sensorId, statsModality);
- mDaemon = daemon;
+ @NonNull String owner, @NonNull BiometricUtils utils, int sensorId) {
+ super(context, token, listener, biometricId, userId, owner, utils, sensorId,
+ BiometricsProtoEnums.MODALITY_FACE);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java
new file mode 100644
index 000000000000..441cb14f6600
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.face.V1_0.IBiometricsFace;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.ClientMonitor;
+
+import java.util.ArrayList;
+
+/**
+ * Face-specific resetLockout client supporting the {@link android.hardware.biometrics.face.V1_0}
+ * and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
+ */
+public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> {
+
+ private static final String TAG = "FaceResetLockoutClient";
+
+ private final ArrayList<Byte> mHardwareAuthToken;
+
+ FaceResetLockoutClient(@NonNull Context context, int userId, String owner, int sensorId,
+ byte[] hardwareAuthToken) {
+ super(context, null /* token */, null /* listener */, userId, owner, 0 /* cookie */,
+ sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
+ BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+
+ mHardwareAuthToken = new ArrayList<>();
+ for (byte b : hardwareAuthToken) {
+ mHardwareAuthToken.add(b);
+ }
+ }
+
+ @Override
+ public void unableToStart() {
+ // Nothing to do here
+ }
+
+ @Override
+ public void start(@NonNull IBiometricsFace daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
+ startHalOperation();
+ }
+
+ @Override
+ protected void startHalOperation() {
+ try {
+ mDaemon.resetLockout(mHardwareAuthToken);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to reset lockout", e);
+ }
+ mFinishCallback.onClientFinished(this);
+ }
+
+ @Override
+ protected void stopHalOperation() {
+ // Not supported for resetLockout
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceRevokeChallengeClient.java
index 102efda8a45d..992a678d8205 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceRevokeChallengeClient.java
@@ -29,17 +29,13 @@ import com.android.server.biometrics.sensors.RevokeChallengeClient;
* Face-specific revokeChallenge client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-public class FaceRevokeChallengeClient extends RevokeChallengeClient {
+public class FaceRevokeChallengeClient extends RevokeChallengeClient<IBiometricsFace> {
private static final String TAG = "FaceRevokeChallengeClient";
- private final IBiometricsFace mDaemon;
-
- FaceRevokeChallengeClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFace daemon, @NonNull IBinder token, @NonNull String owner,
- int sensorId) {
- super(finishCallback, context, token, owner, sensorId);
- mDaemon = daemon;
+ FaceRevokeChallengeClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull String owner, int sensorId) {
+ super(context, token, owner, sensorId);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 088762c1f39d..050fba28043e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -32,8 +32,6 @@ import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
-import android.hardware.biometrics.face.V1_0.OptionalBool;
-import android.hardware.biometrics.face.V1_0.Status;
import android.hardware.face.Face;
import android.hardware.face.IFaceService;
import android.hardware.face.IFaceServiceReceiver;
@@ -87,7 +85,7 @@ import java.util.List;
*
* @hide
*/
-public class FaceService extends BiometricServiceBase {
+public class FaceService extends BiometricServiceBase<IBiometricsFace> {
protected static final String TAG = "FaceService";
private static final boolean DEBUG = true;
@@ -111,19 +109,12 @@ public class FaceService extends BiometricServiceBase {
@Override // Binder call
public void generateChallenge(IBinder token, IFaceServiceReceiver receiver,
- String opPackageName) throws RemoteException {
+ String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to generateChallenge, daemon null");
- receiver.onChallengeGenerated(0L);
- return;
- }
-
- final GenerateChallengeClient client = new FaceGenerateChallengeClient(
- mClientFinishCallback, getContext(), daemon, token,
- new ClientMonitorCallbackConverter(receiver), opPackageName, getSensorId());
+ final GenerateChallengeClient client = new FaceGenerateChallengeClient(getContext(),
+ token, new ClientMonitorCallbackConverter(receiver), opPackageName,
+ getSensorId());
generateChallengeInternal(client);
}
@@ -131,14 +122,8 @@ public class FaceService extends BiometricServiceBase {
public void revokeChallenge(IBinder token, String owner) {
checkPermission(MANAGE_BIOMETRIC);
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to revokeChallenge, daemon null");
- return;
- }
-
- final RevokeChallengeClient client = new FaceRevokeChallengeClient(
- mClientFinishCallback, getContext(), daemon, token, owner, getSensorId());
+ final RevokeChallengeClient client = new FaceRevokeChallengeClient(getContext(), token,
+ owner, getSensorId());
// TODO(b/137106905): Schedule binder calls in FaceService to avoid deadlocks.
if (getCurrentClient() == null) {
@@ -153,37 +138,27 @@ public class FaceService extends BiometricServiceBase {
}
@Override // Binder call
- public void enroll(int userId, final IBinder token, final byte[] cryptoToken,
+ public void enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
- final int[] disabledFeatures, Surface surface) throws RemoteException {
+ final int[] disabledFeatures, Surface surface) {
checkPermission(MANAGE_BIOMETRIC);
- updateActiveGroup(userId, opPackageName);
+ updateActiveGroup(userId);
mHandler.post(() -> {
mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
UserHandle.CURRENT);
});
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to enroll, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
-
- final boolean restricted = isRestricted();
- final EnrollClient client = new FaceEnrollClient(mClientFinishCallback, getContext(),
- daemon, token, new ClientMonitorCallbackConverter(receiver),
- userId, cryptoToken, restricted, opPackageName, getBiometricUtils(),
- disabledFeatures, ENROLL_TIMEOUT_SEC, statsModality(),
+ final EnrollClient client = new FaceEnrollClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
+ opPackageName, getBiometricUtils(), disabledFeatures, ENROLL_TIMEOUT_SEC,
convertSurfaceToNativeHandle(surface), getSensorId());
enrollInternal(client, userId);
}
@Override // Binder call
- public void enrollRemotely(int userId, final IBinder token, final byte[] cryptoToken,
+ public void enrollRemotely(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures) {
checkPermission(MANAGE_BIOMETRIC);
@@ -198,27 +173,18 @@ public class FaceService extends BiometricServiceBase {
@Override // Binder call
public void authenticate(final IBinder token, final long opId, int userId,
- final IFaceServiceReceiver receiver, final int flags,
- final String opPackageName) throws RemoteException {
+ final IFaceServiceReceiver receiver, final String opPackageName) {
checkPermission(USE_BIOMETRIC_INTERNAL);
- updateActiveGroup(userId, opPackageName);
-
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to authenticate, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
+ updateActiveGroup(userId);
final boolean restricted = isRestricted();
final int statsClient = isKeyguard(opPackageName) ? BiometricsProtoEnums.CLIENT_KEYGUARD
: BiometricsProtoEnums.CLIENT_UNKNOWN;
- final AuthenticationClient client = new FaceAuthenticationClient(mClientFinishCallback,
- getContext(), daemon, token, new ClientMonitorCallbackConverter(receiver),
- userId, opId, restricted, opPackageName, 0 /* cookie */,
- false /* requireConfirmation */, getSensorId(), isStrongBiometric(),
- statsClient, mTaskStackListener, mLockoutTracker, mUsageStats);
+ final AuthenticationClient client = new FaceAuthenticationClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), userId, opId, restricted,
+ opPackageName, 0 /* cookie */, false /* requireConfirmation */, getSensorId(),
+ isStrongBiometric(), statsClient, mTaskStackListener, mLockoutTracker,
+ mUsageStats);
authenticateInternal(client, opPackageName);
}
@@ -226,23 +192,14 @@ public class FaceService extends BiometricServiceBase {
public void prepareForAuthentication(boolean requireConfirmation, IBinder token, long opId,
int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, int cookie, int callingUid, int callingPid,
- int callingUserId) throws RemoteException {
+ int callingUserId) {
checkPermission(USE_BIOMETRIC_INTERNAL);
- updateActiveGroup(userId, opPackageName);
-
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to prepare for authentication, daemon null");
- sensorReceiver.onError(getSensorId(), cookie,
- BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
- return;
- }
+ updateActiveGroup(userId);
final boolean restricted = true; // BiometricPrompt is always restricted
- final AuthenticationClient client = new FaceAuthenticationClient(mClientFinishCallback,
- getContext(), daemon, token, new ClientMonitorCallbackConverter(sensorReceiver),
- userId, opId, restricted, opPackageName, cookie, requireConfirmation,
- getSensorId(), isStrongBiometric(),
+ final AuthenticationClient client = new FaceAuthenticationClient(getContext(), token,
+ new ClientMonitorCallbackConverter(sensorReceiver), userId, opId, restricted,
+ opPackageName, cookie, requireConfirmation, getSensorId(), isStrongBiometric(),
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, mTaskStackListener,
mLockoutTracker, mUsageStats);
authenticateInternal(client, opPackageName, callingUid, callingPid,
@@ -272,34 +229,23 @@ public class FaceService extends BiometricServiceBase {
@Override // Binder call
public void remove(final IBinder token, final int faceId, final int userId,
- final IFaceServiceReceiver receiver, final String opPackageName)
- throws RemoteException {
+ final IFaceServiceReceiver receiver, final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
- updateActiveGroup(userId, opPackageName);
+ updateActiveGroup(userId);
if (token == null) {
Slog.w(TAG, "remove(): token is null");
return;
}
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to remove, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
-
- final boolean restricted = isRestricted();
- final RemovalClient client = new FaceRemovalClient(mClientFinishCallback, getContext(),
- daemon, token, new ClientMonitorCallbackConverter(receiver), faceId, userId,
- restricted, opPackageName, getBiometricUtils(), getSensorId(), statsModality());
+ final RemovalClient client = new FaceRemovalClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), faceId, userId, opPackageName,
+ getBiometricUtils(), getSensorId());
removeInternal(client);
}
@Override
- public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback)
- throws RemoteException {
+ public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback) {
checkPermission(USE_BIOMETRIC_INTERNAL);
FaceService.super.addLockoutResetCallback(callback);
}
@@ -369,6 +315,12 @@ public class FaceService extends BiometricServiceBase {
return FaceService.this.hasEnrolledBiometrics(userId);
}
+ @Override
+ public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
+ checkPermission(USE_BIOMETRIC_INTERNAL);
+ return mLockoutTracker.getLockoutModeForUser(userId);
+ }
+
@Override // Binder call
public long getAuthenticatorId(int callingUserId) {
checkPermission(USE_BIOMETRIC_INTERNAL);
@@ -386,65 +338,49 @@ public class FaceService extends BiometricServiceBase {
Slog.d(TAG, "Resetting lockout for user: " + userId);
- updateActiveGroup(userId, null /* opPackageName */);
- try {
- final ArrayList<Byte> token = new ArrayList<>();
- for (int i = 0; i < hardwareAuthToken.length; i++) {
- token.add(hardwareAuthToken[i]);
- }
- mDaemon.resetLockout(token);
- } catch (RemoteException e) {
- Slog.e(getTag(), "Unable to reset lockout", e);
- }
+ updateActiveGroup(userId);
+ final FaceResetLockoutClient client = new FaceResetLockoutClient(getContext(),
+ userId, getContext().getOpPackageName(), getSensorId(), hardwareAuthToken);
+ startClient(client, true /* initiatedByClient */);
});
}
@Override
- public void setFeature(int userId, int feature, boolean enabled, final byte[] token,
- IFaceServiceReceiver receiver, final String opPackageName) {
+ public void setFeature(final IBinder token, int userId, int feature, boolean enabled,
+ final byte[] hardwareAuthToken, IFaceServiceReceiver receiver,
+ final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
mHandler.post(() -> {
if (DEBUG) {
Slog.d(TAG, "setFeature for user(" + userId + ")");
}
- updateActiveGroup(userId, opPackageName);
+ updateActiveGroup(userId);
if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
Slog.e(TAG, "No enrolled biometrics while setting feature: " + feature);
return;
}
- final ArrayList<Byte> byteToken = new ArrayList<>();
- for (int i = 0; i < token.length; i++) {
- byteToken.add(token[i]);
- }
-
- // TODO: Support multiple faces
final int faceId = getFirstTemplateForUser(mCurrentUserId);
- if (mDaemon != null) {
- try {
- final int result = mDaemon.setFeature(feature, enabled, byteToken, faceId);
- receiver.onFeatureSet(result == Status.OK, feature);
- } catch (RemoteException e) {
- Slog.e(getTag(), "Unable to set feature: " + feature
- + " to enabled:" + enabled, e);
- }
- }
+ final FaceSetFeatureClient client = new FaceSetFeatureClient(getContext(),
+ token, new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
+ getSensorId(), feature, enabled, hardwareAuthToken, faceId);
+ startClient(client, true /* initiatedByClient */);
});
}
@Override
- public void getFeature(int userId, int feature, IFaceServiceReceiver receiver,
- final String opPackageName) {
+ public void getFeature(final IBinder token, int userId, int feature,
+ IFaceServiceReceiver receiver, final String opPackageName) {
checkPermission(MANAGE_BIOMETRIC);
mHandler.post(() -> {
if (DEBUG) {
Slog.d(TAG, "getFeature for user(" + userId + ")");
}
- updateActiveGroup(userId, opPackageName);
+ updateActiveGroup(userId);
// This should ideally return tri-state, but the user isn't shown settings unless
// they are enrolled so it's fine for now.
if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
@@ -455,31 +391,14 @@ public class FaceService extends BiometricServiceBase {
// TODO: Support multiple faces
final int faceId = getFirstTemplateForUser(mCurrentUserId);
- if (mDaemon != null) {
- try {
- OptionalBool result = mDaemon.getFeature(feature, faceId);
- receiver.onFeatureGet(result.status == Status.OK, feature, result.value);
- } catch (RemoteException e) {
- Slog.e(getTag(), "Unable to getRequireAttention", e);
- }
- }
+ final FaceGetFeatureClient client = new FaceGetFeatureClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
+ getSensorId(), feature, faceId);
+ startClient(client, true /* initiatedByClient */);
});
}
- @Override
- public void userActivity() {
- checkPermission(MANAGE_BIOMETRIC);
-
- if (mDaemon != null) {
- try {
- mDaemon.userActivity();
- } catch (RemoteException e) {
- Slog.e(getTag(), "Unable to send userActivity", e);
- }
- }
- }
-
// TODO: Support multiple faces
private int getFirstTemplateForUser(int user) {
final List<Face> faces = FaceService.this.getEnrolledTemplates(user);
@@ -658,6 +577,11 @@ public class FaceService extends BiometricServiceBase {
}
@Override
+ protected IBiometricsFace getDaemon() {
+ return getFaceDaemon();
+ }
+
+ @Override
protected BiometricUtils getBiometricUtils() {
return FaceUtils.getInstance();
}
@@ -683,12 +607,11 @@ public class FaceService extends BiometricServiceBase {
}
@Override
- protected void updateActiveGroup(int userId, String clientPackage) {
+ protected void updateActiveGroup(int userId) {
IBiometricsFace daemon = getFaceDaemon();
if (daemon != null) {
try {
- userId = getUserOrWorkProfileId(clientPackage, userId);
if (userId != mCurrentUserId) {
final File baseDir = Environment.getDataVendorDeDirectory(userId);
final File faceDir = new File(baseDir, FACE_DATA_DIR);
@@ -770,19 +693,10 @@ public class FaceService extends BiometricServiceBase {
@Override
protected void doTemplateCleanupForUser(int userId) {
- final IBiometricsFace daemon = getFaceDaemon();
- if (daemon == null) {
- Slog.e(TAG, "daemon null, skipping template cleanup");
- return;
- }
-
- final boolean restricted = !hasPermission(getManageBiometricPermission());
final List<? extends BiometricAuthenticator.Identifier> enrolledList =
getEnrolledTemplates(userId);
- final FaceInternalCleanupClient client = new FaceInternalCleanupClient(
- mClientFinishCallback, getContext(), daemon, userId, restricted,
- getContext().getOpPackageName(), getSensorId(), statsModality(), enrolledList,
- getBiometricUtils());
+ final FaceInternalCleanupClient client = new FaceInternalCleanupClient(getContext(), userId,
+ getContext().getOpPackageName(), getSensorId(), enrolledList, getBiometricUtils());
cleanupInternal(client);
}
@@ -816,7 +730,7 @@ public class FaceService extends BiometricServiceBase {
if (DEBUG) Slog.v(TAG, "Face HAL id: " + halId);
if (halId != 0) {
loadAuthenticatorIds();
- updateActiveGroup(ActivityManager.getCurrentUser(), null);
+ updateActiveGroup(ActivityManager.getCurrentUser());
doTemplateCleanupForUser(ActivityManager.getCurrentUser());
} else {
Slog.w(TAG, "Failed to open Face HAL!");
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java
new file mode 100644
index 000000000000..91f63e185ff8
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.face.V1_0.IBiometricsFace;
+import android.hardware.biometrics.face.V1_0.Status;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+import java.util.ArrayList;
+
+/**
+ * Face-specific setFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
+ * and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
+ */
+public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> {
+
+ private static final String TAG = "FaceSetFeatureClient";
+
+ private final int mFeature;
+ private final boolean mEnabled;
+ private final ArrayList<Byte> mHardwareAuthToken;
+ private final int mFaceId;
+
+ FaceSetFeatureClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull String owner, int sensorId, int feature, boolean enabled,
+ byte[] hardwareAuthToken, int faceId) {
+ super(context, token, listener, userId, owner, 0 /* cookie */, sensorId,
+ BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN);
+ mFeature = feature;
+ mEnabled = enabled;
+ mFaceId = faceId;
+
+ mHardwareAuthToken = new ArrayList<>();
+ for (byte b : hardwareAuthToken) {
+ mHardwareAuthToken.add(b);
+ }
+ }
+
+ @Override
+ public void unableToStart() {
+ try {
+ getListener().onFeatureSet(false /* success */, mFeature);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to send error", e);
+ }
+ }
+
+ @Override
+ public void start(@NonNull IBiometricsFace daemon, @NonNull FinishCallback finishCallback) {
+ super.start(daemon, finishCallback);
+
+ startHalOperation();
+ mFinishCallback.onClientFinished(this);
+ }
+
+ @Override
+ protected void startHalOperation() {
+ try {
+ final int result = mDaemon.setFeature(mFeature, mEnabled, mHardwareAuthToken, mFaceId);
+ getListener().onFeatureSet(result == Status.OK, mFeature);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to set feature: " + mFeature + " to enabled: " + mEnabled, e);
+ }
+ }
+
+ @Override
+ protected void stopHalOperation() {
+ // Not supported for SetFeature
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java
index d4e9882aeef1..ba89d51b1f61 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticationClient.java
@@ -41,26 +41,22 @@ import java.util.ArrayList;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-class FingerprintAuthenticationClient extends AuthenticationClient {
+class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFingerprint> {
private static final String TAG = "Biometrics/FingerprintAuthClient";
- private final IBiometricsFingerprint mDaemon;
private final LockoutFrameworkImpl mLockoutFrameworkImpl;
- FingerprintAuthenticationClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFingerprint daemon,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- int targetUserId, long operationId, boolean restricted, @NonNull String owner,
- int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
- @Nullable Surface surface, int statsClient,
+ FingerprintAuthenticationClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
+ boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
+ int sensorId, boolean isStrongBiometric, @Nullable Surface surface, int statsClient,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker) {
- super(finishCallback, context, token, listener, targetUserId, operationId, restricted,
+ super(context, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
lockoutTracker);
- mDaemon = daemon;
mLockoutFrameworkImpl = lockoutTracker;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
index abfbedaa4489..3418c466aa69 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
@@ -23,6 +23,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import com.android.server.biometrics.SensorConfig;
+import com.android.server.biometrics.sensors.LockoutTracker;
/**
* Shim that converts IFingerprintService into a common reusable IBiometricAuthenticator interface.
@@ -68,6 +69,12 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
}
@Override
+ public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId)
+ throws RemoteException {
+ return mFingerprintService.getLockoutModeForUser(userId);
+ }
+
+ @Override
public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException {
mFingerprintService.resetLockout(userId, hardwareAuthToken);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java
index e5d2887d3581..34681c38808b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintEnrollClient.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.os.IBinder;
import android.os.RemoteException;
@@ -33,20 +34,16 @@ import com.android.server.biometrics.sensors.EnrollClient;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-public class FingerprintEnrollClient extends EnrollClient {
+public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint> {
private static final String TAG = "FingerprintEnrollClient";
- private final IBiometricsFingerprint mDaemon;
- FingerprintEnrollClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFingerprint daemon, @NonNull IBinder token,
+ FingerprintEnrollClient(@NonNull Context context, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull byte[] hardwareAuthToken, boolean restricted, @NonNull String owner,
- @NonNull BiometricUtils utils, int timeoutSec, int statsModality,
- int sensorId, boolean shouldVibrate) {
- super(finishCallback, context, token, listener, userId, hardwareAuthToken, restricted,
- owner, utils, timeoutSec, statsModality, sensorId, shouldVibrate);
- mDaemon = daemon;
+ @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
+ int timeoutSec, int sensorId) {
+ super(context, token, listener, userId, hardwareAuthToken, owner, utils, timeoutSec,
+ BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, true /* shouldVibrate */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintGenerateChallengeClient.java
index 5ff49f377f0a..2fa433305070 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintGenerateChallengeClient.java
@@ -31,18 +31,14 @@ import com.android.server.biometrics.sensors.GenerateChallengeClient;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-public class FingerprintGenerateChallengeClient extends GenerateChallengeClient {
+public class FingerprintGenerateChallengeClient
+ extends GenerateChallengeClient<IBiometricsFingerprint> {
private static final String TAG = "FingerprintGenerateChallengeClient";
- private final IBiometricsFingerprint mDaemon;
-
- FingerprintGenerateChallengeClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFingerprint daemon,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- @NonNull String owner, int sensorId) {
- super(finishCallback, context, token, listener, owner, sensorId);
- mDaemon = daemon;
+ FingerprintGenerateChallengeClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener, @NonNull String owner, int sensorId) {
+ super(context, token, listener, owner, sensorId);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalCleanupClient.java
index 1688bde935ac..71e76703b9d5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalCleanupClient.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.os.IBinder;
@@ -34,36 +35,31 @@ import java.util.List;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-class FingerprintInternalCleanupClient extends InternalCleanupClient {
- private final IBiometricsFingerprint mDaemon;
+class FingerprintInternalCleanupClient extends InternalCleanupClient<IBiometricsFingerprint> {
- FingerprintInternalCleanupClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFingerprint daemon, int userId,
- boolean restricted, @NonNull String owner, int sensorId, int statsModality,
- @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
+ FingerprintInternalCleanupClient(@NonNull Context context,int userId, @NonNull String owner,
+ int sensorId, @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
@NonNull BiometricUtils utils) {
- super(finishCallback, context, userId, restricted, owner, sensorId, statsModality,
+ super(context, userId, owner, sensorId, BiometricsProtoEnums.MODALITY_FINGERPRINT,
enrolledList, utils);
- mDaemon = daemon;
}
@Override
- protected InternalEnumerateClient getEnumerateClient(FinishCallback finishCallback,
- Context context, IBinder token, int userId, boolean restricted, String owner,
+ protected InternalEnumerateClient<IBiometricsFingerprint> getEnumerateClient(
+ Context context, IBinder token, int userId, String owner,
List<? extends BiometricAuthenticator.Identifier> enrolledList, BiometricUtils utils,
- int sensorId, int statsModality) {
- return new FingerprintInternalEnumerateClient(finishCallback, context, mDaemon, token,
- userId, restricted, owner, enrolledList, utils, sensorId, statsModality);
+ int sensorId) {
+ return new FingerprintInternalEnumerateClient(context, token, userId, owner, enrolledList,
+ utils, sensorId);
}
@Override
- protected RemovalClient getRemovalClient(FinishCallback finishCallback, Context context,
- IBinder token, int biometricId, int userId, boolean restricted, String owner,
- BiometricUtils utils, int sensorId, int statsModality) {
+ protected RemovalClient<IBiometricsFingerprint> getRemovalClient(Context context, IBinder token,
+ int biometricId, int userId, String owner, BiometricUtils utils, int sensorId) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
- return new FingerprintRemovalClient(finishCallback, context, mDaemon, token,
- null /* ClientMonitorCallbackConverter */, biometricId, userId, restricted,
- owner, utils, sensorId, statsModality);
+ return new FingerprintRemovalClient(context, token,
+ null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
+ sensorId);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java
index 2b34f087e230..ba412e3956ce 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintInternalEnumerateClient.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.os.IBinder;
import android.os.RemoteException;
@@ -34,19 +35,15 @@ import java.util.List;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-class FingerprintInternalEnumerateClient extends InternalEnumerateClient {
+class FingerprintInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFingerprint> {
private static final String TAG = "FingerprintInternalEnumerateClient";
- private final IBiometricsFingerprint mDaemon;
-
- FingerprintInternalEnumerateClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFingerprint daemon,
- @NonNull IBinder token, int userId, boolean restricted, @NonNull String owner,
+ FingerprintInternalEnumerateClient(@NonNull Context context, @NonNull IBinder token, int userId,
+ @NonNull String owner,
@NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
- @NonNull BiometricUtils utils, int sensorId, int statsModality) {
- super(finishCallback, context, token, userId, restricted, owner, enrolledList, utils,
- sensorId, statsModality);
- mDaemon = daemon;
+ @NonNull BiometricUtils utils, int sensorId) {
+ super(context, token, userId, owner, enrolledList, utils, sensorId,
+ BiometricsProtoEnums.MODALITY_FINGERPRINT);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java
index d284dc673ea1..6d7e76162029 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRemovalClient.java
@@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.NonNull;
import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.os.IBinder;
import android.os.RemoteException;
@@ -32,19 +33,14 @@ import com.android.server.biometrics.sensors.RemovalClient;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-class FingerprintRemovalClient extends RemovalClient {
+class FingerprintRemovalClient extends RemovalClient<IBiometricsFingerprint> {
private static final String TAG = "FingerprintRemovalClient";
- private final IBiometricsFingerprint mDaemon;
-
- FingerprintRemovalClient(@NonNull FinishCallback finishCallback, @NonNull Context context,
- @NonNull IBiometricsFingerprint daemon, @NonNull IBinder token,
+ FingerprintRemovalClient(@NonNull Context context, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
- boolean restricted, @NonNull String owner, @NonNull BiometricUtils utils, int sensorId,
- int statsModality) {
- super(finishCallback, context, token, listener, biometricId, userId, restricted, owner,
- utils, sensorId, statsModality);
- mDaemon = daemon;
+ @NonNull String owner, @NonNull BiometricUtils utils, int sensorId) {
+ super(context, token, listener, biometricId, userId, owner, utils, sensorId,
+ BiometricsProtoEnums.MODALITY_FINGERPRINT);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRevokeChallengeClient.java
index 99e9d54b6a5e..ccbea31d7c48 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintRevokeChallengeClient.java
@@ -30,17 +30,14 @@ import com.android.server.biometrics.sensors.RevokeChallengeClient;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-public class FingerprintRevokeChallengeClient extends RevokeChallengeClient {
+public class FingerprintRevokeChallengeClient
+ extends RevokeChallengeClient<IBiometricsFingerprint> {
private static final String TAG = "FingerprintRevokeChallengeClient";
- private final IBiometricsFingerprint mDaemon;
-
- FingerprintRevokeChallengeClient(@NonNull FinishCallback finishCallback,
- @NonNull Context context, @NonNull IBiometricsFingerprint daemon,
- @NonNull IBinder token, @NonNull String owner, int sensorId) {
- super(finishCallback, context, token, owner, sensorId);
- mDaemon = daemon;
+ FingerprintRevokeChallengeClient(@NonNull Context context, @NonNull IBinder token,
+ @NonNull String owner, int sensorId) {
+ super(context, token, owner, sensorId);
}
@Override
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 ba3d76f3e876..d2a25dba7936 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
@@ -91,7 +91,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*
* @hide
*/
-public class FingerprintService extends BiometricServiceBase {
+public class FingerprintService extends BiometricServiceBase<IBiometricsFingerprint> {
protected static final String TAG = "FingerprintService";
private static final boolean DEBUG = true;
@@ -109,19 +109,12 @@ public class FingerprintService extends BiometricServiceBase {
@Override // Binder call
public void generateChallenge(IBinder token, IFingerprintServiceReceiver receiver,
- String opPackageName) throws RemoteException {
+ String opPackageName) {
checkPermission(MANAGE_FINGERPRINT);
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to generateChallenge, daemon null");
- receiver.onChallengeGenerated(0L);
- return;
- }
-
final GenerateChallengeClient client = new FingerprintGenerateChallengeClient(
- mClientFinishCallback, getContext(), daemon, token,
- new ClientMonitorCallbackConverter(receiver), opPackageName, getSensorId());
+ getContext(), token, new ClientMonitorCallbackConverter(receiver),
+ opPackageName, getSensorId());
generateChallengeInternal(client);
}
@@ -129,37 +122,21 @@ public class FingerprintService extends BiometricServiceBase {
public void revokeChallenge(IBinder token, String owner) {
checkPermission(MANAGE_FINGERPRINT);
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "startPostEnroll: no fingerprint HAL!");
- return;
- }
-
- final RevokeChallengeClient client = new FingerprintRevokeChallengeClient(
- mClientFinishCallback, getContext(), daemon, token, owner, getSensorId());
+ final RevokeChallengeClient client = new FingerprintRevokeChallengeClient(getContext(),
+ token, owner, getSensorId());
revokeChallengeInternal(client);
}
@Override // Binder call
public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
- final IFingerprintServiceReceiver receiver, final int flags,
- final String opPackageName, Surface surface) throws RemoteException {
+ final IFingerprintServiceReceiver receiver, final String opPackageName,
+ final Surface surface) {
checkPermission(MANAGE_FINGERPRINT);
- updateActiveGroup(userId, opPackageName);
-
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to enroll, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
+ updateActiveGroup(userId);
- final boolean restricted = isRestricted();
- final EnrollClient client = new FingerprintEnrollClient(mClientFinishCallback,
- getContext(), daemon, token, new ClientMonitorCallbackConverter(receiver),
- userId, cryptoToken, restricted, opPackageName, getBiometricUtils(),
- ENROLL_TIMEOUT_SEC, statsModality(), getSensorId(), true /* shouldVibrate */);
+ final EnrollClient client = new FingerprintEnrollClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), userId, cryptoToken,
+ opPackageName, getBiometricUtils(), ENROLL_TIMEOUT_SEC, getSensorId());
enrollInternal(client, userId);
}
@@ -172,17 +149,9 @@ public class FingerprintService extends BiometricServiceBase {
@Override // Binder call
public void authenticate(final IBinder token, final long opId, final int userId,
- final IFingerprintServiceReceiver receiver, final int flags,
- final String opPackageName, Surface surface) throws RemoteException {
- updateActiveGroup(userId, opPackageName);
-
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to authenticate, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
+ final IFingerprintServiceReceiver receiver, final String opPackageName,
+ final Surface surface) {
+ updateActiveGroup(userId);
final boolean isStrongBiometric;
final long ident = Binder.clearCallingIdentity();
@@ -195,9 +164,8 @@ public class FingerprintService extends BiometricServiceBase {
final boolean restricted = isRestricted();
final int statsClient = isKeyguard(opPackageName) ? BiometricsProtoEnums.CLIENT_KEYGUARD
: BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
- final AuthenticationClient client = new FingerprintAuthenticationClient(
- mClientFinishCallback, getContext(), daemon, token,
- new ClientMonitorCallbackConverter(receiver), userId, opId, restricted,
+ final AuthenticationClient client = new FingerprintAuthenticationClient(getContext(),
+ token, new ClientMonitorCallbackConverter(receiver), userId, opId, restricted,
opPackageName, 0 /* cookie */, false /* requireConfirmation */, getSensorId(),
isStrongBiometric, surface, statsClient, mTaskStackListener, mLockoutTracker);
authenticateInternal(client, opPackageName);
@@ -209,21 +177,11 @@ public class FingerprintService extends BiometricServiceBase {
int cookie, int callingUid, int callingPid, int callingUserId,
Surface surface) throws RemoteException {
checkPermission(MANAGE_BIOMETRIC);
- updateActiveGroup(userId, opPackageName);
-
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to prepare for authentication, daemon null");
- sensorReceiver.onError(getSensorId(), cookie,
- BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
+ updateActiveGroup(userId);
final boolean restricted = true; // BiometricPrompt is always restricted
- final AuthenticationClient client = new FingerprintAuthenticationClient(
- mClientFinishCallback, getContext(), daemon, token,
- new ClientMonitorCallbackConverter(sensorReceiver), userId, opId,
+ final AuthenticationClient client = new FingerprintAuthenticationClient(getContext(),
+ token, new ClientMonitorCallbackConverter(sensorReceiver), userId, opId,
restricted, opPackageName, cookie, false /* requireConfirmation */,
getSensorId(), isStrongBiometric(), surface,
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, mTaskStackListener,
@@ -258,26 +216,16 @@ public class FingerprintService extends BiometricServiceBase {
final IFingerprintServiceReceiver receiver, final String opPackageName)
throws RemoteException {
checkPermission(MANAGE_FINGERPRINT);
- updateActiveGroup(userId, opPackageName);
+ updateActiveGroup(userId);
if (token == null) {
Slog.w(TAG, "remove(): token is null");
return;
}
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "Unable to remove, daemon null");
- receiver.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
- return;
- }
-
- final boolean restricted = isRestricted();
- final RemovalClient client = new FingerprintRemovalClient(mClientFinishCallback,
- getContext(), daemon, token, new ClientMonitorCallbackConverter(receiver),
- fingerId, userId, restricted, opPackageName, getBiometricUtils(),
- getSensorId(), statsModality());
+ final RemovalClient client = new FingerprintRemovalClient(getContext(), token,
+ new ClientMonitorCallbackConverter(receiver), fingerId, userId, opPackageName,
+ getBiometricUtils(), getSensorId());
removeInternal(client);
}
@@ -366,6 +314,12 @@ public class FingerprintService extends BiometricServiceBase {
}
@Override // Binder call
+ public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
+ checkPermission(USE_BIOMETRIC_INTERNAL);
+ return mLockoutTracker.getLockoutModeForUser(userId);
+ }
+
+ @Override // Binder call
public long getAuthenticatorId(int callingUserId) {
checkPermission(USE_BIOMETRIC_INTERNAL);
return FingerprintService.this.getAuthenticatorId(callingUserId);
@@ -612,6 +566,11 @@ public class FingerprintService extends BiometricServiceBase {
}
@Override
+ protected IBiometricsFingerprint getDaemon() {
+ return getFingerprintDaemon();
+ }
+
+ @Override
protected BiometricUtils getBiometricUtils() {
return FingerprintUtils.getInstance();
}
@@ -635,12 +594,11 @@ public class FingerprintService extends BiometricServiceBase {
}
@Override
- protected void updateActiveGroup(int userId, String clientPackage) {
+ protected void updateActiveGroup(int userId) {
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon != null) {
try {
- userId = getUserOrWorkProfileId(clientPackage, userId);
if (userId != mCurrentUserId) {
int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
if (firstSdkInt < Build.VERSION_CODES.BASE) {
@@ -747,18 +705,10 @@ public class FingerprintService extends BiometricServiceBase {
@Override
protected void doTemplateCleanupForUser(int userId) {
- final IBiometricsFingerprint daemon = getFingerprintDaemon();
- if (daemon == null) {
- Slog.e(TAG, "daemon null, skipping template cleanup");
- return;
- }
-
- final boolean restricted = !hasPermission(getManageBiometricPermission());
final List<? extends BiometricAuthenticator.Identifier> enrolledList =
getEnrolledTemplates(userId);
final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
- mClientFinishCallback, getContext(), daemon, userId, restricted,
- getContext().getOpPackageName(), getSensorId(), statsModality(), enrolledList,
+ getContext(), userId, getContext().getOpPackageName(), getSensorId(), enrolledList,
getBiometricUtils());
cleanupInternal(client);
}
@@ -793,7 +743,7 @@ public class FingerprintService extends BiometricServiceBase {
if (halId != 0) {
loadAuthenticatorIds();
final int userId = ActivityManager.getCurrentUser();
- updateActiveGroup(userId, null);
+ updateActiveGroup(userId);
doTemplateCleanupForUser(userId);
} else {
Slog.w(TAG, "Failed to open Fingerprint HAL!");
diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
index a2e51371233b..9e0405792746 100644
--- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
@@ -23,6 +23,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import com.android.server.biometrics.SensorConfig;
+import com.android.server.biometrics.sensors.LockoutTracker;
/**
* TODO(b/141025588): Add JavaDoc.
@@ -63,6 +64,12 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
}
@Override
+ public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId)
+ throws RemoteException {
+ return LockoutTracker.LOCKOUT_NONE;
+ }
+
+ @Override
public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException {
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java
index 1e7b606802ea..023ed460429c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java
@@ -85,6 +85,11 @@ public class IrisService extends BiometricServiceBase {
}
@Override
+ protected Object getDaemon() {
+ return null;
+ }
+
+ @Override
protected BiometricUtils getBiometricUtils() {
return null;
}
@@ -95,7 +100,7 @@ public class IrisService extends BiometricServiceBase {
}
@Override
- protected void updateActiveGroup(int userId, String clientPackage) {
+ protected void updateActiveGroup(int userId) {
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 4afed48ce8ee..f0be9f1d3213 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -64,6 +64,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.server.biometrics.sensors.LockoutTracker;
import org.junit.Before;
import org.junit.Test;
@@ -825,6 +826,62 @@ public class BiometricServiceTest {
}
@Test
+ public void testBiometricAuth_whenBiometricLockoutTimed_sendsErrorAndModality()
+ throws Exception {
+ testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_TIMED,
+ BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT);
+ }
+
+ @Test
+ public void testBiometricAuth_whenBiometricLockoutPermanent_sendsErrorAndModality()
+ throws Exception {
+ testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_PERMANENT,
+ BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
+ }
+
+ private void testBiometricAuth_whenLockout(@LockoutTracker.LockoutMode int lockoutMode,
+ int biometricPromptError) throws Exception {
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(lockoutMode);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
+ false /* requireConfirmation */, null /* authenticators */);
+ waitForIdle();
+
+ // Modality and error are sent
+ verify(mReceiver1).onError(eq(BiometricAuthenticator.TYPE_FINGERPRINT),
+ eq(biometricPromptError), eq(0) /* vendorCode */);
+ }
+
+ @Test
+ public void testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential()
+ throws Exception {
+ when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true);
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(LockoutTracker.LOCKOUT_PERMANENT);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
+ false /* requireConfirmation */,
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG);
+ waitForIdle();
+
+ verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+ assertNotNull(mBiometricService.mCurrentAuthSession);
+ assertEquals(AuthSession.STATE_SHOWING_DEVICE_CREDENTIAL,
+ mBiometricService.mCurrentAuthSession.getState());
+ assertEquals(Authenticators.DEVICE_CREDENTIAL,
+ mBiometricService.mCurrentAuthSession.mPromptInfo.getAuthenticators());
+ verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
+ eq(mBiometricService.mCurrentAuthSession.mPromptInfo),
+ any(IBiometricSysuiReceiver.class),
+ eq(0 /* biometricModality */),
+ anyBoolean() /* requireConfirmation */,
+ anyInt() /* userId */,
+ eq(TEST_PACKAGE_NAME),
+ anyLong() /* sessionId */);
+ }
+
+ @Test
public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() {
final boolean allowDeviceCredential = false;
final @Authenticators.Types int authenticators =
@@ -1199,6 +1256,29 @@ public class BiometricServiceTest {
}
@Test
+ public void testCanAuthenticate_whenLockoutTimed() throws Exception {
+ testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED);
+ }
+
+ @Test
+ public void testCanAuthenticate_whenLockoutPermanent() throws Exception {
+ testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT);
+ }
+
+ private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode)
+ throws Exception {
+ // When only biometric is requested, and sensor is strong enough
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(lockoutMode);
+
+ // Lockout is not considered an error for BiometricManager#canAuthenticate
+ assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
+ invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
+ }
+
+ @Test
public void testAuthenticatorActualStrength() {
// Tuple of OEM config, updatedStrength, and expectedStrength
final int[][] testCases = {
@@ -1497,6 +1577,8 @@ public class BiometricServiceTest {
when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
.thenReturn(enrolled);
when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(LockoutTracker.LOCKOUT_NONE);
mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FINGERPRINT, modality, strength,
mFingerprintAuthenticator);
}
@@ -1504,6 +1586,8 @@ public class BiometricServiceTest {
if ((modality & BiometricAuthenticator.TYPE_FACE) != 0) {
when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(enrolled);
when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
+ when(mFaceAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(LockoutTracker.LOCKOUT_NONE);
mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, strength,
mFaceAuthenticator);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
index 8aa0406469ec..b05a819ba489 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java
@@ -225,7 +225,11 @@ public class UtilsTest {
{BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE},
{BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT,
- BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE}
+ BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE},
+ {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+ BiometricManager.BIOMETRIC_SUCCESS},
+ {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
+ BiometricManager.BIOMETRIC_SUCCESS}
};
for (int i = 0; i < testCases.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricServiceBaseTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricServiceBaseTest.java
index 8fc9d449ff6e..d4b299db8c4d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricServiceBaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricServiceBaseTest.java
@@ -51,6 +51,11 @@ public class BiometricServiceBaseTest {
}
@Override
+ protected Object getDaemon() {
+ return null;
+ }
+
+ @Override
protected BiometricUtils getBiometricUtils() {
return null;
}
@@ -61,7 +66,7 @@ public class BiometricServiceBaseTest {
}
@Override
- protected void updateActiveGroup(int userId, String clientPackage) {
+ protected void updateActiveGroup(int userId) {
}
@Override