From 6726fd5cc66e43d54b2988a1b107888f343c5d74 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 27 Jun 2017 00:41:45 +0100 Subject: [PATCH] Update fingerprint haptic patterns Have fingerprint take advantage of the haptics capabilities of new devices. In particular, use prebaked DOUBLE_CLICK effect for failure since we tune that to feel good for a specific piece of hardware, and use the equivalent of the long press effect since we tune that to be the strongest feeling single click effect that doesn't cause the device to feel "buzzy" or annoying. Bug: 62392467 Test: manual Change-Id: I9331718b1d515959a4b5f8bd0f17243b28a6f788 --- .../fingerprint/AuthenticationClient.java | 4 +- .../server/fingerprint/ClientMonitor.java | 57 ++++++++++++++++--- .../server/fingerprint/EnrollClient.java | 2 +- .../server/fingerprint/FingerprintUtils.java | 18 ------ 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java index 5339bac8b0302..370e569f2598e 100644 --- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java +++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java @@ -79,7 +79,7 @@ public abstract class AuthenticationClient extends ClientMonitor { } if (!authenticated) { if (receiver != null) { - FingerprintUtils.vibrateFingerprintError(getContext()); + vibrateError(); } // allow system-defined limit of number of attempts before giving up int lockoutMode = handleFailedAttempt(); @@ -99,7 +99,7 @@ public abstract class AuthenticationClient extends ClientMonitor { result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode } else { if (receiver != null) { - FingerprintUtils.vibrateFingerprintSuccess(getContext()); + vibrateSuccess(); } result |= true; // we have a valid fingerprint, done resetFailedAttempts(); diff --git a/services/core/java/com/android/server/fingerprint/ClientMonitor.java b/services/core/java/com/android/server/fingerprint/ClientMonitor.java index 1a2e1443d329e..3eae157c53aa9 100644 --- a/services/core/java/com/android/server/fingerprint/ClientMonitor.java +++ b/services/core/java/com/android/server/fingerprint/ClientMonitor.java @@ -23,6 +23,8 @@ import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.os.IBinder; import android.os.RemoteException; +import android.os.VibrationEffect; +import android.os.Vibrator; import android.util.Slog; import java.util.NoSuchElementException; @@ -36,14 +38,18 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { protected static final String TAG = FingerprintService.TAG; // TODO: get specific name protected static final int ERROR_ESRCH = 3; // Likely fingerprint HAL is dead. See errno.h. protected static final boolean DEBUG = FingerprintService.DEBUG; + private static final long[] DEFAULT_SUCCESS_VIBRATION_PATTERN = new long[] {0, 30}; + private final Context mContext; + private final long mHalDeviceId; + private final int mTargetUserId; + private final int mGroupId; + // True if client does not have MANAGE_FINGERPRINT permission + private final boolean mIsRestricted; + private final String mOwner; + private final VibrationEffect mSuccessVibrationEffect; + private final VibrationEffect mErrorVibrationEffect; private IBinder mToken; private IFingerprintServiceReceiver mReceiver; - private int mTargetUserId; - private int mGroupId; - private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission - private String mOwner; - private Context mContext; - private long mHalDeviceId; protected boolean mAlreadyCancelled; /** @@ -68,6 +74,8 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { mGroupId = groupId; mIsRestricted = restricted; mOwner = owner; + mSuccessVibrationEffect = getSuccessVibrationEffect(context); + mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); try { if (token != null) { token.linkToDeath(this, 0); @@ -79,7 +87,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { /** * Contacts fingerprint HAL to start the client. - * @return 0 on succes, errno from driver on failure + * @return 0 on success, errno from driver on failure */ public abstract int start(); @@ -211,4 +219,39 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient { public final IBinder getToken() { return mToken; } + + public final void vibrateSuccess() { + Vibrator vibrator = mContext.getSystemService(Vibrator.class); + if (vibrator != null) { + vibrator.vibrate(mSuccessVibrationEffect); + } + } + + public final void vibrateError() { + Vibrator vibrator = mContext.getSystemService(Vibrator.class); + if (vibrator != null) { + vibrator.vibrate(mErrorVibrationEffect); + } + } + + private static VibrationEffect getSuccessVibrationEffect(Context ctx) { + int[] arr = ctx.getResources().getIntArray( + com.android.internal.R.array.config_longPressVibePattern); + final long[] vibePattern; + if (arr == null || arr.length == 0) { + vibePattern = DEFAULT_SUCCESS_VIBRATION_PATTERN; + } else { + vibePattern = new long[arr.length]; + for (int i = 0; i < arr.length; i++) { + vibePattern[i] = arr[i]; + } + } + if (vibePattern.length == 1) { + return VibrationEffect.createOneShot( + vibePattern[0], VibrationEffect.DEFAULT_AMPLITUDE); + } else { + return VibrationEffect.createWaveform(vibePattern, -1); + } + } + } diff --git a/services/core/java/com/android/server/fingerprint/EnrollClient.java b/services/core/java/com/android/server/fingerprint/EnrollClient.java index 61708946f806a..c9efcf2fd6874 100644 --- a/services/core/java/com/android/server/fingerprint/EnrollClient.java +++ b/services/core/java/com/android/server/fingerprint/EnrollClient.java @@ -65,7 +65,7 @@ public abstract class EnrollClient extends ClientMonitor { if (receiver == null) return true; // client not listening - FingerprintUtils.vibrateFingerprintSuccess(getContext()); + vibrateSuccess(); MetricsLogger.action(getContext(), MetricsEvent.ACTION_FINGERPRINT_ENROLL); try { receiver.onEnrollResult(getHalDeviceId(), fpId, groupId, remaining); diff --git a/services/core/java/com/android/server/fingerprint/FingerprintUtils.java b/services/core/java/com/android/server/fingerprint/FingerprintUtils.java index 49dc8e4dac71b..5fbd735d4ac5e 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintUtils.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintUtils.java @@ -18,7 +18,6 @@ package com.android.server.fingerprint; import android.content.Context; import android.hardware.fingerprint.Fingerprint; -import android.os.Vibrator; import android.text.TextUtils; import android.util.SparseArray; @@ -31,9 +30,6 @@ import java.util.List; */ public class FingerprintUtils { - private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30}; - private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30}; - private static final Object sInstanceLock = new Object(); private static FingerprintUtils sInstance; @@ -72,20 +68,6 @@ public class FingerprintUtils { getStateForUser(ctx, userId).renameFingerprint(fingerId, name); } - public static void vibrateFingerprintError(Context context) { - Vibrator vibrator = context.getSystemService(Vibrator.class); - if (vibrator != null) { - vibrator.vibrate(FP_ERROR_VIBRATE_PATTERN, -1); - } - } - - public static void vibrateFingerprintSuccess(Context context) { - Vibrator vibrator = context.getSystemService(Vibrator.class); - if (vibrator != null) { - vibrator.vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1); - } - } - private FingerprintsUserState getStateForUser(Context ctx, int userId) { synchronized (this) { FingerprintsUserState state = mUsers.get(userId);