summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Haining Chen <hainingc@google.com> 2024-01-05 12:57:06 -0800
committer Haining Chen <hainingc@google.com> 2024-01-22 17:32:27 -0800
commita6d2a35907c81ce4a5be2835e4d59fb2c81c06cc (patch)
treee79a5dff6dd6bc2652d2298a133385b8eb8ef871
parent376a6a6a970472600063074ba4a458283df5967a (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
-rw-r--r--core/java/android/hardware/biometrics/AuthenticationStateListener.aidl16
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt4
-rw-r--r--services/core/java/com/android/server/biometrics/AuthService.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java34
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java32
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java25
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java15
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java19
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java24
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");