diff options
| author | 2024-01-05 12:57:06 -0800 | |
|---|---|---|
| committer | 2024-01-22 17:32:27 -0800 | |
| commit | a6d2a35907c81ce4a5be2835e4d59fb2c81c06cc (patch) | |
| tree | e79a5dff6dd6bc2652d2298a133385b8eb8ef871 | |
| parent | 376a6a6a970472600063074ba4a458283df5967a (diff) | |
Add onAuthenticationSucceeded and onAuthenticationFailed
Add onAuthenticationSucceeded and onAuthenticationFailed in
AuthenticationStateListener to allow other system components to response
to biometric authentication results
Flag: ACONFIG android.adaptiveauth.report_biometric_auth_attempts DEVELOPMENT
Bug: 285053096
Test: m -j
Test: atest AuthServiceTest
Test: atest FingerprintAuthenticationClientTest
Test: atest FaceAuthenticationClientTest
Change-Id: I9ebfa7c01d06a871f4e9221ecd7244835ac1b29c
17 files changed, 266 insertions, 22 deletions
diff --git a/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl index 73ac333cfd89..d51e62e709c2 100644 --- a/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl +++ b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl @@ -33,4 +33,20 @@ oneway interface AuthenticationStateListener { * Defines behavior in response to authentication stopping */ void onAuthenticationStopped(); + + /** + * Defines behavior in response to a successful authentication + * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested + * authentication + * @param userId The user Id for the requested authentication + */ + void onAuthenticationSucceeded(int requestReason, int userId); + + /** + * Defines behavior in response to a failed authentication + * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested + * authentication + * @param userId The user Id for the requested authentication + */ + void onAuthenticationFailed(int requestReason, int userId); } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 0096877f548a..fb9ebab30250 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -15,6 +15,7 @@ */ package android.hardware.face; +import android.hardware.biometrics.AuthenticationStateListener; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricStateListener; @@ -176,6 +177,14 @@ interface IFaceService { // authenticators. The callback is automatically removed after it's invoked. void addAuthenticatorsRegisteredCallback(IFaceAuthenticatorsRegisteredCallback callback); + // Registers AuthenticationStateListener. + @EnforcePermission("USE_BIOMETRIC_INTERNAL") + void registerAuthenticationStateListener(AuthenticationStateListener listener); + + // Unregisters AuthenticationStateListener. + @EnforcePermission("USE_BIOMETRIC_INTERNAL") + void unregisterAuthenticationStateListener(AuthenticationStateListener listener); + // Registers BiometricStateListener. void registerBiometricStateListener(IBiometricStateListener listener); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt index ad2136af4b86..d28dbc0ae06f 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt @@ -94,6 +94,10 @@ constructor( override fun onAuthenticationStopped() { updateFingerprintAuthenticateReason(AuthenticationReason.NotRunning) } + + override fun onAuthenticationSucceeded(requestReason: Int, userId: Int) {} + + override fun onAuthenticationFailed(requestReason: Int, userId: Int) {} } updateFingerprintAuthenticateReason(AuthenticationReason.NotRunning) diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 8fd2ee2bdc33..21e6bac53cde 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -439,6 +439,10 @@ public class AuthService extends SystemService { if (fingerprintService != null) { fingerprintService.registerAuthenticationStateListener(listener); } + final IFaceService faceService = mInjector.getFaceService(); + if (faceService != null) { + faceService.registerAuthenticationStateListener(listener); + } } @Override @@ -449,6 +453,10 @@ public class AuthService extends SystemService { if (fingerprintService != null) { fingerprintService.unregisterAuthenticationStateListener(listener); } + final IFaceService faceService = mInjector.getFaceService(); + if (faceService != null) { + faceService.unregisterAuthenticationStateListener(listener); + } } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java index 58635353c780..1ae4d6465c57 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java @@ -91,6 +91,40 @@ public class AuthenticationStateListeners implements IBinder.DeathRecipient { } } + /** + * Defines behavior in response to a successful authentication + * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested + * authentication + * @param userId The user Id for the requested authentication + */ + public void onAuthenticationSucceeded(int requestReason, int userId) { + for (AuthenticationStateListener listener: mAuthenticationStateListeners) { + try { + listener.onAuthenticationSucceeded(requestReason, userId); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in notifying listener that authentication " + + "succeeded", e); + } + } + } + + /** + * Defines behavior in response to a failed authentication + * @param requestReason Reason from [BiometricRequestConstants.RequestReason] for the requested + * authentication + * @param userId The user Id for the requested authentication + */ + public void onAuthenticationFailed(int requestReason, int userId) { + for (AuthenticationStateListener listener: mAuthenticationStateListeners) { + try { + listener.onAuthenticationFailed(requestReason, userId); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in notifying listener that authentication " + + "failed", e); + } + } + } + @Override public void binderDied() { // Do nothing, handled below diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 0f964bb75944..fba6661a02b6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; +import android.hardware.biometrics.AuthenticationStateListener; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricService; @@ -63,6 +64,7 @@ import com.android.server.SystemService; import com.android.server.biometrics.Flags; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; @@ -99,6 +101,8 @@ public class FaceService extends SystemService { private final BiometricStateCallback<ServiceProvider, FaceSensorPropertiesInternal> mBiometricStateCallback; @NonNull + private final AuthenticationStateListeners mAuthenticationStateListeners; + @NonNull private final FaceProviderFunction mFaceProviderFunction; @NonNull private final Function<String, FaceProvider> mFaceProvider; @NonNull @@ -664,7 +668,8 @@ public class FaceService extends SystemService { for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) { providers.add( Face10.newInstance(getContext(), mBiometricStateCallback, - hidlSensor, mLockoutResetDispatcher)); + mAuthenticationStateListeners, hidlSensor, + mLockoutResetDispatcher)); } return providers; @@ -799,6 +804,24 @@ public class FaceService extends SystemService { public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { mBiometricStateCallback.registerBiometricStateListener(listener); } + + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) + @Override + public void registerAuthenticationStateListener( + @NonNull AuthenticationStateListener listener) { + super.registerAuthenticationStateListener_enforcePermission(); + + mAuthenticationStateListeners.registerAuthenticationStateListener(listener); + } + + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) + @Override + public void unregisterAuthenticationStateListener( + @NonNull AuthenticationStateListener listener) { + super.unregisterAuthenticationStateListener_enforcePermission(); + + mAuthenticationStateListeners.unregisterAuthenticationStateListener(listener); + } } public FaceService(Context context) { @@ -817,6 +840,7 @@ public class FaceService extends SystemService { mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context)); + mAuthenticationStateListeners = new AuthenticationStateListeners(); mRegistry = new FaceServiceRegistry(mServiceWrapper, biometricServiceSupplier); mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() { @Override @@ -837,8 +861,8 @@ public class FaceService extends SystemService { try { final SensorProps[] props = face.getSensorProps(); return new FaceProvider(getContext(), - mBiometricStateCallback, props, name, mLockoutResetDispatcher, - BiometricContext.getInstance(getContext()), + mBiometricStateCallback, mAuthenticationStateListeners, props, name, + mLockoutResetDispatcher, BiometricContext.getInstance(getContext()), false /* resetLockoutRequiresChallenge */); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); @@ -850,7 +874,7 @@ public class FaceService extends SystemService { if (Flags.deHidl()) { mFaceProviderFunction = faceProviderFunction != null ? faceProviderFunction : ((filteredSensorProps, resetLockoutRequiresChallenge) -> new FaceProvider( - getContext(), mBiometricStateCallback, + getContext(), mBiometricStateCallback, mAuthenticationStateListeners, filteredSensorProps.second, filteredSensorProps.first, mLockoutResetDispatcher, BiometricContext.getInstance(getContext()), 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 470dc4b7172c..b1b321692720 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 @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.face.aidl; +import static android.adaptiveauth.Flags.reportBiometricAuthAttempts; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.NotificationManager; @@ -43,6 +45,7 @@ import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthenticationClient; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; @@ -76,6 +79,8 @@ public class FaceAuthenticationClient private ICancellationSignal mCancellationSignal; @Nullable private final SensorPrivacyManager mSensorPrivacyManager; + @NonNull + private final AuthenticationStateListeners mAuthenticationStateListeners; @FaceManager.FaceAcquired private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN; @@ -88,11 +93,13 @@ public class FaceAuthenticationClient @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext, boolean isStrongBiometric, @NonNull UsageStats usageStats, @NonNull LockoutTracker lockoutCache, boolean allowBackgroundAuthentication, - @Authenticators.Types int sensorStrength) { + @Authenticators.Types int sensorStrength, + @NonNull AuthenticationStateListeners authenticationStateListeners) { this(context, lazyDaemon, token, requestId, listener, operationId, restricted, options, cookie, requireConfirmation, logger, biometricContext, isStrongBiometric, usageStats, lockoutCache, allowBackgroundAuthentication, - context.getSystemService(SensorPrivacyManager.class), sensorStrength); + context.getSystemService(SensorPrivacyManager.class), sensorStrength, + authenticationStateListeners); } @VisibleForTesting @@ -106,7 +113,8 @@ public class FaceAuthenticationClient boolean isStrongBiometric, @NonNull UsageStats usageStats, @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication, SensorPrivacyManager sensorPrivacyManager, - @Authenticators.Types int biometricStrength) { + @Authenticators.Types int biometricStrength, + @NonNull AuthenticationStateListeners authenticationStateListeners) { super(context, lazyDaemon, token, listener, operationId, restricted, options, cookie, requireConfirmation, logger, biometricContext, isStrongBiometric, null /* taskStackListener */, lockoutTracker, @@ -117,6 +125,7 @@ public class FaceAuthenticationClient mNotificationManager = context.getSystemService(NotificationManager.class); mSensorPrivacyManager = sensorPrivacyManager; mAuthSessionCoordinator = biometricContext.getAuthSessionCoordinator(); + mAuthenticationStateListeners = authenticationStateListeners; final Resources resources = getContext().getResources(); mBiometricPromptIgnoreList = resources.getIntArray( @@ -230,6 +239,16 @@ public class FaceAuthenticationClient 0 /* error */, 0 /* vendorError */, getTargetUserId())); + + if (reportBiometricAuthAttempts()) { + if (authenticated) { + mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(), + getTargetUserId()); + } else { + mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(), + getTargetUserId()); + } + } } @Override 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 e4ecf1a61155..d01c2687b1ff 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 @@ -59,6 +59,7 @@ 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.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.BiometricStateCallback; @@ -103,6 +104,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { @NonNull private final BiometricStateCallback mBiometricStateCallback; @NonNull + private final AuthenticationStateListeners mAuthenticationStateListeners; + @NonNull private final String mHalInstanceName; @NonNull private final Handler mHandler; @@ -156,18 +159,20 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { public FaceProvider(@NonNull Context context, @NonNull BiometricStateCallback biometricStateCallback, + @NonNull AuthenticationStateListeners authenticationStateListeners, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull BiometricContext biometricContext, boolean resetLockoutRequiresChallenge) { - this(context, biometricStateCallback, props, halInstanceName, lockoutResetDispatcher, - biometricContext, null /* daemon */, getHandler(), resetLockoutRequiresChallenge, - false /* testHalEnabled */); + this(context, biometricStateCallback, authenticationStateListeners, props, halInstanceName, + lockoutResetDispatcher, biometricContext, null /* daemon */, getHandler(), + resetLockoutRequiresChallenge, false /* testHalEnabled */); } @VisibleForTesting FaceProvider(@NonNull Context context, @NonNull BiometricStateCallback biometricStateCallback, + @NonNull AuthenticationStateListeners authenticationStateListeners, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @@ -178,6 +183,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { boolean testHalEnabled) { mContext = context; mBiometricStateCallback = biometricStateCallback; + mAuthenticationStateListeners = authenticationStateListeners; mHalInstanceName = halInstanceName; mFaceSensors = new SensorList<>(ActivityManager.getService()); if (Flags.deHidl()) { @@ -610,7 +616,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mAuthenticationStatsCollector), mBiometricContext, isStrongBiometric, mUsageStats, lockoutTracker, - allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId)); + allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId), + mAuthenticationStateListeners); scheduleForSensor(sensorId, client, new ClientMonitorCallback() { @Override public void onClientStarted( 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 53376669b387..48a676ce4937 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 @@ -64,6 +64,7 @@ import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.sensors.AcquisitionClient; import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.AuthenticationConsumer; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.BiometricStateCallback; @@ -119,6 +120,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull private final FaceSensorPropertiesInternal mSensorProperties; @NonNull private final BiometricStateCallback mBiometricStateCallback; + @NonNull + private final AuthenticationStateListeners mAuthenticationStateListeners; @NonNull private final Context mContext; @NonNull private final BiometricScheduler<IBiometricsFace, AidlSession> mScheduler; @NonNull private final Handler mHandler; @@ -350,6 +353,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @VisibleForTesting Face10(@NonNull Context context, @NonNull BiometricStateCallback biometricStateCallback, + @NonNull AuthenticationStateListeners authenticationStateListeners, @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull Handler handler, @@ -358,6 +362,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mSensorProperties = sensorProps; mContext = context; mBiometricStateCallback = biometricStateCallback; + mAuthenticationStateListeners = authenticationStateListeners; mSensorId = sensorProps.sensorId; mScheduler = scheduler; mHandler = handler; @@ -392,11 +397,12 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { public static Face10 newInstance(@NonNull Context context, @NonNull BiometricStateCallback biometricStateCallback, + @NonNull AuthenticationStateListeners authenticationStateListeners, @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { final Handler handler = new Handler(Looper.getMainLooper()); - return new Face10(context, biometricStateCallback, sensorProps, lockoutResetDispatcher, - handler, new BiometricScheduler<>( + return new Face10(context, biometricStateCallback, authenticationStateListeners, + sensorProps, lockoutResetDispatcher, handler, new BiometricScheduler<>( BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityTracker */), BiometricContext.getInstance(context)); @@ -846,7 +852,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient, mAuthenticationStatsCollector), mBiometricContext, isStrongBiometric, mUsageStats, mLockoutTracker, - allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId)); + allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId), + mAuthenticationStateListeners); mScheduler.scheduleClientMonitor(client); } @@ -860,7 +867,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient, mAuthenticationStatsCollector), mBiometricContext, isStrongBiometric, mLockoutTracker, mUsageStats, - allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId)); + allowBackgroundAuthentication, Utils.getCurrentStrength(mSensorId), + mAuthenticationStateListeners); 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 8ab88923d01e..e44b26399549 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 @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.face.hidl; +import static android.adaptiveauth.Flags.reportBiometricAuthAttempts; + import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; @@ -36,6 +38,7 @@ 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.AuthenticationClient; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -65,6 +68,8 @@ class FaceAuthenticationClient private int mLastAcquire; private SensorPrivacyManager mSensorPrivacyManager; + @NonNull + private final AuthenticationStateListeners mAuthenticationStateListeners; FaceAuthenticationClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon, @@ -75,7 +80,8 @@ class FaceAuthenticationClient @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext, boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats, boolean allowBackgroundAuthentication, - @Authenticators.Types int sensorStrength) { + @Authenticators.Types int sensorStrength, + @NonNull AuthenticationStateListeners authenticationStateListeners) { super(context, lazyDaemon, token, listener, operationId, restricted, options, cookie, requireConfirmation, logger, biometricContext, isStrongBiometric, null /* taskStackListener */, @@ -84,6 +90,7 @@ class FaceAuthenticationClient setRequestId(requestId); mUsageStats = usageStats; mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); + mAuthenticationStateListeners = authenticationStateListeners; final Resources resources = getContext().getResources(); mBiometricPromptIgnoreList = resources.getIntArray( @@ -186,6 +193,16 @@ class FaceAuthenticationClient 0 /* error */, 0 /* vendorError */, getTargetUserId())); + + if (reportBiometricAuthAttempts()) { + if (authenticated) { + mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(), + getTargetUserId()); + } else { + mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(), + getTargetUserId()); + } + } } @Override 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 145885de5c32..378f937f1289 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 @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static android.adaptiveauth.Flags.reportBiometricAuthAttempts; + import static com.android.systemui.shared.Flags.sidefpsControllerRefactor; import android.annotation.NonNull; @@ -231,8 +233,16 @@ public class FingerprintAuthenticationClient if (sidefpsControllerRefactor()) { mAuthenticationStateListeners.onAuthenticationStopped(); } + if (reportBiometricAuthAttempts()) { + mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(), + getTargetUserId()); + } } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; + if (reportBiometricAuthAttempts()) { + mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(), + getTargetUserId()); + } } } 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 4c1d4d6d6d12..7a329e9d69e9 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 @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.hidl; +import static android.adaptiveauth.Flags.reportBiometricAuthAttempts; + import static com.android.systemui.shared.Flags.sidefpsControllerRefactor; import android.annotation.NonNull; @@ -142,6 +144,10 @@ class FingerprintAuthenticationClient if (sidefpsControllerRefactor()) { mAuthenticationStateListeners.onAuthenticationStopped(); } + if (reportBiometricAuthAttempts()) { + mAuthenticationStateListeners.onAuthenticationSucceeded(getRequestReason(), + getTargetUserId()); + } } else { mState = STATE_STARTED_PAUSED_ATTEMPTED; final @LockoutTracker.LockoutMode int lockoutMode = @@ -161,6 +167,10 @@ class FingerprintAuthenticationClient onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */); cancel(); } + if (reportBiometricAuthAttempts()) { + mAuthenticationStateListeners.onAuthenticationFailed(getRequestReason(), + getTargetUserId()); + } } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java index 88b2ed4f79c9..071db68704af 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java @@ -16,6 +16,7 @@ package com.android.server.biometrics; +import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS; import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.TEST_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; @@ -491,6 +492,22 @@ public class AuthServiceTest { } @Test + public void testRegisterAuthenticationStateListener_callsFaceService() throws Exception { + mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS); + setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */); + + mAuthService = new AuthService(mContext, mInjector); + mAuthService.onStart(); + + final AuthenticationStateListener listener = mock(AuthenticationStateListener.class); + + mAuthService.mImpl.registerAuthenticationStateListener(listener); + + waitForIdle(); + verify(mFaceService).registerAuthenticationStateListener(eq(listener)); + } + + @Test public void testRegisterKeyguardCallback_callsBiometricServiceRegisterKeyguardCallback() throws Exception { setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */); 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 3a3dd6ea2746..f8b5b04294cd 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 @@ -16,6 +16,7 @@ package com.android.server.biometrics.sensors.face.aidl; +import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT; import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; @@ -49,6 +50,7 @@ import android.os.IBinder; import android.os.PowerManager; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import android.testing.TestableContext; import androidx.test.filters.SmallTest; @@ -58,6 +60,7 @@ import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; import com.android.server.biometrics.sensors.AuthSessionCoordinator; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutTracker; @@ -81,6 +84,8 @@ import java.util.function.Consumer; @SmallTest public class FaceAuthenticationClientTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private static final int USER_ID = 12; private static final long OP_ID = 32; private static final int WAKE_REASON = WakeReason.LIFT; @@ -105,6 +110,8 @@ public class FaceAuthenticationClientTest { @Mock private ClientMonitorCallback mCallback; @Mock + private AuthenticationStateListeners mAuthenticationStateListeners; + @Mock private AidlResponseHandler mAidlResponseHandler; @Mock private ActivityTaskManager mActivityTaskManager; @@ -264,6 +271,29 @@ public class FaceAuthenticationClientTest { verify(mHal, never()).authenticate(anyInt()); } + @Test + public void testAuthenticationStateListeners_onAuthenticationSucceeded() + throws RemoteException { + mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS); + final FaceAuthenticationClient client = createClient(); + client.start(mCallback); + client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */), + true /* authenticated */, new ArrayList<>()); + + verify(mAuthenticationStateListeners).onAuthenticationSucceeded(anyInt(), anyInt()); + } + + @Test + public void testAuthenticationStateListeners_onAuthenticationFailed() throws RemoteException { + mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS); + final FaceAuthenticationClient client = createClient(); + client.start(mCallback); + client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */), + false /* authenticated */, new ArrayList<>()); + + verify(mAuthenticationStateListeners).onAuthenticationFailed(anyInt(), anyInt()); + } + private FaceAuthenticationClient createClient() throws RemoteException { return createClient(2 /* version */, mClientMonitorCallbackConverter, false /* allowBackgroundAuthentication */, @@ -311,7 +341,8 @@ public class FaceAuthenticationClientTest { false /* requireConfirmation */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, mUsageStats, lockoutTracker, allowBackgroundAuthentication, - null /* sensorPrivacyManager */, 0 /* biometricStrength */) { + null /* sensorPrivacyManager */, 0 /* biometricStrength */, + mAuthenticationStateListeners) { @Override protected ActivityTaskManager getActivityTaskManager() { return mActivityTaskManager; diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java index 772ec8b73393..7648bd17f53c 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java @@ -51,6 +51,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.BiometricStateCallback; @@ -89,6 +90,8 @@ public class FaceProviderTest { private BiometricContext mBiometricContext; @Mock private BiometricStateCallback mBiometricStateCallback; + @Mock + private AuthenticationStateListeners mAuthenticationStateListeners; private final TestLooper mLooper = new TestLooper(); private SensorProps[] mSensorProps; @@ -119,8 +122,8 @@ public class FaceProviderTest { mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); mFaceProvider = new FaceProvider(mContext, mBiometricStateCallback, - mSensorProps, TAG, mLockoutResetDispatcher, mBiometricContext, - mDaemon, new Handler(mLooper.getLooper()), + mAuthenticationStateListeners, mSensorProps, TAG, mLockoutResetDispatcher, + mBiometricContext, mDaemon, new Handler(mLooper.getLooper()), false /* resetLockoutRequiresChallenge */, false /* testHalEnabled */); } @@ -154,7 +157,7 @@ public class FaceProviderTest { final HidlFaceSensorConfig[] hidlFaceSensorConfig = new HidlFaceSensorConfig[]{faceSensorConfig}; mFaceProvider = new FaceProvider(mContext, - mBiometricStateCallback, hidlFaceSensorConfig, TAG, + mBiometricStateCallback, mAuthenticationStateListeners, hidlFaceSensorConfig, TAG, mLockoutResetDispatcher, mBiometricContext, mDaemon, new Handler(mLooper.getLooper()), true /* resetLockoutRequiresChallenge */, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java index e558c4d64180..78c1e08ba832 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java @@ -44,6 +44,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; +import com.android.server.biometrics.sensors.AuthenticationStateListeners; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.LockoutResetDispatcher; @@ -81,6 +82,8 @@ public class Face10Test { private BiometricContext mBiometricContext; @Mock private BiometricStateCallback mBiometricStateCallback; + @Mock + private AuthenticationStateListeners mAuthenticationStateListeners; private final Handler mHandler = new Handler(Looper.getMainLooper()); private LockoutResetDispatcher mLockoutResetDispatcher; @@ -116,8 +119,8 @@ public class Face10Test { Face10.sSystemClock = Clock.fixed( Instant.ofEpochMilli(100), ZoneId.of("America/Los_Angeles")); - mFace10 = new Face10(mContext, mBiometricStateCallback, sensorProps, - mLockoutResetDispatcher, mHandler, mScheduler, mBiometricContext); + mFace10 = new Face10(mContext, mBiometricStateCallback, mAuthenticationStateListeners, + sensorProps, mLockoutResetDispatcher, mHandler, mScheduler, mBiometricContext); mBinder = new Binder(); } 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 774ea5bc6b16..4ed6f74d30fa 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 @@ -16,6 +16,7 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static android.adaptiveauth.Flags.FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR; @@ -451,6 +452,29 @@ public class FingerprintAuthenticationClientTest { } @Test + public void testAuthenticationStateListeners_onAuthenticationSucceeded() + throws RemoteException { + mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS); + final FingerprintAuthenticationClient client = createClient(); + client.start(mCallback); + client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */, + 2 /* deviceId */), true /* authenticated */, new ArrayList<>()); + + verify(mAuthenticationStateListeners).onAuthenticationSucceeded(anyInt(), anyInt()); + } + + @Test + public void testAuthenticationStateListeners_onAuthenticationFailed() throws RemoteException { + mSetFlagsRule.enableFlags(FLAG_REPORT_BIOMETRIC_AUTH_ATTEMPTS); + final FingerprintAuthenticationClient client = createClient(); + client.start(mCallback); + client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */, + 2 /* deviceId */), false /* authenticated */, new ArrayList<>()); + + verify(mAuthenticationStateListeners).onAuthenticationFailed(anyInt(), anyInt()); + } + + @Test public void cancelsAuthWhenNotInForeground() throws Exception { final ActivityManager.RunningTaskInfo topTask = new ActivityManager.RunningTaskInfo(); topTask.topActivity = new ComponentName("other", "thing"); |