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
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 5339bac..370e569 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 @@
         }
         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 @@
             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 1a2e144..3eae157 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.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 @@
     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 @@
         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 @@
 
     /**
      * 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 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 6170894..c9efcf2 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 @@
         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 49dc8e4..5fbd735 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 @@
 
 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 @@
  */
 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 @@
         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);