Merge "Add snapshot of ambient light value to log during enrollment and authentication operations." into sc-dev am: d4fce118fc

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14785964

Change-Id: Ie7f30d8a0a4dd02e702822f669f2f32f97750b23
This commit is contained in:
Joe Bolinger
2021-06-14 18:49:33 +00:00
committed by Automerger Merge Worker
11 changed files with 177 additions and 21 deletions

View File

@@ -679,7 +679,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
latency,
mDebugEnabled,
-1 /* sensorId */);
-1 /* sensorId */,
-1f /* ambientLightLux */);
} else {
final long latency = System.currentTimeMillis() - mStartTimeMs;

View File

@@ -69,6 +69,31 @@ public abstract class BaseClientMonitor extends LoggableMonitor
}
}
/** Holder for wrapping multiple handlers into a single Callback. */
protected static class CompositeCallback implements Callback {
@NonNull
private final Callback[] mCallbacks;
public CompositeCallback(@NonNull Callback... callbacks) {
mCallbacks = callbacks;
}
@Override
public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
for (int i = 0; i < mCallbacks.length; i++) {
mCallbacks[i].onClientStarted(clientMonitor);
}
}
@Override
public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
for (int i = mCallbacks.length - 1; i >= 0; i--) {
mCallbacks[i].onClientFinished(clientMonitor, success);
}
}
}
private final int mSequentialId;
@NonNull private final Context mContext;
private final int mTargetUserId;
@@ -125,7 +150,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
int statsClient) {
super(statsModality, statsAction, statsClient);
super(context, statsModality, statsAction, statsClient);
mSequentialId = sCount++;
mContext = context;
mToken = token;
@@ -153,10 +178,19 @@ public abstract class BaseClientMonitor extends LoggableMonitor
* @param callback invoked when the operation is complete (succeeds, fails, etc)
*/
public void start(@NonNull Callback callback) {
mCallback = callback;
mCallback = wrapCallbackForStart(callback);
mCallback.onClientStarted(this);
}
/**
* Called during start to provide subclasses a hook for decorating the callback.
*
* Returns the original callback unless overridden.
*/
@NonNull
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return callback;
}
public boolean isAlreadyDone() {
return mAlreadyDone;

View File

@@ -16,7 +16,13 @@
package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.face.FaceManager;
@@ -37,9 +43,41 @@ public abstract class LoggableMonitor {
final int mStatsModality;
private final int mStatsAction;
private final int mStatsClient;
@NonNull private final SensorManager mSensorManager;
private long mFirstAcquireTimeMs;
private boolean mLightSensorEnabled = false;
private boolean mShouldLogMetrics = true;
// report only the most recent value
// consider com.android.server.display.utils.AmbientFilter or similar if need arises
private volatile float mLastAmbientLux = 0;
private final SensorEventListener mLightSensorListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
mLastAmbientLux = event.values[0];
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Not used.
}
};
/**
* @param context system_server context
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
*/
public LoggableMonitor(@NonNull Context context, int statsModality, int statsAction,
int statsClient) {
mStatsModality = statsModality;
mStatsAction = statsAction;
mStatsClient = statsClient;
mSensorManager = context.getSystemService(SensorManager.class);
}
/**
* Only valid for AuthenticationClient.
* @return true if the client is authenticating for a crypto operation.
@@ -48,17 +86,6 @@ public abstract class LoggableMonitor {
return false;
}
/**
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
*/
public LoggableMonitor(int statsModality, int statsAction, int statsClient) {
mStatsModality = statsModality;
mStatsAction = statsAction;
mStatsClient = statsClient;
}
protected void setShouldLog(boolean shouldLog) {
mShouldLogMetrics = shouldLog;
}
@@ -131,7 +158,6 @@ public abstract class LoggableMonitor {
}
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
if (!mShouldLogMetrics) {
return;
}
@@ -199,7 +225,8 @@ public abstract class LoggableMonitor {
+ ", Client: " + mStatsClient
+ ", RequireConfirmation: " + requireConfirmation
+ ", State: " + authState
+ ", Latency: " + latency);
+ ", Latency: " + latency
+ ", Lux: " + mLastAmbientLux);
} else {
Slog.v(TAG, "Authentication latency: " + latency);
}
@@ -217,7 +244,8 @@ public abstract class LoggableMonitor {
authState,
sanitizeLatency(latency),
Utils.isDebugEnabled(context, targetUserId),
-1 /* sensorId */);
-1 /* sensorId */,
mLastAmbientLux /* ambientLightLux */);
}
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -230,6 +258,7 @@ public abstract class LoggableMonitor {
+ ", User: " + targetUserId
+ ", Client: " + mStatsClient
+ ", Latency: " + latency
+ ", Lux: " + mLastAmbientLux
+ ", Success: " + enrollSuccessful);
} else {
Slog.v(TAG, "Enroll latency: " + latency);
@@ -244,7 +273,8 @@ public abstract class LoggableMonitor {
targetUserId,
sanitizeLatency(latency),
enrollSuccessful,
-1 /* sensorId */);
-1, /* sensorId */
mLastAmbientLux /* ambientLightLux */);
}
private long sanitizeLatency(long latency) {
@@ -255,4 +285,46 @@ public abstract class LoggableMonitor {
return latency;
}
/** Get a callback to start/stop ALS capture when client runs. */
@NonNull
protected BaseClientMonitor.Callback createALSCallback() {
return new BaseClientMonitor.Callback() {
@Override
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
setLightSensorLoggingEnabled(getAmbientLightSensor(mSensorManager));
}
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
setLightSensorLoggingEnabled(null);
}
};
}
/** The sensor to use for ALS logging. */
@Nullable
protected Sensor getAmbientLightSensor(@NonNull SensorManager sensorManager) {
return mShouldLogMetrics ? sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) : null;
}
private void setLightSensorLoggingEnabled(@Nullable Sensor lightSensor) {
if (DEBUG) {
Slog.v(TAG, "capturing ambient light using: "
+ (lightSensor != null ? lightSensor : "[disabled]"));
}
if (lightSensor != null) {
if (!mLightSensorEnabled) {
mLightSensorEnabled = true;
mLastAmbientLux = 0;
mSensorManager.registerListener(mLightSensorListener, lightSensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
} else {
mLightSensorEnabled = false;
mLastAmbientLux = 0;
mSensorManager.unregisterListener(mLightSensorListener);
}
}
}

View File

@@ -99,6 +99,12 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
"face_custom_success_error", 0) == 1;
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
protected void startHalOperation() {
try {
@@ -229,7 +235,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
}
@Override public void onLockoutTimed(long durationMillis) {
@Override
public void onLockoutTimed(long durationMillis) {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
@@ -242,7 +249,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
}
@Override public void onLockoutPermanent() {
@Override
public void onLockoutPermanent() {
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
// Lockout metrics are logged as an error code.
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;

View File

@@ -95,6 +95,12 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
ReEnrollNotificationUtils.cancelNotification(getContext());
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
public void destroy() {
try {

View File

@@ -88,6 +88,12 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
"face_custom_success_error", 0) == 1;
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
protected void startHalOperation() {
try {
@@ -186,7 +192,6 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@Override
public void onAcquired(int acquireInfo, int vendorCode) {
mLastAcquire = acquireInfo;
if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {

View File

@@ -68,6 +68,12 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
.getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(

View File

@@ -70,6 +70,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
mUdfpsOverlayController = udfpsOverlayController;
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {

View File

@@ -79,6 +79,12 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
}
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
super.onEnrollResult(identifier, remaining);

View File

@@ -69,6 +69,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
mUdfpsOverlayController = udfpsOverlayController;
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {

View File

@@ -72,6 +72,12 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
}
}
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
return new CompositeCallback(createALSCallback(), callback);
}
@Override
protected boolean hasReachedEnrollmentLimit() {
final int limit = getContext().getResources().getInteger(