diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java new file mode 100644 index 0000000000000..c3471bd1d7714 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java @@ -0,0 +1,126 @@ +/* + * 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; + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java similarity index 65% rename from services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java rename to services/core/java/com/android/server/biometrics/log/BiometricLogger.java index b4c82f2ed7990..d029af38c6837 100644 --- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java @@ -1,5 +1,5 @@ /* - * 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. @@ -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; @@ -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 - 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() { @@ -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; } @@ -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; } @@ -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 @@ -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; } @@ -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 @@ -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; } @@ -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 @@ -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; } @@ -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. @@ -352,7 +302,7 @@ public abstract class LoggableMonitor { * @param startWithClient if probe should start automatically when the operation starts. */ @NonNull - protected CallbackWithProbe createALSCallback(boolean startWithClient) { + public CallbackWithProbe createALSCallback(boolean startWithClient) { return new CallbackWithProbe<>(new ALSProbe(), startWithClient); } diff --git a/services/core/java/com/android/server/biometrics/log/CallbackWithProbe.java b/services/core/java/com/android/server/biometrics/log/CallbackWithProbe.java new file mode 100644 index 0000000000000..c985d5d2e5979 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/log/CallbackWithProbe.java @@ -0,0 +1,55 @@ +/* + * 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 probe type + */ +public class CallbackWithProbe 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; + } +} diff --git a/services/core/java/com/android/server/biometrics/log/Probe.java b/services/core/java/com/android/server/biometrics/log/Probe.java new file mode 100644 index 0000000000000..9e6fc6b8b8b2e --- /dev/null +++ b/services/core/java/com/android/server/biometrics/log/Probe.java @@ -0,0 +1,30 @@ +/* + * 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(); +} diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index 6f7176816ddbe..e29caa8461cf2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -105,7 +105,8 @@ public abstract class AcquisitionClient extends HalClientMonitor implement // that do not handle lockout under the HAL. In these cases, ensure that the framework only // sends errors once per ClientMonitor. if (mShouldSendErrorToClient) { - logOnError(getContext(), errorCode, vendorCode, getTargetUserId()); + getLogger().logOnError(getContext(), errorCode, vendorCode, + isCryptoOperation(), getTargetUserId()); try { if (getListener() != null) { mShouldSendErrorToClient = false; @@ -163,7 +164,8 @@ public abstract class AcquisitionClient extends HalClientMonitor 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); diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 358263df916b3..0eb5aaf143c4d 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -180,8 +180,8 @@ public abstract class AuthenticationClient extends AcquisitionClient @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList hardwareAuthToken) { - super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation, - getTargetUserId(), isBiometricPrompt()); + getLogger().logOnAuthenticated(getContext(), authenticated, mRequireConfirmation, + isCryptoOperation(), getTargetUserId(), isBiometricPrompt()); final ClientMonitorCallbackConverter listener = getListener(); diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java index 26bbb403f39f0..1248c8b6d4d93 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -27,18 +27,18 @@ import android.os.RemoteException; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.biometrics.log.BiometricLogger; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; /** - * Abstract base class for keeping track and dispatching events from the biometric's HAL to the + * Abstract base class for keeping track and dispatching events from the biometric's HAL to * the current client. Subclasses are responsible for coordinating the interaction with * the biometric's HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.). */ -public abstract class BaseClientMonitor extends LoggableMonitor - implements IBinder.DeathRecipient { +public abstract class BaseClientMonitor implements IBinder.DeathRecipient { private static final String TAG = "Biometrics/ClientMonitor"; protected static final boolean DEBUG = true; @@ -108,6 +108,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor private final int mTargetUserId; @NonNull private final String mOwner; private final int mSensorId; // sensorId as configured by the framework + @NonNull private final BiometricLogger mLogger; @Nullable private IBinder mToken; private long mRequestId; @@ -160,7 +161,14 @@ 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(context, statsModality, statsAction, statsClient); + this(context, token, listener, userId, owner, cookie, sensorId, + new BiometricLogger(context, statsModality, statsAction, statsClient)); + } + + @VisibleForTesting + BaseClientMonitor(@NonNull Context context, + @Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId, + @NonNull String owner, int cookie, int sensorId, @NonNull BiometricLogger logger) { mSequentialId = sCount++; mContext = context; mToken = token; @@ -170,6 +178,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor mOwner = owner; mCookie = cookie; mSensorId = sensorId; + mLogger = logger; try { if (token != null) { @@ -180,10 +189,6 @@ public abstract class BaseClientMonitor extends LoggableMonitor } } - public int getCookie() { - return mCookie; - } - /** * Starts the ClientMonitor's lifecycle. * @param callback invoked when the operation is complete (succeeds, fails, etc) @@ -257,6 +262,20 @@ public abstract class BaseClientMonitor extends LoggableMonitor } } + /** + * Only valid for AuthenticationClient. + * @return true if the client is authenticating for a crypto operation. + */ + protected boolean isCryptoOperation() { + return false; + } + + /** Logger for this client */ + @NonNull + public BiometricLogger getLogger() { + return mLogger; + } + public final Context getContext() { return mContext; } @@ -281,6 +300,11 @@ public abstract class BaseClientMonitor extends LoggableMonitor return mSensorId; } + /** Cookie set when this monitor was created. */ + public int getCookie() { + return mCookie; + } + /** Unique request id. */ public final long getRequestId() { return mRequestId; diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java index 2826e0c97305d..c83323a3eb3fb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java @@ -89,7 +89,8 @@ public abstract class EnrollClient extends AcquisitionClient implements En if (remaining == 0) { mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(), identifier); - logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs, + getLogger().logOnEnrolled(getTargetUserId(), + System.currentTimeMillis() - mEnrollmentStartTimeMs, true /* enrollSuccessful */); mCallback.onClientFinished(this, true /* success */); } @@ -116,7 +117,8 @@ public abstract class EnrollClient extends AcquisitionClient implements En */ @Override public void onError(int error, int vendorCode) { - logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs, + getLogger().logOnEnrolled(getTargetUserId(), + System.currentTimeMillis() - mEnrollmentStartTimeMs, false /* enrollSuccessful */); super.onError(error, vendorCode); } diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java index 579dfd69ec66b..82a8437277937 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -23,7 +23,6 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.os.IBinder; import android.util.Slog; -import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.BiometricsProto; import java.util.ArrayList; @@ -128,10 +127,9 @@ public abstract class InternalCleanupClient extends HalClientMonitor + identifier.getBiometricId() + " " + identifier.getName()); mUtils.removeBiometricForUser(getContext(), getTargetUserId(), identifier.getBiometricId()); - FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, - mStatsModality, - BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK, - -1 /* sensorId */); + + getLogger().logUnknownEnrollmentInFramework(); } mEnrolledList.clear(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index 4131ae127ab24..757a52cb8d8c0 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -105,7 +105,8 @@ class FaceAuthenticationClient extends AuthenticationClient implements @NonNull @Override protected Callback wrapCallbackForStart(@NonNull Callback callback) { - return new CompositeCallback(createALSCallback(true /* startWithClient */), callback); + return new CompositeCallback( + getLogger().createALSCallback(true /* startWithClient */), callback); } @Override @@ -241,7 +242,8 @@ class FaceAuthenticationClient extends AuthenticationClient implements mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT; - logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + getLogger().logOnError(getContext(), error, 0 /* vendorCode */, + isCryptoOperation(), getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); @@ -256,7 +258,8 @@ class FaceAuthenticationClient extends AuthenticationClient implements mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); // Lockout metrics are logged as an error code. final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT; - logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + getLogger().logOnError(getContext(), error, 0 /* vendorCode */, + isCryptoOperation(), getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java index aae4fbe9b0d73..b5f89b497273a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java @@ -111,7 +111,7 @@ public class FaceEnrollClient extends EnrollClient { @Override protected Callback wrapCallbackForStart(@NonNull Callback callback) { return new CompositeCallback(mPreviewHandleDeleterCallback, - createALSCallback(true /* startWithClient */), callback); + getLogger().createALSCallback(true /* startWithClient */), callback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java index 7548d2871a15e..80faf3ea17c55 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java @@ -95,7 +95,8 @@ class FaceAuthenticationClient extends AuthenticationClient { @NonNull @Override protected Callback wrapCallbackForStart(@NonNull Callback callback) { - return new CompositeCallback(createALSCallback(true /* startWithClient */), callback); + return new CompositeCallback( + getLogger().createALSCallback(true /* startWithClient */), callback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java index 31e5c86103fbe..5c69d6fb65c99 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java @@ -70,7 +70,8 @@ public class FaceEnrollClient extends EnrollClient { @NonNull @Override protected Callback wrapCallbackForStart(@NonNull Callback callback) { - return new CompositeCallback(createALSCallback(true /* startWithClient */), callback); + return new CompositeCallback( + getLogger().createALSCallback(true /* startWithClient */), callback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index e4d5fba3a4713..96f485394c701 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -33,6 +33,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.log.CallbackWithProbe; +import com.android.server.biometrics.log.Probe; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -80,7 +82,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient imp mLockoutCache = lockoutCache; mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController); mSensorProps = sensorProps; - mALSProbeCallback = createALSCallback(false /* startWithClient */); + mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */); } @Override @@ -233,7 +235,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient imp mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; - logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + getLogger().logOnError(getContext(), error, 0 /* vendorCode */, + isCryptoOperation(), getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); @@ -251,7 +254,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient imp mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); // Lockout metrics are logged as an error code. final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; - logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + getLogger().logOnError(getContext(), error, 0 /* vendorCode */, + isCryptoOperation(), getTargetUserId()); try { getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index 67507ccbbbfef..e3f26df1a4572 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -76,14 +76,15 @@ class FingerprintEnrollClient extends EnrollClient implements Udfps { mEnrollReason = enrollReason; if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) { - setShouldLog(false); + getLogger().disableMetrics(); } } @NonNull @Override protected Callback wrapCallbackForStart(@NonNull Callback callback) { - return new CompositeCallback(createALSCallback(true /* startWithClient */), callback); + return new CompositeCallback( + getLogger().createALSCallback(true /* startWithClient */), callback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 273f8a545db55..38fe73fc9b889 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -364,7 +364,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage final ClientMonitorCallbackConverter listener = client.getListener(); final String opPackageName = client.getOwnerString(); final boolean restricted = authClient.isRestricted(); - final int statsClient = client.getStatsClient(); + final int statsClient = client.getLogger().getStatsClient(); final boolean isKeyguard = authClient.isKeyguard(); // Don't actually send cancel() to the HAL, since successful auth already finishes diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java index 3058e2508f5fb..d9b290febd9d2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java @@ -32,6 +32,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.log.CallbackWithProbe; +import com.android.server.biometrics.log.Probe; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BiometricNotificationUtils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -80,7 +82,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient @Override public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList hardwareAuthToken) { - logOnAuthenticated(getContext(), authenticated, false /* requireConfirmation */, - getTargetUserId(), false /* isBiometricPrompt */); + getLogger().logOnAuthenticated(getContext(), authenticated, false /* requireConfirmation */, + isCryptoOperation(), getTargetUserId(), false /* isBiometricPrompt */); // Do not distinguish between success/failures. vibrateSuccess(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java index cc50bdfb59aec..dd92e3ed3026a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java @@ -69,14 +69,15 @@ public class FingerprintEnrollClient extends EnrollClient callback = + mLogger.createALSCallback(true /* startWithClient */); + + callback.onClientStarted(mClient); + verify(mSensorManager).registerListener(any(), any(), anyInt()); + + callback.onClientFinished(mClient, true /* success */); + verify(mSensorManager).unregisterListener(any(SensorEventListener.class)); + } + + @Test + public void testALSCallbackDoesNotStart() { + mLogger = createLogger(); + final CallbackWithProbe callback = + mLogger.createALSCallback(false /* startWithClient */); + + callback.onClientStarted(mClient); + callback.onClientFinished(mClient, true /* success */); + verify(mSensorManager, never()).registerListener(any(), any(), anyInt()); + } +}