Merge "Add support for vibrator 1.1 HAL and TICK effect."
diff --git a/Android.mk b/Android.mk
index 623b522..d847d49 100644
--- a/Android.mk
+++ b/Android.mk
@@ -598,6 +598,7 @@
     android.hardware.usb-V1.0-java-constants             \
     android.hardware.usb-V1.1-java-constants             \
     android.hardware.vibrator-V1.0-java-constants        \
+    android.hardware.vibrator-V1.1-java-constants        \
 
 # Loaded with System.loadLibrary by android.view.textclassifier
 LOCAL_REQUIRED_MODULES += libtextclassifier
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 6aa601a..fe9e8c6 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -16,7 +16,7 @@
 
 package android.os;
 
-import android.hardware.vibrator.V1_0.Constants.Effect;
+import android.hardware.vibrator.V1_1.Constants.Effect_1_1;
 
 import java.util.Arrays;
 
@@ -41,7 +41,7 @@
      * @see #get(int)
      * @hide
      */
-    public static final int EFFECT_CLICK = Effect.CLICK;
+    public static final int EFFECT_CLICK = Effect_1_1.CLICK;
 
     /**
      * A double click effect.
@@ -49,7 +49,14 @@
      * @see #get(int)
      * @hide
      */
-    public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK;
+    public static final int EFFECT_DOUBLE_CLICK = Effect_1_1.DOUBLE_CLICK;
+
+    /**
+     * A tick effect.
+     * @see #get(int)
+     * @hide
+     */
+    public static final int EFFECT_TICK = Effect_1_1.TICK;
 
     /** @hide to prevent subclassing from outside of the framework */
     public VibrationEffect() { }
@@ -382,9 +389,14 @@
 
         @Override
         public void validate() {
-            if (mEffectId != EFFECT_CLICK) {
-                throw new IllegalArgumentException(
-                        "Unknown prebaked effect type (value=" + mEffectId + ")");
+            switch (mEffectId) {
+                case EFFECT_CLICK:
+                case EFFECT_DOUBLE_CLICK:
+                case EFFECT_TICK:
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown prebaked effect type (value=" + mEffectId + ")");
             }
         }
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 94228ab..e085697 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -965,14 +965,6 @@
         <item>10</item>
     </integer-array>
 
-    <!-- Vibrator pattern for feedback about a context click -->
-    <integer-array name="config_contextClickVibePattern">
-        <item>0</item>
-        <item>1</item>
-        <item>20</item>
-        <item>21</item>
-    </integer-array>
-
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
     <!-- Display low battery warning when battery level dips to this value.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6554d44..d56c3ee 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1558,7 +1558,6 @@
   <java-symbol type="array" name="config_longPressVibePattern" />
   <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
   <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
-  <java-symbol type="array" name="config_contextClickVibePattern" />
   <java-symbol type="array" name="config_virtualKeyVibePattern" />
   <java-symbol type="attr" name="actionModePopupWindowStyle" />
   <java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 03e9dd2..7ba3d7d 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -221,19 +221,24 @@
 
         long[] clickEffectTimings = getLongIntArray(context.getResources(),
                 com.android.internal.R.array.config_virtualKeyVibePattern);
-        VibrationEffect clickEffect;
-        if (clickEffectTimings.length == 0) {
-            clickEffect = null;
-        } else if (clickEffectTimings.length == 1) {
-            clickEffect = VibrationEffect.createOneShot(
-                    clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE);
-        } else {
-            clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
-        }
+        VibrationEffect clickEffect = createEffect(clickEffectTimings);
         VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
                 new long[] {0, 30, 100, 30} /*timings*/, -1);
+        long[] tickEffectTimings = getLongIntArray(context.getResources(),
+                com.android.internal.R.array.config_clockTickVibePattern);
+        VibrationEffect tickEffect = createEffect(tickEffectTimings);
 
-        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
+        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect };
+    }
+
+    private static VibrationEffect createEffect(long[] timings) {
+        if (timings == null || timings.length == 0) {
+            return null;
+        } else if (timings.length == 1) {
+            return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE);
+        } else {
+            return VibrationEffect.createWaveform(timings, -1);
+        }
     }
 
     public void systemReady() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6aba9cb..8eebb10 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -429,15 +429,6 @@
     // Vibrator pattern for haptic feedback of a long press.
     long[] mLongPressVibePattern;
 
-    // Vibrator pattern for haptic feedback of virtual key press.
-    long[] mVirtualKeyVibePattern;
-
-    // Vibrator pattern for a short vibration.
-    long[] mKeyboardTapVibePattern;
-
-    // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
-    long[] mClockTickVibePattern;
-
     // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
     long[] mCalendarDateVibePattern;
 
@@ -447,9 +438,6 @@
     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
     long[] mSafeModeEnabledVibePattern;
 
-    // Vibrator pattern for haptic feedback of a context click.
-    long[] mContextClickVibePattern;
-
     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
     boolean mEnableShiftMenuBugReports = false;
 
@@ -2060,20 +2048,12 @@
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_longPressVibePattern);
-        mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_virtualKeyVibePattern);
-        mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_keyboardTapVibePattern);
-        mClockTickVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_clockTickVibePattern);
         mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_calendarDateVibePattern);
         mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
-        mContextClickVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_contextClickVibePattern);
 
         mScreenshotChordEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableScreenshotChord);
@@ -7700,8 +7680,7 @@
             case HapticFeedbackConstants.KEYBOARD_TAP:
                 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
             case HapticFeedbackConstants.CLOCK_TICK:
-                pattern = mClockTickVibePattern;
-                break;
+                return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
             case HapticFeedbackConstants.CALENDAR_DATE:
                 pattern = mCalendarDateVibePattern;
                 break;
@@ -7712,8 +7691,7 @@
                 pattern = mSafeModeEnabledVibePattern;
                 break;
             case HapticFeedbackConstants.CONTEXT_CLICK:
-                pattern = mContextClickVibePattern;
-                break;
+                return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
             default:
                 return null;
         }
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index e6c2b1d..362dd9f 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -100,6 +100,7 @@
     android.hardware.tv.cec@1.0 \
     android.hardware.tv.input@1.0 \
     android.hardware.vibrator@1.0 \
+    android.hardware.vibrator@1.1 \
     android.hardware.vr@1.0 \
     android.frameworks.schedulerservice@1.0 \
     android.frameworks.sensorservice@1.0 \
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 76ce890..804cd17 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/vibrator/1.0/IVibrator.h>
 #include <android/hardware/vibrator/1.0/types.h>
+#include <android/hardware/vibrator/1.1/IVibrator.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -35,6 +36,8 @@
 using android::hardware::vibrator::V1_0::EffectStrength;
 using android::hardware::vibrator::V1_0::IVibrator;
 using android::hardware::vibrator::V1_0::Status;
+using android::hardware::vibrator::V1_1::Effect_1_1;
+using IVibrator_1_1 = android::hardware::vibrator::V1_1::IVibrator;
 
 namespace android
 {
@@ -108,11 +111,26 @@
     if (mHal != nullptr) {
         Status status;
         uint32_t lengthMs;
-        mHal->perform(static_cast<Effect>(effect), static_cast<EffectStrength>(strength),
-                [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
-                    status = retStatus;
-                    lengthMs = retLengthMs;
-                });
+        auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
+            status = retStatus;
+            lengthMs = retLengthMs;
+        };
+        EffectStrength effectStrength(static_cast<EffectStrength>(strength));
+
+        if (effect < 0  || effect > static_cast<uint32_t>(Effect_1_1::TICK)) {
+            ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
+                    static_cast<int32_t>(effect));
+        } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) {
+            sp<IVibrator_1_1> hal_1_1 = IVibrator_1_1::castFrom(mHal);
+            if (hal_1_1 != nullptr) {
+                hal_1_1->perform_1_1(static_cast<Effect_1_1>(effect), effectStrength, callback);
+            } else {
+                ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version",
+                        static_cast<int32_t>(effect));
+            }
+        } else {
+            mHal->perform(static_cast<Effect>(effect), effectStrength, callback);
+        }
         if (status == Status::OK) {
             return lengthMs;
         } else if (status != Status::UNSUPPORTED_OPERATION) {