From 16f0d3494ed09f4d1d86afaac03b5cd0cf793a53 Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Thu, 27 Jan 2022 13:12:21 -0800 Subject: [PATCH 1/2] Connect SysUI sessions with biometric operations logs. Update framework stats logging with new atom changes. The AoD flag is not yet reported accurately and requires the additional HAL method because most operations start when the screen is on. Bug: 204585936 Bug: 204584403 Test: atest com.android.server.biometrics.sensors Test: statsd_testdrive 87 Test: statsd_testdrive 88 Change-Id: I62cb38c9e1f8254266c51119c26fd22dfc992b1c --- .../server/biometrics/AuthSession.java | 31 +++--- .../biometrics/log/BiometricContext.java | 18 ++- .../log/BiometricContextProvider.java | 103 +++++++++++++++-- .../log/BiometricFrameworkStatsLogger.java | 48 +++++--- .../biometrics/log/BiometricLogger.java | 32 +++--- .../biometrics/sensors/AcquisitionClient.java | 8 +- .../sensors/AuthenticationClient.java | 4 +- .../biometrics/sensors/HalClientMonitor.java | 6 +- .../biometrics/sensors/face/FaceService.java | 3 +- .../face/aidl/FaceAuthenticationClient.java | 19 +--- .../sensors/face/aidl/FaceDetectClient.java | 10 +- .../sensors/face/aidl/FaceEnrollClient.java | 10 +- .../sensors/face/aidl/FaceProvider.java | 35 +++--- .../biometrics/sensors/face/aidl/Sensor.java | 7 +- .../biometrics/sensors/face/hidl/Face10.java | 34 +++--- .../fingerprint/FingerprintService.java | 7 +- .../aidl/FingerprintAuthenticationClient.java | 17 +-- .../aidl/FingerprintDetectClient.java | 10 +- .../aidl/FingerprintEnrollClient.java | 10 +- .../fingerprint/aidl/FingerprintProvider.java | 32 +++--- .../sensors/fingerprint/aidl/Sensor.java | 7 +- .../fingerprint/hidl/Fingerprint21.java | 29 +++-- .../hidl/Fingerprint21UdfpsMock.java | 11 +- .../hidl/FingerprintDetectClient.java | 5 +- .../log/BiometricContextProviderTest.java | 105 +++++++++++++++++- .../biometrics/log/BiometricLoggerTest.java | 50 ++++----- .../aidl/FaceAuthenticationClientTest.java | 19 ++-- .../face/aidl/FaceDetectClientTest.java | 18 +-- .../face/aidl/FaceEnrollClientTest.java | 22 +++- .../sensors/face/aidl/FaceProviderTest.java | 10 +- .../sensors/face/hidl/Face10Test.java | 6 +- .../FingerprintAuthenticationClientTest.java | 16 ++- .../aidl/FingerprintDetectClientTest.java | 11 +- .../aidl/FingerprintEnrollClientTest.java | 16 ++- .../aidl/FingerprintProviderTest.java | 10 +- .../fingerprint/hidl/Fingerprint21Test.java | 10 +- 36 files changed, 531 insertions(+), 258 deletions(-) diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index 0da6a1ba3109d..79705a32c2643 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -53,6 +53,7 @@ import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; +import android.hardware.biometrics.common.OperationContext; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -64,6 +65,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.FrameworkStatsLog; +import com.android.server.biometrics.log.BiometricFrameworkStatsLogger; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -681,16 +683,18 @@ public final class AuthSession implements IBinder.DeathRecipient { + ", Latency: " + latency); } - FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, + final OperationContext operationContext = new OperationContext(); + operationContext.isCrypto = isCrypto(); + BiometricFrameworkStatsLogger.getInstance().authenticate( + operationContext, statsModality(), - mUserId, - isCrypto(), + BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, - mPreAuthInfo.confirmationRequested, - FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, - latency, mDebugEnabled, - -1 /* sensorId */, + latency, + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, + mPreAuthInfo.confirmationRequested, + mUserId, -1f /* ambientLightLux */); } else { final long latency = System.currentTimeMillis() - mStartTimeMs; @@ -711,17 +715,18 @@ public final class AuthSession implements IBinder.DeathRecipient { + ", Latency: " + latency); } // Auth canceled - FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, + final OperationContext operationContext = new OperationContext(); + operationContext.isCrypto = isCrypto(); + BiometricFrameworkStatsLogger.getInstance().error( + operationContext, statsModality(), - mUserId, - isCrypto(), BiometricsProtoEnums.ACTION_AUTHENTICATE, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, - error, - 0 /* vendorCode */, mDebugEnabled, latency, - -1 /* sensorId */); + error, + 0 /* vendorCode */, + mUserId); } } diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java index 8d28298542dc0..c5e266f87149f 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricContext.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java @@ -17,6 +17,8 @@ package com.android.server.biometrics.log; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; import android.hardware.biometrics.common.OperationContext; import java.util.function.Consumer; @@ -26,11 +28,21 @@ import java.util.function.Consumer; * logging or optimizations. */ public interface BiometricContext { - /** Gets the context source. */ - static BiometricContext getInstance() { - return BiometricContextProvider.sInstance.get(); + /** Gets the context source from the system context. */ + static BiometricContext getInstance(@NonNull Context context) { + return BiometricContextProvider.defaultProvider(context); } + /** Update the given context with the most recent values and return it. */ + OperationContext updateContext(@NonNull OperationContext operationContext, + boolean isCryptoOperation); + + /** The session id for keyguard entry, if active, or null. */ + @Nullable Integer getKeyguardEntrySessionId(); + + /** The session id for biometric prompt usage, if active, or null. */ + @Nullable Integer getBiometricPromptSessionId(); + /** If the display is in AOD. */ boolean isAoD(); 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 65e9e3dec60f0..70acaff05e304 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java @@ -18,16 +18,22 @@ package com.android.server.biometrics.log; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.StatusBarManager; import android.content.Context; import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.common.OperationContext; +import android.hardware.biometrics.common.OperationReason; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; -import android.util.Singleton; +import android.os.ServiceManager.ServiceNotFoundException; +import android.os.UserHandle; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.InstanceId; +import com.android.internal.statusbar.ISessionListener; import com.android.internal.statusbar.IStatusBarService; import java.util.Map; @@ -41,22 +47,41 @@ class BiometricContextProvider implements BiometricContext { private static final String TAG = "BiometricContextProvider"; - static final Singleton sInstance = - new Singleton() { - @Override - protected BiometricContextProvider create() { - return new BiometricContextProvider(IStatusBarService.Stub.asInterface( - ServiceManager.getService( + private static final int SESSION_TYPES = + StatusBarManager.SESSION_KEYGUARD | StatusBarManager.SESSION_BIOMETRIC_PROMPT; + + private static BiometricContextProvider sInstance; + + static BiometricContextProvider defaultProvider(@NonNull Context context) { + synchronized (BiometricContextProvider.class) { + if (sInstance == null) { + try { + sInstance = new BiometricContextProvider( + new AmbientDisplayConfiguration(context), + IStatusBarService.Stub.asInterface(ServiceManager.getServiceOrThrow( Context.STATUS_BAR_SERVICE)), null /* handler */); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException("Failed to find required service", e); } - }; + } + } + return sInstance; + } @NonNull private final Map> mSubscribers = new ConcurrentHashMap<>(); + @Nullable + private final Map mSession = new ConcurrentHashMap<>(); + + private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; + private boolean mIsDozing = false; + @VisibleForTesting - BiometricContextProvider(@NonNull IStatusBarService service, @Nullable Handler handler) { + BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration, + @NonNull IStatusBarService service, @Nullable Handler handler) { + mAmbientDisplayConfiguration = ambientDisplayConfiguration; try { service.setBiometicContextListener(new IBiometricContextListener.Stub() { @Override @@ -73,16 +98,70 @@ class BiometricContextProvider implements BiometricContext { } } }); + service.registerSessionListener(SESSION_TYPES, new ISessionListener.Stub() { + @Override + public void onSessionStarted(int sessionType, InstanceId instance) { + mSession.put(sessionType, instance); + } + + @Override + public void onSessionEnded(int sessionType, InstanceId instance) { + final InstanceId id = mSession.remove(sessionType); + if (id != null && instance != null && id.getId() != instance.getId()) { + Slog.w(TAG, "session id mismatch"); + } + } + }); } catch (RemoteException e) { Slog.e(TAG, "Unable to register biometric context listener", e); } } - private boolean mIsDozing = false; + @Override + public OperationContext updateContext(@NonNull OperationContext operationContext, + boolean isCryptoOperation) { + operationContext.isAoD = isAoD(); + operationContext.isCrypto = isCryptoOperation; + setFirstSessionId(operationContext); + return operationContext; + } + + private void setFirstSessionId(@NonNull OperationContext operationContext) { + Integer sessionId = getKeyguardEntrySessionId(); + if (sessionId != null) { + operationContext.id = sessionId; + operationContext.reason = OperationReason.KEYGUARD; + return; + } + + sessionId = getBiometricPromptSessionId(); + if (sessionId != null) { + operationContext.id = sessionId; + operationContext.reason = OperationReason.BIOMETRIC_PROMPT; + return; + } + + operationContext.id = 0; + operationContext.reason = OperationReason.UNKNOWN; + } + + @Nullable + @Override + public Integer getKeyguardEntrySessionId() { + final InstanceId id = mSession.get(StatusBarManager.SESSION_KEYGUARD); + return id != null ? id.getId() : null; + } + + @Nullable + @Override + public Integer getBiometricPromptSessionId() { + final InstanceId id = mSession.get(StatusBarManager.SESSION_BIOMETRIC_PROMPT); + return id != null ? id.getId() : null; + } @Override public boolean isAoD() { - return mIsDozing; + return mIsDozing && mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); } @Override @@ -98,7 +177,7 @@ class BiometricContextProvider implements BiometricContext { private void notifySubscribers() { mSubscribers.forEach((context, consumer) -> { - context.isAoD = mIsDozing; + context.isAoD = isAoD(); consumer.accept(context); }); } diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java index c3471bd1d7714..8965227a1bb4c 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java @@ -17,6 +17,8 @@ package com.android.server.biometrics.log; import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.OperationContext; +import android.hardware.biometrics.common.OperationReason; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; @@ -33,42 +35,49 @@ public class BiometricFrameworkStatsLogger { private BiometricFrameworkStatsLogger() {} + /** Shared instance. */ public static BiometricFrameworkStatsLogger getInstance() { return sInstance; } /** {@see FrameworkStatsLog.BIOMETRIC_ACQUIRED}. */ - public void acquired( + public void acquired(OperationContext operationContext, int statsModality, int statsAction, int statsClient, boolean isDebug, - int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { + int acquiredInfo, int vendorCode, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, statsModality, targetUserId, - isCrypto, + operationContext.isCrypto, statsAction, statsClient, acquiredInfo, vendorCode, isDebug, - -1 /* sensorId */); + -1 /* sensorId */, + operationContext.id, + sessionType(operationContext.reason), + operationContext.isAoD); } /** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */ - public void authenticate( + public void authenticate(OperationContext operationContext, int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, - boolean authenticated, int authState, boolean requireConfirmation, boolean isCrypto, - int targetUserId, boolean isBiometricPrompt, float ambientLightLux) { + int authState, boolean requireConfirmation, + int targetUserId, float ambientLightLux) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality, targetUserId, - isCrypto, + operationContext.isCrypto, statsClient, requireConfirmation, authState, sanitizeLatency(latency), isDebug, -1 /* sensorId */, - ambientLightLux); + ambientLightLux, + operationContext.id, + sessionType(operationContext.reason), + operationContext.isAoD); } /** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */ @@ -84,20 +93,23 @@ public class BiometricFrameworkStatsLogger { } /** {@see FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED}. */ - public void error( + public void error(OperationContext operationContext, int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, - int error, int vendorCode, boolean isCrypto, int targetUserId) { + int error, int vendorCode, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality, targetUserId, - isCrypto, + operationContext.isCrypto, statsAction, statsClient, error, vendorCode, isDebug, sanitizeLatency(latency), - -1 /* sensorId */); + -1 /* sensorId */, + operationContext.id, + sessionType(operationContext.reason), + operationContext.isAoD); } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ @@ -123,4 +135,14 @@ public class BiometricFrameworkStatsLogger { } return latency; } + + private static int sessionType(@OperationReason byte reason) { + if (reason == OperationReason.BIOMETRIC_PROMPT) { + return BiometricsProtoEnums.SESSION_TYPE_BIOMETRIC_PROMPT; + } + if (reason == OperationReason.KEYGUARD) { + return BiometricsProtoEnums.SESSION_TYPE_KEYGUARD_ENTRY; + } + return BiometricsProtoEnums.SESSION_TYPE_UNKNOWN; + } } diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java index 018839079e22c..2a8d9f1967eb8 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java @@ -25,6 +25,7 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.OperationContext; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.util.Slog; @@ -144,8 +145,8 @@ public class BiometricLogger { } /** Log an acquisition event. */ - public void logOnAcquired(Context context, - int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { + public void logOnAcquired(Context context, OperationContext operationContext, + int acquiredInfo, int vendorCode, int targetUserId) { if (!mShouldLogMetrics) { return; } @@ -165,7 +166,7 @@ public class BiometricLogger { if (DEBUG) { Slog.v(TAG, "Acquired! Modality: " + mStatsModality + ", User: " + targetUserId - + ", IsCrypto: " + isCrypto + + ", IsCrypto: " + operationContext.isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", AcquiredInfo: " + acquiredInfo @@ -176,14 +177,14 @@ public class BiometricLogger { return; } - mSink.acquired(mStatsModality, mStatsAction, mStatsClient, + mSink.acquired(operationContext, mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), - acquiredInfo, vendorCode, isCrypto, targetUserId); + acquiredInfo, vendorCode, targetUserId); } /** Log an error during an operation. */ - public void logOnError(Context context, - int error, int vendorCode, boolean isCrypto, int targetUserId) { + public void logOnError(Context context, OperationContext operationContext, + int error, int vendorCode, int targetUserId) { if (!mShouldLogMetrics) { return; } @@ -194,7 +195,7 @@ public class BiometricLogger { if (DEBUG) { Slog.v(TAG, "Error! Modality: " + mStatsModality + ", User: " + targetUserId - + ", IsCrypto: " + isCrypto + + ", IsCrypto: " + operationContext.isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", Error: " + error @@ -208,14 +209,14 @@ public class BiometricLogger { return; } - mSink.error(mStatsModality, mStatsAction, mStatsClient, + mSink.error(operationContext, mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), latency, - error, vendorCode, isCrypto, targetUserId); + error, vendorCode, targetUserId); } /** Log authentication attempt. */ - public void logOnAuthenticated(Context context, - boolean authenticated, boolean requireConfirmation, boolean isCrypto, + public void logOnAuthenticated(Context context, OperationContext operationContext, + boolean authenticated, boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) { if (!mShouldLogMetrics) { return; @@ -241,7 +242,7 @@ public class BiometricLogger { if (DEBUG) { Slog.v(TAG, "Authenticated! Modality: " + mStatsModality + ", User: " + targetUserId - + ", IsCrypto: " + isCrypto + + ", IsCrypto: " + operationContext.isCrypto + ", Client: " + mStatsClient + ", RequireConfirmation: " + requireConfirmation + ", State: " + authState @@ -255,10 +256,9 @@ public class BiometricLogger { return; } - mSink.authenticate(mStatsModality, mStatsAction, mStatsClient, + mSink.authenticate(operationContext, mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), - latency, authenticated, authState, requireConfirmation, isCrypto, - targetUserId, isBiometricPrompt, mLastAmbientLux); + latency, authState, requireConfirmation, targetUserId, mLastAmbientLux); } /** Log enrollment outcome. */ diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index e07a68c6d94dc..0f0032b72b0ae 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -110,8 +110,8 @@ public abstract class AcquisitionClient extends HalClientMonitor implement // that do not handle lockout under the HAL. In these cases, ensure that the framework only // sends errors once per ClientMonitor. if (mShouldSendErrorToClient) { - getLogger().logOnError(getContext(), errorCode, vendorCode, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnError(getContext(), getOperationContext(), + errorCode, vendorCode, getTargetUserId()); try { if (getListener() != null) { mShouldSendErrorToClient = false; @@ -169,8 +169,8 @@ public abstract class AcquisitionClient extends HalClientMonitor implement protected final void onAcquiredInternal(int acquiredInfo, int vendorCode, boolean shouldSend) { - getLogger().logOnAcquired(getContext(), acquiredInfo, vendorCode, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnAcquired(getContext(), getOperationContext(), + acquiredInfo, vendorCode, getTargetUserId()); if (DEBUG) { Slog.v(TAG, "Acquired: " + acquiredInfo + " " + vendorCode + ", shouldSend: " + shouldSend); 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 949edd0e79edb..54b79e1f8e4af 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -166,8 +166,8 @@ public abstract class AuthenticationClient extends AcquisitionClient @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList hardwareAuthToken) { - getLogger().logOnAuthenticated(getContext(), authenticated, mRequireConfirmation, - isCryptoOperation(), getTargetUserId(), isBiometricPrompt()); + getLogger().logOnAuthenticated(getContext(), getOperationContext(), + authenticated, mRequireConfirmation, getTargetUserId(), isBiometricPrompt()); final ClientMonitorCallbackConverter listener = getListener(); diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java index eabafceab590a..cc841931f4603 100644 --- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java @@ -37,7 +37,7 @@ public abstract class HalClientMonitor extends BaseClientMonitor { protected final Supplier mLazyDaemon; @NonNull - protected final OperationContext mOperationContext = new OperationContext(); + private final OperationContext mOperationContext = new OperationContext(); /** * @param context system_server context @@ -84,4 +84,8 @@ public abstract class HalClientMonitor extends BaseClientMonitor { // subclasses should do this earlier in most cases, but ensure it happens now getBiometricContext().unsubscribe(mOperationContext); } + + protected OperationContext getOperationContext() { + return getBiometricContext().updateContext(mOperationContext, isCryptoOperation()); + } } 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 039b08e805c16..2e820574b435c 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 @@ -57,6 +57,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -645,7 +646,7 @@ public class FaceService extends SystemService { try { final SensorProps[] props = face.getSensorProps(); final FaceProvider provider = new FaceProvider(getContext(), props, instance, - mLockoutResetDispatcher); + mLockoutResetDispatcher, BiometricContext.getInstance(getContext())); mServiceProviders.add(provider); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); 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 75a1e0cf21a82..7765ab3b8e536 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 @@ -26,8 +26,6 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationContext; -import android.hardware.biometrics.common.OperationReason; import android.hardware.biometrics.face.IFace; import android.hardware.face.FaceAuthenticationFrame; import android.hardware.face.FaceManager; @@ -157,13 +155,8 @@ class FaceAuthenticationClient extends AuthenticationClient final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { - final OperationContext context = new OperationContext(); - // TODO: add reason, id - context.id = 0; - context.reason = OperationReason.UNKNOWN; - context.isAoD = getBiometricContext().isAoD(); - context.isCrypto = isCryptoOperation(); - return session.getSession().authenticateWithContext(mOperationId, context); + return session.getSession().authenticateWithContext( + mOperationId, getOperationContext()); } else { return session.getSession().authenticate(mOperationId); } @@ -282,8 +275,8 @@ class FaceAuthenticationClient extends AuthenticationClient mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT; - getLogger().logOnError(getContext(), error, 0 /* vendorCode */, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnError(getContext(), getOperationContext(), + error, 0 /* vendorCode */, getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); @@ -298,8 +291,8 @@ class FaceAuthenticationClient extends AuthenticationClient mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; - getLogger().logOnError(getContext(), error, 0 /* vendorCode */, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnError(getContext(), getOperationContext(), + error, 0 /* vendorCode */, getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java index c79e60124c455..efedcf8152289 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java @@ -22,8 +22,6 @@ import android.content.Context; import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationContext; -import android.hardware.biometrics.common.OperationReason; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -116,13 +114,7 @@ public class FaceDetectClient extends AcquisitionClient implements final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { - final OperationContext context = new OperationContext(); - // TODO: add reason, id - context.id = 0; - context.reason = OperationReason.UNKNOWN; - context.isAoD = getBiometricContext().isAoD(); - context.isCrypto = isCryptoOperation(); - return session.getSession().detectInteractionWithContext(context); + return session.getSession().detectInteractionWithContext(getOperationContext()); } else { return session.getSession().detectInteraction(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java index 6f6dadc8a041e..da7853654ebf6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationContext; -import android.hardware.biometrics.common.OperationReason; import android.hardware.biometrics.face.EnrollmentType; import android.hardware.biometrics.face.Feature; import android.hardware.biometrics.face.IFace; @@ -200,14 +198,8 @@ public class FaceEnrollClient extends EnrollClient { HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken); if (session.hasContextMethods()) { - final OperationContext context = new OperationContext(); - // TODO: add reason, id - context.id = 0; - context.reason = OperationReason.UNKNOWN; - context.isAoD = getBiometricContext().isAoD(); - context.isCrypto = isCryptoOperation(); return session.getSession().enrollWithContext( - hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle, context); + hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle, getOperationContext()); } else { return session.getSession().enroll(hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle); 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 64b0892e92bbc..4e03ee9a618c2 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 @@ -90,7 +90,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { @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; private final class BiometricTaskStackListener extends TaskStackListener { @@ -128,7 +128,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { public FaceProvider(@NonNull Context context, @NonNull SensorProps[] props, @NonNull String halInstanceName, - @NonNull LockoutResetDispatcher lockoutResetDispatcher) { + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull BiometricContext biometricContext) { mContext = context; mHalInstanceName = halInstanceName; mSensors = new SparseArray<>(); @@ -137,6 +138,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mLockoutResetDispatcher = lockoutResetDispatcher; mActivityTaskManager = ActivityTaskManager.getInstance(); mTaskStackListener = new BiometricTaskStackListener(); + mBiometricContext = biometricContext; for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; @@ -156,7 +158,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { prop.supportsDetectInteraction, prop.halControlsPreview, false /* resetLockoutRequiresChallenge */); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, - internalProp, lockoutResetDispatcher); + internalProp, lockoutResetDispatcher, mBiometricContext); mSensors.put(sensorId, sensor); Slog.d(getTag(), "Added: " + internalProp); @@ -242,7 +244,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client); @@ -253,7 +255,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mHandler.post(() -> { final InvalidationRequesterClient client = new InvalidationRequesterClient<>(mContext, userId, sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), + mBiometricContext, FaceUtils.getInstance(sensorId)); scheduleForSensor(sensorId, client); }); @@ -294,7 +297,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mSensors.get(sensorId).getLazySession(), userId, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds(), callback); scheduleForSensor(sensorId, client); }); @@ -324,7 +327,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); scheduleForSensor(sensorId, client); }); } @@ -337,7 +340,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mSensors.get(sensorId).getLazySession(), token, userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), challenge); + mBiometricContext, challenge); scheduleForSensor(sensorId, client); }); } @@ -358,7 +361,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { ENROLL_TIMEOUT_SEC, previewSurface, sensorId, createLogger(BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), maxTemplatesPerUser, debugConsent); + mBiometricContext, maxTemplatesPerUser, debugConsent); scheduleForSensor(sensorId, client, new ClientMonitorCallback() { @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, @@ -391,7 +394,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mSensors.get(sensorId).getLazySession(), token, id, callback, userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), isStrongBiometric); + mBiometricContext, isStrongBiometric); scheduleForSensor(sensorId, client); }); @@ -416,7 +419,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), isStrongBiometric, + mBiometricContext, isStrongBiometric, mUsageStats, mSensors.get(sensorId).getLockoutCache(), allowBackgroundAuthentication, isKeyguardBypassEnabled); scheduleForSensor(sensorId, client); @@ -472,7 +475,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { opPackageName, FaceUtils.getInstance(sensorId), sensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client); }); @@ -486,7 +489,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), hardwareAuthToken, + mBiometricContext, hardwareAuthToken, mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher); scheduleForSensor(sensorId, client); @@ -508,7 +511,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mSensors.get(sensorId).getLazySession(), token, new ClientMonitorCallbackConverter(receiver), userId, mContext.getOpPackageName(), sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), mBiometricContext, feature, enabled, hardwareAuthToken); scheduleForSensor(sensorId, client); }); @@ -527,7 +530,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, mContext.getOpPackageName(), sensorId, BiometricLogger.ofUnknown(mContext), - BiometricContext.getInstance()); + mBiometricContext); scheduleForSensor(sensorId, client); }); } @@ -550,7 +553,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), enrolledList, + mBiometricContext, enrolledList, FaceUtils.getInstance(sensorId), mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client, callback); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java index fa07d120eb71a..b69c7600e75af 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java @@ -476,7 +476,8 @@ public class Sensor { Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context, @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties, - @NonNull LockoutResetDispatcher lockoutResetDispatcher) { + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull BiometricContext biometricContext) { mTag = tag; mProvider = provider; mContext = context; @@ -492,7 +493,7 @@ public class Sensor { public StopUserClient getStopUserClient(int userId) { return new FaceStopUserClient(mContext, mLazySession, mToken, userId, mSensorProperties.sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), biometricContext, () -> mCurrentSession = null); } @@ -529,7 +530,7 @@ public class Sensor { return new FaceStartUserClient(mContext, provider::getHalInstance, mToken, newUserId, mSensorProperties.sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), biometricContext, resultController, userStartedCallback); } }); 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 be1ed7d92aeb2..73c759f7738c3 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 @@ -119,6 +119,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull private final Map mAuthenticatorIds; @Nullable private IBiometricsFace mDaemon; @NonNull private final HalResultController mHalResultController; + @NonNull private final BiometricContext mBiometricContext; // for requests that do not use biometric prompt @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); private int mCurrentUserId = UserHandle.USER_NULL; @@ -155,6 +156,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull private final LockoutHalImpl mLockoutTracker; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; + HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler, @NonNull BiometricScheduler scheduler, @NonNull LockoutHalImpl lockoutTracker, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { @@ -337,12 +339,14 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull Handler handler, - @NonNull BiometricScheduler scheduler) { + @NonNull BiometricScheduler scheduler, + @NonNull BiometricContext biometricContext) { mSensorProperties = sensorProps; mContext = context; mSensorId = sensorProps.sensorId; mScheduler = scheduler; mHandler = handler; + mBiometricContext = biometricContext; mUsageStats = new UsageStats(context); mAuthenticatorIds = new HashMap<>(); mLazyDaemon = Face10.this::getDaemon; @@ -367,7 +371,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { final Handler handler = new Handler(Looper.getMainLooper()); return new Face10(context, sensorProps, lockoutResetDispatcher, handler, new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_FACE, - null /* gestureAvailabilityTracker */)); + null /* gestureAvailabilityTracker */), + BiometricContext.getInstance(context)); } @Override @@ -538,7 +543,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { opPackageName, mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), sSystemClock.millis()); + mBiometricContext, sSystemClock.millis()); mGeneratedChallengeCache = client; mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override @@ -570,7 +575,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon, token, userId, opPackageName, mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, @@ -601,7 +606,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { ENROLL_TIMEOUT_SEC, previewSurface, mSensorId, createLogger(BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override @@ -649,8 +654,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon, token, requestId, receiver, userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, mSensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), isStrongBiometric, mLockoutTracker, mUsageStats, - allowBackgroundAuthentication, isKeyguardBypassEnabled); + mBiometricContext, isStrongBiometric, mLockoutTracker, + mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled); mScheduler.scheduleClientMonitor(client); }); } @@ -685,7 +690,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { FaceUtils.getLegacyInstance(mSensorId), mSensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), mAuthenticatorIds); + mBiometricContext, mAuthenticatorIds); mScheduler.scheduleClientMonitor(client); }); } @@ -703,7 +708,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { FaceUtils.getLegacyInstance(mSensorId), mSensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), mAuthenticatorIds); + mBiometricContext, mAuthenticatorIds); mScheduler.scheduleClientMonitor(client); }); } @@ -722,7 +727,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), hardwareAuthToken); + mBiometricContext, hardwareAuthToken); mScheduler.scheduleClientMonitor(client); }); } @@ -744,7 +749,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext, mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, opPackageName, mSensorId, BiometricLogger.ofUnknown(mContext), - BiometricContext.getInstance(), feature, enabled, hardwareAuthToken, faceId); + mBiometricContext, + feature, enabled, hardwareAuthToken, faceId); mScheduler.scheduleClientMonitor(client); }); } @@ -764,7 +770,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { final int faceId = faces.get(0).getBiometricId(); final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon, token, listener, userId, opPackageName, mSensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), mBiometricContext, feature, faceId); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override @@ -793,7 +799,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId, createLogger(BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), enrolledList, + mBiometricContext, enrolledList, FaceUtils.getLegacyInstance(mSensorId), mAuthenticatorIds); mScheduler.scheduleClientMonitor(client, callback); }); @@ -918,7 +924,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), hasEnrolled, mAuthenticatorIds); + mBiometricContext, hasEnrolled, mAuthenticatorIds); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 6366e19ef1917..b4befd23671fd 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -83,6 +83,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -815,7 +816,8 @@ public class FingerprintService extends SystemService { UserHandle.USER_CURRENT) != 0) { fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), mFingerprintStateCallback, hidlSensor, - mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + mLockoutResetDispatcher, mGestureAvailabilityDispatcher, + BiometricContext.getInstance(getContext())); } else { fingerprint21 = Fingerprint21.newInstance(getContext(), mFingerprintStateCallback, hidlSensor, mHandler, @@ -843,7 +845,8 @@ public class FingerprintService extends SystemService { final FingerprintProvider provider = new FingerprintProvider(getContext(), mFingerprintStateCallback, props, instance, mLockoutResetDispatcher, - mGestureAvailabilityDispatcher); + mGestureAvailabilityDispatcher, + BiometricContext.getInstance(getContext())); mServiceProviders.add(provider); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); 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 184e1ea7d0030..a8d059d514de7 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 @@ -24,7 +24,6 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationReason; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; @@ -178,12 +177,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { - // TODO: add reason, id - mOperationContext.id = 0; - mOperationContext.reason = OperationReason.UNKNOWN; - mOperationContext.isAoD = getBiometricContext().isAoD(); - mOperationContext.isCrypto = isCryptoOperation(); - return session.getSession().authenticateWithContext(mOperationId, mOperationContext); + return session.getSession().authenticateWithContext( + mOperationId, getOperationContext()); } else { return session.getSession().authenticate(mOperationId); } @@ -279,8 +274,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; - getLogger().logOnError(getContext(), error, 0 /* vendorCode */, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnError(getContext(), getOperationContext(), + error, 0 /* vendorCode */, getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); @@ -298,8 +293,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; - getLogger().logOnError(getContext(), error, 0 /* vendorCode */, - isCryptoOperation(), getTargetUserId()); + getLogger().logOnError(getContext(), getOperationContext(), + error, 0 /* vendorCode */, getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java index 9d348e118b465..0e89814c6ad29 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricOverlayConstants; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationContext; -import android.hardware.biometrics.common.OperationReason; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; import android.os.RemoteException; @@ -99,13 +97,7 @@ class FingerprintDetectClient extends AcquisitionClient implements final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { - final OperationContext context = new OperationContext(); - // TODO: add reason, id - context.id = 0; - context.reason = OperationReason.UNKNOWN; - context.isAoD = getBiometricContext().isAoD(); - context.isCrypto = isCryptoOperation(); - return session.getSession().detectInteractionWithContext(context); + return session.getSession().detectInteractionWithContext(getOperationContext()); } else { return session.getSession().detectInteraction(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index ed16a6dd3b5c8..bce972a38cfd0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -23,8 +23,6 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired; import android.hardware.biometrics.common.ICancellationSignal; -import android.hardware.biometrics.common.OperationContext; -import android.hardware.biometrics.common.OperationReason; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; @@ -178,13 +176,7 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken); if (session.hasContextMethods()) { - final OperationContext context = new OperationContext(); - // TODO: add reason, id - context.id = 0; - context.reason = OperationReason.UNKNOWN; - context.isAoD = getBiometricContext().isAoD(); - context.isCrypto = isCryptoOperation(); - return session.getSession().enrollWithContext(hat, context); + return session.getSession().enrollWithContext(hat, getOperationContext()); } else { return session.getSession().enroll(hat); } 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 221ff94141e28..f810bca9707df 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 @@ -101,7 +101,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @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 IFingerprint mDaemon; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ISidefpsController mSidefpsController; @@ -144,7 +144,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, + @NonNull BiometricContext biometricContext) { mContext = context; mFingerprintStateCallback = fingerprintStateCallback; mHalInstanceName = halInstanceName; @@ -153,6 +154,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mLockoutResetDispatcher = lockoutResetDispatcher; mActivityTaskManager = ActivityTaskManager.getInstance(); mTaskStackListener = new BiometricTaskStackListener(); + mBiometricContext = biometricContext; final List workaroundLocations = getWorkaroundSensorProps(context); @@ -184,7 +186,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi location.sensorRadius)) .collect(Collectors.toList())); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, - internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher); + internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher, + mBiometricContext); mSensors.put(sensorId, sensor); Slog.d(getTag(), "Added: " + internalProp); @@ -303,7 +306,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client); }); @@ -313,7 +316,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mHandler.post(() -> { final InvalidationRequesterClient client = new InvalidationRequesterClient<>(mContext, userId, sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), + mBiometricContext, FingerprintUtils.getInstance(sensorId)); scheduleForSensor(sensorId, client); }); @@ -327,7 +331,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), hardwareAuthToken, + mBiometricContext, hardwareAuthToken, mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher); scheduleForSensor(sensorId, client); }); @@ -343,7 +347,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); scheduleForSensor(sensorId, client); }); } @@ -358,7 +362,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), challenge); + mBiometricContext, challenge); scheduleForSensor(sensorId, client); }); } @@ -378,7 +382,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi opPackageName, FingerprintUtils.getInstance(sensorId), sensorId, createLogger(BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getSensorProperties(), mUdfpsOverlayController, mSidefpsController, maxTemplatesPerUser, enrollReason); scheduleForSensor(sensorId, client, new ClientMonitorCallback() { @@ -419,7 +423,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getLazySession(), token, id, callback, userId, opPackageName, sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), + mBiometricContext, mUdfpsOverlayController, isStrongBiometric); scheduleForSensor(sensorId, client, mFingerprintStateCallback); }); @@ -439,7 +443,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi userId, operationId, restricted, opPackageName, cookie, false /* requireConfirmation */, sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), isStrongBiometric, + mBiometricContext, isStrongBiometric, mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication, mSensors.get(sensorId).getSensorProperties()); @@ -503,7 +507,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi opPackageName, FingerprintUtils.getInstance(sensorId), sensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client, mFingerprintStateCallback); }); @@ -520,7 +524,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, enrolledList, FingerprintUtils.getInstance(sensorId), mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(callback, @@ -559,7 +563,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getLazySession(), userId, sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds(), callback); scheduleForSensor(sensorId, client); }); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index 27226b30f548a..63e345e40ad7b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -429,7 +429,8 @@ public class Sensor { Sensor(@NonNull String tag, @NonNull FingerprintProvider provider, @NonNull Context context, @NonNull Handler handler, @NonNull FingerprintSensorPropertiesInternal sensorProperties, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, + @NonNull BiometricContext biometricContext) { mTag = tag; mProvider = provider; mContext = context; @@ -447,7 +448,7 @@ public class Sensor { public StopUserClient getStopUserClient(int userId) { return new FingerprintStopUserClient(mContext, mLazySession, mToken, userId, mSensorProperties.sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), biometricContext, () -> mCurrentSession = null); } @@ -484,7 +485,7 @@ public class Sensor { return new FingerprintStartUserClient(mContext, provider::getHalInstance, mToken, newUserId, mSensorProperties.sensorId, - BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(), + BiometricLogger.ofUnknown(mContext), biometricContext, resultController, userStartedCallback); } }); 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 6c35c8c914480..9d60859a4a217 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 @@ -120,6 +120,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @NonNull private final HalResultController mHalResultController; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; @Nullable private ISidefpsController mSidefpsController; + @NonNull private final BiometricContext mBiometricContext; // for requests that do not use biometric prompt @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); private int mCurrentUserId = UserHandle.USER_NULL; @@ -320,15 +321,18 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } } + @VisibleForTesting Fingerprint21(@NonNull Context context, @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull HalResultController controller) { + @NonNull HalResultController controller, + @NonNull BiometricContext biometricContext) { mContext = context; mFingerprintStateCallback = fingerprintStateCallback; + mBiometricContext = biometricContext; mSensorProperties = sensorProps; mSensorId = sensorProps.sensorId; @@ -370,7 +374,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider final HalResultController controller = new HalResultController(sensorProps.sensorId, context, handler, scheduler); return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler, - lockoutResetDispatcher, controller); + lockoutResetDispatcher, controller, BiometricContext.getInstance(context)); } @Override @@ -497,7 +501,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mContext.getOpPackageName(), mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, this::getCurrentUser, hasEnrolled, mAuthenticatorIds, force); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override @@ -544,7 +548,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider userId, mContext.getOpPackageName(), sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), mLockoutTracker); + mBiometricContext, mLockoutTracker); mScheduler.scheduleClientMonitor(client); }); } @@ -559,7 +563,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); mScheduler.scheduleClientMonitor(client); }); } @@ -573,7 +577,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance()); + mBiometricContext); mScheduler.scheduleClientMonitor(client); }); } @@ -594,7 +598,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_ENROLL, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), + mBiometricContext, mUdfpsOverlayController, mSidefpsController, enrollReason); mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @@ -636,7 +640,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mLazyDaemon, token, id, listener, userId, opPackageName, mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), mUdfpsOverlayController, isStrongBiometric); + mBiometricContext, mUdfpsOverlayController, + isStrongBiometric); mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); @@ -657,7 +662,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider restricted, opPackageName, cookie, false /* requireConfirmation */, mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), - BiometricContext.getInstance(), isStrongBiometric, + mBiometricContext, isStrongBiometric, mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication, mSensorProperties); @@ -702,7 +707,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), mAuthenticatorIds); + mBiometricContext, mAuthenticatorIds); mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); } @@ -722,7 +727,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), mAuthenticatorIds); + mBiometricContext, mAuthenticatorIds); mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); }); } @@ -739,7 +744,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mSensorProperties.sensorId, createLogger(BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN), - BiometricContext.getInstance(), enrolledList, + mBiometricContext, enrolledList, FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds); mScheduler.scheduleClientMonitor(client, callback); }); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 1694bd92c73c4..149526f21fdb7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -37,6 +37,7 @@ import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.R; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; @@ -247,7 +248,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, + @NonNull BiometricContext biometricContext) { Slog.d(TAG, "Creating Fingerprint23Mock!"); final Handler handler = new Handler(Looper.getMainLooper()); @@ -256,7 +258,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage final MockHalResultController controller = new MockHalResultController(sensorProps.sensorId, context, handler, scheduler); return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler, - handler, lockoutResetDispatcher, controller); + handler, lockoutResetDispatcher, controller, biometricContext); } private static abstract class FakeFingerRunnable implements Runnable { @@ -385,9 +387,10 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage @NonNull TestableBiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull MockHalResultController controller) { + @NonNull MockHalResultController controller, + @NonNull BiometricContext biometricContext) { super(context, fingerprintStateCallback, sensorProps, scheduler, handler, - lockoutResetDispatcher, controller); + lockoutResetDispatcher, controller, biometricContext); mScheduler = scheduler; mScheduler.init(this); mHandler = handler; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java index f10d4e409b0ee..c2929d0f15b23 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java @@ -130,8 +130,9 @@ class FingerprintDetectClient extends AcquisitionClient @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList hardwareAuthToken) { - getLogger().logOnAuthenticated(getContext(), authenticated, false /* requireConfirmation */, - isCryptoOperation(), getTargetUserId(), false /* isBiometricPrompt */); + getLogger().logOnAuthenticated(getContext(), getOperationContext(), + authenticated, false /* requireConfirmation */, + getTargetUserId(), false /* isBiometricPrompt */); // Do not distinguish between success/failures. vibrateSuccess(); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java index ec884f59014f2..5746f6f2d446b 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java @@ -19,18 +19,25 @@ package com.android.server.biometrics.log; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.StatusBarManager; import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.common.OperationContext; +import android.hardware.biometrics.common.OperationReason; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; +import com.android.internal.logging.InstanceId; +import com.android.internal.statusbar.ISessionListener; import com.android.internal.statusbar.IStatusBarService; import com.google.common.collect.ImmutableList; @@ -56,6 +63,10 @@ public class BiometricContextProviderTest { @Mock private IStatusBarService mStatusBarService; + @Mock + private ISessionListener mSessionListener; + @Mock + private AmbientDisplayConfiguration mAmbientDisplayConfiguration; private OperationContext mOpContext = new OperationContext(); private IBiometricContextListener mListener; @@ -63,11 +74,17 @@ public class BiometricContextProviderTest { @Before public void setup() throws RemoteException { - mProvider = new BiometricContextProvider(mStatusBarService, null /* handler */); + when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true); + mProvider = new BiometricContextProvider(mAmbientDisplayConfiguration, mStatusBarService, + null /* handler */); ArgumentCaptor captor = ArgumentCaptor.forClass(IBiometricContextListener.class); verify(mStatusBarService).setBiometicContextListener(captor.capture()); mListener = captor.getValue(); + ArgumentCaptor sessionCaptor = + ArgumentCaptor.forClass(ISessionListener.class); + verify(mStatusBarService).registerSessionListener(anyInt(), sessionCaptor.capture()); + mSessionListener = sessionCaptor.getValue(); } @Test @@ -76,6 +93,12 @@ public class BiometricContextProviderTest { assertThat(mProvider.isAoD()).isTrue(); mListener.onDozeChanged(false); assertThat(mProvider.isAoD()).isFalse(); + + when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false); + mListener.onDozeChanged(true); + assertThat(mProvider.isAoD()).isFalse(); + mListener.onDozeChanged(false); + assertThat(mProvider.isAoD()).isFalse(); } @Test @@ -112,4 +135,84 @@ public class BiometricContextProviderTest { verify(emptyConsumer, never()).accept(any()); verify(nonEmptyConsumer).accept(same(mOpContext)); } + + @Test + public void testSessionId() throws RemoteException { + final int keyguardSessionId = 10; + final int bpSessionId = 20; + + assertThat(mProvider.getBiometricPromptSessionId()).isNull(); + assertThat(mProvider.getKeyguardEntrySessionId()).isNull(); + + mSessionListener.onSessionStarted(StatusBarManager.SESSION_KEYGUARD, + InstanceId.fakeInstanceId(keyguardSessionId)); + + assertThat(mProvider.getBiometricPromptSessionId()).isNull(); + assertThat(mProvider.getKeyguardEntrySessionId()).isEqualTo(keyguardSessionId); + + mSessionListener.onSessionStarted(StatusBarManager.SESSION_BIOMETRIC_PROMPT, + InstanceId.fakeInstanceId(bpSessionId)); + + assertThat(mProvider.getBiometricPromptSessionId()).isEqualTo(bpSessionId); + assertThat(mProvider.getKeyguardEntrySessionId()).isEqualTo(keyguardSessionId); + + mSessionListener.onSessionEnded(StatusBarManager.SESSION_KEYGUARD, + InstanceId.fakeInstanceId(keyguardSessionId)); + + assertThat(mProvider.getBiometricPromptSessionId()).isEqualTo(bpSessionId); + assertThat(mProvider.getKeyguardEntrySessionId()).isNull(); + + mSessionListener.onSessionEnded(StatusBarManager.SESSION_BIOMETRIC_PROMPT, + InstanceId.fakeInstanceId(bpSessionId)); + + assertThat(mProvider.getBiometricPromptSessionId()).isNull(); + assertThat(mProvider.getKeyguardEntrySessionId()).isNull(); + } + + @Test + public void testUpdate() throws RemoteException { + mListener.onDozeChanged(false); + OperationContext context = mProvider.updateContext(mOpContext, false /* crypto */); + + // default state when nothing has been set + assertThat(context).isSameInstanceAs(mOpContext); + assertThat(mOpContext.id).isEqualTo(0); + assertThat(mOpContext.reason).isEqualTo(OperationReason.UNKNOWN); + assertThat(mOpContext.isAoD).isEqualTo(false); + assertThat(mOpContext.isCrypto).isEqualTo(false); + + for (int type : List.of(StatusBarManager.SESSION_BIOMETRIC_PROMPT, + StatusBarManager.SESSION_KEYGUARD)) { + final int id = 40 + type; + final boolean aod = (type & 1) == 0; + + mListener.onDozeChanged(aod); + mSessionListener.onSessionStarted(type, InstanceId.fakeInstanceId(id)); + context = mProvider.updateContext(mOpContext, false /* crypto */); + assertThat(context).isSameInstanceAs(mOpContext); + assertThat(mOpContext.id).isEqualTo(id); + assertThat(mOpContext.reason).isEqualTo(reason(type)); + assertThat(mOpContext.isAoD).isEqualTo(aod); + assertThat(mOpContext.isCrypto).isEqualTo(false); + + mSessionListener.onSessionEnded(type, InstanceId.fakeInstanceId(id)); + } + + context = mProvider.updateContext(mOpContext, false /* crypto */); + assertThat(context).isSameInstanceAs(mOpContext); + assertThat(mOpContext.id).isEqualTo(0); + assertThat(mOpContext.reason).isEqualTo(OperationReason.UNKNOWN); + assertThat(mOpContext.isAoD).isEqualTo(false); + assertThat(mOpContext.isCrypto).isEqualTo(false); + } + + private static byte reason(int type) { + if (type == StatusBarManager.SESSION_BIOMETRIC_PROMPT) { + return OperationReason.BIOMETRIC_PROMPT; + } + if (type == StatusBarManager.SESSION_KEYGUARD) { + return OperationReason.KEYGUARD; + } + return OperationReason.UNKNOWN; + } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java index b0eb810b5da94..fe023374ba884 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java @@ -31,6 +31,7 @@ import android.hardware.Sensor; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.OperationContext; import android.hardware.input.InputSensorInfo; import android.platform.test.annotations.Presubmit; import android.testing.TestableContext; @@ -68,10 +69,12 @@ public class BiometricLoggerTest { @Mock private BaseClientMonitor mClient; + private OperationContext mOpContext; private BiometricLogger mLogger; @Before public void setUp() { + mOpContext = new OperationContext(); mContext.addMockSystemService(SensorManager.class, mSensorManager); when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn( new Sensor(new InputSensorInfo("", "", 0, 0, Sensor.TYPE_LIGHT, 0, 0, 0, 0, 0, 0, @@ -93,14 +96,13 @@ public class BiometricLoggerTest { final int acquiredInfo = 2; final int vendorCode = 3; - final boolean isCrypto = true; final int targetUserId = 9; - mLogger.logOnAcquired(mContext, acquiredInfo, vendorCode, isCrypto, targetUserId); + mLogger.logOnAcquired(mContext, mOpContext, acquiredInfo, vendorCode, targetUserId); - verify(mSink).acquired( + verify(mSink).acquired(eq(mOpContext), eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(), - eq(acquiredInfo), eq(vendorCode), eq(isCrypto), eq(targetUserId)); + eq(acquiredInfo), eq(vendorCode), eq(targetUserId)); } @Test @@ -109,17 +111,16 @@ public class BiometricLoggerTest { final boolean authenticated = true; final boolean requireConfirmation = false; - final boolean isCrypto = false; final int targetUserId = 11; final boolean isBiometricPrompt = true; - mLogger.logOnAuthenticated(mContext, - authenticated, requireConfirmation, isCrypto, targetUserId, isBiometricPrompt); + mLogger.logOnAuthenticated(mContext, mOpContext, + authenticated, requireConfirmation, targetUserId, isBiometricPrompt); - verify(mSink).authenticate( + verify(mSink).authenticate(eq(mOpContext), eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(), - anyLong(), eq(authenticated), anyInt(), eq(requireConfirmation), eq(isCrypto), - eq(targetUserId), eq(isBiometricPrompt), anyFloat()); + anyLong(), anyInt(), eq(requireConfirmation), + eq(targetUserId), anyFloat()); } @Test @@ -143,14 +144,13 @@ public class BiometricLoggerTest { final int error = 7; final int vendorCode = 11; - final boolean isCrypto = false; final int targetUserId = 9; - mLogger.logOnError(mContext, error, vendorCode, isCrypto, targetUserId); + mLogger.logOnError(mContext, mOpContext, error, vendorCode, targetUserId); - verify(mSink).error( + verify(mSink).error(eq(mOpContext), eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(), - anyLong(), eq(error), eq(vendorCode), eq(isCrypto), eq(targetUserId)); + anyLong(), eq(error), eq(vendorCode), eq(targetUserId)); } @Test @@ -175,38 +175,34 @@ public class BiometricLoggerTest { private void testDisabledMetrics(boolean isBadConfig) { mLogger.disableMetrics(); - mLogger.logOnAcquired(mContext, + mLogger.logOnAcquired(mContext, mOpContext, 0 /* acquiredInfo */, 1 /* vendorCode */, - true /* isCrypto */, 8 /* targetUserId */); - mLogger.logOnAuthenticated(mContext, + mLogger.logOnAuthenticated(mContext, mOpContext, true /* authenticated */, true /* requireConfirmation */, - false /* isCrypto */, 4 /* targetUserId */, true/* isBiometricPrompt */); mLogger.logOnEnrolled(2 /* targetUserId */, 10 /* latency */, true /* enrollSuccessful */); - mLogger.logOnError(mContext, + mLogger.logOnError(mContext, mOpContext, 4 /* error */, 0 /* vendorCode */, - false /* isCrypto */, 6 /* targetUserId */); - verify(mSink, never()).acquired( + verify(mSink, never()).acquired(eq(mOpContext), anyInt(), anyInt(), anyInt(), anyBoolean(), - anyInt(), anyInt(), anyBoolean(), anyInt()); - verify(mSink, never()).authenticate( + anyInt(), anyInt(), anyInt()); + verify(mSink, never()).authenticate(eq(mOpContext), anyInt(), anyInt(), anyInt(), anyBoolean(), - anyLong(), anyBoolean(), anyInt(), anyBoolean(), - anyBoolean(), anyInt(), anyBoolean(), anyFloat()); + anyLong(), anyInt(), anyBoolean(), anyInt(), anyFloat()); verify(mSink, never()).enroll( anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyBoolean(), anyFloat()); - verify(mSink, never()).error( + verify(mSink, never()).error(eq(mOpContext), anyInt(), anyInt(), anyInt(), anyBoolean(), - anyLong(), anyInt(), anyInt(), anyBoolean(), anyInt()); + anyLong(), anyInt(), anyInt(), anyInt()); mLogger.logUnknownEnrollmentInFramework(); mLogger.logUnknownEnrollmentInHal(); 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 25585dd0cfc30..aba93b0586695 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,12 +16,13 @@ package com.android.server.biometrics.sensors.face.aidl; -import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -47,6 +48,7 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -57,7 +59,6 @@ public class FaceAuthenticationClientTest { private static final int USER_ID = 12; private static final long OP_ID = 32; - private static final boolean HAS_AOD = true; @Rule public final TestableContext mContext = new TestableContext( @@ -89,7 +90,8 @@ public class FaceAuthenticationClientTest { @Before public void setup() { - when(mBiometricContext.isAoD()).thenReturn(HAS_AOD); + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); } @Test @@ -106,11 +108,12 @@ public class FaceAuthenticationClientTest { final FaceAuthenticationClient client = createClient(2); client.start(mCallback); - verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).authenticateWithContext( + eq(OP_ID), same(mOperationContextCaptor.getValue())); verify(mHal, never()).authenticate(anyLong()); - - final OperationContext opContext = mOperationContextCaptor.getValue(); - assertThat(opContext.isAoD).isEqualTo(HAS_AOD); } private FaceAuthenticationClient createClient(int version) throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java index 6c72ebfd3674f..25135c6670dbc 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java @@ -16,10 +16,11 @@ package com.android.server.biometrics.sensors.face.aidl; -import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -43,6 +44,7 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -52,7 +54,6 @@ import org.mockito.junit.MockitoRule; public class FaceDetectClientTest { private static final int USER_ID = 12; - private static final boolean HAS_AOD = true; @Rule public final TestableContext mContext = new TestableContext( @@ -80,7 +81,8 @@ public class FaceDetectClientTest { @Before public void setup() { - when(mBiometricContext.isAoD()).thenReturn(HAS_AOD); + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); } @Test @@ -97,11 +99,11 @@ public class FaceDetectClientTest { final FaceDetectClient client = createClient(2); client.start(mCallback); - verify(mHal).detectInteractionWithContext(mOperationContextCaptor.capture()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).detectInteractionWithContext(same(mOperationContextCaptor.getValue())); verify(mHal, never()).detectInteraction(); - - final OperationContext opContext = mOperationContextCaptor.getValue(); - assertThat(opContext.isAoD).isEqualTo(HAS_AOD); } private FaceDetectClient createClient(int version) throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java index 22070e9579eec..38e048bc1ba7a 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java @@ -17,11 +17,15 @@ package com.android.server.biometrics.sensors.face.aidl; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyByte; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.face.ISession; import android.hardware.face.Face; import android.os.IBinder; @@ -38,8 +42,12 @@ import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -71,10 +79,18 @@ public class FaceEnrollClientTest { private ClientMonitorCallback mCallback; @Mock private Sensor.HalSessionCallback mHalSessionCallback; + @Captor + private ArgumentCaptor mOperationContextCaptor; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); + @Before + public void setup() { + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); + } + @Test public void enrollNoContext_v1() throws RemoteException { final FaceEnrollClient client = createClient(1); @@ -89,7 +105,11 @@ public class FaceEnrollClientTest { final FaceEnrollClient client = createClient(2); client.start(mCallback); - verify(mHal).enrollWithContext(any(), anyByte(), any(), any(), any()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).enrollWithContext(any(), anyByte(), any(), any(), + same(mOperationContextCaptor.getValue())); verify(mHal, never()).enroll(any(), anyByte(), any(), any()); } 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 0ac00aafbf6ce..12b8264fc20ce 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 @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutResetDispatcher; @@ -60,6 +61,8 @@ public class FaceProviderTest { private UserManager mUserManager; @Mock private IFace mDaemon; + @Mock + private BiometricContext mBiometricContext; private SensorProps[] mSensorProps; private LockoutResetDispatcher mLockoutResetDispatcher; @@ -89,7 +92,7 @@ public class FaceProviderTest { mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); mFaceProvider = new TestableFaceProvider(mDaemon, mContext, mSensorProps, TAG, - mLockoutResetDispatcher); + mLockoutResetDispatcher, mBiometricContext); } @SuppressWarnings("rawtypes") @@ -139,8 +142,9 @@ public class FaceProviderTest { @NonNull Context context, @NonNull SensorProps[] props, @NonNull String halInstanceName, - @NonNull LockoutResetDispatcher lockoutResetDispatcher) { - super(context, props, halInstanceName, lockoutResetDispatcher); + @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull BiometricContext biometricContext) { + super(context, props, halInstanceName, lockoutResetDispatcher, biometricContext); mDaemon = daemon; } 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 21a7a8ae65b97..116d2d5a66a0d 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 @@ -41,6 +41,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.LockoutResetDispatcher; @@ -70,6 +71,8 @@ public class Face10Test { private UserManager mUserManager; @Mock private BiometricScheduler mScheduler; + @Mock + private BiometricContext mBiometricContext; private final Handler mHandler = new Handler(Looper.getMainLooper()); private LockoutResetDispatcher mLockoutResetDispatcher; @@ -100,7 +103,8 @@ public class Face10Test { resetLockoutRequiresChallenge); Face10.sSystemClock = Clock.fixed(Instant.ofEpochMilli(100), ZoneId.of("PST")); - mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mHandler, mScheduler); + mFace10 = new Face10(mContext, 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 5c360e9147c1d..59e697245cbf8 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 @@ -24,7 +24,9 @@ import static org.mockito.Mockito.anyFloat; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -56,6 +58,7 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -68,7 +71,6 @@ public class FingerprintAuthenticationClientTest { private static final int USER_ID = 8; private static final long OP_ID = 7; - private static final boolean HAS_AOD = true; private static final int POINTER_ID = 0; private static final int TOUCH_X = 8; private static final int TOUCH_Y = 20; @@ -115,7 +117,8 @@ public class FingerprintAuthenticationClientTest { public void setup() { when(mBiometricLogger.createALSCallback(anyBoolean())).thenAnswer(i -> new CallbackWithProbe<>(mLuxProbe, i.getArgument(0))); - when(mBiometricContext.isAoD()).thenReturn(HAS_AOD); + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); } @Test @@ -132,11 +135,12 @@ public class FingerprintAuthenticationClientTest { final FingerprintAuthenticationClient client = createClient(2); client.start(mCallback); - verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).authenticateWithContext( + eq(OP_ID), same(mOperationContextCaptor.getValue())); verify(mHal, never()).authenticate(anyLong()); - - final OperationContext opContext = mOperationContextCaptor.getValue(); - assertThat(opContext.isAoD).isEqualTo(HAS_AOD); } @Test diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java index 295fe4766a85f..91b21357e9aaa 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java @@ -16,8 +16,11 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -42,6 +45,7 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -82,6 +86,8 @@ public class FingerprintDetectClientTest { @Before public void setup() { when(mBiometricContext.isAoD()).thenReturn(HAS_AOD); + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); } @Test @@ -100,7 +106,10 @@ public class FingerprintDetectClientTest { client.start(mCallback); - verify(mHal).detectInteractionWithContext(mOperationContextCaptor.capture()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).detectInteractionWithContext(same(mOperationContextCaptor.getValue())); verify(mHal, never()).detectInteraction(); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java index 7e44eab0a5566..018d277c7c445 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java @@ -18,11 +18,14 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,10 +51,12 @@ import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -104,6 +109,12 @@ public class FingerprintEnrollClientTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); + @Before + public void setup() { + when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( + i -> i.getArgument(0)); + } + @Test public void enrollNoContext_v1() throws RemoteException { final FingerprintEnrollClient client = createClient(1); @@ -120,7 +131,10 @@ public class FingerprintEnrollClientTest { client.start(mCallback); - verify(mHal).enrollWithContext(any(), mOperationContextCaptor.capture()); + InOrder order = inOrder(mHal, mBiometricContext); + order.verify(mBiometricContext).updateContext( + mOperationContextCaptor.capture(), anyBoolean()); + order.verify(mHal).enrollWithContext(any(), same(mOperationContextCaptor.getValue())); verify(mHal, never()).enroll(any()); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java index 73f1516562bca..5a1a02eb39c87 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java @@ -40,6 +40,7 @@ import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutResetDispatcher; @@ -71,6 +72,8 @@ public class FingerprintProviderTest { private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; @Mock private FingerprintStateCallback mFingerprintStateCallback; + @Mock + private BiometricContext mBiometricContext; private SensorProps[] mSensorProps; private LockoutResetDispatcher mLockoutResetDispatcher; @@ -105,7 +108,7 @@ public class FingerprintProviderTest { mFingerprintProvider = new TestableFingerprintProvider(mDaemon, mContext, mFingerprintStateCallback, mSensorProps, TAG, mLockoutResetDispatcher, - mGestureAvailabilityDispatcher); + mGestureAvailabilityDispatcher, mBiometricContext); } @SuppressWarnings("rawtypes") @@ -157,9 +160,10 @@ public class FingerprintProviderTest { @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { + @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, + @NonNull BiometricContext biometricContext) { super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher, - gestureAvailabilityDispatcher); + gestureAvailabilityDispatcher, biometricContext); mDaemon = daemon; } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java index f6b92097a9fbf..529f994f27738 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java @@ -39,6 +39,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import com.android.internal.R; +import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; @@ -70,6 +71,8 @@ public class Fingerprint21Test { private BiometricScheduler mScheduler; @Mock private FingerprintStateCallback mFingerprintStateCallback; + @Mock + private BiometricContext mBiometricContext; private LockoutResetDispatcher mLockoutResetDispatcher; private Fingerprint21 mFingerprint21; @@ -101,7 +104,7 @@ public class Fingerprint21Test { mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps, mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, - mHalResultController); + mHalResultController, mBiometricContext); } @Test @@ -126,9 +129,10 @@ public class Fingerprint21Test { @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - @NonNull HalResultController controller) { + @NonNull HalResultController controller, + @NonNull BiometricContext biometricContext) { super(context, fingerprintStateCallback, sensorProps, scheduler, handler, - lockoutResetDispatcher, controller); + lockoutResetDispatcher, controller, biometricContext); } @Override From 0b8634d243c5f73981a8fc321988fb7ee602b3cf Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Fri, 28 Jan 2022 13:35:30 -0800 Subject: [PATCH 2/2] Send AoD context changed notification to HAL. Bug: 204585936 Bug: 204584403 Test: atest FingerprintAuthenticationClientTest FingerprintDetectClientTest FingerprintEnrollClientTest Change-Id: Idcccba362a151d0454d4070475073d07803e4e2a --- .../biometrics/sensors/HalClientMonitor.java | 15 ++++- .../aidl/FingerprintAuthenticationClient.java | 21 +++++-- .../aidl/FingerprintEnrollClient.java | 59 ++++++++++++------- .../statusbar/StatusBarManagerService.java | 6 ++ .../FingerprintAuthenticationClientTest.java | 19 ++++++ .../aidl/FingerprintDetectClientTest.java | 2 - .../aidl/FingerprintEnrollClientTest.java | 44 ++++++++++++++ 7 files changed, 139 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java index cc841931f4603..a6e89115400d0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java @@ -82,10 +82,23 @@ public abstract class HalClientMonitor extends BaseClientMonitor { super.destroy(); // subclasses should do this earlier in most cases, but ensure it happens now - getBiometricContext().unsubscribe(mOperationContext); + unsubscribeBiometricContext(); } protected OperationContext getOperationContext() { return getBiometricContext().updateContext(mOperationContext, isCryptoOperation()); } + + protected ClientMonitorCallback getBiometricContextUnsubscriber() { + return new ClientMonitorCallback() { + @Override + public void onClientFinished(@NonNull BaseClientMonitor monitor, boolean success) { + unsubscribeBiometricContext(); + } + }; + } + + protected void unsubscribeBiometricContext() { + getBiometricContext().unsubscribe(mOperationContext); + } } 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 a8d059d514de7..d26a780085298 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 @@ -24,6 +24,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired; import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; @@ -107,7 +108,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient @NonNull @Override protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) { - return new ClientMonitorCompositeCallback(mALSProbeCallback, callback); + return new ClientMonitorCompositeCallback(mALSProbeCallback, + getBiometricContextUnsubscriber(), callback); } @Override @@ -177,8 +179,17 @@ class FingerprintAuthenticationClient extends AuthenticationClient final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { - return session.getSession().authenticateWithContext( - mOperationId, getOperationContext()); + final OperationContext opContext = getOperationContext(); + final ICancellationSignal cancel = session.getSession().authenticateWithContext( + mOperationId, opContext); + getBiometricContext().subscribe(opContext, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }); + return cancel; } else { return session.getSession().authenticate(mOperationId); } @@ -187,6 +198,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient @Override protected void stopHalOperation() { mSensorOverlays.hide(getSensorId()); + unsubscribeBiometricContext(); + if (mCancellationSignal != null) { try { mCancellationSignal.cancel(); @@ -216,7 +229,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient context.y = y; context.minor = minor; context.major = major; - context.isAoD = false; // TODO; get value + context.isAoD = getBiometricContext().isAoD(); session.getSession().onPointerDownWithContext(context); } else { session.getSession().onPointerDown(0 /* pointerId */, x, y, minor, major); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index bce972a38cfd0..e21d901b135dc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -23,6 +23,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired; import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; @@ -37,6 +38,8 @@ import android.util.Slog; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.log.CallbackWithProbe; +import com.android.server.biometrics.log.Probe; import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; @@ -56,6 +59,7 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps @NonNull private final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final SensorOverlays mSensorOverlays; + @NonNull private final CallbackWithProbe mALSProbeCallback; private final @FingerprintManager.EnrollReason int mEnrollReason; @Nullable private ICancellationSignal mCancellationSignal; @@ -81,6 +85,8 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController); mMaxTemplatesPerUser = maxTemplatesPerUser; + mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */); + mEnrollReason = enrollReason; if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) { getLogger().disableMetrics(); @@ -90,8 +96,8 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps @NonNull @Override protected ClientMonitorCallback wrapCallbackForStart(@NonNull ClientMonitorCallback callback) { - return new ClientMonitorCompositeCallback( - getLogger().createALSCallback(true /* startWithClient */), callback); + return new ClientMonitorCompositeCallback(mALSProbeCallback, + getBiometricContextUnsubscriber(), callback); } @Override @@ -139,22 +145,6 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps >= mMaxTemplatesPerUser; } - @Override - protected void stopHalOperation() { - mSensorOverlays.hide(getSensorId()); - - if (mCancellationSignal != null) { - try { - mCancellationSignal.cancel(); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception when requesting cancel", e); - onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, - 0 /* vendorCode */); - mCallback.onClientFinished(this, false /* success */); - } - } - } - @Override protected void startHalOperation() { mSensorOverlays.show(getSensorId(), getOverlayReasonFromEnrollReason(mEnrollReason), this); @@ -176,16 +166,44 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken); if (session.hasContextMethods()) { - return session.getSession().enrollWithContext(hat, getOperationContext()); + final OperationContext opContext = getOperationContext(); + final ICancellationSignal cancel = session.getSession().enrollWithContext( + hat, opContext); + getBiometricContext().subscribe(opContext, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }); + return cancel; } else { return session.getSession().enroll(hat); } } + @Override + protected void stopHalOperation() { + mSensorOverlays.hide(getSensorId()); + unsubscribeBiometricContext(); + + if (mCancellationSignal != null) { + try { + mCancellationSignal.cancel(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting cancel", e); + onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + } + } + @Override public void onPointerDown(int x, int y, float minor, float major) { try { mIsPointerDown = true; + mALSProbeCallback.getProbe().enable(); final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { @@ -195,7 +213,7 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps context.y = y; context.minor = minor; context.major = major; - context.isAoD = false; + context.isAoD = getBiometricContext().isAoD(); session.getSession().onPointerDownWithContext(context); } else { session.getSession().onPointerDown(0 /* pointerId */, x, y, minor, major); @@ -209,6 +227,7 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps public void onPointerUp() { try { mIsPointerDown = false; + mALSProbeCallback.getProbe().disable(); final AidlSession session = getFreshDaemon(); if (session.hasContextMethods()) { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 344edbbef9c7f..8a87c96fcaaa4 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -158,6 +158,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private final SparseArray mDisplayUiState = new SparseArray<>(); @GuardedBy("mLock") private IUdfpsHbmListener mUdfpsHbmListener; + @GuardedBy("mLock") + private IBiometricContextListener mBiometricContextListener; @GuardedBy("mCurrentRequestAddTilePackages") private final ArrayMap mCurrentRequestAddTilePackages = new ArrayMap<>(); @@ -897,6 +899,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void setBiometicContextListener(IBiometricContextListener listener) { enforceStatusBarService(); + synchronized (mLock) { + mBiometricContextListener = listener; + } if (mBar != null) { try { mBar.setBiometicContextListener(listener); @@ -1327,6 +1332,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D mHandler.post(() -> { synchronized (mLock) { setUdfpsHbmListener(mUdfpsHbmListener); + setBiometicContextListener(mBiometricContextListener); } }); } 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 59e697245cbf8..de0f038e8ec5a 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 @@ -109,6 +109,8 @@ public class FingerprintAuthenticationClientTest { private ArgumentCaptor mOperationContextCaptor; @Captor private ArgumentCaptor mPointerContextCaptor; + @Captor + private ArgumentCaptor> mContextInjector; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @@ -208,6 +210,23 @@ public class FingerprintAuthenticationClientTest { verify(mLuxProbe, times(2)).enable(); } + @Test + public void notifyHalWhenContextChanges() throws RemoteException { + final FingerprintAuthenticationClient client = createClient(); + client.start(mCallback); + + verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture()); + OperationContext opContext = mOperationContextCaptor.getValue(); + + // fake an update to the context + verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture()); + mContextInjector.getValue().accept(opContext); + verify(mHal).onContextChanged(eq(opContext)); + + client.stopHalOperation(); + verify(mBiometricContext).unsubscribe(same(opContext)); + } + @Test public void showHideOverlay_cancel() throws RemoteException { showHideOverlay(c -> c.cancel()); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java index 91b21357e9aaa..93cbef19aca9b 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java @@ -55,7 +55,6 @@ import org.mockito.junit.MockitoRule; public class FingerprintDetectClientTest { private static final int USER_ID = 8; - private static final boolean HAS_AOD = true; @Rule public final TestableContext mContext = new TestableContext( @@ -85,7 +84,6 @@ public class FingerprintDetectClientTest { @Before public void setup() { - when(mBiometricContext.isAoD()).thenReturn(HAS_AOD); when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( i -> i.getArgument(0)); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java index 018d277c7c445..5a96f5cca52a1 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.same; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -47,6 +48,8 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.log.CallbackWithProbe; +import com.android.server.biometrics.log.Probe; import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -101,16 +104,22 @@ public class FingerprintEnrollClientTest { private ClientMonitorCallback mCallback; @Mock private Sensor.HalSessionCallback mHalSessionCallback; + @Mock + private Probe mLuxProbe; @Captor private ArgumentCaptor mOperationContextCaptor; @Captor private ArgumentCaptor mPointerContextCaptor; + @Captor + private ArgumentCaptor> mContextInjector; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Before public void setup() { + when(mBiometricLogger.createALSCallback(anyBoolean())).thenAnswer(i -> + new CallbackWithProbe<>(mLuxProbe, i.getArgument(0))); when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer( i -> i.getArgument(0)); } @@ -185,6 +194,41 @@ public class FingerprintEnrollClientTest { assertThat(pContext.pointerId).isEqualTo(POINTER_ID); } + @Test + public void luxProbeWhenFingerDown() throws RemoteException { + final FingerprintEnrollClient client = createClient(); + client.start(mCallback); + + client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR); + verify(mLuxProbe).enable(); + + client.onAcquired(2, 0); + verify(mLuxProbe, never()).disable(); + + client.onPointerUp(); + verify(mLuxProbe).disable(); + + client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR); + verify(mLuxProbe, times(2)).enable(); + } + + @Test + public void notifyHalWhenContextChanges() throws RemoteException { + final FingerprintEnrollClient client = createClient(); + client.start(mCallback); + + verify(mHal).enrollWithContext(any(), mOperationContextCaptor.capture()); + OperationContext opContext = mOperationContextCaptor.getValue(); + + // fake an update to the context + verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture()); + mContextInjector.getValue().accept(opContext); + verify(mHal).onContextChanged(eq(opContext)); + + client.stopHalOperation(); + verify(mBiometricContext).unsubscribe(same(opContext)); + } + @Test public void showHideOverlay_cancel() throws RemoteException { showHideOverlay(c -> c.cancel());