From 7782d1485e227a2a01a77b189e8c976c2de7b338 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 18 Jan 2019 12:51:33 -0800 Subject: [PATCH] Add logging for Biometrics Bug: 117060268 Bug: 120161047 Test: With LoggableMonitor DEBUG turned on, manually tested and checked logs Change-Id: Ib8b3ec9ed7913e38b17597ac7eda535925e1576a --- .../biometrics/AuthenticationClient.java | 19 ++- .../server/biometrics/BiometricService.java | 98 +++++++++++- .../biometrics/BiometricServiceBase.java | 30 +++- .../server/biometrics/ClientMonitor.java | 4 +- .../server/biometrics/EnrollClient.java | 6 + .../server/biometrics/EnumerateClient.java | 6 + .../server/biometrics/LoggableMonitor.java | 151 ++++++++++++++++++ .../server/biometrics/RemovalClient.java | 6 + .../server/biometrics/face/FaceService.java | 30 +++- .../fingerprint/FingerprintService.java | 45 +++++- .../server/biometrics/iris/IrisService.java | 6 + 11 files changed, 383 insertions(+), 18 deletions(-) create mode 100644 services/core/java/com/android/server/biometrics/LoggableMonitor.java diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java index eaa7a83fab0dd..bd4acdbf4070f 100644 --- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java @@ -19,6 +19,7 @@ package com.android.server.biometrics; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.os.IBinder; import android.os.RemoteException; import android.security.KeyStore; @@ -71,6 +72,11 @@ public abstract class AuthenticationClient extends ClientMonitor { stop(false /* initiatedByClient */); } + @Override + protected int statsAction() { + return BiometricsProtoEnums.ACTION_AUTHENTICATE; + } + public boolean isBiometricPrompt() { return getCookie() != 0; } @@ -79,9 +85,17 @@ public abstract class AuthenticationClient extends ClientMonitor { return mRequireConfirmation; } + @Override + protected boolean isCryptoOperation() { + return mOpId != 0; + } + @Override public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated, ArrayList token) { + super.logOnAuthenticated(authenticated, mRequireConfirmation, getTargetUserId(), + isBiometricPrompt()); + final BiometricServiceBase.ServiceListener listener = getListener(); mMetricsLogger.action(mMetrics.actionBiometricAuth(), authenticated); @@ -142,10 +156,7 @@ public abstract class AuthenticationClient extends ClientMonitor { final int errorCode = lockoutMode == LOCKOUT_TIMED ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; - if (listener != null) { - listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */, - getCookie()); - } + onError(getHalDeviceId(), errorCode, 0 /* vendorCode */); } else { // Don't send onAuthenticationFailed if we're in lockout, it causes a // janky UI on Keyguard/BiometricPrompt since "authentication failed" diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 15d66e6e646f7..3ee1a04850ce9 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -41,6 +41,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceReceiver; @@ -64,6 +65,7 @@ import android.security.KeyStore; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; +import android.util.StatsLog; import com.android.internal.R; import com.android.internal.statusbar.IStatusBarService; @@ -309,6 +311,7 @@ public class BiometricService extends SystemService { // Continue authentication with the same modality/modalities after "try again" is // pressed final int mModality; + final boolean mRequireConfirmation; // The current state, which can be either idle, called, or started private int mState = STATE_AUTH_IDLE; @@ -316,10 +319,13 @@ public class BiometricService extends SystemService { // the authentication. byte[] mTokenEscrow; + // Timestamp when hardware authentication occurred + private long mAuthenticatedTimeMs; + AuthSession(HashMap modalities, IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, - int modality) { + int modality, boolean requireConfirmation) { mModalitiesWaiting = modalities; mToken = token; mSessionId = sessionId; @@ -331,6 +337,11 @@ public class BiometricService extends SystemService { mCallingPid = callingPid; mCallingUserId = callingUserId; mModality = modality; + mRequireConfirmation = requireConfirmation; + } + + boolean isCrypto() { + return mSessionId != 0; } boolean containsCookie(int cookie) { @@ -412,6 +423,7 @@ public class BiometricService extends SystemService { mCurrentAuthSession.mState = STATE_AUTH_IDLE; mCurrentAuthSession = null; } else { + mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis(); // Store the auth token and submit it to keystore after the confirmation // button has been pressed. mCurrentAuthSession.mTokenEscrow = token; @@ -557,6 +569,8 @@ public class BiometricService extends SystemService { return; } + logDialogDismissed(reason); + if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) { // Positive button is used by passive modalities as a "confirm" button, // do not send to client @@ -599,6 +613,77 @@ public class BiometricService extends SystemService { mCurrentAuthSession.mModality); }); } + + private void logDialogDismissed(int reason) { + if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) { + // Explicit auth, authentication confirmed. + // Latency in this case is authenticated -> confirmed. Service + // should have the first half (first acquired -> authenticated). + final long latency = System.currentTimeMillis() + - mCurrentAuthSession.mAuthenticatedTimeMs; + + if (LoggableMonitor.DEBUG) { + Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality() + + ", User: " + mCurrentAuthSession.mUserId + + ", IsCrypto: " + mCurrentAuthSession.isCrypto() + + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT + + ", RequireConfirmation: " + + mCurrentAuthSession.mRequireConfirmation + + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED + + ", Latency: " + latency); + } + + StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + statsModality(), + mCurrentAuthSession.mUserId, + mCurrentAuthSession.isCrypto(), + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, + mCurrentAuthSession.mRequireConfirmation, + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, + latency); + } else { + int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE + ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON + : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL + ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED + : 0; + if (LoggableMonitor.DEBUG) { + Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality() + + ", User: " + mCurrentAuthSession.mUserId + + ", IsCrypto: " + mCurrentAuthSession.isCrypto() + + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE + + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT + + ", Error: " + error); + } + // Auth canceled + StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + statsModality(), + mCurrentAuthSession.mUserId, + mCurrentAuthSession.isCrypto(), + BiometricsProtoEnums.ACTION_AUTHENTICATE, + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, + error, + 0 /* vendorCode */); + } + } + + private int statsModality() { + int modality = 0; + if (mCurrentAuthSession == null) { + return BiometricsProtoEnums.MODALITY_UNKNOWN; + } + if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT) + != 0) { + modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT; + } + if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) { + modality |= BiometricsProtoEnums.MODALITY_IRIS; + } + if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) { + modality |= BiometricsProtoEnums.MODALITY_FACE; + } + return modality; + } }; @Override // Binder call @@ -815,7 +900,11 @@ public class BiometricService extends SystemService { try { boolean requireConfirmation = bundle.getBoolean( BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */); - + if ((modality & TYPE_FACE) != 0) { + // Check if the user has forced confirmation to be required in Settings. + requireConfirmation = requireConfirmation + || mSettingObserver.getFaceAlwaysRequireConfirmation(); + } // Generate random cookies to pass to the services that should prepare to start // authenticating. Store the cookie here and wait for all services to "ack" // with the cookie. Once all cookies are received, we can show the prompt @@ -827,7 +916,7 @@ public class BiometricService extends SystemService { authenticators.put(modality, cookie); mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId, receiver, opPackageName, bundle, callingUid, callingPid, callingUserId, - modality); + modality, requireConfirmation); mPendingAuthSession.mState = STATE_AUTH_CALLED; // No polymorphism :( if ((modality & TYPE_FINGERPRINT) != 0) { @@ -839,9 +928,6 @@ public class BiometricService extends SystemService { Slog.w(TAG, "Iris unsupported"); } if ((modality & TYPE_FACE) != 0) { - // Check if the user has forced confirmation to be required in Settings. - requireConfirmation = requireConfirmation - || mSettingObserver.getFaceAlwaysRequireConfirmation(); mFaceService.prepareForAuthentication(requireConfirmation, token, sessionId, userId, mInternalReceiver, opPackageName, cookie, callingUid, callingPid, callingUserId); diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 2791165293aff..b65535af52b1a 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -35,6 +35,7 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricServiceReceiverInternal; @@ -55,6 +56,7 @@ import android.os.UserManager; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import android.util.StatsLog; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; @@ -220,8 +222,16 @@ public abstract class BiometricServiceBase extends SystemService */ protected void notifyClientActiveCallbacks(boolean isActive) {} + protected abstract int statsModality(); + protected abstract class AuthenticationClientImpl extends AuthenticationClient { + // Used to check if the public API that was invoked was from FingerprintManager. Only + // to be overridden by FingerprintService. + protected boolean isFingerprint() { + return false; + } + public AuthenticationClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, boolean restricted, String owner, int cookie, boolean requireConfirmation) { @@ -229,6 +239,19 @@ public abstract class BiometricServiceBase extends SystemService groupId, opId, restricted, owner, cookie, requireConfirmation); } + @Override + protected int statsClient() { + if (isKeyguard(getOwnerString())) { + return BiometricsProtoEnums.CLIENT_KEYGUARD; + } else if (isBiometricPrompt()) { + return BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT; + } else if (isFingerprint()) { + return BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER; + } else { + return BiometricsProtoEnums.CLIENT_UNKNOWN; + } + } + @Override public void onStart() { try { @@ -296,7 +319,7 @@ public abstract class BiometricServiceBase extends SystemService } } - protected class RemovalClientImpl extends RemovalClient { + protected abstract class RemovalClientImpl extends RemovalClient { private boolean mShouldNotify; public RemovalClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, @@ -318,7 +341,7 @@ public abstract class BiometricServiceBase extends SystemService } } - protected class EnumerateClientImpl extends EnumerateClient { + protected abstract class EnumerateClientImpl extends EnumerateClient { public EnumerateClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int groupId, int userId, @@ -600,6 +623,8 @@ public abstract class BiometricServiceBase extends SystemService mHALDeathCount++; handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /*vendorCode */); + + StatsLog.write(StatsLog.BIOMETRIC_HAL_DEATH_REPORTED, statsModality()); } protected ClientMonitor getCurrentClient() { @@ -653,7 +678,6 @@ public abstract class BiometricServiceBase extends SystemService } else { updateActiveGroup(mCurrentUserId, null); } - } } diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java index d19aff69b8325..e80b39ba9d1ff 100644 --- a/services/core/java/com/android/server/biometrics/ClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java @@ -36,7 +36,7 @@ import java.util.NoSuchElementException; * 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 ClientMonitor implements IBinder.DeathRecipient { +public abstract class ClientMonitor extends LoggableMonitor implements IBinder.DeathRecipient { protected static final int ERROR_ESRCH = 3; // Likely HAL is dead. See errno.h. protected static final boolean DEBUG = BiometricServiceBase.DEBUG; private static final AudioAttributes FINGERPRINT_SONFICATION_ATTRIBUTES = @@ -157,6 +157,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { * @return true if client should be removed */ public boolean onAcquired(int acquiredInfo, int vendorCode) { + super.logOnAcquired(acquiredInfo, vendorCode, getTargetUserId()); try { if (mListener != null) { mListener.onAcquired(getHalDeviceId(), acquiredInfo, vendorCode); @@ -180,6 +181,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { * @return true if client should be removed */ public boolean onError(long deviceId, int error, int vendorCode) { + super.logOnError(error, vendorCode, getTargetUserId()); try { if (mListener != null) { mListener.onError(deviceId, error, vendorCode, getCookie()); diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java index 3ff94bce604d7..1124b7fc67ebf 100644 --- a/services/core/java/com/android/server/biometrics/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/EnrollClient.java @@ -19,6 +19,7 @@ package com.android.server.biometrics; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -50,6 +51,11 @@ public abstract class EnrollClient extends ClientMonitor { mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length); } + @Override + protected int statsAction() { + return BiometricsProtoEnums.ACTION_ENROLL; + } + @Override public boolean onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) { diff --git a/services/core/java/com/android/server/biometrics/EnumerateClient.java b/services/core/java/com/android/server/biometrics/EnumerateClient.java index df6220cfd94bb..0f57f484bb0a9 100644 --- a/services/core/java/com/android/server/biometrics/EnumerateClient.java +++ b/services/core/java/com/android/server/biometrics/EnumerateClient.java @@ -19,6 +19,7 @@ package com.android.server.biometrics; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -37,6 +38,11 @@ public abstract class EnumerateClient extends ClientMonitor { owner, 0 /* cookie */); } + @Override + protected int statsAction() { + return BiometricsProtoEnums.ACTION_ENUMERATE; + } + @Override public int start() { // The biometric template ids will be removed when we get confirmation from the HAL diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java new file mode 100644 index 0000000000000..91c924de27a21 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2019 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; + +import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.face.FaceManager; +import android.util.Slog; +import android.util.StatsLog; + +/** + * Abstract class that adds logging functionality to the ClientMonitor classes. + */ +public abstract class LoggableMonitor { + + public static final String TAG = "BiometricStats"; + public static final boolean DEBUG = true; + + private long mFirstAcquireTimeMs; + + /** + * Only valid for AuthenticationClient. + * @return true if the client is authenticating for a crypto operation. + */ + protected boolean isCryptoOperation() { + return false; + } + + /** + * @return One of {@link BiometricsProtoEnums} MODALITY_* constants. + */ + protected abstract int statsModality(); + + /** + * Action == enroll, authenticate, remove, enumerate. + * @return One of {@link BiometricsProtoEnums} ACTION_* constants. + */ + protected abstract int statsAction(); + + /** + * Only matters for AuthenticationClient. Should only be overridden in + * {@link BiometricServiceBase}, which determines if a client is for BiometricPrompt, Keyguard, + * etc. + * @return one of {@link BiometricsProtoEnums} CLIENT_* constants. + */ + protected int statsClient() { + return BiometricsProtoEnums.CLIENT_UNKNOWN; + } + + protected final void logOnAcquired(int acquiredInfo, int vendorCode, int targetUserId) { + if (statsModality() == BiometricsProtoEnums.MODALITY_FACE) { + if (acquiredInfo == FaceManager.FACE_ACQUIRED_START) { + mFirstAcquireTimeMs = System.currentTimeMillis(); + } + } else if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) { + if (mFirstAcquireTimeMs == 0) { + mFirstAcquireTimeMs = System.currentTimeMillis(); + } + } + if (DEBUG) { + Slog.v(TAG, "Acquired! Modality: " + statsModality() + + ", User: " + targetUserId + + ", IsCrypto: " + isCryptoOperation() + + ", Action: " + statsAction() + + ", Client: " + statsClient() + + ", AcquiredInfo: " + acquiredInfo + + ", VendorCode: " + vendorCode); + } + StatsLog.write(StatsLog.BIOMETRIC_ACQUIRED, + statsModality(), + targetUserId, + isCryptoOperation(), + statsAction(), + statsClient(), + acquiredInfo, + 0 /* vendorCode */); // Don't log vendorCode for now + } + + protected final void logOnError(int error, int vendorCode, int targetUserId) { + if (DEBUG) { + Slog.v(TAG, "Error! Modality: " + statsModality() + + ", User: " + targetUserId + + ", IsCrypto: " + isCryptoOperation() + + ", Action: " + statsAction() + + ", Client: " + statsClient() + + ", Error: " + error + + ", VendorCode: " + vendorCode); + } + StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + statsModality(), + targetUserId, + isCryptoOperation(), + statsAction(), + statsClient(), + error, + vendorCode); + } + + protected final void logOnAuthenticated(boolean authenticated, boolean requireConfirmation, + int targetUserId, boolean isBiometricPrompt) { + int authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN; + if (!authenticated) { + authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED; + } else { + // Authenticated + if (isBiometricPrompt && requireConfirmation) { + authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION; + } else { + authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED; + } + } + + // Only valid if we have a first acquired time, otherwise set to -1 + final long latency = mFirstAcquireTimeMs != 0 + ? (System.currentTimeMillis() - mFirstAcquireTimeMs) + : -1; + + if (DEBUG) { + Slog.v(TAG, "Authenticated! Modality: " + statsModality() + + ", User: " + targetUserId + + ", IsCrypto: " + isCryptoOperation() + + ", Client: " + statsClient() + + ", RequireConfirmation: " + requireConfirmation + + ", State: " + authState + + ", Latency: " + latency); + } + + StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + statsModality(), + targetUserId, + isCryptoOperation(), + statsClient(), + requireConfirmation, + authState, + latency); + } +} diff --git a/services/core/java/com/android/server/biometrics/RemovalClient.java b/services/core/java/com/android/server/biometrics/RemovalClient.java index be233ec893422..0509067b4daf1 100644 --- a/services/core/java/com/android/server/biometrics/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/RemovalClient.java @@ -19,6 +19,7 @@ package com.android.server.biometrics; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -42,6 +43,11 @@ public abstract class RemovalClient extends ClientMonitor { mBiometricUtils = utils; } + @Override + protected int statsAction() { + return BiometricsProtoEnums.ACTION_REMOVE; + } + @Override public int start() { // The biometric template ids will be removed when we get confirmation from the HAL diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index d4be539170fda..90342ee31c3ee 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricServiceReceiverInternal; import android.hardware.biometrics.face.V1_0.IBiometricsFace; @@ -90,6 +91,11 @@ public class FaceService extends BiometricServiceBase { super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId, restricted, owner, cookie, requireConfirmation); } + + @Override + protected int statsModality() { + return FaceService.this.statsModality(); + } } /** @@ -126,6 +132,11 @@ public class FaceService extends BiometricServiceBase { public boolean shouldVibrate() { return false; } + + @Override + protected int statsModality() { + return FaceService.this.statsModality(); + } }; enrollInternal(client, UserHandle.getCallingUserId()); @@ -206,7 +217,12 @@ public class FaceService extends BiometricServiceBase { final boolean restricted = isRestricted(); final RemovalClientImpl client = new RemovalClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), faceId, 0 /* groupId */, - userId, restricted, token.toString()); + userId, restricted, token.toString()) { + @Override + protected int statsModality() { + return FaceService.this.statsModality(); + } + }; client.setShouldNotifyUserActivity(true); removeInternal(client); } @@ -219,7 +235,12 @@ public class FaceService extends BiometricServiceBase { final boolean restricted = isRestricted(); final EnumerateClientImpl client = new EnumerateClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), userId, userId, - restricted, getContext().getOpPackageName()); + restricted, getContext().getOpPackageName()) { + @Override + protected int statsModality() { + return FaceService.this.statsModality(); + } + }; enumerateInternal(client); } @@ -770,6 +791,11 @@ public class FaceService extends BiometricServiceBase { // noop for Face. } + @Override + protected int statsModality() { + return BiometricsProtoEnums.MODALITY_FACE; + } + /** Gets the face daemon */ private synchronized IBiometricsFace getFaceDaemon() { if (mDaemon == null) { diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index f84cda03c5941..62947c7dd8b48 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.IBiometricServiceReceiverInternal; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; @@ -101,6 +102,11 @@ public class FingerprintService extends BiometricServiceBase { } private final class FingerprintAuthClient extends AuthenticationClientImpl { + @Override + protected boolean isFingerprint() { + return true; + } + public FingerprintAuthClient(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, @@ -109,6 +115,11 @@ public class FingerprintService extends BiometricServiceBase { super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId, restricted, owner, cookie, requireConfirmation); } + + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } } /** @@ -147,6 +158,11 @@ public class FingerprintService extends BiometricServiceBase { public boolean shouldVibrate() { return true; } + + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } }; enrollInternal(client, userId); @@ -225,7 +241,12 @@ public class FingerprintService extends BiometricServiceBase { final boolean restricted = isRestricted(); final RemovalClientImpl client = new RemovalClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), fingerId, groupId, - userId, restricted, token.toString()); + userId, restricted, token.toString()) { + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } + }; client.setShouldNotifyUserActivity(true); removeInternal(client); } @@ -238,7 +259,12 @@ public class FingerprintService extends BiometricServiceBase { final boolean restricted = isRestricted(); final EnumerateClientImpl client = new EnumerateClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), userId, userId, - restricted, getContext().getOpPackageName()); + restricted, getContext().getOpPackageName()) { + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } + }; enumerateInternal(client); } @@ -544,6 +570,11 @@ public class FingerprintService extends BiometricServiceBase { } return remaining == 0; } + + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } } /** @@ -558,6 +589,11 @@ public class FingerprintService extends BiometricServiceBase { restricted, owner); } + + @Override + protected int statsModality() { + return FingerprintService.this.statsModality(); + } } private final FingerprintMetrics mFingerprintMetrics = new FingerprintMetrics(); @@ -885,6 +921,11 @@ public class FingerprintService extends BiometricServiceBase { } } + @Override + protected int statsModality() { + return BiometricsProtoEnums.MODALITY_FINGERPRINT; + } + /** Gets the fingerprint daemon */ private synchronized IBiometricsFingerprint getFingerprintDaemon() { if (mDaemon == null) { diff --git a/services/core/java/com/android/server/biometrics/iris/IrisService.java b/services/core/java/com/android/server/biometrics/iris/IrisService.java index 37cdc2a4f07af..eb457b6bedf16 100644 --- a/services/core/java/com/android/server/biometrics/iris/IrisService.java +++ b/services/core/java/com/android/server/biometrics/iris/IrisService.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.iris; import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; import com.android.server.biometrics.BiometricServiceBase; import com.android.server.biometrics.BiometricUtils; @@ -128,4 +129,9 @@ public class IrisService extends BiometricServiceBase { protected boolean checkAppOps(int uid, String opPackageName) { return false; } + + @Override + protected int statsModality() { + return BiometricsProtoEnums.MODALITY_IRIS; + } }