Merge "9/n: Add BiometricScheduler proto dump"

This commit is contained in:
Kevin Chyn
2021-01-22 01:02:32 +00:00
committed by Android (Google) Code Review
42 changed files with 363 additions and 37 deletions

View File

@@ -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

View File

@@ -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<FaceSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);

View File

@@ -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<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);

View File

@@ -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;
}

View File

@@ -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
*/

View File

@@ -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();

View File

@@ -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<T> extends AcquisitionClient<T>
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_AUTHENTICATE;
}
}

View File

@@ -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() + "}";
}

View File

@@ -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<CrashState> mCrashStates;
private int mTotalOperationsHandled;
private final int mRecentOperationsLimit;
@NonNull private final List<Integer> 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.

View File

@@ -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<T> extends AcquisitionClient<T> {
false /* enrollSuccessful */);
super.onError(error, vendorCode);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_ENROLL;
}
}

View File

@@ -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<T> extends HalClientMonitor<T> {
private static final String TAG = "GenerateChallengeClient";
@@ -50,4 +52,9 @@ public abstract class GenerateChallengeClient<T> extends HalClientMonitor<T> {
startHalOperation();
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_GENERATE_CHALLENGE;
}
}

View File

@@ -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<S extends BiometricAuthenticator.Ide
}
((EnumerateConsumer) mCurrentTask).onEnumerationResult(identifier, remaining);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_INTERNAL_CLEANUP;
}
}

View File

@@ -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;
@@ -123,4 +124,9 @@ public abstract class InternalEnumerateClient<T> extends HalClientMonitor<T>
public List<BiometricAuthenticator.Identifier> getUnknownHALTemplates() {
return mUnknownHALTemplates;
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_ENUMERATE;
}
}

View File

@@ -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<S extends BiometricAuthenticator.Identi
public void unableToStart() {
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_INVALIDATE;
}
}

View File

@@ -23,6 +23,8 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IInvalidationCallback;
import com.android.server.biometrics.BiometricsProto;
/**
* ClientMonitor subclass responsible for coordination of authenticatorId invalidation of other
* sensors. See {@link InvalidationClient} for the ClientMonitor subclass responsible for initiating
@@ -89,4 +91,9 @@ public class InvalidationRequesterClient<S extends BiometricAuthenticator.Identi
mBiometricManager.invalidateAuthenticatorIds(getTargetUserId(), getSensorId(),
mInvalidationCallback);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_INVALIDATION_REQUESTER;
}
}

View File

@@ -25,6 +25,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
import java.util.Map;
/**
@@ -90,4 +92,9 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier,
mCallback.onClientFinished(this, true /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_REMOVE;
}
}

View File

@@ -21,6 +21,8 @@ import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import com.android.server.biometrics.BiometricsProto;
public abstract class RevokeChallengeClient<T> extends HalClientMonitor<T> {
public RevokeChallengeClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@@ -42,4 +44,9 @@ public abstract class RevokeChallengeClient<T> extends HalClientMonitor<T> {
startHalOperation();
mCallback.onClientFinished(this, true /* success */);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_REVOKE_CHALLENGE;
}
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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);

View File

@@ -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<ISession> {
mAuthenticatorIds.put(getTargetUserId(), authenticatorId);
mCallback.onClientFinished(this, true /* success */);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_GET_AUTHENTICATOR_ID;
}
}

View File

@@ -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);
}
}

View File

@@ -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<ISession> {
mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId());
mCallback.onClientFinished(this, true /* success */);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_RESET_LOCKOUT;
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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<IBiometricsFace> {
boolean getValue() {
return mValue;
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_GET_FEATURE;
}
}

View File

@@ -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<IBiometricsFace> {
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_RESET_LOCKOUT;
}
}

View File

@@ -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<IBiometricsFace> {
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_SET_FEATURE;
}
}

View File

@@ -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<IBiometricsFace
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_UPDATE_ACTIVE_USER;
}
}

View File

@@ -53,8 +53,8 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
}
@Override
public byte[] dumpSensorServiceStateProto() throws RemoteException {
return mFingerprintService.dumpSensorServiceStateProto(mSensorId);
public byte[] dumpSensorServiceStateProto(boolean clearSchedulerBuffer) throws RemoteException {
return mFingerprintService.dumpSensorServiceStateProto(mSensorId, clearSchedulerBuffer);
}
@Override

View File

@@ -116,13 +116,13 @@ public class FingerprintService extends SystemService implements BiometricServic
}
@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();
@@ -419,7 +419,7 @@ public class FingerprintService extends SystemService implements BiometricServic
for (ServiceProvider provider : mServiceProviders) {
for (FingerprintSensorPropertiesInternal props
: provider.getSensorProperties()) {
provider.dumpProtoState(props.sensorId, proto);
provider.dumpProtoState(props.sensorId, proto, false);
}
}
proto.flush();

View File

@@ -128,7 +128,8 @@ public interface ServiceProvider {
void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller);
void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto);
void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
boolean clearSchedulerBuffer);
void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);

View File

@@ -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.AcquisitionClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
@@ -91,4 +92,9 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_DETECT_INTERACTION;
}
}

View File

@@ -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<ISession> {
mAuthenticatorIds.put(getTargetUserId(), authenticatorId);
mCallback.onClientFinished(this, true /* success */);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_GET_AUTHENTICATOR_ID;
}
}

View File

@@ -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);
}
}

View File

@@ -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<ISession> {
mLockoutResetDispatcher.notifyLockoutResetCallbacks(getSensorId());
mCallback.onClientFinished(this, true /* success */);
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_RESET_LOCKOUT;
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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<IBiometricsFingerprint>
Slog.e(TAG, "Remote exception when sending onDetected", e);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_DETECT_INTERACTION;
}
}

View File

@@ -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<IBiometr
mCallback.onClientFinished(this, false /* success */);
}
}
@Override
public int getProtoEnum() {
return BiometricsProto.CM_UPDATE_ACTIVE_USER;
}
}

View File

@@ -50,7 +50,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
}
@Override
public byte[] dumpSensorServiceStateProto() throws RemoteException {
public byte[] dumpSensorServiceStateProto(boolean clearSchedulerBuffer) throws RemoteException {
return null;
}

View File

@@ -34,11 +34,14 @@ import android.hardware.biometrics.IBiometricService;
import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.util.proto.ProtoOutputStream;
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.nano.BiometricSchedulerProto;
import com.android.server.biometrics.nano.BiometricsProto;
import com.android.server.biometrics.sensors.BiometricScheduler.Operation;
import org.junit.Before;
@@ -52,6 +55,7 @@ public class BiometricSchedulerTest {
private static final String TAG = "BiometricSchedulerTest";
private static final int TEST_SENSOR_ID = 1;
private static final int LOG_NUM_RECENT_OPERATIONS = 2;
private BiometricScheduler mScheduler;
private IBinder mToken;
@@ -66,7 +70,7 @@ public class BiometricSchedulerTest {
MockitoAnnotations.initMocks(this);
mToken = new Binder();
mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */,
mBiometricService);
mBiometricService, LOG_NUM_RECENT_OPERATIONS);
}
@Test
@@ -186,6 +190,88 @@ public class BiometricSchedulerTest {
assertNull(mScheduler.mCurrentOperation);
}
@Test
public void testProtoDump_singleCurrentOperation() throws Exception {
// Nothing so far
BiometricSchedulerProto bsp = getDump(true /* clearSchedulerBuffer */);
assertEquals(BiometricsProto.CM_NONE, bsp.currentOperation);
assertEquals(0, bsp.totalOperations);
assertEquals(0, bsp.recentOperations.length);
// Pretend the scheduler is busy enrolling, and check the proto dump again.
final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken,
() -> 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<Object> {
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<Object> lazyDaemon, int protoEnum) {
super(context, token, lazyDaemon);
mProtoEnum = protoEnum;
}
@Override
public int getProtoEnum() {
return mProtoEnum;
}
}
private static class TestClientMonitor extends HalClientMonitor<Object> {
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);