From 7a707810e754151bdbb6aed635ba483cf55c4bbe Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 19 Jan 2021 18:51:02 -0800 Subject: [PATCH] 9/n: Add BiometricScheduler proto dump 1) Adds biometrics.proto definition for BaseClientMonitor subtypes 2) Adds BiometricScheduler proto dump When dumping the scheduler, the caller may request for the recent operation queue to be cleared after dumping or not. Note that we don't need BiometricScheduler.Operation#STATE_* in the dump, since (for now) we just want to know what operations have been run. We can always add additional state, success/failure, etc in the future if needed. Bug: 159667191 Test: atest com.android.server.biometrics Test: atest CtsBiometricsTestCases Change-Id: I7d2350f00aaeef03ab7d74013b476af053240320 --- .../biometrics/IBiometricAuthenticator.aidl | 2 +- .../android/hardware/face/IFaceService.aidl | 2 +- .../fingerprint/IFingerprintService.aidl | 2 +- core/proto/android/server/biometrics.proto | 39 ++++++- .../server/biometrics/AuthSession.java | 3 - .../server/biometrics/BiometricService.java | 6 +- .../sensors/AuthenticationClient.java | 6 + .../biometrics/sensors/BaseClientMonitor.java | 14 +++ .../sensors/BiometricScheduler.java | 38 +++++- .../biometrics/sensors/EnrollClient.java | 7 ++ .../sensors/GenerateChallengeClient.java | 7 ++ .../sensors/InternalCleanupClient.java | 6 + .../sensors/InternalEnumerateClient.java | 6 + .../sensors/InvalidationClient.java | 7 ++ .../sensors/InvalidationRequesterClient.java | 7 ++ .../biometrics/sensors/RemovalClient.java | 7 ++ .../sensors/RevokeChallengeClient.java | 7 ++ .../sensors/face/FaceAuthenticator.java | 4 +- .../biometrics/sensors/face/FaceService.java | 6 +- .../sensors/face/ServiceProvider.java | 3 +- .../aidl/FaceGetAuthenticatorIdClient.java | 6 + .../sensors/face/aidl/FaceProvider.java | 5 +- .../face/aidl/FaceResetLockoutClient.java | 6 + .../biometrics/sensors/face/aidl/Sensor.java | 5 +- .../biometrics/sensors/face/hidl/Face10.java | 5 +- .../face/hidl/FaceGetFeatureClient.java | 6 + .../face/hidl/FaceResetLockoutClient.java | 6 + .../face/hidl/FaceSetFeatureClient.java | 6 + .../face/hidl/FaceUpdateActiveUserClient.java | 6 + .../fingerprint/FingerprintAuthenticator.java | 4 +- .../fingerprint/FingerprintService.java | 6 +- .../sensors/fingerprint/ServiceProvider.java | 3 +- .../aidl/FingerprintDetectClient.java | 6 + .../FingerprintGetAuthenticatorIdClient.java | 6 + .../fingerprint/aidl/FingerprintProvider.java | 5 +- .../aidl/FingerprintResetLockoutClient.java | 6 + .../sensors/fingerprint/aidl/Sensor.java | 5 +- .../fingerprint/hidl/Fingerprint21.java | 5 +- .../hidl/FingerprintDetectClient.java | 6 + .../FingerprintUpdateActiveUserClient.java | 6 + .../sensors/iris/IrisAuthenticator.java | 2 +- .../sensors/BiometricSchedulerTest.java | 110 +++++++++++++++++- 42 files changed, 363 insertions(+), 37 deletions(-) diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl index fcdf61e99471c..c854ac9847d8c 100644 --- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl +++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl @@ -38,7 +38,7 @@ interface IBiometricAuthenticator { SensorPropertiesInternal getSensorProperties(String opPackageName); // Requests a proto dump of the sensor. See biometrics.proto - byte[] dumpSensorServiceStateProto(); + byte[] dumpSensorServiceStateProto(boolean clearSchedulerBuffer); // This method prepares the service to start authenticating, but doesn't start authentication. // This is protected by the MANAGE_BIOMETRIC signature permission. This method should only be diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 3b19f12a41bac..1b188e87e90fa 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -35,7 +35,7 @@ interface IFaceService { ITestSession createTestSession(int sensorId, String opPackageName); // Requests a proto dump of the specified sensor - byte[] dumpSensorServiceStateProto(int sensorId); + byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer); // Retrieve static sensor properties for all face sensors List getSensorPropertiesInternal(String opPackageName); diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 74c5b5864e877..3657a83039ad4 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -36,7 +36,7 @@ interface IFingerprintService { ITestSession createTestSession(int sensorId, String opPackageName); // Requests a proto dump of the specified sensor - byte[] dumpSensorServiceStateProto(int sensorId); + byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer); // Retrieve static sensor properties for all fingerprint sensors List getSensorPropertiesInternal(String opPackageName); diff --git a/core/proto/android/server/biometrics.proto b/core/proto/android/server/biometrics.proto index 14b5c52acce4c..900235ea65fb9 100644 --- a/core/proto/android/server/biometrics.proto +++ b/core/proto/android/server/biometrics.proto @@ -120,8 +120,8 @@ message SensorStateProto { optional Modality modality = 2; - // State of the sensor's scheduler. True if currently handling an operation, false if idle. - optional bool is_busy = 3; + // State of the sensor's scheduler. + optional BiometricSchedulerProto scheduler = 3; // User states for this sensor. repeated UserStateProto user_states = 4; @@ -136,4 +136,39 @@ message UserStateProto { // Number of fingerprints enrolled optional int32 num_enrolled = 2; +} + +// BiometricScheduler dump +message BiometricSchedulerProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + // Operation currently being handled by the BiometricScheduler + optional ClientMonitorEnum current_operation = 1; + + // Total number of operations that have been handled, not including the current one if one + // exists. Kept in FIFO order (most recent at the end of the array) + optional int32 total_operations = 2; + + // A list of recent past operations in the order which they were handled + repeated ClientMonitorEnum recent_operations = 3; +} + +// BaseClientMonitor subtypes +enum ClientMonitorEnum { + CM_NONE = 0; + CM_UPDATE_ACTIVE_USER = 1; + CM_ENROLL = 2; + CM_AUTHENTICATE = 3; + CM_REMOVE = 4; + CM_GET_AUTHENTICATOR_ID = 5; + CM_ENUMERATE = 6; + CM_INTERNAL_CLEANUP = 7; + CM_SET_FEATURE = 8; + CM_GET_FEATURE = 9; + CM_GENERATE_CHALLENGE = 10; + CM_REVOKE_CHALLENGE = 11; + CM_RESET_LOCKOUT = 12; + CM_DETECT_INTERACTION = 13; + CM_INVALIDATION_REQUESTER = 14; + CM_INVALIDATE = 15; } \ No newline at end of file diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index 52152ab78992d..14292d9c5f8de 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -37,7 +37,6 @@ import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; -import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.IBinder; import android.os.RemoteException; @@ -62,8 +61,6 @@ public final class AuthSession implements IBinder.DeathRecipient { private static final String TAG = "BiometricService/AuthSession"; private static final boolean DEBUG = false; - - /* * Defined in biometrics.proto */ diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 3387049d69f38..614c5f1b65bfb 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -815,12 +815,16 @@ public class BiometricService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { if (args.length > 0 && "--proto".equals(args[0])) { + final boolean clearSchedulerBuffer = args.length > 1 + && "--clear-scheduler-buffer".equals(args[1]); + Slog.d(TAG, "ClearSchedulerBuffer: " + clearSchedulerBuffer); final ProtoOutputStream proto = new ProtoOutputStream(fd); proto.write(BiometricServiceStateProto.AUTH_SESSION_STATE, mCurrentAuthSession != null ? mCurrentAuthSession.getState() : STATE_AUTH_IDLE); for (BiometricSensor sensor : mSensors) { - byte[] serviceState = sensor.impl.dumpSensorServiceStateProto(); + byte[] serviceState = sensor.impl + .dumpSensorServiceStateProto(clearSchedulerBuffer); proto.write(BiometricServiceStateProto.SENSOR_SERVICE_STATES, serviceState); } proto.flush(); 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 5663495db037c..3f6ae6439aa4c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -33,6 +33,7 @@ import android.security.KeyStore; import android.util.EventLog; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.Utils; import java.util.ArrayList; @@ -298,4 +299,9 @@ public abstract class AuthenticationClient extends AcquisitionClient mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); } } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_AUTHENTICATE; + } } 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 f3c37efd4b612..8fa3bbbf615ae 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -24,6 +24,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; + import java.util.NoSuchElementException; /** @@ -79,6 +81,12 @@ public abstract class BaseClientMonitor extends LoggableMonitor @NonNull protected Callback mCallback; + /** + * Returns a ClientMonitorEnum constant defined in biometrics.proto + * @return + */ + public abstract int getProtoEnum(); + /** * @param context system_server context * @param token a unique token for the client @@ -195,10 +203,16 @@ public abstract class BaseClientMonitor extends LoggableMonitor return mSensorId; } + @VisibleForTesting + public Callback getCallback() { + return mCallback; + } + @Override public String toString() { return "{[" + mSequentialId + "] " + this.getClass().getSimpleName() + + ", " + getProtoEnum() + ", " + getOwnerString() + ", " + getCookie() + "}"; } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index aa7faf51b1b66..c86bfcb4a88ea 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -28,8 +28,11 @@ import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.biometrics.BiometricSchedulerProto; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import java.io.PrintWriter; @@ -51,6 +54,8 @@ import java.util.Locale; public class BiometricScheduler { private static final String BASE_TAG = "BiometricScheduler"; + // Number of recent operations to keep in our logs for dumpsys + private static final int LOG_NUM_RECENT_OPERATIONS = 50; /** * Contains all the necessary information for a HAL operation. @@ -200,6 +205,10 @@ public class BiometricScheduler { @VisibleForTesting @Nullable Operation mCurrentOperation; @NonNull private final ArrayDeque mCrashStates; + private int mTotalOperationsHandled; + private final int mRecentOperationsLimit; + @NonNull private final List mRecentOperations; + // Internal callback, notified when an operation is complete. Notifies the requester // that the operation is complete, before performing internal scheduler work (such as // starting the next client). @@ -240,7 +249,12 @@ public class BiometricScheduler { mCurrentOperation.mClientMonitor.getSensorId(), false /* active */); } + if (mRecentOperations.size() >= mRecentOperationsLimit) { + mRecentOperations.remove(0); + } + mRecentOperations.add(mCurrentOperation.mClientMonitor.getProtoEnum()); mCurrentOperation = null; + mTotalOperationsHandled++; startNextOperationIfIdle(); }); } @@ -249,13 +263,15 @@ public class BiometricScheduler { @VisibleForTesting BiometricScheduler(@NonNull String tag, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher, - @NonNull IBiometricService biometricService) { + @NonNull IBiometricService biometricService, int recentOperationsLimit) { mBiometricTag = tag; mInternalCallback = new InternalCallback(); mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher; mPendingOperations = new ArrayDeque<>(); mBiometricService = biometricService; mCrashStates = new ArrayDeque<>(); + mRecentOperationsLimit = recentOperationsLimit; + mRecentOperations = new ArrayList<>(); } /** @@ -267,7 +283,7 @@ public class BiometricScheduler { public BiometricScheduler(@NonNull String tag, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { this(tag, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE))); + ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS); } /** @@ -602,6 +618,24 @@ public class BiometricScheduler { } } + public byte[] dumpProtoState(boolean clearSchedulerBuffer) { + final ProtoOutputStream proto = new ProtoOutputStream(); + proto.write(BiometricSchedulerProto.CURRENT_OPERATION, mCurrentOperation != null + ? mCurrentOperation.mClientMonitor.getProtoEnum() : BiometricsProto.CM_NONE); + proto.write(BiometricSchedulerProto.TOTAL_OPERATIONS, mTotalOperationsHandled); + Slog.d(getTag(), "Total operations: " + mTotalOperationsHandled); + for (int i = 0; i < mRecentOperations.size(); i++) { + Slog.d(getTag(), "Operation: " + mRecentOperations.get(i)); + proto.write(BiometricSchedulerProto.RECENT_OPERATIONS, mRecentOperations.get(i)); + } + proto.flush(); + + if (clearSchedulerBuffer) { + mRecentOperations.clear(); + } + return proto.getBytes(); + } + /** * Clears the scheduler of anything work-related. This should be used for example when the * HAL dies. 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 8bf9680d60cd1..8d81016dab596 100644 --- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java @@ -24,6 +24,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; + import java.util.Arrays; /** @@ -106,4 +108,9 @@ public abstract class EnrollClient extends AcquisitionClient { false /* enrollSuccessful */); super.onError(error, vendorCode); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_ENROLL; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java index 6a622c339d0ba..741946e147cde 100644 --- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java @@ -23,6 +23,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; + public abstract class GenerateChallengeClient extends HalClientMonitor { private static final String TAG = "GenerateChallengeClient"; @@ -50,4 +52,9 @@ public abstract class GenerateChallengeClient extends HalClientMonitor { startHalOperation(); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_GENERATE_CHALLENGE; + } } 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 8529e810f9a18..ce24e5efdc072 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -24,6 +24,7 @@ import android.os.IBinder; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; +import com.android.server.biometrics.BiometricsProto; import java.util.ArrayList; import java.util.List; @@ -166,4 +167,9 @@ public abstract class InternalCleanupClient extends HalClientMonitor public List getUnknownHALTemplates() { return mUnknownHALTemplates; } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_ENUMERATE; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java index 630e5eaae377a..cede4a7252467 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java @@ -24,6 +24,8 @@ import android.hardware.biometrics.IInvalidationCallback; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; + import java.util.Map; /** @@ -70,4 +72,9 @@ public abstract class InvalidationClient extends HalClientMonitor { public RevokeChallengeClient(@NonNull Context context, @NonNull LazyDaemon lazyDaemon, @@ -42,4 +44,9 @@ public abstract class RevokeChallengeClient extends HalClientMonitor { startHalOperation(); mCallback.onClientFinished(this, true /* success */); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_REVOKE_CHALLENGE; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java index 54ab2e5646768..f37cf18a13207 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java @@ -52,8 +52,8 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { } @Override - public byte[] dumpSensorServiceStateProto() throws RemoteException { - return mFaceService.dumpSensorServiceStateProto(mSensorId); + public byte[] dumpSensorServiceStateProto(boolean clearSchedulerBuffer) throws RemoteException { + return mFaceService.dumpSensorServiceStateProto(mSensorId, clearSchedulerBuffer); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index f055d559cc83d..1a63dded4298f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -147,13 +147,13 @@ public class FaceService extends SystemService implements BiometricServiceCallba } @Override - public byte[] dumpSensorServiceStateProto(int sensorId) { + public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); final ProtoOutputStream proto = new ProtoOutputStream(); final ServiceProvider provider = getProviderForSensor(sensorId); if (provider != null) { - provider.dumpProtoState(sensorId, proto); + provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer); } proto.flush(); return proto.getBytes(); @@ -405,7 +405,7 @@ public class FaceService extends SystemService implements BiometricServiceCallba final ProtoOutputStream proto = new ProtoOutputStream(fd); for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { - provider.dumpProtoState(props.sensorId, proto); + provider.dumpProtoState(props.sensorId, proto, false); } } proto.flush(); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java index 51b427d772a11..32428ac131142 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java @@ -121,7 +121,8 @@ public interface ServiceProvider { void scheduleInternalCleanup(int sensorId, int userId); - void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto); + void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer); void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java index 5fb194c75d77c..773647b4bf20b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java @@ -23,6 +23,7 @@ import android.hardware.biometrics.face.ISession; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.HalClientMonitor; import java.util.Map; @@ -65,4 +66,9 @@ class FaceGetAuthenticatorIdClient extends HalClientMonitor { mAuthenticatorIds.put(getTargetUserId(), authenticatorId); mCallback.onClientFinished(this, true /* success */); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_GET_AUTHENTICATOR_ID; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 810489b1c740b..20318e3f836a9 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -571,9 +571,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } @Override - public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) { + public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer) { if (mSensors.contains(sensorId)) { - mSensors.get(sensorId).dumpProtoState(sensorId, proto); + mSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java index f355158d57278..71bac577a4a03 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java @@ -25,6 +25,7 @@ import android.hardware.keymaster.HardwareAuthToken; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutCache; @@ -81,4 +82,9 @@ public class FaceResetLockoutClient extends HalClientMonitor { mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId()); mCallback.onClientFinished(this, true /* success */); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_RESET_LOCKOUT; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java index b28713e613992..9b00ba63d8460 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java @@ -486,12 +486,13 @@ public class Sensor implements IBinder.DeathRecipient { mTestHalEnabled = enabled; } - void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) { + void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer) { final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES); proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId); proto.write(SensorStateProto.MODALITY, SensorStateProto.FACE); - proto.write(SensorStateProto.IS_BUSY, mScheduler.getCurrentClient() != null); + proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer)); for (UserInfo user : UserManager.get(mContext).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index 5e7ddeb64fb4c..7010d9669b8d3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -767,12 +767,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } @Override - public void dumpProtoState(int sensorId, ProtoOutputStream proto) { + public void dumpProtoState(int sensorId, ProtoOutputStream proto, + boolean clearSchedulerBuffer) { final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES); proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId); proto.write(SensorStateProto.MODALITY, SensorStateProto.FACE); - proto.write(SensorStateProto.IS_BUSY, mScheduler.getCurrentClient() != null); + proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer)); for (UserInfo user : UserManager.get(mContext).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java index 442303b037fb8..722a3b843e12b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java @@ -27,6 +27,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.HalClientMonitor; @@ -88,4 +89,9 @@ public class FaceGetFeatureClient extends HalClientMonitor { boolean getValue() { return mValue; } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_GET_FEATURE; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java index e0548e073a98a..14a46481ddc62 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java @@ -23,6 +23,7 @@ import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.HalClientMonitor; import java.util.ArrayList; @@ -71,4 +72,9 @@ public class FaceResetLockoutClient extends HalClientMonitor { mCallback.onClientFinished(this, false /* success */); } } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_RESET_LOCKOUT; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java index 43560434f1478..6290e001f65b3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java @@ -25,6 +25,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.HalClientMonitor; @@ -88,4 +89,9 @@ public class FaceSetFeatureClient extends HalClientMonitor { mCallback.onClientFinished(this, false /* success */); } } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_SET_FEATURE; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java index 0e72f941b4d24..70e20339ce987 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java @@ -24,6 +24,7 @@ import android.os.Environment; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.HalClientMonitor; import java.io.File; @@ -91,4 +92,9 @@ public class FaceUpdateActiveUserClient extends HalClientMonitor { mCallback.onClientFinished(this, false /* success */); } } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_DETECT_INTERACTION; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java index 02d4ac3dd98e3..ce1a31899a0ca 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java @@ -23,6 +23,7 @@ import android.hardware.biometrics.fingerprint.ISession; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.HalClientMonitor; import java.util.Map; @@ -65,4 +66,9 @@ class FingerprintGetAuthenticatorIdClient extends HalClientMonitor { mAuthenticatorIds.put(getTargetUserId(), authenticatorId); mCallback.onClientFinished(this, true /* success */); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_GET_AUTHENTICATOR_ID; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 8a666f9acb7fc..727184f183c14 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -627,9 +627,10 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) { + public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer) { if (mSensors.contains(sensorId)) { - mSensors.get(sensorId).dumpProtoState(sensorId, proto); + mSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java index cd84cdfda5e5d..ddcfcad59203a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java @@ -25,6 +25,7 @@ import android.hardware.keymaster.HardwareAuthToken; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutCache; @@ -76,4 +77,9 @@ class FingerprintResetLockoutClient extends HalClientMonitor { mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId()); mCallback.onClientFinished(this, true /* success */); } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_RESET_LOCKOUT; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index 911f6b48af415..f0e7e1cf5d254 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -481,12 +481,13 @@ class Sensor implements IBinder.DeathRecipient { mTestHalEnabled = enabled; } - void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) { + void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer) { final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES); proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId); proto.write(SensorStateProto.MODALITY, SensorStateProto.FINGERPRINT); - proto.write(SensorStateProto.IS_BUSY, mScheduler.getCurrentClient() != null); + proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer)); for (UserInfo user : UserManager.get(mContext).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 6cc8687b34265..acc575fb19731 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -714,12 +714,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) { + public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer) { final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES); proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId); proto.write(SensorStateProto.MODALITY, SensorStateProto.FINGERPRINT); - proto.write(SensorStateProto.IS_BUSY, mScheduler.getCurrentClient() != null); + proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer)); for (UserInfo user : UserManager.get(mContext).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java index 55995ea5b89df..6318139f3aaed 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java @@ -28,6 +28,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.AcquisitionClient; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; @@ -123,4 +124,9 @@ class FingerprintDetectClient extends AcquisitionClient Slog.e(TAG, "Remote exception when sending onDetected", e); } } + + @Override + public int getProtoEnum() { + return BiometricsProto.CM_DETECT_INTERACTION; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java index f6ec4d9435434..11ffbb27128ac 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java @@ -26,6 +26,7 @@ import android.os.RemoteException; import android.os.SELinux; import android.util.Slog; +import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.sensors.HalClientMonitor; import java.io.File; @@ -121,4 +122,9 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor mock(Object.class), BiometricsProto.CM_ENROLL); + mScheduler.scheduleClientMonitor(client); + waitForIdle(); + bsp = getDump(true /* clearSchedulerBuffer */); + assertEquals(BiometricsProto.CM_ENROLL, bsp.currentOperation); + // No operations have completed yet + assertEquals(0, bsp.totalOperations); + assertEquals(0, bsp.recentOperations.length); + // Finish this operation, so the next scheduled one can start + client.getCallback().onClientFinished(client, true); + } + + @Test + public void testProtoDump_fifo() throws Exception { + // Add the first operation + final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken, + () -> mock(Object.class), BiometricsProto.CM_ENROLL); + mScheduler.scheduleClientMonitor(client); + waitForIdle(); + BiometricSchedulerProto bsp = getDump(false /* clearSchedulerBuffer */); + assertEquals(BiometricsProto.CM_ENROLL, bsp.currentOperation); + // No operations have completed yet + assertEquals(0, bsp.totalOperations); + assertEquals(0, bsp.recentOperations.length); + // Finish this operation, so the next scheduled one can start + client.getCallback().onClientFinished(client, true); + + // Add another operation + final TestClientMonitor2 client2 = new TestClientMonitor2(mContext, mToken, + () -> mock(Object.class), BiometricsProto.CM_REMOVE); + mScheduler.scheduleClientMonitor(client2); + waitForIdle(); + bsp = getDump(false /* clearSchedulerBuffer */); + assertEquals(BiometricsProto.CM_REMOVE, bsp.currentOperation); + assertEquals(1, bsp.totalOperations); // Enroll finished + assertEquals(1, bsp.recentOperations.length); + assertEquals(BiometricsProto.CM_ENROLL, bsp.recentOperations[0]); + client2.getCallback().onClientFinished(client2, true); + + // And another operation + final TestClientMonitor2 client3 = new TestClientMonitor2(mContext, mToken, + () -> mock(Object.class), BiometricsProto.CM_AUTHENTICATE); + mScheduler.scheduleClientMonitor(client3); + waitForIdle(); + bsp = getDump(false /* clearSchedulerBuffer */); + assertEquals(BiometricsProto.CM_AUTHENTICATE, bsp.currentOperation); + assertEquals(2, bsp.totalOperations); + assertEquals(2, bsp.recentOperations.length); + assertEquals(BiometricsProto.CM_ENROLL, bsp.recentOperations[0]); + assertEquals(BiometricsProto.CM_REMOVE, bsp.recentOperations[1]); + + // Finish the last operation, and check that the first operation is removed from the FIFO. + // The test initializes the scheduler with "LOG_NUM_RECENT_OPERATIONS = 2" :) + client3.getCallback().onClientFinished(client3, true); + waitForIdle(); + bsp = getDump(true /* clearSchedulerBuffer */); + assertEquals(3, bsp.totalOperations); + assertEquals(2, bsp.recentOperations.length); + assertEquals(BiometricsProto.CM_REMOVE, bsp.recentOperations[0]); + assertEquals(BiometricsProto.CM_AUTHENTICATE, bsp.recentOperations[1]); + // Nothing is currently running anymore + assertEquals(BiometricsProto.CM_NONE, bsp.currentOperation); + + // RecentOperations queue is cleared (by the previous dump) + bsp = getDump(true /* clearSchedulerBuffer */); + assertEquals(0, bsp.recentOperations.length); + } + + private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception { + return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer)); + } + private static class BiometricPromptClientMonitor extends AuthenticationClient { public BiometricPromptClientMonitor(@NonNull Context context, @NonNull IBinder token, @@ -207,6 +293,21 @@ public class BiometricSchedulerTest { } } + private static class TestClientMonitor2 extends TestClientMonitor { + private final int mProtoEnum; + + public TestClientMonitor2(@NonNull Context context, @NonNull IBinder token, + @NonNull LazyDaemon lazyDaemon, int protoEnum) { + super(context, token, lazyDaemon); + mProtoEnum = protoEnum; + } + + @Override + public int getProtoEnum() { + return mProtoEnum; + } + } + private static class TestClientMonitor extends HalClientMonitor { private boolean mUnableToStart; private boolean mStarted; @@ -229,6 +330,13 @@ public class BiometricSchedulerTest { mUnableToStart = true; } + @Override + public int getProtoEnum() { + // Anything other than CM_NONE, which is used to represent "idle". Tests that need + // real proto enums should use TestClientMonitor2 + return BiometricsProto.CM_UPDATE_ACTIVE_USER; + } + @Override public void start(@NonNull Callback callback) { super.start(callback);