Add a new KEYBOARD_TAP haptic feedback type for very short, low-latency vibration.

The minimum value varies from device to device, so this is useful for defining
the shortest and most efficient vibration. The VibratorService creates a Thread
when playing back vibration patterns, so this allows you to avoid thread creation
and associated scheduling delays by specifying a one-shot duration in the config
file.
diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
index 99a8f48..c879ece 100755
--- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -175,6 +175,9 @@
     // Vibrator pattern for haptic feedback of virtual key press.
     long[] mVirtualKeyVibePattern;
     
+    // Vibrator pattern for a short vibration.
+    long[] mKeyboardTapVibePattern;
+
     // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
     long[] mSafeModeDisabledVibePattern;
     
@@ -539,6 +542,8 @@
                 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);
         mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
@@ -2368,31 +2373,44 @@
             }
         }
     }
-    
+
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
         final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
         if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
             return false;
         }
+        long[] pattern = null;
         switch (effectId) {
             case HapticFeedbackConstants.LONG_PRESS:
-                mVibrator.vibrate(mLongPressVibePattern, -1);
-                return true;
+                pattern = mLongPressVibePattern;
+                break;
             case HapticFeedbackConstants.VIRTUAL_KEY:
-                mVibrator.vibrate(mVirtualKeyVibePattern, -1);
-                return true;
+                pattern = mVirtualKeyVibePattern;
+                break;
+            case HapticFeedbackConstants.KEYBOARD_TAP:
+                pattern = mKeyboardTapVibePattern;
+                break;
             case HapticFeedbackConstants.SAFE_MODE_DISABLED:
-                mVibrator.vibrate(mSafeModeDisabledVibePattern, -1);
-                return true;
+                pattern = mSafeModeDisabledVibePattern;
+                break;
             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
-                mVibrator.vibrate(mSafeModeEnabledVibePattern, -1);
-                return true;
+                pattern = mSafeModeEnabledVibePattern;
+                break;
             case HapticFeedbackConstants.SCROLL_BARRIER:
-                mVibrator.vibrate(mScrollBarrierVibePattern, -1);
-                return true;
+                pattern = mScrollBarrierVibePattern;
+                break;
+            default:
+                return false;
         }
-        return false;
+        if (pattern.length == 1) {
+            // One-shot vibration
+            mVibrator.vibrate(pattern[0]);
+        } else {
+            // Pattern vibration
+            mVibrator.vibrate(pattern, -1);
+        }
+        return true;
     }
     
     public void keyFeedbackFromInput(KeyEvent event) {