Loading services/core/java/com/android/server/biometrics/AuthSession.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +36 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java +84 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -37,26 +43,47 @@ 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; /** * Only valid for AuthenticationClient. * @return true if the client is authenticating for a crypto operation. */ protected boolean isCryptoOperation() { return false; // 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(int statsModality, int statsAction, int statsClient) { 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. */ protected boolean isCryptoOperation() { return false; } protected void setShouldLog(boolean shouldLog) { Loading Loading @@ -131,7 +158,6 @@ public abstract class LoggableMonitor { } protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading Loading @@ -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); } Loading @@ -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) { Loading @@ -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); Loading @@ -244,7 +273,8 @@ public abstract class LoggableMonitor { targetUserId, sanitizeLatency(latency), enrollSuccessful, -1 /* sensorId */); -1, /* sensorId */ mLastAmbientLux /* ambientLightLux */); } private long sanitizeLatency(long latency) { Loading @@ -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); } } } services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +10 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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; Loading services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +6 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
services/core/java/com/android/server/biometrics/AuthSession.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +36 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading
services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java +84 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -37,26 +43,47 @@ 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; /** * Only valid for AuthenticationClient. * @return true if the client is authenticating for a crypto operation. */ protected boolean isCryptoOperation() { return false; // 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(int statsModality, int statsAction, int statsClient) { 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. */ protected boolean isCryptoOperation() { return false; } protected void setShouldLog(boolean shouldLog) { Loading Loading @@ -131,7 +158,6 @@ public abstract class LoggableMonitor { } protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading Loading @@ -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); } Loading @@ -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) { Loading @@ -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); Loading @@ -244,7 +273,8 @@ public abstract class LoggableMonitor { targetUserId, sanitizeLatency(latency), enrollSuccessful, -1 /* sensorId */); -1, /* sensorId */ mLastAmbientLux /* ambientLightLux */); } private long sanitizeLatency(long latency) { Loading @@ -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); } } }
services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +10 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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; Loading
services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +6 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading