Loading services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; import android.hardware.biometrics.BiometricsProtoEnums; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; /** * Wrapper for {@link FrameworkStatsLog} to isolate the testable parts. */ public class BiometricFrameworkStatsLogger { private static final String TAG = "BiometricFrameworkStatsLogger"; private static final BiometricFrameworkStatsLogger sInstance = new BiometricFrameworkStatsLogger(); private BiometricFrameworkStatsLogger() {} public static BiometricFrameworkStatsLogger getInstance() { return sInstance; } /** {@see FrameworkStatsLog.BIOMETRIC_ACQUIRED}. */ public void acquired( int statsModality, int statsAction, int statsClient, boolean isDebug, int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, statsModality, targetUserId, isCrypto, statsAction, statsClient, acquiredInfo, vendorCode, isDebug, -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */ public void authenticate( int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, boolean authenticated, int authState, boolean requireConfirmation, boolean isCrypto, int targetUserId, boolean isBiometricPrompt, float ambientLightLux) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality, targetUserId, isCrypto, statsClient, requireConfirmation, authState, sanitizeLatency(latency), isDebug, -1 /* sensorId */, ambientLightLux); } /** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */ public void enroll(int statsModality, int statsAction, int statsClient, int targetUserId, long latency, boolean enrollSuccessful, float ambientLightLux) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, statsModality, targetUserId, sanitizeLatency(latency), enrollSuccessful, -1, /* sensorId */ ambientLightLux); } /** {@see FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED}. */ public void error( int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, int error, int vendorCode, boolean isCrypto, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality, targetUserId, isCrypto, statsAction, statsClient, error, vendorCode, isDebug, sanitizeLatency(latency), -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ public void reportUnknownTemplateEnrolledHal(int statsModality) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality, BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL, -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ public void reportUnknownTemplateEnrolledFramework(int statsModality) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality, BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK, -1 /* sensorId */); } private long sanitizeLatency(long latency) { if (latency < 0) { Slog.w(TAG, "found a negative latency : " + latency); return -1; } return latency; } } services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java→services/core/java/com/android/server/biometrics/log/BiometricLogger.java +68 −118 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.server.biometrics.sensors; package com.android.server.biometrics.log; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -29,71 +29,28 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.Utils; /** * Abstract class that adds logging functionality to the ClientMonitor classes. * Logger for all reported Biometric framework events. */ public abstract class LoggableMonitor { public class BiometricLogger { public static final String TAG = "Biometrics/LoggableMonitor"; public static final String TAG = "BiometricLogger"; public static final boolean DEBUG = false; final int mStatsModality; private final int mStatsModality; private final int mStatsAction; private final int mStatsClient; private final BiometricFrameworkStatsLogger mSink; @NonNull private final SensorManager mSensorManager; private long mFirstAcquireTimeMs; private boolean mLightSensorEnabled = false; private boolean mShouldLogMetrics = true; /** * Probe for loggable attributes that can be continuously monitored, such as ambient light. * * Disable probes when the sensors are in states that are not interesting for monitoring * purposes to save power. */ protected interface Probe { /** Ensure the probe is actively sampling for new data. */ void enable(); /** Stop sampling data. */ void disable(); } /** * Client monitor callback that exposes a probe. * * Disables the probe when the operation completes. */ protected static class CallbackWithProbe<T extends Probe> implements BaseClientMonitor.Callback { private final boolean mStartWithClient; private final T mProbe; public CallbackWithProbe(@NonNull T probe, boolean startWithClient) { mProbe = probe; mStartWithClient = startWithClient; } @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { if (mStartWithClient) { mProbe.enable(); } } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mProbe.disable(); } @NonNull public T getProbe() { return mProbe; } } private class ALSProbe implements Probe { @Override public void enable() { Loading Loading @@ -128,26 +85,30 @@ public abstract class LoggableMonitor { * @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) { public BiometricLogger( @NonNull Context context, int statsModality, int statsAction, int statsClient) { this(statsModality, statsAction, statsClient, BiometricFrameworkStatsLogger.getInstance(), context.getSystemService(SensorManager.class)); } @VisibleForTesting BiometricLogger( int statsModality, int statsAction, int statsClient, BiometricFrameworkStatsLogger logSink, SensorManager sensorManager) { mStatsModality = statsModality; mStatsAction = statsAction; mStatsClient = statsClient; mSensorManager = context.getSystemService(SensorManager.class); mSink = logSink; mSensorManager = sensorManager; } /** * 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) { mShouldLogMetrics = shouldLog; /** Disable logging metrics and only log critical events, such as system health issues. */ public void disableMetrics() { mShouldLogMetrics = false; } /** {@link BiometricsProtoEnums} CLIENT_* constants */ public int getStatsClient() { return mStatsClient; } Loading @@ -171,8 +132,9 @@ public abstract class LoggableMonitor { return shouldSkipLogging; } protected final void logOnAcquired(Context context, int acquiredInfo, int vendorCode, int targetUserId) { /** Log an acquisition event. */ public void logOnAcquired(Context context, int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading @@ -192,7 +154,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Acquired! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", AcquiredInfo: " + acquiredInfo Loading @@ -203,19 +165,14 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, mStatsModality, targetUserId, isCryptoOperation(), mStatsAction, mStatsClient, acquiredInfo, vendorCode, mSink.acquired(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), -1 /* sensorId */); acquiredInfo, vendorCode, isCrypto, targetUserId); } protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) { /** Log an error during an operation. */ public void logOnError(Context context, int error, int vendorCode, boolean isCrypto, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading @@ -226,7 +183,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Error! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", Error: " + error Loading @@ -240,21 +197,15 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, mStatsModality, targetUserId, isCryptoOperation(), mStatsAction, mStatsClient, error, vendorCode, Utils.isDebugEnabled(context, targetUserId), sanitizeLatency(latency), -1 /* sensorId */); mSink.error(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), latency, error, vendorCode, isCrypto, targetUserId); } protected final void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) { /** Log authentication attempt. */ public void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, boolean isCrypto, int targetUserId, boolean isBiometricPrompt) { if (!mShouldLogMetrics) { return; } Loading @@ -279,7 +230,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Authenticated! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Client: " + mStatsClient + ", RequireConfirmation: " + requireConfirmation + ", State: " + authState Loading @@ -293,20 +244,14 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, mStatsModality, targetUserId, isCryptoOperation(), mStatsClient, requireConfirmation, authState, sanitizeLatency(latency), mSink.authenticate(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), -1 /* sensorId */, mLastAmbientLux /* ambientLightLux */); latency, authenticated, authState, requireConfirmation, isCrypto, targetUserId, isBiometricPrompt, mLastAmbientLux); } protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) { /** Log enrollment outcome. */ public void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) { if (!mShouldLogMetrics) { return; } Loading @@ -326,25 +271,30 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, mStatsModality, targetUserId, sanitizeLatency(latency), enrollSuccessful, -1, /* sensorId */ mLastAmbientLux /* ambientLightLux */); mSink.enroll(mStatsModality, mStatsAction, mStatsClient, targetUserId, latency, enrollSuccessful, mLastAmbientLux); } private long sanitizeLatency(long latency) { if (latency < 0) { Slog.w(TAG, "found a negative latency : " + latency); return -1; /** Report unexpected enrollment reported by the HAL. */ public void logUnknownEnrollmentInHal() { if (shouldSkipLogging()) { return; } return latency; mSink.reportUnknownTemplateEnrolledHal(mStatsModality); } /** Report unknown enrollment in framework settings */ public void logUnknownEnrollmentInFramework() { if (shouldSkipLogging()) { return; } mSink.reportUnknownTemplateEnrolledFramework(mStatsModality); } /** * Get a callback to start/stop ALS capture when client runs. * Get a callback to start/stop ALS capture when a client runs. * * If the probe should not run for the entire operation, do not set startWithClient and * start/stop the problem when needed. Loading @@ -352,7 +302,7 @@ public abstract class LoggableMonitor { * @param startWithClient if probe should start automatically when the operation starts. */ @NonNull protected CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) { public CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) { return new CallbackWithProbe<>(new ALSProbe(), startWithClient); } Loading services/core/java/com/android/server/biometrics/log/CallbackWithProbe.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; import android.annotation.NonNull; import com.android.server.biometrics.sensors.BaseClientMonitor; /** * Client monitor callback that exposes a probe. * * Disables the probe when the operation completes. * * @param <T> probe type */ public class CallbackWithProbe<T extends Probe> implements BaseClientMonitor.Callback { private final boolean mStartWithClient; private final T mProbe; public CallbackWithProbe(@NonNull T probe, boolean startWithClient) { mProbe = probe; mStartWithClient = startWithClient; } @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { if (mStartWithClient) { mProbe.enable(); } } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mProbe.disable(); } @NonNull public T getProbe() { return mProbe; } } services/core/java/com/android/server/biometrics/log/Probe.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; /** * Probe for loggable attributes that can be continuously monitored, such as ambient light. * * Disable probes when the sensors are in states that are not interesting for monitoring * purposes to save power. */ public interface Probe { /** Ensure the probe is actively sampling for new data. */ void enable(); /** Stop sampling data. */ void disable(); } services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +4 −2 Original line number Diff line number Diff line Loading @@ -105,7 +105,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) { logOnError(getContext(), errorCode, vendorCode, getTargetUserId()); getLogger().logOnError(getContext(), errorCode, vendorCode, isCryptoOperation(), getTargetUserId()); try { if (getListener() != null) { mShouldSendErrorToClient = false; Loading Loading @@ -163,7 +164,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement protected final void onAcquiredInternal(int acquiredInfo, int vendorCode, boolean shouldSend) { super.logOnAcquired(getContext(), acquiredInfo, vendorCode, getTargetUserId()); getLogger().logOnAcquired(getContext(), acquiredInfo, vendorCode, isCryptoOperation(), getTargetUserId()); if (DEBUG) { Slog.v(TAG, "Acquired: " + acquiredInfo + " " + vendorCode + ", shouldSend: " + shouldSend); Loading Loading
services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; import android.hardware.biometrics.BiometricsProtoEnums; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; /** * Wrapper for {@link FrameworkStatsLog} to isolate the testable parts. */ public class BiometricFrameworkStatsLogger { private static final String TAG = "BiometricFrameworkStatsLogger"; private static final BiometricFrameworkStatsLogger sInstance = new BiometricFrameworkStatsLogger(); private BiometricFrameworkStatsLogger() {} public static BiometricFrameworkStatsLogger getInstance() { return sInstance; } /** {@see FrameworkStatsLog.BIOMETRIC_ACQUIRED}. */ public void acquired( int statsModality, int statsAction, int statsClient, boolean isDebug, int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, statsModality, targetUserId, isCrypto, statsAction, statsClient, acquiredInfo, vendorCode, isDebug, -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */ public void authenticate( int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, boolean authenticated, int authState, boolean requireConfirmation, boolean isCrypto, int targetUserId, boolean isBiometricPrompt, float ambientLightLux) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality, targetUserId, isCrypto, statsClient, requireConfirmation, authState, sanitizeLatency(latency), isDebug, -1 /* sensorId */, ambientLightLux); } /** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */ public void enroll(int statsModality, int statsAction, int statsClient, int targetUserId, long latency, boolean enrollSuccessful, float ambientLightLux) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, statsModality, targetUserId, sanitizeLatency(latency), enrollSuccessful, -1, /* sensorId */ ambientLightLux); } /** {@see FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED}. */ public void error( int statsModality, int statsAction, int statsClient, boolean isDebug, long latency, int error, int vendorCode, boolean isCrypto, int targetUserId) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality, targetUserId, isCrypto, statsAction, statsClient, error, vendorCode, isDebug, sanitizeLatency(latency), -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ public void reportUnknownTemplateEnrolledHal(int statsModality) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality, BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL, -1 /* sensorId */); } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ public void reportUnknownTemplateEnrolledFramework(int statsModality) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality, BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK, -1 /* sensorId */); } private long sanitizeLatency(long latency) { if (latency < 0) { Slog.w(TAG, "found a negative latency : " + latency); return -1; } return latency; } }
services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java→services/core/java/com/android/server/biometrics/log/BiometricLogger.java +68 −118 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.server.biometrics.sensors; package com.android.server.biometrics.log; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -29,71 +29,28 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.Utils; /** * Abstract class that adds logging functionality to the ClientMonitor classes. * Logger for all reported Biometric framework events. */ public abstract class LoggableMonitor { public class BiometricLogger { public static final String TAG = "Biometrics/LoggableMonitor"; public static final String TAG = "BiometricLogger"; public static final boolean DEBUG = false; final int mStatsModality; private final int mStatsModality; private final int mStatsAction; private final int mStatsClient; private final BiometricFrameworkStatsLogger mSink; @NonNull private final SensorManager mSensorManager; private long mFirstAcquireTimeMs; private boolean mLightSensorEnabled = false; private boolean mShouldLogMetrics = true; /** * Probe for loggable attributes that can be continuously monitored, such as ambient light. * * Disable probes when the sensors are in states that are not interesting for monitoring * purposes to save power. */ protected interface Probe { /** Ensure the probe is actively sampling for new data. */ void enable(); /** Stop sampling data. */ void disable(); } /** * Client monitor callback that exposes a probe. * * Disables the probe when the operation completes. */ protected static class CallbackWithProbe<T extends Probe> implements BaseClientMonitor.Callback { private final boolean mStartWithClient; private final T mProbe; public CallbackWithProbe(@NonNull T probe, boolean startWithClient) { mProbe = probe; mStartWithClient = startWithClient; } @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { if (mStartWithClient) { mProbe.enable(); } } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mProbe.disable(); } @NonNull public T getProbe() { return mProbe; } } private class ALSProbe implements Probe { @Override public void enable() { Loading Loading @@ -128,26 +85,30 @@ public abstract class LoggableMonitor { * @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) { public BiometricLogger( @NonNull Context context, int statsModality, int statsAction, int statsClient) { this(statsModality, statsAction, statsClient, BiometricFrameworkStatsLogger.getInstance(), context.getSystemService(SensorManager.class)); } @VisibleForTesting BiometricLogger( int statsModality, int statsAction, int statsClient, BiometricFrameworkStatsLogger logSink, SensorManager sensorManager) { mStatsModality = statsModality; mStatsAction = statsAction; mStatsClient = statsClient; mSensorManager = context.getSystemService(SensorManager.class); mSink = logSink; mSensorManager = sensorManager; } /** * 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) { mShouldLogMetrics = shouldLog; /** Disable logging metrics and only log critical events, such as system health issues. */ public void disableMetrics() { mShouldLogMetrics = false; } /** {@link BiometricsProtoEnums} CLIENT_* constants */ public int getStatsClient() { return mStatsClient; } Loading @@ -171,8 +132,9 @@ public abstract class LoggableMonitor { return shouldSkipLogging; } protected final void logOnAcquired(Context context, int acquiredInfo, int vendorCode, int targetUserId) { /** Log an acquisition event. */ public void logOnAcquired(Context context, int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading @@ -192,7 +154,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Acquired! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", AcquiredInfo: " + acquiredInfo Loading @@ -203,19 +165,14 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, mStatsModality, targetUserId, isCryptoOperation(), mStatsAction, mStatsClient, acquiredInfo, vendorCode, mSink.acquired(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), -1 /* sensorId */); acquiredInfo, vendorCode, isCrypto, targetUserId); } protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) { /** Log an error during an operation. */ public void logOnError(Context context, int error, int vendorCode, boolean isCrypto, int targetUserId) { if (!mShouldLogMetrics) { return; } Loading @@ -226,7 +183,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Error! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Action: " + mStatsAction + ", Client: " + mStatsClient + ", Error: " + error Loading @@ -240,21 +197,15 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, mStatsModality, targetUserId, isCryptoOperation(), mStatsAction, mStatsClient, error, vendorCode, Utils.isDebugEnabled(context, targetUserId), sanitizeLatency(latency), -1 /* sensorId */); mSink.error(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), latency, error, vendorCode, isCrypto, targetUserId); } protected final void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) { /** Log authentication attempt. */ public void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, boolean isCrypto, int targetUserId, boolean isBiometricPrompt) { if (!mShouldLogMetrics) { return; } Loading @@ -279,7 +230,7 @@ public abstract class LoggableMonitor { if (DEBUG) { Slog.v(TAG, "Authenticated! Modality: " + mStatsModality + ", User: " + targetUserId + ", IsCrypto: " + isCryptoOperation() + ", IsCrypto: " + isCrypto + ", Client: " + mStatsClient + ", RequireConfirmation: " + requireConfirmation + ", State: " + authState Loading @@ -293,20 +244,14 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, mStatsModality, targetUserId, isCryptoOperation(), mStatsClient, requireConfirmation, authState, sanitizeLatency(latency), mSink.authenticate(mStatsModality, mStatsAction, mStatsClient, Utils.isDebugEnabled(context, targetUserId), -1 /* sensorId */, mLastAmbientLux /* ambientLightLux */); latency, authenticated, authState, requireConfirmation, isCrypto, targetUserId, isBiometricPrompt, mLastAmbientLux); } protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) { /** Log enrollment outcome. */ public void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) { if (!mShouldLogMetrics) { return; } Loading @@ -326,25 +271,30 @@ public abstract class LoggableMonitor { return; } FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, mStatsModality, targetUserId, sanitizeLatency(latency), enrollSuccessful, -1, /* sensorId */ mLastAmbientLux /* ambientLightLux */); mSink.enroll(mStatsModality, mStatsAction, mStatsClient, targetUserId, latency, enrollSuccessful, mLastAmbientLux); } private long sanitizeLatency(long latency) { if (latency < 0) { Slog.w(TAG, "found a negative latency : " + latency); return -1; /** Report unexpected enrollment reported by the HAL. */ public void logUnknownEnrollmentInHal() { if (shouldSkipLogging()) { return; } return latency; mSink.reportUnknownTemplateEnrolledHal(mStatsModality); } /** Report unknown enrollment in framework settings */ public void logUnknownEnrollmentInFramework() { if (shouldSkipLogging()) { return; } mSink.reportUnknownTemplateEnrolledFramework(mStatsModality); } /** * Get a callback to start/stop ALS capture when client runs. * Get a callback to start/stop ALS capture when a client runs. * * If the probe should not run for the entire operation, do not set startWithClient and * start/stop the problem when needed. Loading @@ -352,7 +302,7 @@ public abstract class LoggableMonitor { * @param startWithClient if probe should start automatically when the operation starts. */ @NonNull protected CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) { public CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) { return new CallbackWithProbe<>(new ALSProbe(), startWithClient); } Loading
services/core/java/com/android/server/biometrics/log/CallbackWithProbe.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; import android.annotation.NonNull; import com.android.server.biometrics.sensors.BaseClientMonitor; /** * Client monitor callback that exposes a probe. * * Disables the probe when the operation completes. * * @param <T> probe type */ public class CallbackWithProbe<T extends Probe> implements BaseClientMonitor.Callback { private final boolean mStartWithClient; private final T mProbe; public CallbackWithProbe(@NonNull T probe, boolean startWithClient) { mProbe = probe; mStartWithClient = startWithClient; } @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { if (mStartWithClient) { mProbe.enable(); } } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mProbe.disable(); } @NonNull public T getProbe() { return mProbe; } }
services/core/java/com/android/server/biometrics/log/Probe.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.biometrics.log; /** * Probe for loggable attributes that can be continuously monitored, such as ambient light. * * Disable probes when the sensors are in states that are not interesting for monitoring * purposes to save power. */ public interface Probe { /** Ensure the probe is actively sampling for new data. */ void enable(); /** Stop sampling data. */ void disable(); }
services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +4 −2 Original line number Diff line number Diff line Loading @@ -105,7 +105,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) { logOnError(getContext(), errorCode, vendorCode, getTargetUserId()); getLogger().logOnError(getContext(), errorCode, vendorCode, isCryptoOperation(), getTargetUserId()); try { if (getListener() != null) { mShouldSendErrorToClient = false; Loading Loading @@ -163,7 +164,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement protected final void onAcquiredInternal(int acquiredInfo, int vendorCode, boolean shouldSend) { super.logOnAcquired(getContext(), acquiredInfo, vendorCode, getTargetUserId()); getLogger().logOnAcquired(getContext(), acquiredInfo, vendorCode, isCryptoOperation(), getTargetUserId()); if (DEBUG) { Slog.v(TAG, "Acquired: " + acquiredInfo + " " + vendorCode + ", shouldSend: " + shouldSend); Loading