Merge changes from topic "blog"

* changes:
  Send AoD context changed notification to HAL.
  Connect SysUI sessions with biometric operations logs.
This commit is contained in:
Joe Bolinger
2022-02-01 00:43:43 +00:00
committed by Android (Google) Code Review
37 changed files with 665 additions and 280 deletions

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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<BiometricContextProvider> sInstance =
new Singleton<BiometricContextProvider>() {
@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<OperationContext, Consumer<OperationContext>> mSubscribers =
new ConcurrentHashMap<>();
@Nullable
private final Map<Integer, InstanceId> 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);
});
}

View File

@@ -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;
}
}

View File

@@ -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. */

View File

@@ -110,8 +110,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> 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<T> extends HalClientMonitor<T> 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);

View File

@@ -166,8 +166,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> hardwareAuthToken) {
getLogger().logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
isCryptoOperation(), getTargetUserId(), isBiometricPrompt());
getLogger().logOnAuthenticated(getContext(), getOperationContext(),
authenticated, mRequireConfirmation, getTargetUserId(), isBiometricPrompt());
final ClientMonitorCallbackConverter listener = getListener();

View File

@@ -37,7 +37,7 @@ public abstract class HalClientMonitor<T> extends BaseClientMonitor {
protected final Supplier<T> 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<T> 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);
}
}

View File

@@ -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);

View File

@@ -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<AidlSession>
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<AidlSession>
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<AidlSession>
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 */);

View File

@@ -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<AidlSession> 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();
}

View File

@@ -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<AidlSession> {
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);

View File

@@ -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<Face> 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);

View File

@@ -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);
}
});

View File

@@ -119,6 +119,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@NonNull private final Map<Integer, Long> 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,

View File

@@ -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);

View File

@@ -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<AidlSession>
@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<AidlSession>
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<AidlSession>
@Override
protected void stopHalOperation() {
mSensorOverlays.hide(getSensorId());
unsubscribeBiometricContext();
if (mCancellationSignal != null) {
try {
mCancellationSignal.cancel();
@@ -221,7 +229,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
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<AidlSession>
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<AidlSession>
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 */);

View File

@@ -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<AidlSession> 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();
}

View File

@@ -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<AidlSession> implements Udfps
@NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
@NonNull private final SensorOverlays mSensorOverlays;
@NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
private final @FingerprintManager.EnrollReason int mEnrollReason;
@Nullable private ICancellationSignal mCancellationSignal;
@@ -83,6 +85,8 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> 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<AidlSession> 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<AidlSession> 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<AidlSession> 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<AidlSession> 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<AidlSession> implements Udfps
public void onPointerUp() {
try {
mIsPointerDown = false;
mALSProbeCallback.getProbe().disable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {

View File

@@ -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<SensorLocationInternal> 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<Fingerprint> 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);
});

View File

@@ -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);
}
});

View File

@@ -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);
});

View File

@@ -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;

View File

@@ -130,8 +130,9 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated,
ArrayList<Byte> 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();

View File

@@ -158,6 +158,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
private final SparseArray<UiState> mDisplayUiState = new SparseArray<>();
@GuardedBy("mLock")
private IUdfpsHbmListener mUdfpsHbmListener;
@GuardedBy("mLock")
private IBiometricContextListener mBiometricContextListener;
@GuardedBy("mCurrentRequestAddTilePackages")
private final ArrayMap<String, Long> 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);
}
});
}

View File

@@ -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<IBiometricContextListener> captor =
ArgumentCaptor.forClass(IBiometricContextListener.class);
verify(mStatusBarService).setBiometicContextListener(captor.capture());
mListener = captor.getValue();
ArgumentCaptor<ISessionListener> 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;
}
}

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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<OperationContext> 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());
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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<OperationContext> mOperationContextCaptor;
@Captor
private ArgumentCaptor<PointerContext> mPointerContextCaptor;
@Captor
private ArgumentCaptor<Consumer<OperationContext>> 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());

View File

@@ -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();
}

View File

@@ -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<OperationContext> mOperationContextCaptor;
@Captor
private ArgumentCaptor<PointerContext> mPointerContextCaptor;
@Captor
private ArgumentCaptor<Consumer<OperationContext>> 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());

View File

@@ -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;
}

View File

@@ -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