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..a6e89115400d0 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 @@ -82,6 +82,23 @@ public abstract class HalClientMonitor extends BaseClientMonitor { super.destroy(); // subclasses should do this earlier in most cases, but ensure it happens now + 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/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..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,7 +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.OperationReason; +import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.PointerContext; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.ISidefpsController; @@ -108,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 @@ -178,12 +179,17 @@ 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); + 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); } @@ -192,6 +198,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient @Override protected void stopHalOperation() { mSensorOverlays.hide(getSensorId()); + unsubscribeBiometricContext(); + if (mCancellationSignal != null) { try { mCancellationSignal.cancel(); @@ -221,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); @@ -279,8 +287,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 +306,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..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 @@ -24,7 +24,6 @@ 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; @@ -39,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; @@ -58,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; @@ -83,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(); @@ -92,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 @@ -141,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); @@ -178,22 +166,44 @@ 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); + 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()) { @@ -203,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); @@ -217,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/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/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/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..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 @@ -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; @@ -107,6 +109,8 @@ public class FingerprintAuthenticationClientTest { private ArgumentCaptor mOperationContextCaptor; @Captor private ArgumentCaptor mPointerContextCaptor; + @Captor + private ArgumentCaptor> mContextInjector; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @@ -115,7 +119,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 +137,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 @@ -204,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 295fe4766a85f..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 @@ -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; @@ -51,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( @@ -81,7 +84,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 +104,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..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 @@ -18,11 +18,15 @@ 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.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -44,14 +48,18 @@ 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; +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; @@ -96,14 +104,26 @@ 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)); + } + @Test public void enrollNoContext_v1() throws RemoteException { final FingerprintEnrollClient client = createClient(1); @@ -120,7 +140,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()); } @@ -171,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()); 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