diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index 65e498e144751d739c4fdbe7354082a3f30e7a05..8b1577cb4b1c6992d0cecbb88bda58de500dd4b0 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -41,5 +41,5 @@ interface IVibratorManagerService {
     // There is no order guarantee with respect to the two-way APIs above like
     // vibrate/isVibrating/cancel.
     oneway void performHapticFeedback(int uid, int deviceId, String opPkg, int constant,
-            boolean always, String reason);
+            boolean always, String reason, boolean fromIme);
 }
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 04c257b92e29577988db154eec1db6d4bea20f63..2a62c24a86e164601325f9cadde87da4dd30251d 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -206,12 +206,13 @@ public class SystemVibrator extends Vibrator {
     }
 
     @Override
-    public void performHapticFeedback(int constant, boolean always, String reason) {
+    public void performHapticFeedback(
+            int constant, boolean always, String reason, boolean fromIme) {
         if (mVibratorManager == null) {
             Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager.");
             return;
         }
-        mVibratorManager.performHapticFeedback(constant, always, reason);
+        mVibratorManager.performHapticFeedback(constant, always, reason, fromIme);
     }
 
     @Override
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index 8e8392302824ab10d2205632fb9357a60ce65fb3..c80bcac2624ffdc1e0cb60917c34d81518e129a4 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -147,14 +147,15 @@ public class SystemVibratorManager extends VibratorManager {
     }
 
     @Override
-    public void performHapticFeedback(int constant, boolean always, String reason) {
+    public void performHapticFeedback(int constant, boolean always, String reason,
+            boolean fromIme) {
         if (mService == null) {
             Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager service.");
             return;
         }
         try {
             mService.performHapticFeedback(
-                    mUid, mContext.getDeviceId(), mPackageName, constant, always, reason);
+                    mUid, mContext.getDeviceId(), mPackageName, constant, always, reason, fromIme);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to perform haptic feedback.", e);
         }
@@ -244,8 +245,9 @@ public class SystemVibratorManager extends VibratorManager {
         }
 
         @Override
-        public void performHapticFeedback(int effectId, boolean always, String reason) {
-            SystemVibratorManager.this.performHapticFeedback(effectId, always, reason);
+        public void performHapticFeedback(int effectId, boolean always, String reason,
+                boolean fromIme) {
+            SystemVibratorManager.this.performHapticFeedback(effectId, always, reason, fromIme);
         }
 
         @Override
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 2fc24142acf2ab75ad01f4bf9ae0eee192c9e3c7..4b2d4eb833ff87f125e7fdbabbf60737d7a99337 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -534,10 +534,12 @@ public abstract class Vibrator {
      *          {@code false} if the vibration for the haptic feedback should respect the applicable
      *          vibration intensity settings.
      * @param reason the reason for this haptic feedback.
+     * @param fromIme the haptic feedback is performed from an IME.
      *
      * @hide
      */
-    public void performHapticFeedback(int constant, boolean always, String reason) {
+    public void performHapticFeedback(int constant, boolean always, String reason,
+            boolean fromIme) {
         Log.w(TAG, "performHapticFeedback is not supported");
     }
 
diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java
index e0b6a9fd28f00527b3d20c46f83a8192acf4bfe0..513c4bd7ec0ca9f5b1643513daff43dd5a27122e 100644
--- a/core/java/android/os/VibratorManager.java
+++ b/core/java/android/os/VibratorManager.java
@@ -146,9 +146,11 @@ public abstract class VibratorManager {
      *          vibration intensity settings applicable to the corresponding vibration.
      *          {@code false} otherwise.
      * @param reason the reason for this haptic feedback.
+     * @param fromIme the haptic feedback is performed from an IME.
      * @hide
      */
-    public void performHapticFeedback(int constant, boolean always, String reason) {
+    public void performHapticFeedback(int constant, boolean always, String reason,
+            boolean fromIme) {
         Log.w(TAG, "performHapticFeedback is not supported");
     }
 
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d68a47c54d4b7eecb8f372dd772debeba795f651..e126836020b4dd88d6a86705550c7e6e6141abea 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -148,13 +148,13 @@ interface IWindowSession {
             int seqId);
 
     @UnsupportedAppUsage
-    boolean performHapticFeedback(int effectId, boolean always);
+    boolean performHapticFeedback(int effectId, boolean always, boolean fromIme);
 
     /**
      * Called by attached views to perform predefined haptic feedback without requiring VIBRATE
      * permission.
      */
-    oneway void performHapticFeedbackAsync(int effectId, boolean always);
+    oneway void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme);
 
     /**
      * Initiate the drag operation itself
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a2faabc575c412562f8faa71149a8b2a597d491f..3478286abd571bf287279ebbe48128e2b5f60b59 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25,6 +25,7 @@ import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
@@ -28376,15 +28377,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         }
 
         final boolean always = (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0;
+        boolean fromIme = false;
+        if (mAttachInfo.mViewRootImpl != null) {
+            fromIme = mAttachInfo.mViewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD;
+        }
         if (Flags.useVibratorHapticFeedback()) {
             if (!mAttachInfo.canPerformHapticFeedback()) {
                 return false;
             }
             getSystemVibrator().performHapticFeedback(
-                    feedbackConstant, always, "View#performHapticFeedback");
+                    feedbackConstant, always, "View#performHapticFeedback", fromIme);
             return true;
         }
-        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always);
+        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always, fromIme);
     }
 
     private Vibrator getSystemVibrator() {
@@ -31427,7 +31432,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
         interface Callbacks {
             void playSoundEffect(int effectId);
-            boolean performHapticFeedback(int effectId, boolean always);
+            boolean performHapticFeedback(int effectId, boolean always, boolean fromIme);
         }
 
         /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 333cbb39d9c72c2277faa4ed28e9c69623886c2c..708751a2505390a01b57501d659fdb2dc75942e5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -9201,18 +9201,18 @@ public final class ViewRootImpl implements ViewParent,
      * {@inheritDoc}
      */
     @Override
-    public boolean performHapticFeedback(int effectId, boolean always) {
+    public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) {
         if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) {
             return false;
         }
 
         try {
             if (USE_ASYNC_PERFORM_HAPTIC_FEEDBACK) {
-                mWindowSession.performHapticFeedbackAsync(effectId, always);
+                mWindowSession.performHapticFeedbackAsync(effectId, always, fromIme);
                 return true;
             } else {
                 // Original blocking binder call path.
-                return mWindowSession.performHapticFeedback(effectId, always);
+                return mWindowSession.performHapticFeedback(effectId, always, fromIme);
             }
         } catch (RemoteException e) {
             return false;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 2b2c507257494ce40760af27bdfcd2d20c397264..22d8ed91d455cbe0fe51d442aa8d46ff5947ba26 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -479,13 +479,13 @@ public class WindowlessWindowManager implements IWindowSession {
     }
 
     @Override
-    public boolean performHapticFeedback(int effectId, boolean always) {
+    public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) {
         return false;
     }
 
     @Override
-    public void performHapticFeedbackAsync(int effectId, boolean always) {
-        performHapticFeedback(effectId, always);
+    public void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme) {
+        performHapticFeedback(effectId, always, fromIme);
     }
 
     @Override
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 7c58de67ded600222d465895508ed6c5e0a1539f..1a242eff73b1379d218bef619234e876c0f88209 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -451,7 +451,7 @@ public class ViewRootImplTest {
         ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display);
 
         boolean result = viewRootImpl.performHapticFeedback(
-                HapticFeedbackConstants.CONTEXT_CLICK, true);
+                HapticFeedbackConstants.CONTEXT_CLICK, true, false /* fromIme */);
 
         assertThat(result).isFalse();
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 428fca082f755091ed8b959ba0cb800a2978374c..e9a7fe1371ac24cc3459395e2b0f8df1300e1de6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6410,7 +6410,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     private boolean performHapticFeedback(int effectId, boolean always, String reason) {
         return performHapticFeedback(Process.myUid(), mContext.getOpPackageName(),
-            effectId, always, reason);
+            effectId, always, reason, false /* fromIme */);
     }
 
     @Override
@@ -6420,7 +6420,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     @Override
     public boolean performHapticFeedback(int uid, String packageName, int effectId,
-            boolean always, String reason) {
+            boolean always, String reason, boolean fromIme) {
         if (!mVibrator.hasVibrator()) {
             return false;
         }
@@ -6431,7 +6431,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         }
         VibrationAttributes attrs =
                 mHapticFeedbackVibrationProvider.getVibrationAttributesForHapticFeedback(
-                        effectId, /* bypassVibrationIntensitySetting= */ always);
+                        effectId, /* bypassVibrationIntensitySetting= */ always, fromIme);
         VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, effectId);
         mVibrator.vibrate(uid, packageName, effect, reason, attrs);
         return true;
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 2174fd62ea00151361d2d779c80724e8fecef315..5956594acd2604a2aaa524f0feefc919bc00bb50 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1072,7 +1072,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
      * Call from application to perform haptic feedback on its window.
      */
     public boolean performHapticFeedback(int uid, String packageName, int effectId,
-            boolean always, String reason);
+            boolean always, String reason, boolean fromIme);
 
     /**
      * Called when we have started keeping the screen on because a window
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
index 519acec2f7b4ab8b6abb0f7e6b1a8ed24e6f74a5..126af1fe84963322821890b780042c06d45525cd 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
@@ -190,10 +190,11 @@ public final class HapticFeedbackVibrationProvider {
      *      to get.
      * @param bypassVibrationIntensitySetting {@code true} if the returned attribute should bypass
      *      vibration intensity settings. {@code false} otherwise.
+     * @param fromIme the haptic feedback is performed from an IME.
      * @return the {@link VibrationAttributes} that should be used for the provided haptic feedback.
      */
     public VibrationAttributes getVibrationAttributesForHapticFeedback(
-            int effectId, boolean bypassVibrationIntensitySetting) {
+            int effectId, boolean bypassVibrationIntensitySetting, boolean fromIme) {
         VibrationAttributes attrs;
         switch (effectId) {
             case HapticFeedbackConstants.EDGE_SQUEEZE:
@@ -209,7 +210,7 @@ public final class HapticFeedbackVibrationProvider {
                 break;
             case HapticFeedbackConstants.KEYBOARD_TAP:
             case HapticFeedbackConstants.KEYBOARD_RELEASE:
-                attrs = createKeyboardVibrationAttributes();
+                attrs = createKeyboardVibrationAttributes(fromIme);
                 break;
             default:
                 attrs = TOUCH_VIBRATION_ATTRIBUTES;
@@ -222,7 +223,7 @@ public final class HapticFeedbackVibrationProvider {
         if (shouldBypassInterruptionPolicy(effectId)) {
             flags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
         }
-        if (shouldBypassIntensityScale(effectId)) {
+        if (shouldBypassIntensityScale(effectId, fromIme)) {
             flags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE;
         }
 
@@ -337,9 +338,9 @@ public final class HapticFeedbackVibrationProvider {
                 /* fallbackForPredefinedEffect= */ predefinedEffectFallback);
     }
 
-    private boolean shouldBypassIntensityScale(int effectId) {
-        if (!Flags.keyboardCategoryEnabled() || mKeyboardVibrationFixedAmplitude < 0) {
-            // shouldn't bypass if not support keyboard category or no fixed amplitude
+    private boolean shouldBypassIntensityScale(int effectId, boolean isIme) {
+        if (!Flags.keyboardCategoryEnabled() || mKeyboardVibrationFixedAmplitude < 0 || !isIme) {
+            // Shouldn't bypass if not support keyboard category, no fixed amplitude or not an IME.
             return false;
         }
         switch (effectId) {
@@ -353,8 +354,9 @@ public final class HapticFeedbackVibrationProvider {
         return false;
     }
 
-    private static VibrationAttributes createKeyboardVibrationAttributes() {
-        if (!Flags.keyboardCategoryEnabled()) {
+    private VibrationAttributes createKeyboardVibrationAttributes(boolean fromIme) {
+        // Use touch attribute when the keyboard category is disable or it's not from an IME.
+        if (!Flags.keyboardCategoryEnabled() || !fromIme) {
             return TOUCH_VIBRATION_ATTRIBUTES;
         }
 
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 78e0ebbb53fafb0af9626a0e2fae0f8c0075daa6..78ebe24571498338cf0709da72ab76a9ad24493e 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -416,14 +416,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
     }
 
     @Override // Binder call
-    public void performHapticFeedback(
-            int uid, int deviceId, String opPkg, int constant, boolean always, String reason) {
+    public void performHapticFeedback(int uid, int deviceId, String opPkg, int constant,
+            boolean always, String reason, boolean fromIme) {
         // Note that the `performHapticFeedback` method does not take a token argument from the
         // caller, and instead, uses this service as the token. This is to mitigate performance
         // impact that would otherwise be caused due to marshal latency. Haptic feedback effects are
         // short-lived, so we don't need to cancel when the process dies.
         performHapticFeedbackInternal(
-                uid, deviceId, opPkg, constant, always, reason, /* token= */ this);
+                uid, deviceId, opPkg, constant, always, reason, /* token= */ this, fromIme);
     }
 
     /**
@@ -435,7 +435,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
     @Nullable
     HalVibration performHapticFeedbackInternal(
             int uid, int deviceId, String opPkg, int constant, boolean always, String reason,
-            IBinder token) {
+            IBinder token, boolean fromIme) {
         HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
         if (hapticVibrationProvider == null) {
             Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
@@ -449,7 +449,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
         CombinedVibration combinedVibration = CombinedVibration.createParallel(effect);
         VibrationAttributes attrs =
                 hapticVibrationProvider.getVibrationAttributesForHapticFeedback(
-                        constant, /* bypassVibrationIntensitySetting= */ always);
+                        constant, /* bypassVibrationIntensitySetting= */ always, fromIme);
         VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant);
         return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, combinedVibration, attrs,
                 "performHapticFeedback: " + reason, token);
@@ -2300,7 +2300,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
             HalVibration vib = performHapticFeedbackInternal(Binder.getCallingUid(),
                     Context.DEVICE_ID_DEFAULT, SHELL_PACKAGE_NAME, constant,
                     /* always= */ commonOptions.force, /* reason= */ commonOptions.description,
-                    deathBinder);
+                    deathBinder, false /* fromIme */);
             maybeWaitOnVibration(vib, commonOptions);
 
             return 0;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 908cbd340236c3e2c281ab2a14a9e867ec0ea047..30134d815fa699d845251b8f0b8874925d505a47 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -336,19 +336,19 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
     }
 
     @Override
-    public boolean performHapticFeedback(int effectId, boolean always) {
+    public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) {
         final long ident = Binder.clearCallingIdentity();
         try {
             return mService.mPolicy.performHapticFeedback(mUid, mPackageName,
-                        effectId, always, null);
+                        effectId, always, null, fromIme);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
 
     @Override
-    public void performHapticFeedbackAsync(int effectId, boolean always) {
-        performHapticFeedback(effectId, always);
+    public void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme) {
+        performHapticFeedback(effectId, always, fromIme);
     }
 
     /* Drag/drop */
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
index 3d0dca0de87e0e841b1ed4191fa0a82dca198ab6..e3d45967848a3fb5a5a92380ce0882b6189a0a55 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
@@ -17,9 +17,11 @@
 package com.android.server.vibrator;
 
 import static android.os.VibrationAttributes.CATEGORY_KEYBOARD;
+import static android.os.VibrationAttributes.CATEGORY_UNKNOWN;
 import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
 import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
 import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
 import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK;
 import static android.os.VibrationEffect.Composition.PRIMITIVE_TICK;
 import static android.os.VibrationEffect.EFFECT_CLICK;
@@ -285,7 +287,8 @@ public class HapticFeedbackVibrationProviderTest {
         HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
 
         VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ false);
+                SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ false,
+                false /* fromIme*/);
 
         assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isFalse();
     }
@@ -295,7 +298,7 @@ public class HapticFeedbackVibrationProviderTest {
         HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
 
         VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ true);
+                SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ true, false /* fromIme*/);
 
         assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isTrue();
     }
@@ -307,7 +310,7 @@ public class HapticFeedbackVibrationProviderTest {
 
         for (int effectId : SCROLL_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/);
             assertWithMessage("Expected FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId)
                    .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isTrue();
         }
@@ -320,40 +323,59 @@ public class HapticFeedbackVibrationProviderTest {
 
         for (int effectId : SCROLL_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/);
             assertWithMessage("Expected no FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId)
                    .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isFalse();
         }
     }
 
     @Test
-    public void testVibrationAttribute_keyboardCategoryOff_notUseKeyboardCategory() {
+    public void testVibrationAttribute_keyboardCategoryOff_isIme_notUseKeyboardCategory() {
         mSetFlagsRule.disableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
         HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
 
         for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/);
+            assertWithMessage("Expected USAGE_TOUCH for effect " + effectId)
+                    .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH);
             assertWithMessage("Expected no CATEGORY_KEYBOARD for effect " + effectId)
-                    .that(attrs.getCategory()).isEqualTo(0);
+                    .that(attrs.getCategory()).isEqualTo(CATEGORY_UNKNOWN);
         }
     }
 
     @Test
-    public void testVibrationAttribute_keyboardCategoryOn_useKeyboardCategory() {
+    public void testVibrationAttribute_keyboardCategoryOn_notIme_notUseKeyboardCategory() {
         mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
         HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
 
         for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/);
+            assertWithMessage("Expected USAGE_TOUCH for effect " + effectId)
+                    .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH);
+            assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId)
+                    .that(attrs.getCategory()).isEqualTo(CATEGORY_UNKNOWN);
+        }
+    }
+
+    @Test
+    public void testVibrationAttribute_keyboardCategoryOn_isIme_useKeyboardCategory() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
+        HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+        for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
+            VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+                    effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/);
+            assertWithMessage("Expected USAGE_TOUCH for effect " + effectId)
+                    .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH);
             assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId)
                     .that(attrs.getCategory()).isEqualTo(CATEGORY_KEYBOARD);
         }
     }
 
     @Test
-    public void testVibrationAttribute_noFixAmplitude_keyboardCategoryOn_noBypassIntensityScale() {
+    public void testVibrationAttribute_noFixAmplitude_notBypassIntensityScale() {
         mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
         mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK);
         mockKeyboardVibrationFixedAmplitude(-1);
@@ -361,7 +383,23 @@ public class HapticFeedbackVibrationProviderTest {
 
         for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/);
+            assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect "
+                    + effectId)
+                    .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse();
+        }
+    }
+
+    @Test
+    public void testVibrationAttribute_notIme_notBypassIntensityScale() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
+        mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK);
+        mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE);
+        HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+        for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
+            VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+                    effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/);
             assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect "
                     + effectId)
                     .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse();
@@ -369,7 +407,7 @@ public class HapticFeedbackVibrationProviderTest {
     }
 
     @Test
-    public void testVibrationAttribute_fixAmplitude_keyboardCategoryOn_bypassIntensityScale() {
+    public void testVibrationAttribute_fixAmplitude_isIme_bypassIntensityScale() {
         mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
         mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK);
         mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE);
@@ -377,7 +415,7 @@ public class HapticFeedbackVibrationProviderTest {
 
         for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
             VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
-                    effectId, /* bypassVibrationIntensitySetting= */ false);
+                    effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/);
             assertWithMessage("Expected FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect "
                     + effectId)
                     .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isTrue();
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index d2ad61f2ba9f516450cd5065ee03e26cbbaf03f8..1ea90f55b727df7623b99b9c89bf8bf6a6c6b818 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -2526,7 +2526,7 @@ public class VibratorManagerServiceTest {
                 int constant, boolean always) throws InterruptedException {
         HalVibration vib =
                 service.performHapticFeedbackInternal(UID, Context.DEVICE_ID_DEFAULT, PACKAGE_NAME,
-                        constant, always, "some reason", service);
+                        constant, always, "some reason", service, false /* fromIme */);
         if (vib != null) {
             vib.waitForEnd();
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 7551b1650ad0d242439992692f160a8577723f45..1233686a4b485e4d91e0c4a450bc79da7073ea3d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -265,7 +265,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
 
     @Override
     public boolean performHapticFeedback(int uid, String packageName, int effectId,
-            boolean always, String reason) {
+            boolean always, String reason, boolean fromIme) {
         return false;
     }