diff options
41 files changed, 550 insertions, 483 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/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 0cf233790a8d..1be553ee6b99 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -80,6 +80,9 @@ 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); diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index b72881ace9df..7111b86daba5 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -84,6 +84,9 @@ 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); 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..4d5060c2c37b 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,11 +47,11 @@ 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, boolean restricted, + @NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction, int statsClient) { - super(finishCallback, context, token, listener, userId, restricted, owner, cookie, sensorId, + super(context, token, listener, userId, restricted, owner, cookie, sensorId, statsModality, statsAction, statsClient); mPowerManager = context.getSystemService(PowerManager.class); mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); @@ -59,6 +59,16 @@ public abstract class AcquisitionClient extends ClientMonitor } @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..3c30623e7308 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"; @@ -48,14 +49,16 @@ public abstract class AuthenticationClient extends AcquisitionClient { private long mStartTimeMs; private boolean mAlreadyCancelled; - public AuthenticationClient(@NonNull FinishCallback finishCallback, @NonNull Context context, + 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(finishCallback, context, token, listener, targetUserId, restricted, owner, cookie, - sensorId, statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); + super(context, token, listener, targetUserId, restricted, owner, cookie, sensorId, + statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient); mIsStrongBiometric = isStrongBiometric; mOperationId = operationId; mRequireConfirmation = requireConfirmation; @@ -183,7 +186,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 +209,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 f450e03ecdee..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(); @@ -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(); @@ -252,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); @@ -338,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()); } @@ -519,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; } @@ -545,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)) { @@ -621,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(" @@ -638,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 */); } @@ -750,7 +744,7 @@ public abstract class BiometricServiceBase extends SystemService * @param initiatedByClient true for authenticate, remove and enroll */ @VisibleForTesting - protected 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 " + @@ -810,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() @@ -822,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); } @@ -934,21 +937,6 @@ 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 void listenForUserSwitches() { try { ActivityManager.getService().registerUserSwitchObserver( 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 7633a0fd5291..2e75c6c7724c 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,25 +51,24 @@ 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) @@ -83,12 +82,11 @@ 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, - @Nullable 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, boolean restricted, + @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; @@ -112,10 +110,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. 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..7e8af3c62d67 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,12 +41,12 @@ 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, + public EnrollClient(@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, boolean shouldVibrate) { - super(finishCallback, context, token, listener, userId, restricted, owner, 0 /* cookie */, + super(context, token, listener, userId, restricted, owner, 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricUtils = utils; @@ -88,7 +88,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..b521a87cfee6 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 */, + super(context, token, listener, 0 /* userId */, false /* restricted */, 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..ed63ad05ecce 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,21 +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, boolean restricted, String owner, List<? extends BiometricAuthenticator.Identifier> enrolledList, BiometricUtils utils, int sensorId, int statsModality); - 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, boolean restricted, String owner, BiometricUtils utils, + int sensorId, int statsModality); - protected InternalCleanupClient(@NonNull FinishCallback finishCallback, - @NonNull Context context, int userId, boolean restricted, + protected InternalCleanupClient(@NonNull Context context, int userId, boolean restricted, @NonNull String owner, int sensorId, int statsModality, @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList, @NonNull BiometricUtils utils) { - super(finishCallback, context, null /* token */, null /* ClientMonitorCallbackConverter */, + super(context, null /* token */, null /* ClientMonitorCallbackConverter */, userId, restricted, owner, 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricUtils = utils; @@ -109,22 +108,29 @@ public abstract class InternalCleanupClient extends ClientMonitor implements Enu private void startCleanupUnknownHalTemplates() { UserTemplate template = mUnknownHALTemplates.get(0); mUnknownHALTemplates.remove(template); - mCurrentTask = getRemovalClient(mRemoveFinishCallback, getContext(), getToken(), + mCurrentTask = getRemovalClient(getContext(), getToken(), template.mIdentifier.getBiometricId(), template.mUserId, getIsRestricted(), getContext().getPackageName(), mBiometricUtils, getSensorId(), mStatsModality); 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(), + getIsRestricted(), getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId(), + mStatsModality); + 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..633cedf4b556 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, - @NonNull String owner, + protected InternalEnumerateClient(@NonNull Context context, @NonNull IBinder token, int userId, + boolean restricted, @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, restricted, 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..68dac6bda40a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -27,18 +27,18 @@ 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 */, + public RemovalClient(@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(context, token, listener, userId, restricted, owner, 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricId = biometricId; @@ -46,7 +46,14 @@ public abstract class RemovalClient extends ClientMonitor implements RemovalCons } @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..f8dff5783ec3 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, - BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, - BiometricsProtoEnums.CLIENT_UNKNOWN); + public RevokeChallengeClient(Context context, IBinder token, String owner, int sensorId) { + super(context, token, null /* listener */, 0 /* userId */, false /* restricted */, 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..ec77880d888f 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,6 +16,8 @@ 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.face.V1_0.IBiometricsFace; @@ -39,24 +41,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, - int sensorId) { - super(finishCallback, context, token, listener, userId, hardwareAuthToken, restricted, + FaceEnrollClient(@NonNull Context context, @NonNull IBinder token, + @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull byte[] hardwareAuthToken, boolean restricted, @NonNull String owner, + @NonNull BiometricUtils utils, @NonNull int[] disabledFeatures, int timeoutSec, + int statsModality, @Nullable NativeHandle surfaceHandle, int sensorId) { + super(context, token, listener, userId, hardwareAuthToken, restricted, owner, utils, timeoutSec, statsModality, sensorId, false /* shouldVibrate */); - mDaemon = daemon; 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 index a54e71c72ed6..0b75a68d0e92 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java @@ -33,28 +33,36 @@ 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 { +public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { private static final String TAG = "FaceGetFeatureClient"; - private final IBiometricsFace mDaemon; private final int mFeature; private final int mFaceId; - FaceGetFeatureClient(@NonNull FinishCallback finishCallback, @NonNull Context context, - @NonNull IBiometricsFace daemon, @NonNull IBinder token, + FaceGetFeatureClient(@NonNull Context context, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, int feature, int faceId) { - super(finishCallback, context, token, listener, userId, false /* restricted */, owner, + super(context, token, listener, userId, false /* restricted */, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); - mDaemon = daemon; 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() { + public void start(@NonNull IBiometricsFace daemon, @NonNull FinishCallback finishCallback) { + super.start(daemon, finishCallback); startHalOperation(); } 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..e52f6c7cb747 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 @@ -34,36 +34,32 @@ 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, + FaceInternalCleanupClient(@NonNull Context context, int userId, boolean restricted, + @NonNull String owner, int sensorId, int statsModality, @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList, @NonNull BiometricUtils utils) { - super(finishCallback, context, userId, restricted, owner, sensorId, statsModality, + super(context, userId, restricted, owner, sensorId, statsModality, enrolledList, utils); - mDaemon = daemon; } @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, boolean restricted, 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); + return new FaceInternalEnumerateClient(context, token, userId, restricted, owner, + enrolledList, utils, sensorId, statsModality); } @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, boolean restricted, String owner, BiometricUtils utils, + int sensorId, int statsModality) { // 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, restricted, owner, utils, sensorId, statsModality); } } 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..83798c56311c 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 @@ -34,19 +34,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, - @NonNull String owner, + FaceInternalEnumerateClient(@NonNull Context context, @NonNull IBinder token, int userId, + boolean restricted, @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, + super(context, token, userId, restricted, owner, enrolledList, utils, sensorId, statsModality); - mDaemon = daemon; } @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..1184ea93f4a3 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 @@ -31,18 +31,15 @@ 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, + super(context, token, listener, biometricId, userId, restricted, owner, utils, sensorId, statsModality); - mDaemon = daemon; } @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 index a54a0176dac1..171ee042f37e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceResetLockoutClient.java @@ -31,21 +31,18 @@ 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 { +public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> { private static final String TAG = "FaceResetLockoutClient"; - private final IBiometricsFace mDaemon; private final ArrayList<Byte> mHardwareAuthToken; - FaceResetLockoutClient(@NonNull FinishCallback finishCallback, @NonNull Context context, - @NonNull IBiometricsFace daemon, int userId, String owner, int sensorId, + FaceResetLockoutClient(@NonNull Context context, int userId, String owner, int sensorId, byte[] hardwareAuthToken) { - super(finishCallback, context, null /* token */, null /* listener */, userId, + super(context, null /* token */, null /* listener */, userId, false /* restricted */, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); - mDaemon = daemon; mHardwareAuthToken = new ArrayList<>(); for (byte b : hardwareAuthToken) { @@ -54,7 +51,14 @@ public class FaceResetLockoutClient extends ClientMonitor { } @Override - public void start() { + public void unableToStart() { + // Nothing to do here + } + + @Override + public void start(@NonNull IBiometricsFace daemon, @NonNull FinishCallback finishCallback) { + super.start(daemon, finishCallback); + startHalOperation(); } 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 872c164c932f..aa1db19c4492 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 @@ -85,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; @@ -109,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); } @@ -129,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,7 +140,7 @@ public class FaceService extends BiometricServiceBase { @Override // Binder call public void enroll(int userId, final IBinder token, final byte[] cryptoToken, final IFaceServiceReceiver receiver, final String opPackageName, - final int[] disabledFeatures, Surface surface) throws RemoteException { + final int[] disabledFeatures, Surface surface) { checkPermission(MANAGE_BIOMETRIC); updateActiveGroup(userId); @@ -162,17 +149,9 @@ public class FaceService extends BiometricServiceBase { 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), + final EnrollClient client = new FaceEnrollClient(getContext(), token, + new ClientMonitorCallbackConverter(receiver), userId, cryptoToken, restricted, opPackageName, getBiometricUtils(), disabledFeatures, ENROLL_TIMEOUT_SEC, statsModality(), convertSurfaceToNativeHandle(surface), getSensorId()); @@ -197,26 +176,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 String opPackageName) { checkPermission(USE_BIOMETRIC_INTERNAL); updateActiveGroup(userId); - 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; - } - 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); } @@ -224,23 +195,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); - 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; - } - 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, @@ -270,8 +232,7 @@ 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); @@ -280,24 +241,15 @@ public class FaceService extends BiometricServiceBase { 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, + final RemovalClient client = new FaceRemovalClient(getContext(), token, + new ClientMonitorCallbackConverter(receiver), faceId, userId, restricted, opPackageName, getBiometricUtils(), getSensorId(), statsModality()); 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); } @@ -367,6 +319,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); @@ -384,16 +342,9 @@ public class FaceService extends BiometricServiceBase { Slog.d(TAG, "Resetting lockout for user: " + userId); - final IBiometricsFace daemon = getFaceDaemon(); - if (daemon == null) { - Slog.e(TAG, "daemon null, skipping template cleanup"); - return; - } - updateActiveGroup(userId); - final FaceResetLockoutClient client = new FaceResetLockoutClient( - mClientFinishCallback, getContext(), daemon, userId, - getContext().getOpPackageName(), getSensorId(), hardwareAuthToken); + final FaceResetLockoutClient client = new FaceResetLockoutClient(getContext(), + userId, getContext().getOpPackageName(), getSensorId(), hardwareAuthToken); startClient(client, true /* initiatedByClient */); }); } @@ -416,16 +367,9 @@ public class FaceService extends BiometricServiceBase { final int faceId = getFirstTemplateForUser(mCurrentUserId); - final IBiometricsFace daemon = getFaceDaemon(); - if (daemon == null) { - Slog.e(TAG, "daemon null, skipping template cleanup"); - return; - } - - final FaceSetFeatureClient client = new FaceSetFeatureClient(mClientFinishCallback, - getContext(), daemon, token, new ClientMonitorCallbackConverter(receiver), - userId, opPackageName, getSensorId(), feature, enabled, hardwareAuthToken, - faceId); + final FaceSetFeatureClient client = new FaceSetFeatureClient(getContext(), + token, new ClientMonitorCallbackConverter(receiver), userId, opPackageName, + getSensorId(), feature, enabled, hardwareAuthToken, faceId); startClient(client, true /* initiatedByClient */); }); @@ -451,15 +395,9 @@ public class FaceService extends BiometricServiceBase { // TODO: Support multiple faces final int faceId = getFirstTemplateForUser(mCurrentUserId); - final IBiometricsFace daemon = getFaceDaemon(); - if (daemon == null) { - Slog.e(TAG, "daemon null, skipping template cleanup"); - return; - } - - final FaceGetFeatureClient client = new FaceGetFeatureClient(mClientFinishCallback, - getContext(), daemon, token, new ClientMonitorCallbackConverter(receiver), - userId, opPackageName, getSensorId(), feature, faceId); + final FaceGetFeatureClient client = new FaceGetFeatureClient(getContext(), token, + new ClientMonitorCallbackConverter(receiver), userId, opPackageName, + getSensorId(), feature, faceId); startClient(client, true /* initiatedByClient */); }); @@ -643,6 +581,11 @@ public class FaceService extends BiometricServiceBase { } @Override + protected IBiometricsFace getDaemon() { + return getFaceDaemon(); + } + + @Override protected BiometricUtils getBiometricUtils() { return FaceUtils.getInstance(); } @@ -754,19 +697,12 @@ 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, + restricted, getContext().getOpPackageName(), getSensorId(), statsModality(), + enrolledList, getBiometricUtils()); cleanupInternal(client); } 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 index c0420f49b9ed..229608720562 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceSetFeatureClient.java @@ -34,25 +34,22 @@ 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 { +public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> { private static final String TAG = "FaceSetFeatureClient"; - private final IBiometricsFace mDaemon; private final int mFeature; private final boolean mEnabled; private final ArrayList<Byte> mHardwareAuthToken; private final int mFaceId; - FaceSetFeatureClient(@NonNull FinishCallback finishCallback, @NonNull Context context, - @NonNull IBiometricsFace daemon, @NonNull IBinder token, + 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(finishCallback, context, token, listener, userId, false /* restricted */, + super(context, token, listener, userId, false /* restricted */, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); - mDaemon = daemon; mFeature = feature; mEnabled = enabled; mFaceId = faceId; @@ -64,7 +61,18 @@ public class FaceSetFeatureClient extends ClientMonitor { } @Override - public void start() { + 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); } 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..cd593290ec7e 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 @@ -33,20 +33,17 @@ 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, + super(context, token, listener, userId, hardwareAuthToken, restricted, owner, utils, timeoutSec, statsModality, sensorId, shouldVibrate); - mDaemon = daemon; } @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..a2c3e7b65a22 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 @@ -34,35 +34,32 @@ 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, + FingerprintInternalCleanupClient(@NonNull Context context,int userId, boolean restricted, @NonNull String owner, int sensorId, int statsModality, @NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList, @NonNull BiometricUtils utils) { - super(finishCallback, context, userId, restricted, owner, sensorId, statsModality, + super(context, userId, restricted, owner, sensorId, statsModality, enrolledList, utils); - mDaemon = daemon; } @Override - protected InternalEnumerateClient getEnumerateClient(FinishCallback finishCallback, + protected InternalEnumerateClient<IBiometricsFingerprint> getEnumerateClient( Context context, IBinder token, int userId, boolean restricted, String owner, List<? extends BiometricAuthenticator.Identifier> enrolledList, BiometricUtils utils, int sensorId, int statsModality) { - return new FingerprintInternalEnumerateClient(finishCallback, context, mDaemon, token, + return new FingerprintInternalEnumerateClient(context, token, userId, restricted, owner, enrolledList, utils, sensorId, statsModality); } @Override - protected RemovalClient getRemovalClient(FinishCallback finishCallback, Context context, + protected RemovalClient<IBiometricsFingerprint> getRemovalClient(Context context, IBinder token, int biometricId, int userId, boolean restricted, String owner, BiometricUtils utils, int sensorId, int statsModality) { // Internal remove does not need to send results to anyone. Cleanup (enumerate + remove) // is all done internally. - return new FingerprintRemovalClient(finishCallback, context, mDaemon, token, + return new FingerprintRemovalClient(context, token, null /* ClientMonitorCallbackConverter */, biometricId, userId, restricted, owner, utils, sensorId, statsModality); } 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..d03b39ca242d 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 @@ -34,19 +34,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, + boolean restricted, @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, + super(context, token, userId, restricted, owner, enrolledList, utils, sensorId, statsModality); - mDaemon = daemon; } @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..aa7a99666792 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 @@ -32,19 +32,15 @@ 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, + super(context, token, listener, biometricId, userId, restricted, owner, utils, sensorId, statsModality); - mDaemon = daemon; } @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 80c355f47758..e6e5dc2043c4 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 @@ -90,7 +90,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; @@ -108,19 +108,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); } @@ -128,37 +121,23 @@ 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 String opPackageName, Surface surface) { checkPermission(MANAGE_FINGERPRINT); updateActiveGroup(userId); - 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; - } - 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, restricted, + opPackageName, getBiometricUtils(), ENROLL_TIMEOUT_SEC, statsModality(), + getSensorId(), true /* shouldVibrate */); enrollInternal(client, userId); } @@ -172,17 +151,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 { + final String opPackageName, Surface surface) { updateActiveGroup(userId); - 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 boolean isStrongBiometric; final long ident = Binder.clearCallingIdentity(); try { @@ -194,9 +165,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); @@ -210,19 +180,9 @@ public class FingerprintService extends BiometricServiceBase { checkPermission(MANAGE_BIOMETRIC); updateActiveGroup(userId); - 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; - } - 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, @@ -264,19 +224,10 @@ public class FingerprintService extends BiometricServiceBase { 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, restricted, + opPackageName, getBiometricUtils(), getSensorId(), statsModality()); removeInternal(client); } @@ -365,6 +316,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); @@ -513,6 +470,11 @@ public class FingerprintService extends BiometricServiceBase { } @Override + protected IBiometricsFingerprint getDaemon() { + return getFingerprintDaemon(); + } + + @Override protected BiometricUtils getBiometricUtils() { return FingerprintUtils.getInstance(); } @@ -647,19 +609,12 @@ 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, - getBiometricUtils()); + getContext(), userId, restricted, getContext().getOpPackageName(), getSensorId(), + statsModality(), enrolledList, getBiometricUtils()); cleanupInternal(client); } 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 a7c8e7209b06..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; } 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 26268143b3aa..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; } |