diff options
19 files changed, 157 insertions, 112 deletions
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl index 8b1577cb4b1c..97993b609fda 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 fromIme); + String reason, int flags, int privFlags); } diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 2a62c24a86e1..5339d7331426 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -206,13 +206,12 @@ public class SystemVibrator extends Vibrator { } @Override - public void performHapticFeedback( - int constant, boolean always, String reason, boolean fromIme) { + public void performHapticFeedback(int constant, String reason, int flags, int privFlags) { if (mVibratorManager == null) { Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager."); return; } - mVibratorManager.performHapticFeedback(constant, always, reason, fromIme); + mVibratorManager.performHapticFeedback(constant, reason, flags, privFlags); } @Override diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java index c80bcac2624f..a9846ba7e264 100644 --- a/core/java/android/os/SystemVibratorManager.java +++ b/core/java/android/os/SystemVibratorManager.java @@ -147,15 +147,14 @@ public class SystemVibratorManager extends VibratorManager { } @Override - public void performHapticFeedback(int constant, boolean always, String reason, - boolean fromIme) { + public void performHapticFeedback(int constant, String reason, int flags, int privFlags) { 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, fromIme); + mService.performHapticFeedback(mUid, mContext.getDeviceId(), mPackageName, constant, + reason, flags, privFlags); } catch (RemoteException e) { Log.w(TAG, "Failed to perform haptic feedback.", e); } @@ -245,9 +244,8 @@ public class SystemVibratorManager extends VibratorManager { } @Override - public void performHapticFeedback(int effectId, boolean always, String reason, - boolean fromIme) { - SystemVibratorManager.this.performHapticFeedback(effectId, always, reason, fromIme); + public void performHapticFeedback(int effectId, String reason, int flags, int privFlags) { + SystemVibratorManager.this.performHapticFeedback(effectId, reason, flags, privFlags); } @Override diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index 8af371c74880..71c83f20741d 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -33,6 +33,7 @@ import android.media.AudioAttributes; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibratorFrequencyProfile; import android.util.Log; +import android.view.HapticFeedbackConstants; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -519,17 +520,15 @@ public abstract class Vibrator { * * @param constant the ID for the haptic feedback. This should be one of the constants defined * in {@link HapticFeedbackConstants}. - * @param always {@code true} if the haptic feedback should be played regardless of the user - * vibration intensity settings applicable to the corresponding vibration. - * {@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. + * @param flags Additional flags as per {@link HapticFeedbackConstants}. + * @param privFlags Additional private flags as per {@link HapticFeedbackConstants}. * * @hide */ - public void performHapticFeedback(int constant, boolean always, String reason, - boolean fromIme) { + public void performHapticFeedback(int constant, String reason, + @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags) { Log.w(TAG, "performHapticFeedback is not supported"); } diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java index 513c4bd7ec0c..2c7a852cf29f 100644 --- a/core/java/android/os/VibratorManager.java +++ b/core/java/android/os/VibratorManager.java @@ -23,6 +23,7 @@ import android.annotation.SystemService; import android.app.ActivityThread; import android.content.Context; import android.util.Log; +import android.view.HapticFeedbackConstants; /** * Provides access to all vibrators from the device, as well as the ability to run them @@ -142,15 +143,14 @@ public abstract class VibratorManager { * * @param constant the ID of the requested haptic feedback. Should be one of the constants * defined in {@link HapticFeedbackConstants}. - * @param always {@code true} if the haptic feedback should be played regardless of the user - * 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. + * @param flags Additional flags as per {@link HapticFeedbackConstants}. + * @param privFlags Additional private flags as per {@link HapticFeedbackConstants}. * @hide */ - public void performHapticFeedback(int constant, boolean always, String reason, - boolean fromIme) { + public void performHapticFeedback(int constant, String reason, + @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags) { Log.w(TAG, "performHapticFeedback is not supported"); } diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java index 69228cafa34b..1fe06d474803 100644 --- a/core/java/android/view/HapticFeedbackConstants.java +++ b/core/java/android/view/HapticFeedbackConstants.java @@ -16,11 +16,30 @@ package android.view; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Constants to be used to perform haptic feedback effects via * {@link View#performHapticFeedback(int)} */ public class HapticFeedbackConstants { + /** @hide **/ + @IntDef(flag = true, prefix = "FLAG_", value = { + FLAG_IGNORE_VIEW_SETTING, + FLAG_IGNORE_GLOBAL_SETTING, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Flags {} + + /** @hide **/ + @IntDef(flag = true, prefix = "PRIVATE_FLAG_", value = { + PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PrivateFlags {} private HapticFeedbackConstants() {} @@ -258,4 +277,14 @@ public class HapticFeedbackConstants { */ @Deprecated public static final int FLAG_IGNORE_GLOBAL_SETTING = 0x0002; + + /** + * Flag for {@link android.os.Vibrator#performHapticFeedback(int, boolean, String, int, int)} or + * {@link ViewRootImpl#performHapticFeedback(int, boolean, int, int)}: Perform the haptic + * feedback with the input method vibration settings, e.g. applying the keyboard vibration + * user settings to the KEYBOARD_* constants. + * + * @hide + */ + public static final int PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS = 0x0001; } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 070d33bb9be6..14407ca32388 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -140,13 +140,13 @@ interface IWindowSession { int seqId); @UnsupportedAppUsage - boolean performHapticFeedback(int effectId, boolean always, boolean fromIme); + boolean performHapticFeedback(int effectId, int flags, int privFlags); /** * Called by attached views to perform predefined haptic feedback without requiring VIBRATE * permission. */ - oneway void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme); + oneway void performHapticFeedbackAsync(int effectId, int flags, int privFlags); /** * Initiate the drag operation itself diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 88d7a834ff53..2edbcc2592cc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28636,20 +28636,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return false; } - 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; + int privFlags = 0; + if (mAttachInfo.mViewRootImpl != null + && mAttachInfo.mViewRootImpl.mWindowAttributes.type == TYPE_INPUT_METHOD) { + privFlags = HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS; } if (Flags.useVibratorHapticFeedback()) { if (!mAttachInfo.canPerformHapticFeedback()) { return false; } - getSystemVibrator().performHapticFeedback( - feedbackConstant, always, "View#performHapticFeedback", fromIme); + getSystemVibrator().performHapticFeedback(feedbackConstant, + "View#performHapticFeedback", flags, privFlags); return true; } - return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always, fromIme); + return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, flags, privFlags); } private Vibrator getSystemVibrator() { @@ -31684,7 +31684,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, interface Callbacks { void playSoundEffect(int effectId); - boolean performHapticFeedback(int effectId, boolean always, boolean fromIme); + + boolean performHapticFeedback(int effectId, + @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e5b17c8d1001..596726f83c15 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -9666,18 +9666,18 @@ public final class ViewRootImpl implements ViewParent, * {@inheritDoc} */ @Override - public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) { + public boolean performHapticFeedback(int effectId, int flags, int privFlags) { if ((mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { return false; } try { if (USE_ASYNC_PERFORM_HAPTIC_FEEDBACK) { - mWindowSession.performHapticFeedbackAsync(effectId, always, fromIme); + mWindowSession.performHapticFeedbackAsync(effectId, flags, privFlags); return true; } else { // Original blocking binder call path. - return mWindowSession.performHapticFeedback(effectId, always, fromIme); + return mWindowSession.performHapticFeedback(effectId, flags, privFlags); } } catch (RemoteException e) { return false; diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 55f22a631c3b..78718586329e 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -503,13 +503,13 @@ public class WindowlessWindowManager implements IWindowSession { } @Override - public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) { + public boolean performHapticFeedback(int effectId, int flags, int privFlags) { return false; } @Override - public void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme) { - performHapticFeedback(effectId, always, fromIme); + public void performHapticFeedbackAsync(int effectId, int flags, int privFlags) { + performHapticFeedback(effectId, flags, privFlags); } @Override diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index 033ac7cec1bc..c5b75ff50da7 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -17,6 +17,7 @@ package android.view; import static android.util.SequenceUtils.getInitSeq; +import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING; import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT; import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH; import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT; @@ -494,8 +495,8 @@ public class ViewRootImplTest { 0, displayInfo, new DisplayAdjustments()); ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, display); - boolean result = viewRootImpl.performHapticFeedback( - HapticFeedbackConstants.CONTEXT_CLICK, true, false /* fromIme */); + boolean result = viewRootImpl.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK, + FLAG_IGNORE_GLOBAL_SETTING, 0 /* privFlags */); 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 8dc97566d1d2..8419a608dc41 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -933,8 +933,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onWakeUp() { synchronized (mLock) { if (shouldEnableWakeGestureLp()) { - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, - "Wake Up"); + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, "Wake Up"); mWindowWakeUpPolicy.wakeUpFromWakeGesture(); } } @@ -1403,7 +1402,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, "Power - Long Press - Global Actions"); showGlobalActions(); break; @@ -1415,14 +1414,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (ActivityManager.isUserAMonkey()) { break; } - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, "Power - Long Press - Shut Off"); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); break; case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST: mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, "Power - Long Press - Go To Voice Assist"); // Some devices allow the voice assistant intent during setup (and use that intent // to launch something else, like Settings). So we explicitly allow that via the @@ -1431,7 +1430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case LONG_PRESS_POWER_ASSISTANT: mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.ASSISTANT_BUTTON, false, + performHapticFeedback(HapticFeedbackConstants.ASSISTANT_BUTTON, "Power - Long Press - Go To Assistant"); final int powerKeyDeviceId = INVALID_INPUT_DEVICE_ID; launchAssistAction(null, powerKeyDeviceId, eventTime, @@ -1446,7 +1445,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, "Power - Very Long Press - Show Global Actions"); showGlobalActions(); break; @@ -1599,8 +1598,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY: mTalkbackShortcutController.toggleTalkback(mCurrentUserId); if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) { - performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */ - false, /* reason = */ + performHapticFeedback(HapticFeedbackConstants.CONFIRM, "Stem primary - Triple Press - Toggle Accessibility"); } break; @@ -1771,7 +1769,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void run() { mEndCallKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, "End Call - Long Press - Show Global Actions"); showGlobalActionsInternal(); } @@ -2087,8 +2085,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return; } mHomeConsumed = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, - "Home - Long Press"); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, "Home - Long Press"); switch (mLongPressOnHomeBehavior) { case LONG_PRESS_HOME_ALL_APPS: if (mHasFeatureLeanback) { @@ -2530,7 +2527,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS: performHapticFeedback( - HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false, + HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, "Power + Volume Up - Global Actions"); showGlobalActions(); mPowerKeyHandled = true; @@ -5078,8 +5075,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (useHapticFeedback) { - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, - "Virtual Key - Press"); + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, "Virtual Key - Press"); } if (isWakeKey) { @@ -5971,8 +5967,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void setSafeMode(boolean safeMode) { mSafeMode = safeMode; if (safeMode) { - performHapticFeedback(HapticFeedbackConstants.SAFE_MODE_ENABLED, true, - "Safe Mode Enabled"); + performHapticFeedback(Process.myUid(), mContext.getOpPackageName(), + HapticFeedbackConstants.SAFE_MODE_ENABLED, + "Safe Mode Enabled", HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING, + 0 /* privFlags */); } } @@ -6441,9 +6439,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Global.THEATER_MODE_ON, 0) == 1; } - private boolean performHapticFeedback(int effectId, boolean always, String reason) { + private boolean performHapticFeedback(int effectId, String reason) { return performHapticFeedback(Process.myUid(), mContext.getOpPackageName(), - effectId, always, reason, false /* fromIme */); + effectId, reason, 0 /* flags */, 0 /* privFlags */); } @Override @@ -6452,8 +6450,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public boolean performHapticFeedback(int uid, String packageName, int effectId, - boolean always, String reason, boolean fromIme) { + public boolean performHapticFeedback(int uid, String packageName, int effectId, String reason, + int flags, int privFlags) { if (!mVibrator.hasVibrator()) { return false; } @@ -6464,7 +6462,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } VibrationAttributes attrs = mHapticFeedbackVibrationProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ always, fromIme); + effectId, flags, privFlags); 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 6c05d70f8513..1b394f65c5eb 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -80,6 +80,7 @@ import android.os.RemoteException; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.Display; +import android.view.HapticFeedbackConstants; import android.view.IDisplayFoldListener; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; @@ -1079,7 +1080,8 @@ 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 fromIme); + String reason, @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags); /** * 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 8138168f609e..98a2ba0d62cf 100644 --- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java +++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java @@ -186,13 +186,13 @@ public final class HapticFeedbackVibrationProvider { * * @param effectId the haptic feedback effect ID whose respective vibration attributes we want * 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. + * @param flags Additional flags as per {@link HapticFeedbackConstants}. + * @param privFlags Additional private flags as per {@link HapticFeedbackConstants}. * @return the {@link VibrationAttributes} that should be used for the provided haptic feedback. */ - public VibrationAttributes getVibrationAttributesForHapticFeedback( - int effectId, boolean bypassVibrationIntensitySetting, boolean fromIme) { + public VibrationAttributes getVibrationAttributesForHapticFeedback(int effectId, + @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags) { VibrationAttributes attrs; switch (effectId) { case HapticFeedbackConstants.EDGE_SQUEEZE: @@ -208,7 +208,7 @@ public final class HapticFeedbackVibrationProvider { break; case HapticFeedbackConstants.KEYBOARD_TAP: case HapticFeedbackConstants.KEYBOARD_RELEASE: - attrs = createKeyboardVibrationAttributes(fromIme); + attrs = createKeyboardVibrationAttributes(privFlags); break; case HapticFeedbackConstants.BIOMETRIC_CONFIRM: case HapticFeedbackConstants.BIOMETRIC_REJECT: @@ -218,18 +218,23 @@ public final class HapticFeedbackVibrationProvider { attrs = TOUCH_VIBRATION_ATTRIBUTES; } - int flags = 0; + int vibFlags = 0; + boolean fromIme = + (privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) != 0; + boolean bypassVibrationIntensitySetting = + (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0; if (bypassVibrationIntensitySetting) { - flags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; + vibFlags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; } if (shouldBypassInterruptionPolicy(effectId)) { - flags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; + vibFlags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; } if (shouldBypassIntensityScale(effectId, fromIme)) { - flags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; + vibFlags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE; } - return flags == 0 ? attrs : new VibrationAttributes.Builder(attrs).setFlags(flags).build(); + return vibFlags == 0 ? attrs : new VibrationAttributes.Builder(attrs) + .setFlags(vibFlags).build(); } /** @@ -373,12 +378,16 @@ public final class HapticFeedbackVibrationProvider { return false; } - 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) { + private VibrationAttributes createKeyboardVibrationAttributes( + @HapticFeedbackConstants.PrivateFlags int privFlags) { + // Use touch attribute when the keyboard category is disable. + if (!Flags.keyboardCategoryEnabled()) { + return TOUCH_VIBRATION_ATTRIBUTES; + } + // Use touch attribute when the haptic is not apply to IME. + if ((privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) == 0) { return TOUCH_VIBRATION_ATTRIBUTES; } - return new VibrationAttributes.Builder(TOUCH_VIBRATION_ATTRIBUTES) .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .build(); diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 5c15ccb55c65..4437a2ddf3a7 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -65,6 +65,7 @@ import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; +import android.view.HapticFeedbackConstants; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -439,13 +440,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @Override // Binder call public void performHapticFeedback(int uid, int deviceId, String opPkg, int constant, - boolean always, String reason, boolean fromIme) { + String reason, int flags, int privFlags) { // 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, fromIme); + performHapticFeedbackInternal(uid, deviceId, opPkg, constant, reason, /* token= */ + this, flags, privFlags); } /** @@ -456,8 +457,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @VisibleForTesting @Nullable HalVibration performHapticFeedbackInternal( - int uid, int deviceId, String opPkg, int constant, boolean always, String reason, - IBinder token, boolean fromIme) { + int uid, int deviceId, String opPkg, int constant, String reason, + IBinder token, int flags, int privFlags) { HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider(); if (hapticVibrationProvider == null) { Slog.e(TAG, "performHapticFeedback; haptic vibration provider not ready."); @@ -474,9 +475,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return null; } CombinedVibration vib = CombinedVibration.createParallel(effect); - VibrationAttributes attrs = - hapticVibrationProvider.getVibrationAttributesForHapticFeedback( - constant, /* bypassVibrationIntensitySetting= */ always, fromIme); + VibrationAttributes attrs = hapticVibrationProvider.getVibrationAttributesForHapticFeedback( + constant, flags, privFlags); reason = "performHapticFeedback(constant=" + constant + "): " + reason; VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant); return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, vib, attrs, reason, token); @@ -2295,10 +2295,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { IBinder deathBinder = commonOptions.background ? VibratorManagerService.this : mShellCallbacksToken; + int flags = commonOptions.force + ? HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING : 0; HalVibration vib = performHapticFeedbackInternal(Binder.getCallingUid(), Context.DEVICE_ID_DEFAULT, SHELL_PACKAGE_NAME, constant, - /* always= */ commonOptions.force, /* reason= */ commonOptions.description, - deathBinder, false /* fromIme */); + /* reason= */ commonOptions.description, deathBinder, flags, /* privFlags */ 0); 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 f5108f5bc93f..c26684f60731 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -324,19 +324,19 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } @Override - public boolean performHapticFeedback(int effectId, boolean always, boolean fromIme) { + public boolean performHapticFeedback(int effectId, int flags, int privFlags) { final long ident = Binder.clearCallingIdentity(); try { - return mService.mPolicy.performHapticFeedback(mUid, mPackageName, - effectId, always, null, fromIme); + return mService.mPolicy.performHapticFeedback(mUid, mPackageName, effectId, null, flags, + privFlags); } finally { Binder.restoreCallingIdentity(ident); } } @Override - public void performHapticFeedbackAsync(int effectId, boolean always, boolean fromIme) { - performHapticFeedback(effectId, always, fromIme); + public void performHapticFeedbackAsync(int effectId, int flags, int privFlags) { + performHapticFeedback(effectId, flags, privFlags); } /* 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 633a3c985b7f..901c0361092f 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java @@ -54,6 +54,7 @@ import android.os.vibrator.Flags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.AtomicFile; import android.util.SparseArray; +import android.view.HapticFeedbackConstants; import androidx.test.InstrumentationRegistry; @@ -292,7 +293,7 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : BIOMETRIC_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, /* fromIme= */ false); + effectId, /* flags */ 0, /* privFlags */ 0); assertThat(attrs.getUsage()).isEqualTo(VibrationAttributes.USAGE_COMMUNICATION_REQUEST); } } @@ -302,8 +303,7 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ false, - false /* fromIme*/); + SAFE_MODE_ENABLED, /* flags */ 0, /* privFlags */ 0); assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isFalse(); } @@ -313,7 +313,8 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ true, false /* fromIme*/); + SAFE_MODE_ENABLED, + /* flags */ HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING, /* privFlags */ 0); assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isTrue(); } @@ -325,7 +326,7 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/); + effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isTrue(); } @@ -338,7 +339,7 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/); + effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected no FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isFalse(); } @@ -351,7 +352,8 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/); + effectId, /* flags */ 0, + HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); assertWithMessage("Expected no CATEGORY_KEYBOARD for effect " + effectId) @@ -366,7 +368,7 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/); + effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId) @@ -381,7 +383,8 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/); + effectId, /* flags */ 0, + HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId) @@ -398,7 +401,8 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/); + effectId, /* flags */ 0, + HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse(); @@ -414,7 +418,7 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, false /* fromIme*/); + effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected no FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_SCALE)).isFalse(); @@ -430,7 +434,8 @@ public class HapticFeedbackVibrationProviderTest { for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback( - effectId, /* bypassVibrationIntensitySetting= */ false, true /* fromIme*/); + effectId, /* flags */ 0, + HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); 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 18752847910b..ef944dbba3ca 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -2661,9 +2661,10 @@ public class VibratorManagerServiceTest { private HalVibration performHapticFeedbackAndWaitUntilFinished(VibratorManagerService service, int constant, boolean always) throws InterruptedException { - HalVibration vib = - service.performHapticFeedbackInternal(UID, Context.DEVICE_ID_DEFAULT, PACKAGE_NAME, - constant, always, "some reason", service, false /* fromIme */); + HalVibration vib = service.performHapticFeedbackInternal(UID, Context.DEVICE_ID_DEFAULT, + PACKAGE_NAME, constant, "some reason", service, + always ? HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING : 0 /* flags */, + 0 /* privFlags */); 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 38ad9a7e0dca..4b0668f7a056 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -270,8 +270,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public boolean performHapticFeedback(int uid, String packageName, int effectId, - boolean always, String reason, boolean fromIme) { + public boolean performHapticFeedback(int uid, String packageName, int effectId, String reason, + int flags, int privFlags) { return false; } |