Merge "Clean up framework stats logging."
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.log;
|
||||
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
|
||||
/**
|
||||
* Wrapper for {@link FrameworkStatsLog} to isolate the testable parts.
|
||||
*/
|
||||
public class BiometricFrameworkStatsLogger {
|
||||
|
||||
private static final String TAG = "BiometricFrameworkStatsLogger";
|
||||
|
||||
private static final BiometricFrameworkStatsLogger sInstance =
|
||||
new BiometricFrameworkStatsLogger();
|
||||
|
||||
private BiometricFrameworkStatsLogger() {}
|
||||
|
||||
public static BiometricFrameworkStatsLogger getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_ACQUIRED}. */
|
||||
public void acquired(
|
||||
int statsModality, int statsAction, int statsClient, boolean isDebug,
|
||||
int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED,
|
||||
statsModality,
|
||||
targetUserId,
|
||||
isCrypto,
|
||||
statsAction,
|
||||
statsClient,
|
||||
acquiredInfo,
|
||||
vendorCode,
|
||||
isDebug,
|
||||
-1 /* sensorId */);
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
|
||||
public void authenticate(
|
||||
int statsModality, int statsAction, int statsClient, boolean isDebug, long latency,
|
||||
boolean authenticated, int authState, boolean requireConfirmation, boolean isCrypto,
|
||||
int targetUserId, boolean isBiometricPrompt, float ambientLightLux) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
|
||||
statsModality,
|
||||
targetUserId,
|
||||
isCrypto,
|
||||
statsClient,
|
||||
requireConfirmation,
|
||||
authState,
|
||||
sanitizeLatency(latency),
|
||||
isDebug,
|
||||
-1 /* sensorId */,
|
||||
ambientLightLux);
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */
|
||||
public void enroll(int statsModality, int statsAction, int statsClient,
|
||||
int targetUserId, long latency, boolean enrollSuccessful, float ambientLightLux) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED,
|
||||
statsModality,
|
||||
targetUserId,
|
||||
sanitizeLatency(latency),
|
||||
enrollSuccessful,
|
||||
-1, /* sensorId */
|
||||
ambientLightLux);
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED}. */
|
||||
public void error(
|
||||
int statsModality, int statsAction, int statsClient, boolean isDebug, long latency,
|
||||
int error, int vendorCode, boolean isCrypto, int targetUserId) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED,
|
||||
statsModality,
|
||||
targetUserId,
|
||||
isCrypto,
|
||||
statsAction,
|
||||
statsClient,
|
||||
error,
|
||||
vendorCode,
|
||||
isDebug,
|
||||
sanitizeLatency(latency),
|
||||
-1 /* sensorId */);
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */
|
||||
public void reportUnknownTemplateEnrolledHal(int statsModality) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
statsModality,
|
||||
BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL,
|
||||
-1 /* sensorId */);
|
||||
}
|
||||
|
||||
/** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */
|
||||
public void reportUnknownTemplateEnrolledFramework(int statsModality) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
statsModality,
|
||||
BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK,
|
||||
-1 /* sensorId */);
|
||||
}
|
||||
|
||||
private long sanitizeLatency(long latency) {
|
||||
if (latency < 0) {
|
||||
Slog.w(TAG, "found a negative latency : " + latency);
|
||||
return -1;
|
||||
}
|
||||
return latency;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.sensors;
|
||||
package com.android.server.biometrics.log;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -29,71 +29,28 @@ import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.Utils;
|
||||
|
||||
/**
|
||||
* Abstract class that adds logging functionality to the ClientMonitor classes.
|
||||
* Logger for all reported Biometric framework events.
|
||||
*/
|
||||
public abstract class LoggableMonitor {
|
||||
public class BiometricLogger {
|
||||
|
||||
public static final String TAG = "Biometrics/LoggableMonitor";
|
||||
public static final String TAG = "BiometricLogger";
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
final int mStatsModality;
|
||||
private final int mStatsModality;
|
||||
private final int mStatsAction;
|
||||
private final int mStatsClient;
|
||||
private final BiometricFrameworkStatsLogger mSink;
|
||||
@NonNull private final SensorManager mSensorManager;
|
||||
|
||||
private long mFirstAcquireTimeMs;
|
||||
private boolean mLightSensorEnabled = false;
|
||||
private boolean mShouldLogMetrics = true;
|
||||
|
||||
/**
|
||||
* Probe for loggable attributes that can be continuously monitored, such as ambient light.
|
||||
*
|
||||
* Disable probes when the sensors are in states that are not interesting for monitoring
|
||||
* purposes to save power.
|
||||
*/
|
||||
protected interface Probe {
|
||||
/** Ensure the probe is actively sampling for new data. */
|
||||
void enable();
|
||||
/** Stop sampling data. */
|
||||
void disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Client monitor callback that exposes a probe.
|
||||
*
|
||||
* Disables the probe when the operation completes.
|
||||
*/
|
||||
protected static class CallbackWithProbe<T extends Probe>
|
||||
implements BaseClientMonitor.Callback {
|
||||
private final boolean mStartWithClient;
|
||||
private final T mProbe;
|
||||
|
||||
public CallbackWithProbe(@NonNull T probe, boolean startWithClient) {
|
||||
mProbe = probe;
|
||||
mStartWithClient = startWithClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
if (mStartWithClient) {
|
||||
mProbe.enable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
|
||||
mProbe.disable();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public T getProbe() {
|
||||
return mProbe;
|
||||
}
|
||||
}
|
||||
|
||||
private class ALSProbe implements Probe {
|
||||
@Override
|
||||
public void enable() {
|
||||
@@ -128,26 +85,30 @@ public abstract class LoggableMonitor {
|
||||
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
|
||||
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
|
||||
*/
|
||||
public LoggableMonitor(@NonNull Context context, int statsModality, int statsAction,
|
||||
int statsClient) {
|
||||
public BiometricLogger(
|
||||
@NonNull Context context, int statsModality, int statsAction, int statsClient) {
|
||||
this(statsModality, statsAction, statsClient,
|
||||
BiometricFrameworkStatsLogger.getInstance(),
|
||||
context.getSystemService(SensorManager.class));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BiometricLogger(
|
||||
int statsModality, int statsAction, int statsClient,
|
||||
BiometricFrameworkStatsLogger logSink, SensorManager sensorManager) {
|
||||
mStatsModality = statsModality;
|
||||
mStatsAction = statsAction;
|
||||
mStatsClient = statsClient;
|
||||
mSensorManager = context.getSystemService(SensorManager.class);
|
||||
mSink = logSink;
|
||||
mSensorManager = sensorManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid for AuthenticationClient.
|
||||
* @return true if the client is authenticating for a crypto operation.
|
||||
*/
|
||||
protected boolean isCryptoOperation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void setShouldLog(boolean shouldLog) {
|
||||
mShouldLogMetrics = shouldLog;
|
||||
/** Disable logging metrics and only log critical events, such as system health issues. */
|
||||
public void disableMetrics() {
|
||||
mShouldLogMetrics = false;
|
||||
}
|
||||
|
||||
/** {@link BiometricsProtoEnums} CLIENT_* constants */
|
||||
public int getStatsClient() {
|
||||
return mStatsClient;
|
||||
}
|
||||
@@ -171,8 +132,9 @@ public abstract class LoggableMonitor {
|
||||
return shouldSkipLogging;
|
||||
}
|
||||
|
||||
protected final void logOnAcquired(Context context, int acquiredInfo, int vendorCode,
|
||||
int targetUserId) {
|
||||
/** Log an acquisition event. */
|
||||
public void logOnAcquired(Context context,
|
||||
int acquiredInfo, int vendorCode, boolean isCrypto, int targetUserId) {
|
||||
if (!mShouldLogMetrics) {
|
||||
return;
|
||||
}
|
||||
@@ -192,7 +154,7 @@ public abstract class LoggableMonitor {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Acquired! Modality: " + mStatsModality
|
||||
+ ", User: " + targetUserId
|
||||
+ ", IsCrypto: " + isCryptoOperation()
|
||||
+ ", IsCrypto: " + isCrypto
|
||||
+ ", Action: " + mStatsAction
|
||||
+ ", Client: " + mStatsClient
|
||||
+ ", AcquiredInfo: " + acquiredInfo
|
||||
@@ -203,19 +165,14 @@ public abstract class LoggableMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED,
|
||||
mStatsModality,
|
||||
targetUserId,
|
||||
isCryptoOperation(),
|
||||
mStatsAction,
|
||||
mStatsClient,
|
||||
acquiredInfo,
|
||||
vendorCode,
|
||||
mSink.acquired(mStatsModality, mStatsAction, mStatsClient,
|
||||
Utils.isDebugEnabled(context, targetUserId),
|
||||
-1 /* sensorId */);
|
||||
acquiredInfo, vendorCode, isCrypto, targetUserId);
|
||||
}
|
||||
|
||||
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
|
||||
/** Log an error during an operation. */
|
||||
public void logOnError(Context context,
|
||||
int error, int vendorCode, boolean isCrypto, int targetUserId) {
|
||||
if (!mShouldLogMetrics) {
|
||||
return;
|
||||
}
|
||||
@@ -226,7 +183,7 @@ public abstract class LoggableMonitor {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Error! Modality: " + mStatsModality
|
||||
+ ", User: " + targetUserId
|
||||
+ ", IsCrypto: " + isCryptoOperation()
|
||||
+ ", IsCrypto: " + isCrypto
|
||||
+ ", Action: " + mStatsAction
|
||||
+ ", Client: " + mStatsClient
|
||||
+ ", Error: " + error
|
||||
@@ -240,21 +197,15 @@ public abstract class LoggableMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED,
|
||||
mStatsModality,
|
||||
targetUserId,
|
||||
isCryptoOperation(),
|
||||
mStatsAction,
|
||||
mStatsClient,
|
||||
error,
|
||||
vendorCode,
|
||||
Utils.isDebugEnabled(context, targetUserId),
|
||||
sanitizeLatency(latency),
|
||||
-1 /* sensorId */);
|
||||
mSink.error(mStatsModality, mStatsAction, mStatsClient,
|
||||
Utils.isDebugEnabled(context, targetUserId), latency,
|
||||
error, vendorCode, isCrypto, targetUserId);
|
||||
}
|
||||
|
||||
protected final void logOnAuthenticated(Context context, boolean authenticated,
|
||||
boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) {
|
||||
/** Log authentication attempt. */
|
||||
public void logOnAuthenticated(Context context,
|
||||
boolean authenticated, boolean requireConfirmation, boolean isCrypto,
|
||||
int targetUserId, boolean isBiometricPrompt) {
|
||||
if (!mShouldLogMetrics) {
|
||||
return;
|
||||
}
|
||||
@@ -279,7 +230,7 @@ public abstract class LoggableMonitor {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Authenticated! Modality: " + mStatsModality
|
||||
+ ", User: " + targetUserId
|
||||
+ ", IsCrypto: " + isCryptoOperation()
|
||||
+ ", IsCrypto: " + isCrypto
|
||||
+ ", Client: " + mStatsClient
|
||||
+ ", RequireConfirmation: " + requireConfirmation
|
||||
+ ", State: " + authState
|
||||
@@ -293,20 +244,14 @@ public abstract class LoggableMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
|
||||
mStatsModality,
|
||||
targetUserId,
|
||||
isCryptoOperation(),
|
||||
mStatsClient,
|
||||
requireConfirmation,
|
||||
authState,
|
||||
sanitizeLatency(latency),
|
||||
mSink.authenticate(mStatsModality, mStatsAction, mStatsClient,
|
||||
Utils.isDebugEnabled(context, targetUserId),
|
||||
-1 /* sensorId */,
|
||||
mLastAmbientLux /* ambientLightLux */);
|
||||
latency, authenticated, authState, requireConfirmation, isCrypto,
|
||||
targetUserId, isBiometricPrompt, mLastAmbientLux);
|
||||
}
|
||||
|
||||
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
|
||||
/** Log enrollment outcome. */
|
||||
public void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
|
||||
if (!mShouldLogMetrics) {
|
||||
return;
|
||||
}
|
||||
@@ -326,25 +271,30 @@ public abstract class LoggableMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED,
|
||||
mStatsModality,
|
||||
targetUserId,
|
||||
sanitizeLatency(latency),
|
||||
enrollSuccessful,
|
||||
-1, /* sensorId */
|
||||
mLastAmbientLux /* ambientLightLux */);
|
||||
mSink.enroll(mStatsModality, mStatsAction, mStatsClient,
|
||||
targetUserId, latency, enrollSuccessful, mLastAmbientLux);
|
||||
}
|
||||
|
||||
private long sanitizeLatency(long latency) {
|
||||
if (latency < 0) {
|
||||
Slog.w(TAG, "found a negative latency : " + latency);
|
||||
return -1;
|
||||
/** Report unexpected enrollment reported by the HAL. */
|
||||
public void logUnknownEnrollmentInHal() {
|
||||
if (shouldSkipLogging()) {
|
||||
return;
|
||||
}
|
||||
return latency;
|
||||
|
||||
mSink.reportUnknownTemplateEnrolledHal(mStatsModality);
|
||||
}
|
||||
|
||||
/** Report unknown enrollment in framework settings */
|
||||
public void logUnknownEnrollmentInFramework() {
|
||||
if (shouldSkipLogging()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSink.reportUnknownTemplateEnrolledFramework(mStatsModality);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a callback to start/stop ALS capture when client runs.
|
||||
* Get a callback to start/stop ALS capture when a client runs.
|
||||
*
|
||||
* If the probe should not run for the entire operation, do not set startWithClient and
|
||||
* start/stop the problem when needed.
|
||||
@@ -352,7 +302,7 @@ public abstract class LoggableMonitor {
|
||||
* @param startWithClient if probe should start automatically when the operation starts.
|
||||
*/
|
||||
@NonNull
|
||||
protected CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) {
|
||||
public CallbackWithProbe<Probe> createALSCallback(boolean startWithClient) {
|
||||
return new CallbackWithProbe<>(new ALSProbe(), startWithClient);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.log;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
|
||||
/**
|
||||
* Client monitor callback that exposes a probe.
|
||||
*
|
||||
* Disables the probe when the operation completes.
|
||||
*
|
||||
* @param <T> probe type
|
||||
*/
|
||||
public class CallbackWithProbe<T extends Probe> implements BaseClientMonitor.Callback {
|
||||
private final boolean mStartWithClient;
|
||||
private final T mProbe;
|
||||
|
||||
public CallbackWithProbe(@NonNull T probe, boolean startWithClient) {
|
||||
mProbe = probe;
|
||||
mStartWithClient = startWithClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
if (mStartWithClient) {
|
||||
mProbe.enable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
|
||||
mProbe.disable();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public T getProbe() {
|
||||
return mProbe;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.log;
|
||||
|
||||
/**
|
||||
* Probe for loggable attributes that can be continuously monitored, such as ambient light.
|
||||
*
|
||||
* Disable probes when the sensors are in states that are not interesting for monitoring
|
||||
* purposes to save power.
|
||||
*/
|
||||
public interface Probe {
|
||||
/** Ensure the probe is actively sampling for new data. */
|
||||
void enable();
|
||||
/** Stop sampling data. */
|
||||
void disable();
|
||||
}
|
||||
@@ -105,7 +105,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
|
||||
// that do not handle lockout under the HAL. In these cases, ensure that the framework only
|
||||
// sends errors once per ClientMonitor.
|
||||
if (mShouldSendErrorToClient) {
|
||||
logOnError(getContext(), errorCode, vendorCode, getTargetUserId());
|
||||
getLogger().logOnError(getContext(), errorCode, vendorCode,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
try {
|
||||
if (getListener() != null) {
|
||||
mShouldSendErrorToClient = false;
|
||||
@@ -163,7 +164,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
|
||||
|
||||
protected final void onAcquiredInternal(int acquiredInfo, int vendorCode,
|
||||
boolean shouldSend) {
|
||||
super.logOnAcquired(getContext(), acquiredInfo, vendorCode, getTargetUserId());
|
||||
getLogger().logOnAcquired(getContext(), acquiredInfo, vendorCode,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Acquired: " + acquiredInfo + " " + vendorCode
|
||||
+ ", shouldSend: " + shouldSend);
|
||||
|
||||
@@ -180,8 +180,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
@Override
|
||||
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
|
||||
boolean authenticated, ArrayList<Byte> hardwareAuthToken) {
|
||||
super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
|
||||
getTargetUserId(), isBiometricPrompt());
|
||||
getLogger().logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
|
||||
isCryptoOperation(), getTargetUserId(), isBiometricPrompt());
|
||||
|
||||
final ClientMonitorCallbackConverter listener = getListener();
|
||||
|
||||
|
||||
@@ -27,18 +27,18 @@ import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.biometrics.log.BiometricLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Abstract base class for keeping track and dispatching events from the biometric's HAL to the
|
||||
* Abstract base class for keeping track and dispatching events from the biometric's HAL to
|
||||
* the current client. Subclasses are responsible for coordinating the interaction with
|
||||
* the biometric's HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
|
||||
*/
|
||||
public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
implements IBinder.DeathRecipient {
|
||||
public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
|
||||
|
||||
private static final String TAG = "Biometrics/ClientMonitor";
|
||||
protected static final boolean DEBUG = true;
|
||||
@@ -108,6 +108,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
private final int mTargetUserId;
|
||||
@NonNull private final String mOwner;
|
||||
private final int mSensorId; // sensorId as configured by the framework
|
||||
@NonNull private final BiometricLogger mLogger;
|
||||
|
||||
@Nullable private IBinder mToken;
|
||||
private long mRequestId;
|
||||
@@ -160,7 +161,14 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
|
||||
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
|
||||
int statsClient) {
|
||||
super(context, statsModality, statsAction, statsClient);
|
||||
this(context, token, listener, userId, owner, cookie, sensorId,
|
||||
new BiometricLogger(context, statsModality, statsAction, statsClient));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BaseClientMonitor(@NonNull Context context,
|
||||
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
|
||||
@NonNull String owner, int cookie, int sensorId, @NonNull BiometricLogger logger) {
|
||||
mSequentialId = sCount++;
|
||||
mContext = context;
|
||||
mToken = token;
|
||||
@@ -170,6 +178,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
mOwner = owner;
|
||||
mCookie = cookie;
|
||||
mSensorId = sensorId;
|
||||
mLogger = logger;
|
||||
|
||||
try {
|
||||
if (token != null) {
|
||||
@@ -180,10 +189,6 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
}
|
||||
}
|
||||
|
||||
public int getCookie() {
|
||||
return mCookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the ClientMonitor's lifecycle.
|
||||
* @param callback invoked when the operation is complete (succeeds, fails, etc)
|
||||
@@ -257,6 +262,20 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid for AuthenticationClient.
|
||||
* @return true if the client is authenticating for a crypto operation.
|
||||
*/
|
||||
protected boolean isCryptoOperation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Logger for this client */
|
||||
@NonNull
|
||||
public BiometricLogger getLogger() {
|
||||
return mLogger;
|
||||
}
|
||||
|
||||
public final Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
@@ -281,6 +300,11 @@ public abstract class BaseClientMonitor extends LoggableMonitor
|
||||
return mSensorId;
|
||||
}
|
||||
|
||||
/** Cookie set when this monitor was created. */
|
||||
public int getCookie() {
|
||||
return mCookie;
|
||||
}
|
||||
|
||||
/** Unique request id. */
|
||||
public final long getRequestId() {
|
||||
return mRequestId;
|
||||
|
||||
@@ -89,7 +89,8 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> implements En
|
||||
|
||||
if (remaining == 0) {
|
||||
mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(), identifier);
|
||||
logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs,
|
||||
getLogger().logOnEnrolled(getTargetUserId(),
|
||||
System.currentTimeMillis() - mEnrollmentStartTimeMs,
|
||||
true /* enrollSuccessful */);
|
||||
mCallback.onClientFinished(this, true /* success */);
|
||||
}
|
||||
@@ -116,7 +117,8 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> implements En
|
||||
*/
|
||||
@Override
|
||||
public void onError(int error, int vendorCode) {
|
||||
logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs,
|
||||
getLogger().logOnEnrolled(getTargetUserId(),
|
||||
System.currentTimeMillis() - mEnrollmentStartTimeMs,
|
||||
false /* enrollSuccessful */);
|
||||
super.onError(error, vendorCode);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.BiometricsProto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -128,10 +127,9 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
|
||||
mCurrentTask = getRemovalClient(getContext(), mLazyDaemon, getToken(),
|
||||
template.mIdentifier.getBiometricId(), template.mUserId,
|
||||
getContext().getPackageName(), mBiometricUtils, getSensorId(), mAuthenticatorIds);
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
mStatsModality,
|
||||
BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL,
|
||||
-1 /* sensorId */);
|
||||
|
||||
getLogger().logUnknownEnrollmentInHal();
|
||||
|
||||
mCurrentTask.start(mRemoveCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.BiometricsProto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -116,10 +115,8 @@ public abstract class InternalEnumerateClient<T> extends HalClientMonitor<T>
|
||||
+ identifier.getBiometricId() + " " + identifier.getName());
|
||||
mUtils.removeBiometricForUser(getContext(),
|
||||
getTargetUserId(), identifier.getBiometricId());
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
|
||||
mStatsModality,
|
||||
BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK,
|
||||
-1 /* sensorId */);
|
||||
|
||||
getLogger().logUnknownEnrollmentInFramework();
|
||||
}
|
||||
mEnrolledList.clear();
|
||||
}
|
||||
|
||||
@@ -105,7 +105,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
|
||||
@NonNull
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
|
||||
return new CompositeCallback(
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +242,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
|
||||
// Lockout metrics are logged as an error code.
|
||||
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
|
||||
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
|
||||
getLogger().logOnError(getContext(), error, 0 /* vendorCode */,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
|
||||
try {
|
||||
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
|
||||
@@ -256,7 +258,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
|
||||
// Lockout metrics are logged as an error code.
|
||||
final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
|
||||
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
|
||||
getLogger().logOnError(getContext(), error, 0 /* vendorCode */,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
|
||||
try {
|
||||
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
|
||||
|
||||
@@ -111,7 +111,7 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(mPreviewHandleDeleterCallback,
|
||||
createALSCallback(true /* startWithClient */), callback);
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -95,7 +95,8 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
|
||||
return new CompositeCallback(
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,7 +70,8 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
|
||||
return new CompositeCallback(
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.log.CallbackWithProbe;
|
||||
import com.android.server.biometrics.log.Probe;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
@@ -80,7 +82,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
mLockoutCache = lockoutCache;
|
||||
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
|
||||
mSensorProps = sensorProps;
|
||||
mALSProbeCallback = createALSCallback(false /* startWithClient */);
|
||||
mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,7 +235,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
|
||||
// Lockout metrics are logged as an error code.
|
||||
final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
|
||||
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
|
||||
getLogger().logOnError(getContext(), error, 0 /* vendorCode */,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
|
||||
try {
|
||||
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
|
||||
@@ -251,7 +254,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
|
||||
// Lockout metrics are logged as an error code.
|
||||
final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
|
||||
logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
|
||||
getLogger().logOnError(getContext(), error, 0 /* vendorCode */,
|
||||
isCryptoOperation(), getTargetUserId());
|
||||
|
||||
try {
|
||||
getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
|
||||
|
||||
@@ -76,14 +76,15 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
|
||||
|
||||
mEnrollReason = enrollReason;
|
||||
if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
|
||||
setShouldLog(false);
|
||||
getLogger().disableMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
|
||||
return new CompositeCallback(
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -364,7 +364,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
|
||||
final ClientMonitorCallbackConverter listener = client.getListener();
|
||||
final String opPackageName = client.getOwnerString();
|
||||
final boolean restricted = authClient.isRestricted();
|
||||
final int statsClient = client.getStatsClient();
|
||||
final int statsClient = client.getLogger().getStatsClient();
|
||||
final boolean isKeyguard = authClient.isKeyguard();
|
||||
|
||||
// Don't actually send cancel() to the HAL, since successful auth already finishes
|
||||
|
||||
@@ -32,6 +32,8 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.biometrics.log.CallbackWithProbe;
|
||||
import com.android.server.biometrics.log.Probe;
|
||||
import com.android.server.biometrics.sensors.AuthenticationClient;
|
||||
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
|
||||
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
|
||||
@@ -80,7 +82,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
mLockoutFrameworkImpl = lockoutTracker;
|
||||
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
|
||||
mSensorProps = sensorProps;
|
||||
mALSProbeCallback = createALSCallback(false /* startWithClient */);
|
||||
mALSProbeCallback = getLogger().createALSCallback(false /* startWithClient */);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -127,8 +127,8 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
@Override
|
||||
public void onAuthenticated(BiometricAuthenticator.Identifier identifier, boolean authenticated,
|
||||
ArrayList<Byte> hardwareAuthToken) {
|
||||
logOnAuthenticated(getContext(), authenticated, false /* requireConfirmation */,
|
||||
getTargetUserId(), false /* isBiometricPrompt */);
|
||||
getLogger().logOnAuthenticated(getContext(), authenticated, false /* requireConfirmation */,
|
||||
isCryptoOperation(), getTargetUserId(), false /* isBiometricPrompt */);
|
||||
|
||||
// Do not distinguish between success/failures.
|
||||
vibrateSuccess();
|
||||
|
||||
@@ -69,14 +69,15 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
|
||||
|
||||
mEnrollReason = enrollReason;
|
||||
if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
|
||||
setShouldLog(false);
|
||||
getLogger().disableMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
|
||||
return new CompositeCallback(createALSCallback(true /* startWithClient */), callback);
|
||||
return new CompositeCallback(
|
||||
getLogger().createALSCallback(true /* startWithClient */), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.biometrics.log;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyBoolean;
|
||||
import static org.mockito.Mockito.anyFloat;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.anyLong;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.input.InputSensorInfo;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.testing.TestableContext;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
public class BiometricLoggerTest {
|
||||
|
||||
private static final int DEFAULT_MODALITY = BiometricsProtoEnums.MODALITY_FINGERPRINT;
|
||||
private static final int DEFAULT_ACTION = BiometricsProtoEnums.ACTION_AUTHENTICATE;
|
||||
private static final int DEFAULT_CLIENT = BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
|
||||
|
||||
@Rule
|
||||
public TestableContext mContext = new TestableContext(
|
||||
InstrumentationRegistry.getInstrumentation().getContext());
|
||||
@Mock
|
||||
private BiometricFrameworkStatsLogger mSink;
|
||||
@Mock
|
||||
private SensorManager mSensorManager;
|
||||
@Mock
|
||||
private BaseClientMonitor mClient;
|
||||
|
||||
private BiometricLogger mLogger;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext.addMockSystemService(SensorManager.class, mSensorManager);
|
||||
when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(
|
||||
new Sensor(new InputSensorInfo("", "", 0, 0, Sensor.TYPE_LIGHT, 0, 0, 0, 0, 0, 0,
|
||||
"", "", 0, 0, 0))
|
||||
);
|
||||
}
|
||||
|
||||
private BiometricLogger createLogger() {
|
||||
return createLogger(DEFAULT_MODALITY, DEFAULT_ACTION, DEFAULT_CLIENT);
|
||||
}
|
||||
|
||||
private BiometricLogger createLogger(int statsModality, int statsAction, int statsClient) {
|
||||
return new BiometricLogger(statsModality, statsAction, statsClient, mSink, mSensorManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcquired() {
|
||||
mLogger = createLogger();
|
||||
|
||||
final int acquiredInfo = 2;
|
||||
final int vendorCode = 3;
|
||||
final boolean isCrypto = true;
|
||||
final int targetUserId = 9;
|
||||
|
||||
mLogger.logOnAcquired(mContext, acquiredInfo, vendorCode, isCrypto, targetUserId);
|
||||
|
||||
verify(mSink).acquired(
|
||||
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(),
|
||||
eq(acquiredInfo), eq(vendorCode), eq(isCrypto), eq(targetUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuth() {
|
||||
mLogger = createLogger();
|
||||
|
||||
final boolean authenticated = true;
|
||||
final boolean requireConfirmation = false;
|
||||
final boolean isCrypto = false;
|
||||
final int targetUserId = 11;
|
||||
final boolean isBiometricPrompt = true;
|
||||
|
||||
mLogger.logOnAuthenticated(mContext,
|
||||
authenticated, requireConfirmation, isCrypto, targetUserId, isBiometricPrompt);
|
||||
|
||||
verify(mSink).authenticate(
|
||||
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(),
|
||||
anyLong(), eq(authenticated), anyInt(), eq(requireConfirmation), eq(isCrypto),
|
||||
eq(targetUserId), eq(isBiometricPrompt), anyFloat());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnroll() {
|
||||
mLogger = createLogger();
|
||||
|
||||
final int targetUserId = 4;
|
||||
final long latency = 44;
|
||||
final boolean enrollSuccessful = true;
|
||||
|
||||
mLogger.logOnEnrolled(targetUserId, latency, enrollSuccessful);
|
||||
|
||||
verify(mSink).enroll(
|
||||
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT),
|
||||
eq(targetUserId), eq(latency), eq(enrollSuccessful), anyFloat());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testError() {
|
||||
mLogger = createLogger();
|
||||
|
||||
final int error = 7;
|
||||
final int vendorCode = 11;
|
||||
final boolean isCrypto = false;
|
||||
final int targetUserId = 9;
|
||||
|
||||
mLogger.logOnError(mContext, error, vendorCode, isCrypto, targetUserId);
|
||||
|
||||
verify(mSink).error(
|
||||
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(),
|
||||
anyLong(), eq(error), eq(vendorCode), eq(isCrypto), eq(targetUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadModalityActsDisabled() {
|
||||
mLogger = createLogger(
|
||||
BiometricsProtoEnums.MODALITY_UNKNOWN, DEFAULT_ACTION, DEFAULT_CLIENT);
|
||||
testDisabledMetrics(true /* isBadConfig */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadActionActsDisabled() {
|
||||
mLogger = createLogger(
|
||||
DEFAULT_MODALITY, BiometricsProtoEnums.ACTION_UNKNOWN, DEFAULT_CLIENT);
|
||||
testDisabledMetrics(true /* isBadConfig */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableLogger() {
|
||||
mLogger = createLogger();
|
||||
testDisabledMetrics(false /* isBadConfig */);
|
||||
}
|
||||
|
||||
private void testDisabledMetrics(boolean isBadConfig) {
|
||||
mLogger.disableMetrics();
|
||||
mLogger.logOnAcquired(mContext,
|
||||
0 /* acquiredInfo */,
|
||||
1 /* vendorCode */,
|
||||
true /* isCrypto */,
|
||||
8 /* targetUserId */);
|
||||
mLogger.logOnAuthenticated(mContext,
|
||||
true /* authenticated */,
|
||||
true /* requireConfirmation */,
|
||||
false /* isCrypto */,
|
||||
4 /* targetUserId */,
|
||||
true/* isBiometricPrompt */);
|
||||
mLogger.logOnEnrolled(2 /* targetUserId */,
|
||||
10 /* latency */,
|
||||
true /* enrollSuccessful */);
|
||||
mLogger.logOnError(mContext,
|
||||
4 /* error */,
|
||||
0 /* vendorCode */,
|
||||
false /* isCrypto */,
|
||||
6 /* targetUserId */);
|
||||
|
||||
verify(mSink, never()).acquired(
|
||||
anyInt(), anyInt(), anyInt(), anyBoolean(),
|
||||
anyInt(), anyInt(), anyBoolean(), anyInt());
|
||||
verify(mSink, never()).authenticate(
|
||||
anyInt(), anyInt(), anyInt(), anyBoolean(),
|
||||
anyLong(), anyBoolean(), anyInt(), anyBoolean(),
|
||||
anyBoolean(), anyInt(), anyBoolean(), anyFloat());
|
||||
verify(mSink, never()).enroll(
|
||||
anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyBoolean(), anyFloat());
|
||||
verify(mSink, never()).error(
|
||||
anyInt(), anyInt(), anyInt(), anyBoolean(),
|
||||
anyLong(), anyInt(), anyInt(), anyBoolean(), anyInt());
|
||||
|
||||
mLogger.logUnknownEnrollmentInFramework();
|
||||
mLogger.logUnknownEnrollmentInHal();
|
||||
|
||||
verify(mSink, times(isBadConfig ? 0 : 1))
|
||||
.reportUnknownTemplateEnrolledHal(eq(DEFAULT_MODALITY));
|
||||
verify(mSink, times(isBadConfig ? 0 : 1))
|
||||
.reportUnknownTemplateEnrolledFramework(eq(DEFAULT_MODALITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemHealthBadHalTemplate() {
|
||||
mLogger = createLogger();
|
||||
mLogger.logUnknownEnrollmentInHal();
|
||||
verify(mSink).reportUnknownTemplateEnrolledHal(eq(DEFAULT_MODALITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemHealthBadFrameworkTemplate() {
|
||||
mLogger = createLogger();
|
||||
mLogger.logUnknownEnrollmentInFramework();
|
||||
verify(mSink).reportUnknownTemplateEnrolledFramework(eq(DEFAULT_MODALITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testALSCallback() {
|
||||
mLogger = createLogger();
|
||||
final CallbackWithProbe<Probe> callback =
|
||||
mLogger.createALSCallback(true /* startWithClient */);
|
||||
|
||||
callback.onClientStarted(mClient);
|
||||
verify(mSensorManager).registerListener(any(), any(), anyInt());
|
||||
|
||||
callback.onClientFinished(mClient, true /* success */);
|
||||
verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testALSCallbackDoesNotStart() {
|
||||
mLogger = createLogger();
|
||||
final CallbackWithProbe<Probe> callback =
|
||||
mLogger.createALSCallback(false /* startWithClient */);
|
||||
|
||||
callback.onClientStarted(mClient);
|
||||
callback.onClientFinished(mClient, true /* success */);
|
||||
verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user