2/n: Update fingerprint vibration logic
1) adds "mShouldVibrate" as a property for AcquisitionClient. Philosophically, all clients that inherit this class should be able to decide if haptics occur in onAuthentication* 2) UDFPS AIDL enroll haptic occurs when ACQUIRED_GOOD is received 3) UDFPS AIDL auth haptic continues to happen when success/reject is known (documenting reason in the bug below) Test: manual enroll+auth Test: atest com.android.server.biometrics Test: adb shell dumpsys vibrator_manager Bug: 193089985 Change-Id: I8ae60f99d36a4f49985411001670df3ee108768f
This commit is contained in:
@@ -22,6 +22,7 @@ import android.hardware.biometrics.BiometricConstants;
|
||||
import android.media.AudioAttributes;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.VibrationEffect;
|
||||
@@ -49,6 +50,8 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
|
||||
|
||||
private final PowerManager mPowerManager;
|
||||
// If haptics should occur when auth result (success/reject) is known
|
||||
protected final boolean mShouldVibrate;
|
||||
private boolean mShouldSendErrorToClient = true;
|
||||
private boolean mAlreadyCancelled;
|
||||
|
||||
@@ -59,11 +62,12 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
|
||||
|
||||
public AcquisitionClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
|
||||
@NonNull String owner, int cookie, int sensorId, int statsModality,
|
||||
int statsAction, int statsClient) {
|
||||
@NonNull String owner, int cookie, int sensorId, boolean shouldVibrate,
|
||||
int statsModality, int statsAction, int statsClient) {
|
||||
super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId, statsModality,
|
||||
statsAction, statsClient);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
mShouldVibrate = shouldVibrate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,14 +195,22 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
|
||||
protected final void vibrateSuccess() {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
if (vibrator != null) {
|
||||
vibrator.vibrate(SUCCESS_VIBRATION_EFFECT, VIBRATION_SONIFICATION_ATTRIBUTES);
|
||||
vibrator.vibrate(Process.myUid(),
|
||||
getContext().getOpPackageName(),
|
||||
SUCCESS_VIBRATION_EFFECT,
|
||||
getClass().getSimpleName() + "::success",
|
||||
VIBRATION_SONIFICATION_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
|
||||
protected final void vibrateError() {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
if (vibrator != null) {
|
||||
vibrator.vibrate(ERROR_VIBRATION_EFFECT, VIBRATION_SONIFICATION_ATTRIBUTES);
|
||||
vibrator.vibrate(Process.myUid(),
|
||||
getContext().getOpPackageName(),
|
||||
ERROR_VIBRATION_EFFECT,
|
||||
getClass().getSimpleName() + "::error",
|
||||
VIBRATION_SONIFICATION_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +68,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
|
||||
int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
|
||||
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
|
||||
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication) {
|
||||
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication,
|
||||
boolean shouldVibrate) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
|
||||
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
|
||||
shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
statsClient);
|
||||
mIsStrongBiometric = isStrongBiometric;
|
||||
mOperationId = operationId;
|
||||
mRequireConfirmation = requireConfirmation;
|
||||
@@ -204,7 +206,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
|
||||
mAlreadyDone = true;
|
||||
|
||||
if (listener != null) {
|
||||
if (listener != null && mShouldVibrate) {
|
||||
vibrateSuccess();
|
||||
}
|
||||
|
||||
@@ -250,7 +252,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
|
||||
Slog.w(TAG, "Client not listening");
|
||||
}
|
||||
} else {
|
||||
if (listener != null) {
|
||||
if (listener != null && mShouldVibrate) {
|
||||
vibrateError();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> {
|
||||
protected final byte[] mHardwareAuthToken;
|
||||
protected final int mTimeoutSec;
|
||||
protected final BiometricUtils mBiometricUtils;
|
||||
private final boolean mShouldVibrate;
|
||||
|
||||
private long mEnrollmentStartTimeMs;
|
||||
|
||||
@@ -50,15 +49,13 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> {
|
||||
public EnrollClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
|
||||
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
|
||||
@NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
|
||||
int timeoutSec, int statsModality, int sensorId,
|
||||
boolean shouldVibrate) {
|
||||
int timeoutSec, int statsModality, int sensorId, boolean shouldVibrate) {
|
||||
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
|
||||
statsModality, BiometricsProtoEnums.ACTION_ENROLL,
|
||||
shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_ENROLL,
|
||||
BiometricsProtoEnums.CLIENT_UNKNOWN);
|
||||
mBiometricUtils = utils;
|
||||
mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
|
||||
mTimeoutSec = timeoutSec;
|
||||
mShouldVibrate = shouldVibrate;
|
||||
}
|
||||
|
||||
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
|
||||
|
||||
@@ -73,7 +73,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
|
||||
lockoutCache, allowBackgroundAuthentication);
|
||||
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */);
|
||||
mUsageStats = usageStats;
|
||||
mLockoutCache = lockoutCache;
|
||||
mNotificationManager = context.getSystemService(NotificationManager.class);
|
||||
|
||||
@@ -46,8 +46,8 @@ public class FaceDetectClient extends AcquisitionClient<ISession> implements Det
|
||||
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
|
||||
@NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) {
|
||||
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
|
||||
BiometricsProtoEnums.MODALITY_FACE, BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
statsClient);
|
||||
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FACE,
|
||||
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
|
||||
mIsStrongBiometric = isStrongBiometric;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
|
||||
lockoutTracker, allowBackgroundAuthentication);
|
||||
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */);
|
||||
mUsageStats = usageStats;
|
||||
|
||||
final Resources resources = getContext().getResources();
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcqu
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.common.ICancellationSignal;
|
||||
import android.hardware.biometrics.fingerprint.ISession;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -62,11 +63,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
int sensorId, boolean isStrongBiometric, int statsClient,
|
||||
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController,
|
||||
boolean allowBackgroundAuthentication) {
|
||||
boolean allowBackgroundAuthentication,
|
||||
@NonNull FingerprintSensorPropertiesInternal sensorProps) {
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
|
||||
cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
|
||||
lockoutCache, allowBackgroundAuthentication);
|
||||
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */);
|
||||
mLockoutCache = lockoutCache;
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> implements Det
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric,
|
||||
int statsClient) {
|
||||
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
statsClient);
|
||||
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
|
||||
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
|
||||
mIsStrongBiometric = isStrongBiometric;
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
}
|
||||
|
||||
@@ -65,9 +65,10 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
|
||||
@Nullable IUdfpsOverlayController udfpsOvelayController,
|
||||
@Nullable ISidefpsController sidefpsController,
|
||||
int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) {
|
||||
// UDFPS haptics occur when an image is acquired (instead of when the result is known)
|
||||
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
|
||||
0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
|
||||
true /* shouldVibrate */);
|
||||
!sensorProps.isAnyUdfpsType() /* shouldVibrate */);
|
||||
mSensorProps = sensorProps;
|
||||
mUdfpsOverlayController = udfpsOvelayController;
|
||||
mSidefpsController = sidefpsController;
|
||||
@@ -103,6 +104,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
|
||||
// See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE
|
||||
if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD
|
||||
&& mSensorProps.isAnyUdfpsType()) {
|
||||
vibrateSuccess();
|
||||
UdfpsHelper.onAcquiredGood(getSensorId(), mUdfpsOverlayController);
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +395,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
|
||||
operationId, restricted, opPackageName, cookie,
|
||||
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
|
||||
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
|
||||
mUdfpsOverlayController, allowBackgroundAuthentication);
|
||||
mUdfpsOverlayController, allowBackgroundAuthentication,
|
||||
mSensors.get(sensorId).getSensorProperties());
|
||||
scheduleForSensor(sensorId, client, fingerprintStateCallback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
|
||||
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
|
||||
lockoutTracker, allowBackgroundAuthentication);
|
||||
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */);
|
||||
mLockoutFrameworkImpl = lockoutTracker;
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController,
|
||||
boolean isStrongBiometric, int statsClient) {
|
||||
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
|
||||
BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
statsClient);
|
||||
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
|
||||
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
|
||||
mUdfpsOverlayController = udfpsOverlayController;
|
||||
mIsStrongBiometric = isStrongBiometric;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ public class AcquisitionClientTest {
|
||||
@NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
|
||||
@NonNull ClientMonitorCallbackConverter callback) {
|
||||
super(context, lazyDaemon, token, callback, 0 /* userId */, "Test", 0 /* cookie */,
|
||||
TEST_SENSOR_ID /* sensorId */, 0 /* statsModality */, 0 /* statsAction */,
|
||||
TEST_SENSOR_ID /* sensorId */, true /* shouldVibrate */, 0 /* statsModality */,
|
||||
0 /* statsAction */,
|
||||
0 /* statsClient */);
|
||||
}
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ public class BiometricSchedulerTest {
|
||||
false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
|
||||
TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
|
||||
0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
|
||||
false /* isKeyguard */);
|
||||
false /* isKeyguard */, true /* shouldVibrate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -382,7 +382,7 @@ public class BiometricSchedulerTest {
|
||||
false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
|
||||
TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
|
||||
0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
|
||||
false /* isKeyguard */);
|
||||
false /* isKeyguard */, true /* shouldVibrate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user