From a3967d8a7d4b2763e5334866ec9535ae5b021124 Mon Sep 17 00:00:00 2001 From: Joshua McCloskey Date: Thu, 20 Oct 2022 15:58:35 +0000 Subject: [PATCH] Enabled multibiometric lockout for aidl hals Test: atest com.android.server.biometrics Test: atest com.android.server.locksettings Test: tested on hidl fingerprint device Test: tested on hidl face device Test: tested on aidl fingerprint/face device with various different combinations of strengths. The device tested consisted of: * Locking out device in keyguard, resetting, ensuring it works as expected * Locking out device in biometric prompt, resetting, ensuring it works as expected for work profile & default profile. Bug: 244355277 Change-Id: I849dfc13da17a49ec9b20fa58390707e1f8109ab --- .../hardware/biometrics/BiometricManager.java | 19 +++ .../biometrics/BiometricStateListener.java | 1 + .../hardware/biometrics/IAuthService.aidl | 3 + .../biometrics/IBiometricService.aidl | 4 + .../server/biometrics/AuthService.java | 11 ++ .../server/biometrics/BiometricService.java | 17 +++ .../server/biometrics/PreAuthInfo.java | 92 +++++------ .../log/BiometricContextProvider.java | 5 +- .../sensors/AuthResultCoordinator.java | 5 +- .../sensors/AuthSessionCoordinator.java | 49 +++--- .../sensors/AuthSessionListener.java | 8 +- .../sensors/AuthenticationClient.java | 57 +++---- .../sensors/MultiBiometricLockoutState.java | 48 ++++-- .../sensors/PerformanceTracker.java | 6 +- .../face/aidl/FaceAuthenticationClient.java | 46 +++--- .../sensors/face/aidl/FaceProvider.java | 66 +++++--- .../face/aidl/FaceResetLockoutClient.java | 2 +- .../biometrics/sensors/face/hidl/Face10.java | 5 +- .../face/hidl/FaceAuthenticationClient.java | 27 +++- .../aidl/FingerprintAuthenticationClient.java | 38 ++--- .../fingerprint/aidl/FingerprintProvider.java | 68 ++++++--- .../aidl/FingerprintResetLockoutClient.java | 2 +- .../fingerprint/hidl/Fingerprint21.java | 3 +- .../hidl/FingerprintAuthenticationClient.java | 35 ++++- .../locksettings/BiometricDeferredQueue.java | 35 ++++- .../locksettings/LockSettingsService.java | 7 +- .../biometrics/BiometricServiceTest.java | 19 +++ .../sensors/AuthResultCoordinatorTest.java | 47 +++++- .../sensors/AuthSessionCoordinatorTest.java | 135 +++++++++++----- .../sensors/BiometricSchedulerTest.java | 105 +++++++------ .../MultiBiometricLockoutStateTest.java | 144 ++++++++++++------ .../aidl/FaceAuthenticationClientTest.java | 5 +- .../FingerprintAuthenticationClientTest.java | 5 +- 33 files changed, 755 insertions(+), 364 deletions(-) diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index 2eb8cb9f2f81b..6b044fc5bfb6d 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -639,5 +639,24 @@ public class BiometricManager { } } } + + /** + * Notifies AuthService that keyguard has been dismissed for the given userId. + * + * @param userId + * @param hardwareAuthToken + * @hide + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + public void resetLockout(int userId, byte[] hardwareAuthToken) { + if (mService != null) { + try { + mService.resetLockout(userId, hardwareAuthToken); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + } } diff --git a/core/java/android/hardware/biometrics/BiometricStateListener.java b/core/java/android/hardware/biometrics/BiometricStateListener.java index b167cc6323d3e..71b785023835a 100644 --- a/core/java/android/hardware/biometrics/BiometricStateListener.java +++ b/core/java/android/hardware/biometrics/BiometricStateListener.java @@ -73,4 +73,5 @@ public abstract class BiometricStateListener extends IBiometricStateListener.Stu */ public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { } + } diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl index 7c3cc10b2b991..c2e5c0b6d5192 100644 --- a/core/java/android/hardware/biometrics/IAuthService.aidl +++ b/core/java/android/hardware/biometrics/IAuthService.aidl @@ -79,6 +79,9 @@ interface IAuthService { void resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId, int userId, in byte[] hardwareAuthToken); + // See documentation in BiometricManager. + void resetLockout(int userId, in byte[] hardwareAuthToken); + // Provides a localized string that may be used as the label for a button that invokes // BiometricPrompt. CharSequence getButtonLabel(int userId, String opPackageName, int authenticators); diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index 08f9ed6203f5f..c88af5aad738c 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -91,6 +91,10 @@ interface IBiometricService { void resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId, int userId, in byte[] hardwareAuthToken); + // See documentation in BiometricManager. + @EnforcePermission("USE_BIOMETRIC_INTERNAL") + void resetLockout(int userId, in byte[] hardwareAuthToken); + @EnforcePermission("USE_BIOMETRIC_INTERNAL") int getCurrentStrength(int sensorId); diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 4358ee2f05f43..acfc2a72d503f 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -409,6 +409,17 @@ public class AuthService extends SystemService { } } + @Override + public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { + checkInternalPermission(); + final long identity = Binder.clearCallingIdentity(); + try { + mBiometricService.resetLockout(userId, hardwareAuthToken); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public CharSequence getButtonLabel( int userId, diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index cd30d26b69ad8..fab7f1dfb812b 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -72,6 +72,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.DumpUtils; import com.android.server.SystemService; +import com.android.server.biometrics.log.BiometricContext; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -100,6 +101,7 @@ public class BiometricService extends SystemService { private final List mEnabledOnKeyguardCallbacks; private final Random mRandom = new Random(); @NonNull private final Supplier mRequestCounter; + @NonNull private final BiometricContext mBiometricContext; @VisibleForTesting IStatusBarService mStatusBarService; @@ -774,6 +776,16 @@ public class BiometricService extends SystemService { } } + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) + @Override // Binder call + public void resetLockout( + int userId, byte[] hardwareAuthToken) { + Slog.d(TAG, "resetLockout(userId=" + userId + + ", hat=" + (hardwareAuthToken == null ? "null " : "present") + ")"); + mBiometricContext.getAuthSessionCoordinator() + .resetLockoutFor(userId, Authenticators.BIOMETRIC_STRONG, -1); + } + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public int getCurrentStrength(int sensorId) { @@ -984,6 +996,10 @@ public class BiometricService extends SystemService { final AtomicLong generator = new AtomicLong(0); return () -> generator.incrementAndGet(); } + + public BiometricContext getBiometricContext(Context context) { + return BiometricContext.getInstance(context); + } } /** @@ -1010,6 +1026,7 @@ public class BiometricService extends SystemService { mSettingObserver = mInjector.getSettingObserver(context, mHandler, mEnabledOnKeyguardCallbacks); mRequestCounter = mInjector.getRequestGenerator(); + mBiometricContext = injector.getBiometricContext(context); try { injector.getActivityManagerService().registerUserSwitchObserver( diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index aec98f0ea4264..3813fd1971a66 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -48,8 +48,6 @@ import java.util.List; * the PreAuthInfo should not change any sensor state. */ class PreAuthInfo { - private static final String TAG = "BiometricService/PreAuthInfo"; - static final int AUTHENTICATOR_OK = 1; static final int BIOMETRIC_NO_HARDWARE = 2; static final int BIOMETRIC_DISABLED_BY_DEVICE_POLICY = 3; @@ -62,24 +60,7 @@ class PreAuthInfo { static final int BIOMETRIC_LOCKOUT_TIMED = 10; static final int BIOMETRIC_LOCKOUT_PERMANENT = 11; static final int BIOMETRIC_SENSOR_PRIVACY_ENABLED = 12; - @IntDef({AUTHENTICATOR_OK, - BIOMETRIC_NO_HARDWARE, - BIOMETRIC_DISABLED_BY_DEVICE_POLICY, - BIOMETRIC_INSUFFICIENT_STRENGTH, - BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE, - BIOMETRIC_HARDWARE_NOT_DETECTED, - BIOMETRIC_NOT_ENROLLED, - BIOMETRIC_NOT_ENABLED_FOR_APPS, - CREDENTIAL_NOT_ENROLLED, - BIOMETRIC_LOCKOUT_TIMED, - BIOMETRIC_LOCKOUT_PERMANENT, - BIOMETRIC_SENSOR_PRIVACY_ENABLED}) - @Retention(RetentionPolicy.SOURCE) - @interface AuthenticatorStatus {} - - private final boolean mBiometricRequested; - private final int mBiometricStrengthRequested; - + private static final String TAG = "BiometricService/PreAuthInfo"; final boolean credentialRequested; // Sensors that can be used for this request (e.g. strong enough, enrolled, enabled). final List eligibleSensors; @@ -90,6 +71,25 @@ class PreAuthInfo { final boolean ignoreEnrollmentState; final int userId; final Context context; + private final boolean mBiometricRequested; + private final int mBiometricStrengthRequested; + private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, + boolean credentialRequested, List eligibleSensors, + List> ineligibleSensors, boolean credentialAvailable, + boolean confirmationRequested, boolean ignoreEnrollmentState, int userId, + Context context) { + mBiometricRequested = biometricRequested; + mBiometricStrengthRequested = biometricStrengthRequested; + this.credentialRequested = credentialRequested; + + this.eligibleSensors = eligibleSensors; + this.ineligibleSensors = ineligibleSensors; + this.credentialAvailable = credentialAvailable; + this.confirmationRequested = confirmationRequested; + this.ignoreEnrollmentState = ignoreEnrollmentState; + this.userId = userId; + this.context = context; + } static PreAuthInfo create(ITrustManager trustManager, DevicePolicyManager devicePolicyManager, @@ -158,7 +158,8 @@ class PreAuthInfo { * * @return @AuthenticatorStatus */ - private static @AuthenticatorStatus int getStatusForBiometricAuthenticator( + private static @AuthenticatorStatus + int getStatusForBiometricAuthenticator( DevicePolicyManager devicePolicyManager, BiometricService.SettingObserver settingObserver, BiometricSensor sensor, int userId, String opPackageName, @@ -200,7 +201,6 @@ class PreAuthInfo { } } - final @LockoutTracker.LockoutMode int lockoutMode = sensor.impl.getLockoutModeForUser(userId); if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) { @@ -248,8 +248,8 @@ class PreAuthInfo { /** * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT}, - * {@link BiometricAuthenticator#TYPE_IRIS} or {@link BiometricAuthenticator#TYPE_FACE} - * @return + * {@link BiometricAuthenticator#TYPE_IRIS} or + * {@link BiometricAuthenticator#TYPE_FACE} */ private static int mapModalityToDevicePolicyType(int modality) { switch (modality) { @@ -265,24 +265,6 @@ class PreAuthInfo { } } - private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, - boolean credentialRequested, List eligibleSensors, - List> ineligibleSensors, boolean credentialAvailable, - boolean confirmationRequested, boolean ignoreEnrollmentState, int userId, - Context context) { - mBiometricRequested = biometricRequested; - mBiometricStrengthRequested = biometricStrengthRequested; - this.credentialRequested = credentialRequested; - - this.eligibleSensors = eligibleSensors; - this.ineligibleSensors = ineligibleSensors; - this.credentialAvailable = credentialAvailable; - this.confirmationRequested = confirmationRequested; - this.ignoreEnrollmentState = ignoreEnrollmentState; - this.userId = userId; - this.context = context; - } - private Pair calculateErrorByPriority() { // If the caller requested STRONG, and the device contains both STRONG and non-STRONG // sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's @@ -303,6 +285,7 @@ class PreAuthInfo { * surface, combined with the actual sensor/credential and user/system settings, calculate the * internal {@link AuthenticatorStatus} that should be returned to the client. Note that this * will need to be converted into the public API constant. + * * @return Pair with error being the internal {@link AuthenticatorStatus} code */ private Pair getInternalStatus() { @@ -391,7 +374,8 @@ class PreAuthInfo { /** * @return public BiometricManager result for the current request. */ - @BiometricManager.BiometricError int getCanAuthenticateResult() { + @BiometricManager.BiometricError + int getCanAuthenticateResult() { // TODO: Convert this directly return Utils.biometricConstantsToBiometricManager( Utils.authenticatorStatusToBiometricConstant( @@ -401,6 +385,7 @@ class PreAuthInfo { /** * For the given request, generate the appropriate reason why authentication cannot be started. * Note that for some errors, modality is intentionally cleared. + * * @return Pair with modality being filtered if necessary, and error * being one of the public {@link android.hardware.biometrics.BiometricConstants} codes. */ @@ -443,7 +428,8 @@ class PreAuthInfo { * @return bitmask representing the modalities that are running or could be running for the * current session. */ - @BiometricAuthenticator.Modality int getEligibleModalities() { + @BiometricAuthenticator.Modality + int getEligibleModalities() { @BiometricAuthenticator.Modality int modalities = 0; for (BiometricSensor sensor : eligibleSensors) { modalities |= sensor.modality; @@ -474,7 +460,7 @@ class PreAuthInfo { + ", StrengthRequested: " + mBiometricStrengthRequested + ", CredentialRequested: " + credentialRequested); string.append(", Eligible:{"); - for (BiometricSensor sensor: eligibleSensors) { + for (BiometricSensor sensor : eligibleSensors) { string.append(sensor.id).append(" "); } string.append("}"); @@ -489,4 +475,20 @@ class PreAuthInfo { string.append(", "); return string.toString(); } + + @IntDef({AUTHENTICATOR_OK, + BIOMETRIC_NO_HARDWARE, + BIOMETRIC_DISABLED_BY_DEVICE_POLICY, + BIOMETRIC_INSUFFICIENT_STRENGTH, + BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE, + BIOMETRIC_HARDWARE_NOT_DETECTED, + BIOMETRIC_NOT_ENROLLED, + BIOMETRIC_NOT_ENABLED_FOR_APPS, + CREDENTIAL_NOT_ENROLLED, + BIOMETRIC_LOCKOUT_TIMED, + BIOMETRIC_LOCKOUT_PERMANENT, + BIOMETRIC_SENSOR_PRIVACY_ENABLED}) + @Retention(RetentionPolicy.SOURCE) + @interface AuthenticatorStatus { + } } diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java index 23b2714dd50bb..d456736e7e8ba 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java @@ -44,7 +44,7 @@ import java.util.function.Consumer; /** * A default provider for {@link BiometricContext}. */ -final class BiometricContextProvider implements BiometricContext { +public final class BiometricContextProvider implements BiometricContext { private static final String TAG = "BiometricContextProvider"; @@ -83,7 +83,8 @@ final class BiometricContextProvider implements BiometricContext { private boolean mIsAwake = false; @VisibleForTesting - BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration, + public BiometricContextProvider( + @NonNull AmbientDisplayConfiguration ambientDisplayConfiguration, @NonNull IStatusBarService service, @Nullable Handler handler, AuthSessionCoordinator authSessionCoordinator) { mAmbientDisplayConfiguration = ambientDisplayConfiguration; diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java index bdae5f3eac327..a48a9d1c3eaa4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java @@ -75,7 +75,10 @@ class AuthResultCoordinator { * Adds auth success for a given strength to the current operation list. */ void authenticatedFor(@Authenticators.Types int strength) { - updateState(strength, (old) -> AUTHENTICATOR_UNLOCKED | old); + // Only strong unlocks matter. + if (strength == Authenticators.BIOMETRIC_STRONG) { + updateState(strength, (old) -> AUTHENTICATOR_UNLOCKED | old); + } } /** diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java index 5bc9d2341535e..1aee5d48b9ee3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java @@ -75,6 +75,7 @@ public class AuthSessionCoordinator implements AuthSessionListener { mUserId = userId; mIsAuthenticating = true; mAuthOperations.clear(); + mTimedLockouts.clear(); mAuthResultCoordinator = new AuthResultCoordinator(); mRingBuffer.addApiCall("internal : onAuthSessionStarted(" + userId + ")"); } @@ -88,7 +89,6 @@ public class AuthSessionCoordinator implements AuthSessionListener { */ void endAuthSession() { if (mIsAuthenticating) { - mAuthOperations.clear(); final long currentTime = mClock.millis(); for (Pair timedLockouts : mTimedLockouts) { mMultiBiometricLockoutState.increaseLockoutTime(mUserId, timedLockouts.first, @@ -109,16 +109,24 @@ public class AuthSessionCoordinator implements AuthSessionListener { } } + mRingBuffer.addApiCall("internal : onAuthSessionEnded(" + mUserId + ")"); - mIsAuthenticating = false; + clearSession(); } } + private void clearSession() { + mIsAuthenticating = false; + mTimedLockouts.clear(); + mAuthOperations.clear(); + } + /** - * @return true if a user can authenticate with a given strength. + * Returns the current lockout state for a given user/strength. */ - public boolean getCanAuthFor(int userId, @Authenticators.Types int strength) { - return mMultiBiometricLockoutState.canUserAuthenticate(userId, strength); + @LockoutTracker.LockoutMode + public int getLockoutStateFor(int userId, @Authenticators.Types int strength) { + return mMultiBiometricLockoutState.getLockoutState(userId, strength); } @Override @@ -145,19 +153,8 @@ public class AuthSessionCoordinator implements AuthSessionListener { } @Override - public void authenticatedFor(int userId, @Authenticators.Types int biometricStrength, - int sensorId, long requestId) { - final String authStr = - "authenticatedFor(userId=" + userId + ", strength=" + biometricStrength - + " , sensorId=" + sensorId + ", requestId= " + requestId + ")"; - mRingBuffer.addApiCall(authStr); - mAuthResultCoordinator.authenticatedFor(biometricStrength); - attemptToFinish(userId, sensorId, authStr); - } - - @Override - public void lockedOutFor(int userId, @Authenticators.Types int biometricStrength, - int sensorId, long requestId) { + public void lockedOutFor(int userId, @Authenticators.Types int biometricStrength, int sensorId, + long requestId) { final String lockedOutStr = "lockOutFor(userId=" + userId + ", biometricStrength=" + biometricStrength + ", sensorId=" + sensorId + ", requestId=" + requestId + ")"; @@ -179,12 +176,16 @@ public class AuthSessionCoordinator implements AuthSessionListener { } @Override - public void authEndedFor(int userId, @Authenticators.Types int biometricStrength, - int sensorId, long requestId) { + public void authEndedFor(int userId, @Authenticators.Types int biometricStrength, int sensorId, + long requestId, boolean wasSuccessful) { final String authEndedStr = "authEndedFor(userId=" + userId + " ,biometricStrength=" + biometricStrength - + ", sensorId=" + sensorId + ", requestId=" + requestId + ")"; + + ", sensorId=" + sensorId + ", requestId=" + requestId + ", wasSuccessful=" + + wasSuccessful + ")"; mRingBuffer.addApiCall(authEndedStr); + if (wasSuccessful) { + mAuthResultCoordinator.authenticatedFor(biometricStrength); + } attemptToFinish(userId, sensorId, authEndedStr); } @@ -195,6 +196,12 @@ public class AuthSessionCoordinator implements AuthSessionListener { "resetLockoutFor(userId=" + userId + " ,biometricStrength=" + biometricStrength + ", requestId=" + requestId + ")"; mRingBuffer.addApiCall(resetLockStr); + if (biometricStrength == Authenticators.BIOMETRIC_STRONG) { + clearSession(); + } else { + // Lockouts cannot be reset by non-strong biometrics + return; + } mMultiBiometricLockoutState.setAuthenticatorTo(userId, biometricStrength, true /*canAuthenticate */); mMultiBiometricLockoutState.clearLockoutTime(userId, biometricStrength); diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java b/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java index d97f793a84bc7..6bddf14b3a8ef 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java @@ -27,17 +27,11 @@ interface AuthSessionListener { */ void authStartedFor(int userId, int sensorId, long requestId); - /** - * Indicates a successful authentication occurred for a sensor of a given strength. - */ - void authenticatedFor(int userId, @Authenticators.Types int biometricStrength, int sensorId, - long requestId); - /** * Indicates authentication ended for a sensor of a given strength. */ void authEndedFor(int userId, @Authenticators.Types int biometricStrength, int sensorId, - long requestId); + long requestId, boolean wasSuccessful); /** * Indicates a lockout occurred for a sensor of a given strength. 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 8a24ff6cffded..57d28f95eb6a4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -81,9 +81,12 @@ public abstract class AuthenticationClient extends AcquisitionClient @State protected int mState = STATE_NEW; private long mStartTimeMs; - private boolean mAuthAttempted; private boolean mAuthSuccess = false; + private final int mSensorStrength; + // This is used to determine if we should use the old lockout counter (HIDL) or the new lockout + // counter implementation (AIDL) + private final boolean mShouldUseLockoutTracker; public AuthenticationClient(@NonNull Context context, @NonNull Supplier lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, @@ -92,7 +95,7 @@ public abstract class AuthenticationClient extends AcquisitionClient @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext, boolean isStrongBiometric, @Nullable TaskStackListener taskStackListener, @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication, - boolean shouldVibrate, boolean isKeyguardBypassEnabled) { + boolean shouldVibrate, boolean isKeyguardBypassEnabled, int sensorStrength) { super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId, shouldVibrate, biometricLogger, biometricContext); mIsStrongBiometric = isStrongBiometric; @@ -105,22 +108,13 @@ public abstract class AuthenticationClient extends AcquisitionClient mIsRestricted = restricted; mAllowBackgroundAuthentication = allowBackgroundAuthentication; mIsKeyguardBypassEnabled = isKeyguardBypassEnabled; + mShouldUseLockoutTracker = lockoutTracker != null; + mSensorStrength = sensorStrength; } @LockoutTracker.LockoutMode public int handleFailedAttempt(int userId) { - @LockoutTracker.LockoutMode final int lockoutMode = - mLockoutTracker.getLockoutModeForUser(userId); - final PerformanceTracker performanceTracker = - PerformanceTracker.getInstanceForSensorId(getSensorId()); - - if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) { - performanceTracker.incrementPermanentLockoutForUser(userId); - } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) { - performanceTracker.incrementTimedLockoutForUser(userId); - } - - return lockoutMode; + return LockoutTracker.LOCKOUT_NONE; } protected long getStartTimeMs() { @@ -273,10 +267,12 @@ public abstract class AuthenticationClient extends AcquisitionClient cancel(); } else { // Allow system-defined limit of number of attempts before giving up - @LockoutTracker.LockoutMode final int lockoutMode = - handleFailedAttempt(getTargetUserId()); - if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { - markAlreadyDone(); + if (mShouldUseLockoutTracker) { + @LockoutTracker.LockoutMode final int lockoutMode = + handleFailedAttempt(getTargetUserId()); + if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { + markAlreadyDone(); + } } try { @@ -309,13 +305,6 @@ public abstract class AuthenticationClient extends AcquisitionClient @Override public void onAcquired(int acquiredInfo, int vendorCode) { super.onAcquired(acquiredInfo, vendorCode); - - @LockoutTracker.LockoutMode final int lockoutMode = - mLockoutTracker.getLockoutModeForUser(getTargetUserId()); - if (lockoutMode == LockoutTracker.LOCKOUT_NONE) { - PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId()); - pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation()); - } } @Override @@ -331,8 +320,14 @@ public abstract class AuthenticationClient extends AcquisitionClient public void start(@NonNull ClientMonitorCallback callback) { super.start(callback); - @LockoutTracker.LockoutMode final int lockoutMode = - mLockoutTracker.getLockoutModeForUser(getTargetUserId()); + final @LockoutTracker.LockoutMode int lockoutMode; + if (mShouldUseLockoutTracker) { + lockoutMode = mLockoutTracker.getLockoutModeForUser(getTargetUserId()); + } else { + lockoutMode = getBiometricContext().getAuthSessionCoordinator() + .getLockoutStateFor(getTargetUserId(), mSensorStrength); + } + if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { Slog.v(TAG, "In lockout mode(" + lockoutMode + ") ; disallowing authentication"); int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED @@ -406,6 +401,14 @@ public abstract class AuthenticationClient extends AcquisitionClient return mAuthSuccess; } + protected int getSensorStrength() { + return mSensorStrength; + } + + protected LockoutTracker getLockoutTracker() { + return mLockoutTracker; + } + protected int getShowOverlayReason() { if (isKeyguard()) { return BiometricOverlayConstants.REASON_AUTH_KEYGUARD; diff --git a/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java b/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java index 6605d49ece9bb..c24a989405192 100644 --- a/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java +++ b/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java @@ -75,6 +75,9 @@ class MultiBiometricLockoutState { // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = !canAuth; + return; + default: + Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } @@ -89,6 +92,9 @@ class MultiBiometricLockoutState { // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).increaseLockoutTo(duration); + return; + default: + Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } @@ -103,22 +109,34 @@ class MultiBiometricLockoutState { // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).setTimedLockout(0); + return; + default: + Slog.e(TAG, "clearLockoutTime called for invalid strength : " + strength); } } /** - * Indicates if a user can perform an authentication operation with a given - * {@link Authenticators.Types} + * Retrieves the lockout state for a user of a specified strength. * * @param userId The user. * @param strength The strength of biometric that is requested to authenticate. - * @return If a user can authenticate with a given biometric of this strength. */ - boolean canUserAuthenticate(int userId, @Authenticators.Types int strength) { - final boolean canAuthenticate = getAuthMapForUser(userId).get(strength).canAuthenticate(); - Slog.d(TAG, "canUserAuthenticate(userId=" + userId + ", strength=" + strength + ") =" - + canAuthenticate); - return canAuthenticate; + @LockoutTracker.LockoutMode + int getLockoutState(int userId, @Authenticators.Types int strength) { + final Map authMap = getAuthMapForUser(userId); + if (!authMap.containsKey(strength)) { + Slog.e(TAG, "Error, getLockoutState for unknown strength: " + strength + + " returning LOCKOUT_NONE"); + return LockoutTracker.LOCKOUT_NONE; + } + final AuthenticatorState state = authMap.get(strength); + if (state.mPermanentlyLockedOut) { + return LockoutTracker.LOCKOUT_PERMANENT; + } else if (state.isTimedLockout()) { + return LockoutTracker.LOCKOUT_TIMED; + } else { + return LockoutTracker.LOCKOUT_NONE; + } } @Override @@ -152,7 +170,15 @@ class MultiBiometricLockoutState { } boolean canAuthenticate() { - return !mPermanentlyLockedOut && mClock.millis() - mTimedLockout >= 0; + return !mPermanentlyLockedOut && !isTimedLockout(); + } + + boolean isTimedLockout() { + return mClock.millis() - mTimedLockout < 0; + } + + void setTimedLockout(long duration) { + mTimedLockout = duration; } /** @@ -162,10 +188,6 @@ class MultiBiometricLockoutState { mTimedLockout = Math.max(mTimedLockout, duration); } - void setTimedLockout(long duration) { - mTimedLockout = duration; - } - String toString(long currentTime) { final String duration = mTimedLockout - currentTime > 0 ? (mTimedLockout - currentTime) + "ms" : "none"; diff --git a/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java b/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java index 42b22b0fb519d..eed2bddb03121 100644 --- a/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java +++ b/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java @@ -85,7 +85,7 @@ public class PerformanceTracker { } } - void incrementAcquireForUser(int userId, boolean isCrypto) { + public void incrementAcquireForUser(int userId, boolean isCrypto) { createUserEntryIfNecessary(userId); if (isCrypto) { @@ -95,13 +95,13 @@ public class PerformanceTracker { } } - void incrementTimedLockoutForUser(int userId) { + public void incrementTimedLockoutForUser(int userId) { createUserEntryIfNecessary(userId); mAllUsersInfo.get(userId).mTimedLockout++; } - void incrementPermanentLockoutForUser(int userId) { + public void incrementPermanentLockoutForUser(int userId) { createUserEntryIfNecessary(userId); mAllUsersInfo.get(userId).mPermanentLockout++; diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index c27d71f2f0798..b1cb257b24434 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -47,7 +47,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.LockoutConsumer; -import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.face.UsageStats; import java.util.ArrayList; @@ -63,8 +63,6 @@ class FaceAuthenticationClient extends AuthenticationClient @NonNull private final UsageStats mUsageStats; @NonNull - private final LockoutCache mLockoutCache; - @NonNull private final AuthSessionCoordinator mAuthSessionCoordinator; @Nullable private final NotificationManager mNotificationManager; @@ -72,7 +70,6 @@ class FaceAuthenticationClient extends AuthenticationClient private final int[] mBiometricPromptIgnoreListVendor; private final int[] mKeyguardIgnoreList; private final int[] mKeyguardIgnoreListVendor; - private final int mBiometricStrength; @Nullable private ICancellationSignal mCancellationSignal; @Nullable @@ -88,12 +85,12 @@ class FaceAuthenticationClient extends AuthenticationClient @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext, boolean isStrongBiometric, @NonNull UsageStats usageStats, @NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication, - boolean isKeyguardBypassEnabled, @Authenticators.Types int biometricStrength) { + boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) { this(context, lazyDaemon, token, requestId, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext, - isStrongBiometric, usageStats, lockoutCache, allowBackgroundAuthentication, - isKeyguardBypassEnabled, context.getSystemService(SensorPrivacyManager.class), - biometricStrength); + isStrongBiometric, usageStats, lockoutCache /* lockoutCache */, + allowBackgroundAuthentication, isKeyguardBypassEnabled, + context.getSystemService(SensorPrivacyManager.class), sensorStrength); } @VisibleForTesting @@ -109,13 +106,11 @@ class FaceAuthenticationClient extends AuthenticationClient @Authenticators.Types int biometricStrength) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext, - isStrongBiometric, null /* taskStackListener */, lockoutCache, - allowBackgroundAuthentication, - false /* shouldVibrate */, - isKeyguardBypassEnabled); + isStrongBiometric, null /* taskStackListener */, null /* lockoutCache */, + allowBackgroundAuthentication, false /* shouldVibrate */, + isKeyguardBypassEnabled, biometricStrength); setRequestId(requestId); mUsageStats = usageStats; - mLockoutCache = lockoutCache; mNotificationManager = context.getSystemService(NotificationManager.class); mSensorPrivacyManager = sensorPrivacyManager; mAuthSessionCoordinator = biometricContext.getAuthSessionCoordinator(); @@ -129,14 +124,12 @@ class FaceAuthenticationClient extends AuthenticationClient R.array.config_face_acquire_keyguard_ignorelist); mKeyguardIgnoreListVendor = resources.getIntArray( R.array.config_face_acquire_vendor_keyguard_ignorelist); - mBiometricStrength = biometricStrength; } @Override public void start(@NonNull ClientMonitorCallback callback) { super.start(callback); mState = STATE_STARTED; - mAuthSessionCoordinator.authStartedFor(getTargetUserId(), getSensorId(), getRequestId()); } @NonNull @@ -221,9 +214,6 @@ class FaceAuthenticationClient extends AuthenticationClient 0 /* error */, 0 /* vendorError */, getTargetUserId())); - mAuthSessionCoordinator - .authenticatedFor(getTargetUserId(), mBiometricStrength, getSensorId(), - getRequestId()); } @Override @@ -239,8 +229,6 @@ class FaceAuthenticationClient extends AuthenticationClient if (error == BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL) { BiometricNotificationUtils.showReEnrollmentNotification(getContext()); } - mAuthSessionCoordinator.authEndedFor(getTargetUserId(), mBiometricStrength, getSensorId(), - getRequestId()); super.onError(error, vendorCode); } @@ -263,6 +251,8 @@ class FaceAuthenticationClient extends AuthenticationClient mLastAcquire = acquireInfo; final boolean shouldSend = shouldSendAcquiredMessage(acquireInfo, vendorCode); onAcquiredInternal(acquireInfo, vendorCode, shouldSend); + PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId()); + pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation()); } /** @@ -290,35 +280,39 @@ class FaceAuthenticationClient extends AuthenticationClient @Override public void onLockoutTimed(long durationMillis) { - mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); + mAuthSessionCoordinator.lockOutTimed(getTargetUserId(), getSensorStrength(), getSensorId(), + durationMillis, getRequestId()); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT; getLogger().logOnError(getContext(), getOperationContext(), error, 0 /* vendorCode */, getTargetUserId()); + PerformanceTracker.getInstanceForSensorId(getSensorId()) + .incrementTimedLockoutForUser(getTargetUserId()); + try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } - mAuthSessionCoordinator.lockOutTimed(getTargetUserId(), mBiometricStrength, getSensorId(), - durationMillis, getRequestId()); } @Override public void onLockoutPermanent() { - mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); + mAuthSessionCoordinator.lockedOutFor(getTargetUserId(), getSensorStrength(), getSensorId(), + getRequestId()); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; getLogger().logOnError(getContext(), getOperationContext(), error, 0 /* vendorCode */, getTargetUserId()); + PerformanceTracker.getInstanceForSensorId(getSensorId()) + .incrementPermanentLockoutForUser(getTargetUserId()); + try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } - mAuthSessionCoordinator.lockedOutFor(getTargetUserId(), mBiometricStrength, getSensorId(), - getRequestId()); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 6488185c727d5..89852a14ba9b1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -50,10 +50,11 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; -import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; @@ -82,20 +83,34 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { private boolean mTestHalEnabled; - @NonNull private final Context mContext; - @NonNull private final BiometricStateCallback mBiometricStateCallback; - @NonNull private final String mHalInstanceName; - @NonNull @VisibleForTesting + @NonNull + @VisibleForTesting final SparseArray mSensors; // Map of sensors that this HAL supports - @NonNull private final Handler mHandler; - @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; - @NonNull private final UsageStats mUsageStats; - @NonNull private final ActivityTaskManager mActivityTaskManager; - @NonNull private final BiometricTaskStackListener mTaskStackListener; + @NonNull + private final Context mContext; + @NonNull + private final BiometricStateCallback mBiometricStateCallback; + @NonNull + private final String mHalInstanceName; + @NonNull + private final Handler mHandler; + @NonNull + private final LockoutResetDispatcher mLockoutResetDispatcher; + @NonNull + private final UsageStats mUsageStats; + @NonNull + private final ActivityTaskManager mActivityTaskManager; + @NonNull + private final BiometricTaskStackListener mTaskStackListener; // for requests that do not use biometric prompt - @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); - @NonNull private final BiometricContext mBiometricContext; - @Nullable private IFace mDaemon; + @NonNull + private final AtomicLong mRequestCounter = new AtomicLong(0); + @NonNull + private final BiometricContext mBiometricContext; + @NonNull + private final AuthSessionCoordinator mAuthSessionCoordinator; + @Nullable + private IFace mDaemon; private final class BiometricTaskStackListener extends TaskStackListener { @Override @@ -141,6 +156,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mActivityTaskManager = ActivityTaskManager.getInstance(); mTaskStackListener = new BiometricTaskStackListener(); mBiometricContext = biometricContext; + mAuthSessionCoordinator = mBiometricContext.getAuthSessionCoordinator(); for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; @@ -312,7 +328,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { @Override public int getLockoutModeForUser(int sensorId, int userId) { - return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId); + return mBiometricContext.getAuthSessionCoordinator().getLockoutStateFor(userId, + Utils.getCurrentStrength(sensorId)); } @Override @@ -423,7 +440,6 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) { mHandler.post(() -> { final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); - final int biometricStrength = Utils.getCurrentStrength(sensorId); final FaceAuthenticationClient client = new FaceAuthenticationClient( mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback, userId, operationId, restricted, opPackageName, cookie, @@ -431,8 +447,24 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), mBiometricContext, isStrongBiometric, mUsageStats, mSensors.get(sensorId).getLockoutCache(), - allowBackgroundAuthentication, isKeyguardBypassEnabled, biometricStrength); - scheduleForSensor(sensorId, client, mBiometricStateCallback); + allowBackgroundAuthentication, isKeyguardBypassEnabled, + Utils.getCurrentStrength(sensorId) + ); + scheduleForSensor(sensorId, client, new ClientMonitorCallback() { + @Override + public void onClientStarted( + BaseClientMonitor clientMonitor) { + mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId); + } + + @Override + public void onClientFinished( + BaseClientMonitor clientMonitor, + boolean success) { + mAuthSessionCoordinator.authEndedFor(userId, Utils.getCurrentStrength(sensorId), + sensorId, requestId, success); + } + }); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java index 32bed48aec95e..759c52a458073 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java @@ -89,9 +89,9 @@ public class FaceResetLockoutClient extends HalClientMonitor implem void onLockoutCleared() { resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache, mLockoutResetDispatcher); + mCallback.onClientFinished(this, true /* success */); getBiometricContext().getAuthSessionCoordinator() .resetLockoutFor(getTargetUserId(), mBiometricStrength, getRequestId()); - mCallback.onClientFinished(this, true /* success */); } public boolean interruptsPrecedingClients() { diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index 0e0ee19660249..1adc5e3e74b5b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -677,8 +677,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { opPackageName, cookie, false /* requireConfirmation */, mSensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), mBiometricContext, isStrongBiometric, mLockoutTracker, - mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled); - mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); + mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled, + Utils.getCurrentStrength(mSensorId)); + mScheduler.scheduleClientMonitor(client); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 91eec7d19b3ac..d4a7f085b8c5f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -23,6 +23,7 @@ import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFaceConstants; +import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.face.FaceManager; import android.os.IBinder; @@ -39,6 +40,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.face.UsageStats; import java.util.ArrayList; @@ -70,12 +72,12 @@ class FaceAuthenticationClient extends AuthenticationClient { @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext, boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats, boolean allowBackgroundAuthentication, - boolean isKeyguardBypassEnabled) { + boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) { super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext, isStrongBiometric, null /* taskStackListener */, lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */, - isKeyguardBypassEnabled); + isKeyguardBypassEnabled, sensorStrength); setRequestId(requestId); mUsageStats = usageStats; mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); @@ -153,6 +155,21 @@ class FaceAuthenticationClient extends AuthenticationClient { mCallback.onClientFinished(this, true /* success */); } + @Override + public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) { + @LockoutTracker.LockoutMode final int lockoutMode = + getLockoutTracker().getLockoutModeForUser(userId); + final PerformanceTracker performanceTracker = + PerformanceTracker.getInstanceForSensorId(getSensorId()); + if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) { + performanceTracker.incrementPermanentLockoutForUser(userId); + } else if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) { + performanceTracker.incrementTimedLockoutForUser(userId); + } + + return lockoutMode; + } + @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList token) { @@ -204,6 +221,12 @@ class FaceAuthenticationClient extends AuthenticationClient { if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) { BiometricNotificationUtils.showReEnrollmentNotification(getContext()); } + @LockoutTracker.LockoutMode final int lockoutMode = + getLockoutTracker().getLockoutModeForUser(getTargetUserId()); + if (lockoutMode == LockoutTracker.LOCKOUT_NONE) { + PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId()); + pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation()); + } final boolean shouldSend = shouldSend(acquireInfo, vendorCode); onAcquiredInternal(acquireInfo, vendorCode, shouldSend); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 49bd44b24f076..5f38a92f9e139 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -56,7 +56,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.LockoutConsumer; -import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.SensorOverlays; import com.android.server.biometrics.sensors.fingerprint.PowerPressHandler; import com.android.server.biometrics.sensors.fingerprint.Udfps; @@ -75,8 +75,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient private static final int MESSAGE_AUTH_SUCCESS = 2; private static final int MESSAGE_FINGER_UP = 3; @NonNull - private final LockoutCache mLockoutCache; - @NonNull private final SensorOverlays mSensorOverlays; @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @@ -85,7 +83,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient private final Handler mHandler; private final int mSkipWaitForPowerAcquireMessage; private final int mSkipWaitForPowerVendorAcquireMessage; - private final int mBiometricStrength; private final long mFingerUpIgnoresPower = 500; private final AuthSessionCoordinator mAuthSessionCoordinator; @Nullable @@ -140,12 +137,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient biometricContext, isStrongBiometric, taskStackListener, - lockoutCache, + null /* lockoutCache */, allowBackgroundAuthentication, false /* shouldVibrate */, - false /* isKeyguardBypassEnabled */); + false /* isKeyguardBypassEnabled */, + biometricStrength); setRequestId(requestId); - mLockoutCache = lockoutCache; mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController, udfpsOverlay); mSensorProps = sensorProps; @@ -166,7 +163,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient mSkipWaitForPowerVendorAcquireMessage = context.getResources().getInteger( R.integer.config_sidefpsSkipWaitForPowerVendorAcquireMessage); - mBiometricStrength = biometricStrength; mAuthSessionCoordinator = biometricContext.getAuthSessionCoordinator(); mSideFpsLastAcquireStartTime = -1; mClock = clock; @@ -196,8 +192,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient } else { mState = STATE_STARTED; } - mAuthSessionCoordinator.authStartedFor(getTargetUserId(), getSensorId(), - getRequestId()); } @NonNull @@ -211,8 +205,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient protected void handleLifecycleAfterAuth(boolean authenticated) { if (authenticated) { mCallback.onClientFinished(this, true /* success */); - mAuthSessionCoordinator.authenticatedFor( - getTargetUserId(), mBiometricStrength, getSensorId(), getRequestId()); } } @@ -304,6 +296,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient }); } } + PerformanceTracker pt = PerformanceTracker.getInstanceForSensorId(getSensorId()); + pt.incrementAcquireForUser(getTargetUserId(), isCryptoOperation()); } @@ -316,8 +310,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient } mSensorOverlays.hide(getSensorId()); - mAuthSessionCoordinator.authEndedFor(getTargetUserId(), mBiometricStrength, getSensorId(), - getRequestId()); } @Override @@ -455,7 +447,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient @Override public void onLockoutTimed(long durationMillis) { - mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); + mAuthSessionCoordinator.lockOutTimed(getTargetUserId(), getSensorStrength(), getSensorId(), + durationMillis, getRequestId()); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; getLogger() @@ -466,6 +459,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient 0 /* vendorCode */, getTargetUserId()); + PerformanceTracker.getInstanceForSensorId(getSensorId()) + .incrementTimedLockoutForUser(getTargetUserId()); + try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); } catch (RemoteException e) { @@ -474,13 +470,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient mSensorOverlays.hide(getSensorId()); mCallback.onClientFinished(this, false /* success */); - mAuthSessionCoordinator.lockOutTimed(getTargetUserId(), mBiometricStrength, getSensorId(), - durationMillis, getRequestId()); } @Override public void onLockoutPermanent() { - mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); + mAuthSessionCoordinator.lockedOutFor(getTargetUserId(), getSensorStrength(), getSensorId(), + getRequestId()); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; getLogger() @@ -491,6 +486,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient 0 /* vendorCode */, getTargetUserId()); + PerformanceTracker.getInstanceForSensorId(getSensorId()) + .incrementPermanentLockoutForUser(getTargetUserId()); + try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); } catch (RemoteException e) { @@ -499,8 +497,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient mSensorOverlays.hide(getSensorId()); mCallback.onClientFinished(this, false /* success */); - mAuthSessionCoordinator.lockedOutFor(getTargetUserId(), mBiometricStrength, getSensorId(), - getRequestId()); } @Override @@ -515,8 +511,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_POWER_PRESSED, 0, true); mSensorOverlays.hide(getSensorId()); - mAuthSessionCoordinator.authEndedFor(getTargetUserId(), - mBiometricStrength, getSensorId(), getRequestId()); }); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index a42ff9a8a2ba0..b42b1c68ec177 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -58,6 +58,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; @@ -94,15 +95,23 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi private boolean mTestHalEnabled; - @NonNull private final Context mContext; - @NonNull private final BiometricStateCallback mBiometricStateCallback; - @NonNull private final String mHalInstanceName; - @NonNull @VisibleForTesting + @NonNull + @VisibleForTesting final SparseArray mSensors; // Map of sensors that this HAL supports - @NonNull private final Handler mHandler; - @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; - @NonNull private final ActivityTaskManager mActivityTaskManager; - @NonNull private final BiometricTaskStackListener mTaskStackListener; + @NonNull + private final Context mContext; + @NonNull + private final BiometricStateCallback mBiometricStateCallback; + @NonNull + private final String mHalInstanceName; + @NonNull + private final Handler mHandler; + @NonNull + private final LockoutResetDispatcher mLockoutResetDispatcher; + @NonNull + private final ActivityTaskManager mActivityTaskManager; + @NonNull + private final BiometricTaskStackListener mTaskStackListener; // for requests that do not use biometric prompt @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); @NonNull private final BiometricContext mBiometricContext; @@ -110,6 +119,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Nullable private IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ISidefpsController mSidefpsController; @Nullable private IUdfpsOverlay mUdfpsOverlay; + private AuthSessionCoordinator mAuthSessionCoordinator; private final class BiometricTaskStackListener extends TaskStackListener { @Override @@ -154,6 +164,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mActivityTaskManager = ActivityTaskManager.getInstance(); mTaskStackListener = new BiometricTaskStackListener(); mBiometricContext = biometricContext; + mAuthSessionCoordinator = mBiometricContext.getAuthSessionCoordinator(); final List workaroundLocations = getWorkaroundSensorProps(context); @@ -179,11 +190,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi true /* resetLockoutRequiresHardwareAuthToken */, !workaroundLocations.isEmpty() ? workaroundLocations : Arrays.stream(prop.sensorLocations).map(location -> - new SensorLocationInternal( - location.display, - location.sensorLocationX, - location.sensorLocationY, - location.sensorRadius)) + new SensorLocationInternal( + location.display, + location.sensorLocationX, + location.sensorLocationY, + location.sensorRadius)) .collect(Collectors.toList())); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher, @@ -347,7 +358,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getLazySession(), token, new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, - BiometricsProtoEnums.CLIENT_UNKNOWN), + BiometricsProtoEnums.CLIENT_UNKNOWN), mBiometricContext); scheduleForSensor(sensorId, client); }); @@ -445,8 +456,30 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mUdfpsOverlayController, mSidefpsController, mUdfpsOverlay, allowBackgroundAuthentication, mSensors.get(sensorId).getSensorProperties(), mHandler, - Utils.getCurrentStrength(sensorId), SystemClock.elapsedRealtimeClock()); - scheduleForSensor(sensorId, client, mBiometricStateCallback); + Utils.getCurrentStrength(sensorId), + SystemClock.elapsedRealtimeClock()); + scheduleForSensor(sensorId, client, new ClientMonitorCallback() { + + @Override + public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { + mBiometricStateCallback.onClientStarted(clientMonitor); + mAuthSessionCoordinator.authStartedFor(userId, sensorId, requestId); + } + + @Override + public void onBiometricAction(int action) { + mBiometricStateCallback.onBiometricAction(action); + } + + @Override + public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, + boolean success) { + mBiometricStateCallback.onClientFinished(clientMonitor, success); + mAuthSessionCoordinator.authEndedFor(userId, Utils.getCurrentStrength(sensorId), + sensorId, requestId, success); + } + }); + }); } @@ -584,7 +617,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public int getLockoutModeForUser(int sensorId, int userId) { - return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId); + return mBiometricContext.getAuthSessionCoordinator().getLockoutStateFor(userId, + Utils.getCurrentStrength(sensorId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java index 22f504cf56641..0b2421b745f5b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java @@ -93,9 +93,9 @@ class FingerprintResetLockoutClient extends HalClientMonitor implem void onLockoutCleared() { resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache, mLockoutResetDispatcher); + mCallback.onClientFinished(this, true /* success */); getBiometricContext().getAuthSessionCoordinator() .resetLockoutFor(getTargetUserId(), mBiometricStrength, getRequestId()); - mCallback.onClientFinished(this, true /* success */); } /** diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index dbc96df9c4582..1f303634b0b4e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -667,7 +667,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mBiometricContext, isStrongBiometric, mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, mSidefpsController, mUdfpsOverlay, - allowBackgroundAuthentication, mSensorProperties); + allowBackgroundAuthentication, mSensorProperties, + Utils.getCurrentStrength(mSensorId)); mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); }); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index 56fa36ec20e27..089317e322dab 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -23,6 +23,7 @@ import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFingerprintConstants; +import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; @@ -42,6 +43,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.SensorOverlays; import com.android.server.biometrics.sensors.fingerprint.Udfps; import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; @@ -79,12 +81,13 @@ class FingerprintAuthenticationClient extends AuthenticationClient mPendingResetLockoutsForFingerprint; @NonNull private final ArrayList mPendingResetLockoutsForFace; + @NonNull private final ArrayList mPendingResetLockouts; /** * Authentication info for a successful user unlock via Synthetic Password. This can be used to @@ -125,7 +128,6 @@ public class BiometricDeferredQueue { } @Nullable private FaceResetLockoutTask mFaceResetLockoutTask; - private final FaceResetLockoutTask.FinishCallback mFaceFinishCallback = () -> { mFaceResetLockoutTask = null; }; @@ -135,12 +137,14 @@ public class BiometricDeferredQueue { mHandler = handler; mPendingResetLockoutsForFingerprint = new ArrayList<>(); mPendingResetLockoutsForFace = new ArrayList<>(); + mPendingResetLockouts = new ArrayList<>(); } public void systemReady(@Nullable FingerprintManager fingerprintManager, - @Nullable FaceManager faceManager) { + @Nullable FaceManager faceManager, @Nullable BiometricManager biometricManager) { mFingerprintManager = fingerprintManager; mFaceManager = faceManager; + mBiometricManager = biometricManager; } /** @@ -151,7 +155,7 @@ public class BiometricDeferredQueue { * Note that this should only ever be invoked for successful authentications, otherwise it will * consume a Gatekeeper authentication attempt and potentially wipe the user/device. * - * @param userId The user that the operation will apply for. + * @param userId The user that the operation will apply for. * @param gatekeeperPassword The Gatekeeper Password */ void addPendingLockoutResetForUser(int userId, @NonNull byte[] gatekeeperPassword) { @@ -167,6 +171,12 @@ public class BiometricDeferredQueue { mPendingResetLockoutsForFingerprint.add(new UserAuthInfo(userId, gatekeeperPassword)); } + + if (mBiometricManager != null) { + Slog.d(TAG, "Fingerprint addPendingLockoutResetForUser: " + userId); + mPendingResetLockouts.add(new UserAuthInfo(userId, + gatekeeperPassword)); + } }); } @@ -184,6 +194,14 @@ public class BiometricDeferredQueue { new ArrayList<>(mPendingResetLockoutsForFingerprint)); mPendingResetLockoutsForFingerprint.clear(); } + + if (!mPendingResetLockouts.isEmpty()) { + Slog.d(TAG, "Processing pending resetLockouts(Generic)"); + processPendingLockoutsGeneric( + new ArrayList<>(mPendingResetLockouts)); + mPendingResetLockouts.clear(); + } + }); } @@ -257,6 +275,17 @@ public class BiometricDeferredQueue { } } + private void processPendingLockoutsGeneric(List pendingResetLockouts) { + for (UserAuthInfo user : pendingResetLockouts) { + Slog.d(TAG, "Resetting biometric lockout for user: " + user.userId); + final byte[] hat = requestHatFromGatekeeperPassword(mSpManager, user, + 0 /* challenge */); + if (hat != null) { + mBiometricManager.resetLockout(user.userId, hat); + } + } + } + @Nullable private static byte[] requestHatFromGatekeeperPassword( @NonNull SyntheticPasswordManager spManager, diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index c899cf29cc3ee..92b685c78d980 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -70,6 +70,7 @@ import android.content.pm.UserInfo; import android.database.ContentObserver; import android.database.sqlite.SQLiteDatabase; import android.hardware.authsecret.V1_0.IAuthSecret; +import android.hardware.biometrics.BiometricManager; import android.hardware.face.Face; import android.hardware.face.FaceManager; import android.hardware.fingerprint.Fingerprint; @@ -552,6 +553,10 @@ public class LockSettingsService extends ILockSettings.Stub { } } + public BiometricManager getBiometricManager() { + return (BiometricManager) mContext.getSystemService(Context.BIOMETRIC_SERVICE); + } + public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName, int defaultValue) { return Settings.Global.getInt(contentResolver, keyName, defaultValue); @@ -837,7 +842,7 @@ public class LockSettingsService extends ILockSettings.Stub { // TODO: maybe skip this for split system user mode. mStorage.prefetchUser(UserHandle.USER_SYSTEM); mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), - mInjector.getFaceManager()); + mInjector.getFaceManager(), mInjector.getBiometricManager()); } private void loadEscrowData() { 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 85d8aba58dbbf..0d6d1a2e93f92 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 android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; +import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.fingerprint.FingerprintManager; import android.os.Binder; import android.os.IBinder; @@ -75,7 +76,10 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import com.android.internal.R; +import com.android.internal.statusbar.ISessionListener; import com.android.internal.statusbar.IStatusBarService; +import com.android.server.biometrics.log.BiometricContextProvider; +import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.LockoutTracker; import org.junit.Before; @@ -129,6 +133,16 @@ public class BiometricServiceTest { ITrustManager mTrustManager; @Mock DevicePolicyManager mDevicePolicyManager; + @Mock + private IStatusBarService mStatusBarService; + @Mock + private ISessionListener mSessionListener; + @Mock + private AmbientDisplayConfiguration mAmbientDisplayConfiguration; + @Mock + private AuthSessionCoordinator mAuthSessionCoordinator; + + BiometricContextProvider mBiometricContextProvider; @Before public void setUp() { @@ -160,6 +174,11 @@ public class BiometricServiceTest { when(mResources.getString(R.string.biometric_error_user_canceled)) .thenReturn(ERROR_USER_CANCELED); + when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true); + mBiometricContextProvider = new BiometricContextProvider(mAmbientDisplayConfiguration, + mStatusBarService, null /* handler */, mAuthSessionCoordinator); + when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider); + final String[] config = { "0:2:15", // ID0:Fingerprint:Strong "1:8:15", // ID1:Face:Strong diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java index c5a855732e0a5..ebf7fd8c2752d 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java @@ -61,11 +61,11 @@ public class AuthResultCoordinatorTest { assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( AUTHENTICATOR_DEFAULT); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( - AUTHENTICATOR_UNLOCKED); + AUTHENTICATOR_DEFAULT); } @Test - public void testLockout() { + public void testConvenientLockout() { mAuthResultCoordinator.lockedOutFor( BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE); @@ -80,7 +80,7 @@ public class AuthResultCoordinatorTest { } @Test - public void testConvenientLockout() { + public void testConvenientUnlock() { mAuthResultCoordinator.authenticatedFor( BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE); @@ -91,11 +91,26 @@ public class AuthResultCoordinatorTest { assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( AUTHENTICATOR_DEFAULT); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( - AUTHENTICATOR_UNLOCKED); + AUTHENTICATOR_DEFAULT); } @Test public void testWeakLockout() { + mAuthResultCoordinator.lockedOutFor( + BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE); + + Map authMap = mAuthResultCoordinator.getResult(); + + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_STRONG)).isEqualTo( + AUTHENTICATOR_DEFAULT); + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( + AUTHENTICATOR_DEFAULT); + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( + AUTHENTICATOR_LOCKED); + } + + @Test + public void testWeakUnlock() { mAuthResultCoordinator.authenticatedFor( BiometricManager.Authenticators.BIOMETRIC_WEAK); @@ -104,13 +119,29 @@ public class AuthResultCoordinatorTest { assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_STRONG)).isEqualTo( AUTHENTICATOR_DEFAULT); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( - AUTHENTICATOR_UNLOCKED); + AUTHENTICATOR_DEFAULT); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( - AUTHENTICATOR_UNLOCKED); + AUTHENTICATOR_DEFAULT); } @Test public void testStrongLockout() { + mAuthResultCoordinator.lockedOutFor( + BiometricManager.Authenticators.BIOMETRIC_STRONG); + + Map authMap = mAuthResultCoordinator.getResult(); + + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_STRONG)).isEqualTo( + AUTHENTICATOR_LOCKED); + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( + AUTHENTICATOR_LOCKED); + assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( + AUTHENTICATOR_LOCKED); + } + + + @Test + public void testStrongUnlock() { mAuthResultCoordinator.authenticatedFor( BiometricManager.Authenticators.BIOMETRIC_STRONG); @@ -136,9 +167,9 @@ public class AuthResultCoordinatorTest { assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_STRONG)).isEqualTo( AUTHENTICATOR_DEFAULT); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_WEAK)).isEqualTo( - AUTHENTICATOR_UNLOCKED | AUTHENTICATOR_LOCKED); + AUTHENTICATOR_LOCKED); assertThat(authMap.get(BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE)).isEqualTo( - AUTHENTICATOR_UNLOCKED | AUTHENTICATOR_LOCKED); + AUTHENTICATOR_LOCKED); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java index 6e4487548d64a..c3b9cb17ead8f 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java @@ -53,22 +53,28 @@ public class AuthSessionCoordinatorTest { } @Test - public void testUserUnlocked() { + public void testUserUnlockedWithWeak() { mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_STRONG, 1 /* sensorId */, 0 /* requestId */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); - mCoordinator.authenticatedFor(PRIMARY_USER, BIOMETRIC_WEAK, 1 /* sensorId */, - 0 /* requestId */); + mCoordinator.authEndedFor(PRIMARY_USER, BIOMETRIC_WEAK, 1 /* sensorId */, + 0 /* requestId */, true /* wasSuccessful */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test @@ -77,38 +83,79 @@ public class AuthSessionCoordinatorTest { mCoordinator.authStartedFor(PRIMARY_USER, 2 /* sensorId */, 0 /* requestId */); mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_STRONG, 1 /* sensorId */, 0 /* requestId */); - mCoordinator.authenticatedFor(PRIMARY_USER, BIOMETRIC_WEAK, 2 /* sensorId */, - 0 /* requestId */); + mCoordinator.authEndedFor(PRIMARY_USER, BIOMETRIC_WEAK, 2 /* sensorId */, + 0 /* requestId */, false /* wasSuccessful */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); - mCoordinator.authenticatedFor(PRIMARY_USER, BIOMETRIC_WEAK, 1 /* sensorId */, - 0 /* requestId */); + mCoordinator.authEndedFor(PRIMARY_USER, BIOMETRIC_WEAK, 1 /* sensorId */, + 0 /* requestId */, false /* wasSuccessful */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + } + + @Test + public void testWeakAndConvenientCannotResetLockout() { + mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); + mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_STRONG, 1 /* sensorId */, + 0 /* requestId */); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + + mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_WEAK, 0 /* requestId */); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + + mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE, 0 /* requestId */); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test public void testUserCanAuthDuringLockoutOfSameSession() { mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_STRONG, 0 /* requestId */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); mCoordinator.authStartedFor(PRIMARY_USER, 2 /* sensorId */, 0 /* requestId */); mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_WEAK, 2 /* sensorId */, 0 /* requestId */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } @Test @@ -123,25 +170,39 @@ public class AuthSessionCoordinatorTest { mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_STRONG, 0 /* requestId */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_WEAK)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat( + mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); mCoordinator.authStartedFor(PRIMARY_USER, 1 /* sensorId */, 0 /* requestId */); mCoordinator.authStartedFor(PRIMARY_USER, 2 /* sensorId */, 0 /* requestId */); mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_WEAK, 2 /* sensorId */, 0 /* requestId */); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mCoordinator.getLockoutStateFor(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_WEAK)).isFalse(); - assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_STRONG)).isFalse(); + assertThat( + mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mCoordinator.getLockoutStateFor(SECONDARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index 9f30c75785402..4c898b0c4d586 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.sensors; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -78,17 +79,24 @@ public class BiometricSchedulerTest { private static final int TEST_SENSOR_ID = 1; private static final int LOG_NUM_RECENT_OPERATIONS = 2; @Rule - public final TestableContext mContext = - new TestableContext(InstrumentationRegistry.getContext(), null); + public final TestableContext mContext = new TestableContext( + InstrumentationRegistry.getContext(), null); private BiometricScheduler mScheduler; private IBinder mToken; @Mock private IBiometricService mBiometricService; + @Mock + private BiometricContext mBiometricContext; + @Mock + private AuthSessionCoordinator mAuthSessionCoordinator; @Before public void setUp() { MockitoAnnotations.initMocks(this); mToken = new Binder(); + when(mAuthSessionCoordinator.getLockoutStateFor(anyInt(), anyInt())).thenReturn( + BIOMETRIC_SUCCESS); + when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator); mScheduler = new BiometricScheduler(TAG, new Handler(TestableLooper.get(this).getLooper()), BiometricScheduler.SENSOR_TYPE_UNKNOWN, null /* gestureAvailabilityTracker */, mBiometricService, LOG_NUM_RECENT_OPERATIONS); @@ -98,10 +106,10 @@ public class BiometricSchedulerTest { public void testClientDuplicateFinish_ignoredBySchedulerAndDoesNotCrash() { final Supplier nonNullDaemon = () -> mock(Object.class); - final HalClientMonitor client1 = - new TestHalClientMonitor(mContext, mToken, nonNullDaemon); - final HalClientMonitor client2 = - new TestHalClientMonitor(mContext, mToken, nonNullDaemon); + final HalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, + nonNullDaemon); + final HalClientMonitor client2 = new TestHalClientMonitor(mContext, mToken, + nonNullDaemon); mScheduler.scheduleClientMonitor(client1); mScheduler.scheduleClientMonitor(client2); @@ -112,10 +120,9 @@ public class BiometricSchedulerTest { @Test public void testRemovesPendingOperations_whenNullHal_andNotBiometricPrompt() { // Even if second client has a non-null daemon, it needs to be canceled. - final TestHalClientMonitor client1 = new TestHalClientMonitor( - mContext, mToken, () -> null); - final TestHalClientMonitor client2 = new TestHalClientMonitor( - mContext, mToken, () -> mock(Object.class)); + final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, () -> null); + final TestHalClientMonitor client2 = new TestHalClientMonitor(mContext, mToken, + () -> mock(Object.class)); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class); @@ -150,10 +157,10 @@ public class BiometricSchedulerTest { final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class); - final TestAuthenticationClient client1 = - new TestAuthenticationClient(mContext, () -> null, mToken, listener1); - final TestHalClientMonitor client2 = - new TestHalClientMonitor(mContext, mToken, () -> daemon2); + final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, () -> null, + mToken, listener1, mBiometricContext); + final TestHalClientMonitor client2 = new TestHalClientMonitor(mContext, mToken, + () -> daemon2); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class); @@ -188,15 +195,15 @@ public class BiometricSchedulerTest { @Test public void testCancelNotInvoked_whenOperationWaitingForCookie() { final Supplier lazyDaemon1 = () -> mock(Object.class); - final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, - lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class)); + final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, lazyDaemon1, + mToken, mock(ClientMonitorCallbackConverter.class), mBiometricContext); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); // Schedule a BiometricPrompt authentication request mScheduler.scheduleClientMonitor(client1, callback1); - assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart( - mock(ClientMonitorCallback.class))); + assertNotEquals(0, + mScheduler.mCurrentOperation.isReadyToStart(mock(ClientMonitorCallback.class))); assertEquals(client1, mScheduler.mCurrentOperation.getClientMonitor()); assertEquals(0, mScheduler.mPendingOperations.size()); @@ -304,7 +311,7 @@ public class BiometricSchedulerTest { final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon); final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon, - mToken, callback); + mToken, callback, mBiometricContext); // Add a non-cancellable client, then add the auth client mScheduler.scheduleClientMonitor(client1); @@ -367,7 +374,8 @@ public class BiometricSchedulerTest { final Supplier lazyDaemon = () -> mock(Object.class); final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); testCancelsWhenRequestId(requestId, cancelRequestId, started, - new TestAuthenticationClient(mContext, lazyDaemon, mToken, callback)); + new TestAuthenticationClient(mContext, lazyDaemon, mToken, callback, + mBiometricContext)); } @Test @@ -448,11 +456,11 @@ public class BiometricSchedulerTest { final long requestId2 = 20; final Supplier lazyDaemon = () -> mock(Object.class); final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); - final TestAuthenticationClient client1 = new TestAuthenticationClient( - mContext, lazyDaemon, mToken, callback); + final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, lazyDaemon, + mToken, callback, mBiometricContext); client1.setRequestId(requestId1); - final TestAuthenticationClient client2 = new TestAuthenticationClient( - mContext, lazyDaemon, mToken, callback); + final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon, + mToken, callback, mBiometricContext); client2.setRequestId(requestId2); mScheduler.scheduleClientMonitor(client1); @@ -506,8 +514,8 @@ public class BiometricSchedulerTest { @Test public void testClientDestroyed_afterFinish() { final Supplier nonNullDaemon = () -> mock(Object.class); - final TestHalClientMonitor client = - new TestHalClientMonitor(mContext, mToken, nonNullDaemon); + final TestHalClientMonitor client = new TestHalClientMonitor(mContext, mToken, + nonNullDaemon); mScheduler.scheduleClientMonitor(client); client.mCallback.onClientFinished(client, true /* success */); waitForIdle(); @@ -520,7 +528,8 @@ public class BiometricSchedulerTest { final TestableLooper looper = TestableLooper.get(this); final Supplier lazyDaemon1 = () -> mock(Object.class); final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, - lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */); + lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */, + mBiometricContext); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); mScheduler.scheduleClientMonitor(client1, callback1); @@ -555,7 +564,8 @@ public class BiometricSchedulerTest { final TestableLooper looper = TestableLooper.get(this); final Supplier lazyDaemon1 = () -> mock(Object.class); final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, - lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */); + lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */, + mBiometricContext); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); mScheduler.scheduleClientMonitor(client1, callback1); @@ -589,7 +599,8 @@ public class BiometricSchedulerTest { //Run additional auth client final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, - lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */); + lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */, + mBiometricContext); final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class); mScheduler.scheduleClientMonitor(client2, callback2); @@ -626,7 +637,8 @@ public class BiometricSchedulerTest { final TestableLooper looper = TestableLooper.get(this); final Supplier lazyDaemon1 = () -> mock(Object.class); final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, - lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */); + lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class), 0 /* cookie */, + mBiometricContext); final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class); mScheduler.scheduleClientMonitor(client1, callback1); @@ -679,19 +691,22 @@ public class BiometricSchedulerTest { TestAuthenticationClient(@NonNull Context context, @NonNull Supplier lazyDaemon, @NonNull IBinder token, - @NonNull ClientMonitorCallbackConverter listener) { - this(context, lazyDaemon, token, listener, 1 /* cookie */); + @NonNull ClientMonitorCallbackConverter listener, + BiometricContext biometricContext) { + this(context, lazyDaemon, token, listener, 1 /* cookie */, biometricContext); } TestAuthenticationClient(@NonNull Context context, @NonNull Supplier lazyDaemon, @NonNull IBinder token, - @NonNull ClientMonitorCallbackConverter listener, int cookie) { + @NonNull ClientMonitorCallbackConverter listener, int cookie, + @NonNull BiometricContext biometricContext) { super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */, false /* restricted */, TAG, cookie, false /* requireConfirmation */, - TEST_SENSOR_ID, mock(BiometricLogger.class), mock(BiometricContext.class), + TEST_SENSOR_ID, mock(BiometricLogger.class), biometricContext, true /* isStrongBiometric */, null /* taskStackListener */, - mock(LockoutTracker.class), false /* isKeyguard */, - true /* shouldVibrate */, false /* isKeyguardBypassEnabled */); + null /* lockoutTracker */, false /* isKeyguard */, + true /* shouldVibrate */, false /* isKeyguardBypassEnabled */, + 0 /* sensorStrength */); } @Override @@ -742,14 +757,12 @@ public class BiometricSchedulerTest { boolean mStoppedHal = false; int mNumCancels = 0; - TestEnrollClient(@NonNull Context context, - @NonNull Supplier lazyDaemon, @NonNull IBinder token, - @NonNull ClientMonitorCallbackConverter listener) { + TestEnrollClient(@NonNull Context context, @NonNull Supplier lazyDaemon, + @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener) { super(context, lazyDaemon, token, listener, 0 /* userId */, new byte[69], - "test" /* owner */, mock(BiometricUtils.class), - 5 /* timeoutSec */, TEST_SENSOR_ID, - true /* shouldVibrate */, - mock(BiometricLogger.class), mock(BiometricContext.class)); + "test" /* owner */, mock(BiometricUtils.class), 5 /* timeoutSec */, + TEST_SENSOR_ID, true /* shouldVibrate */, mock(BiometricLogger.class), + mock(BiometricContext.class)); } @Override @@ -787,9 +800,9 @@ public class BiometricSchedulerTest { TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token, @NonNull Supplier lazyDaemon, int cookie, int protoEnum) { - super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */, - TAG, cookie, TEST_SENSOR_ID, - mock(BiometricLogger.class), mock(BiometricContext.class)); + super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */, TAG, + cookie, TEST_SENSOR_ID, mock(BiometricLogger.class), + mock(BiometricContext.class)); mProtoEnum = protoEnum; } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java index 0b10a7b35127a..968844e4c9901 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java @@ -50,16 +50,22 @@ public class MultiBiometricLockoutStateTest { private static void unlockAllBiometrics(MultiBiometricLockoutState lockoutState, int userId) { lockoutState.setAuthenticatorTo(userId, BIOMETRIC_STRONG, true /* canAuthenticate */); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_STRONG)).isTrue(); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_WEAK)).isTrue(); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } private static void lockoutAllBiometrics(MultiBiometricLockoutState lockoutState, int userId) { lockoutState.setAuthenticatorTo(userId, BIOMETRIC_STRONG, false /* canAuthenticate */); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_STRONG)).isFalse(); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_WEAK)).isFalse(); - assertThat(lockoutState.canUserAuthenticate(userId, BIOMETRIC_CONVENIENCE)).isFalse(); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(lockoutState.getLockoutState(userId, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } private void unlockAllBiometrics() { @@ -79,9 +85,12 @@ public class MultiBiometricLockoutStateTest { @Test public void testInitialStateLockedOut() { - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } @Test @@ -89,20 +98,26 @@ public class MultiBiometricLockoutStateTest { unlockAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_CONVENIENCE, false /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); assertThat( - mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); + mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test public void testWeakLockout() { unlockAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_WEAK, false /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); assertThat( - mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); + mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test @@ -110,10 +125,13 @@ public class MultiBiometricLockoutStateTest { lockoutAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_STRONG, false /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); assertThat( - mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); + mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test @@ -121,18 +139,24 @@ public class MultiBiometricLockoutStateTest { lockoutAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_CONVENIENCE, true /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } @Test public void testWeakUnlock() { lockoutAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_WEAK, true /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } @Test @@ -140,9 +164,12 @@ public class MultiBiometricLockoutStateTest { lockoutAllBiometrics(); mLockoutState.setAuthenticatorTo(PRIMARY_USER, BIOMETRIC_STRONG, true /* canAuthenticate */); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } @Test @@ -154,45 +181,66 @@ public class MultiBiometricLockoutStateTest { lockoutAllBiometrics(lockoutState, userTwo); lockoutState.setAuthenticatorTo(userOne, BIOMETRIC_WEAK, true /* canAuthenticate */); - assertThat(lockoutState.canUserAuthenticate(userOne, BIOMETRIC_STRONG)).isFalse(); - assertThat(lockoutState.canUserAuthenticate(userOne, BIOMETRIC_WEAK)).isTrue(); - assertThat(lockoutState.canUserAuthenticate(userOne, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(lockoutState.getLockoutState(userOne, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(lockoutState.getLockoutState(userOne, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(lockoutState.getLockoutState(userOne, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); - assertThat(lockoutState.canUserAuthenticate(userTwo, BIOMETRIC_STRONG)).isFalse(); - assertThat(lockoutState.canUserAuthenticate(userTwo, BIOMETRIC_WEAK)).isFalse(); - assertThat(lockoutState.canUserAuthenticate(userTwo, BIOMETRIC_CONVENIENCE)).isFalse(); + assertThat(lockoutState.getLockoutState(userTwo, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(lockoutState.getLockoutState(userTwo, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); + assertThat(lockoutState.getLockoutState(userTwo, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_PERMANENT); } @Test public void testTimedLockout() { - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); mLockoutState.increaseLockoutTime(PRIMARY_USER, BIOMETRIC_STRONG, System.currentTimeMillis() + 1); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); assertThat( - mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); + mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); } @Test public void testTimedLockoutAfterDuration() { - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); when(mClock.millis()).thenReturn(0L); mLockoutState.increaseLockoutTime(PRIMARY_USER, BIOMETRIC_STRONG, 1); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); assertThat( - mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse(); + mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_TIMED); when(mClock.millis()).thenReturn(2L); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue(); - assertThat(mLockoutState.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue(); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_STRONG)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_WEAK)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); + assertThat(mLockoutState.getLockoutState(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isEqualTo( + LockoutTracker.LOCKOUT_NONE); } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java index 2dc3583478fbe..d10d7d433e7a3 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java @@ -47,7 +47,6 @@ import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; -import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.face.UsageStats; import org.junit.Before; @@ -85,8 +84,6 @@ public class FaceAuthenticationClientTest { @Mock private BiometricContext mBiometricContext; @Mock - private LockoutCache mLockoutCache; - @Mock private UsageStats mUsageStats; @Mock private ClientMonitorCallback mCallback; @@ -161,7 +158,7 @@ public class FaceAuthenticationClientTest { false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, - mUsageStats, mLockoutCache, false /* allowBackgroundAuthentication */, + mUsageStats, null /* mLockoutCache */, false /* allowBackgroundAuthentication */, false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */, 0 /* biometricStrength */) { @Override diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index 608eeec72e588..22d1bc5ac4abd 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -63,7 +63,6 @@ import com.android.server.biometrics.log.Probe; import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; -import com.android.server.biometrics.sensors.LockoutCache; import org.junit.Before; import org.junit.Rule; @@ -114,8 +113,6 @@ public class FingerprintAuthenticationClientTest { @Mock private BiometricManager mBiometricManager; @Mock - private LockoutCache mLockoutCache; - @Mock private IUdfpsOverlayController mUdfpsOverlayController; @Mock private ISidefpsController mSideFpsController; @@ -658,7 +655,7 @@ public class FingerprintAuthenticationClientTest { false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, - null /* taskStackListener */, mLockoutCache, + null /* taskStackListener */, null /* lockoutCache */, mUdfpsOverlayController, mSideFpsController, null, allowBackgroundAuthentication, mSensorProps, new Handler(mLooper.getLooper()), 0 /* biometricStrength */, mClock) {