summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lais Andrade <lsandrade@google.com> 2022-01-19 17:24:40 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-19 17:24:40 +0000
commit41fd16dfb790d048ed70c984f195f810af10bbac (patch)
tree01672eebdf30a28e224dbef445dd2dbd9ae12702
parentcfb5200a1bb4315bb1921477ebc13947665263c0 (diff)
parenta01a1f6993558249df3d74bffd4561c9fc7a1c1f (diff)
Merge "Deprecate boolean settings for haptic feedback and vibrate when ringing"
-rw-r--r--core/api/current.txt6
-rw-r--r--core/java/android/os/VibrationAttributes.java20
-rw-r--r--core/java/android/provider/Settings.java10
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java4
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java9
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java40
-rw-r--r--core/java/com/android/internal/widget/SlidingTab.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt53
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadKey.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java39
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java6
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java16
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationScaler.java18
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java4
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java22
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java27
22 files changed, 162 insertions, 196 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 3234e162e5fa..83abc07751c5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -36231,7 +36231,7 @@ package android.provider {
field public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
field public static final String END_BUTTON_BEHAVIOR = "end_button_behavior";
field public static final String FONT_SCALE = "font_scale";
- field public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+ field @Deprecated public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
field @Deprecated public static final String HTTP_PROXY = "http_proxy";
field @Deprecated public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field @Deprecated public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
@@ -36275,7 +36275,7 @@ package android.provider {
field public static final String USER_ROTATION = "user_rotation";
field @Deprecated public static final String USE_GOOGLE_MAIL = "use_google_mail";
field public static final String VIBRATE_ON = "vibrate_on";
- field public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+ field @Deprecated public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
field @Deprecated public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";
field @Deprecated public static final String WALLPAPER_ACTIVITY = "wallpaper_activity";
field @Deprecated public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
@@ -48473,7 +48473,7 @@ package android.view {
field public static final int CLOCK_TICK = 4; // 0x4
field public static final int CONFIRM = 16; // 0x10
field public static final int CONTEXT_CLICK = 6; // 0x6
- field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2
+ field @Deprecated public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2
field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1
field public static final int GESTURE_END = 13; // 0xd
field public static final int GESTURE_START = 12; // 0xc
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 8834725cc3e9..8bc219b7dc57 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -136,6 +136,7 @@ public final class VibrationAttributes implements Parcelable {
*/
@IntDef(prefix = { "FLAG_" }, flag = true, value = {
FLAG_BYPASS_INTERRUPTION_POLICY,
+ FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
})
@Retention(RetentionPolicy.SOURCE)
public @interface Flag{}
@@ -146,10 +147,22 @@ public final class VibrationAttributes implements Parcelable {
public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1;
/**
+ * Flag requesting vibration effect to be played even when user settings are disabling it.
+ *
+ * <p>Flag introduced to represent
+ * {@link android.view.HapticFeedbackConstants#FLAG_IGNORE_GLOBAL_SETTING} and
+ * {@link AudioAttributes#FLAG_BYPASS_MUTE}.
+ *
+ * @hide
+ */
+ public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF = 0x2;
+
+ /**
* All flags supported by vibrator service, update it when adding new flag.
* @hide
*/
- public static final int FLAG_ALL_SUPPORTED = FLAG_BYPASS_INTERRUPTION_POLICY;
+ public static final int FLAG_ALL_SUPPORTED =
+ FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
/** Creates a new {@link VibrationAttributes} instance with given usage. */
public static @NonNull VibrationAttributes createForUsage(int usage) {
@@ -397,6 +410,11 @@ public final class VibrationAttributes implements Parcelable {
if ((audio.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
mFlags |= FLAG_BYPASS_INTERRUPTION_POLICY;
}
+ if ((audio.getAllFlags() & AudioAttributes.FLAG_BYPASS_MUTE) != 0) {
+ // Muted audio stream translates to vibration usage having the value
+ // Vibrator.VIBRATION_INTENSITY_OFF set in the user setting.
+ mFlags |= FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
+ }
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5cdb1fdf64ce..a50f38e73136 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5120,7 +5120,12 @@ public final class Settings {
* It was about AudioManager's setting and thus affected all the applications which
* relied on the setting, while this is purely about the vibration setting for incoming
* calls.
+ *
+ * @deprecated Replaced by using {@link android.os.VibrationAttributes#USAGE_RINGTONE} on
+ * vibrations for incoming calls. User settings are applied automatically by the service and
+ * should not be applied by individual apps.
*/
+ @Deprecated
@Readable
public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
@@ -5181,7 +5186,12 @@ public final class Settings {
/**
* Whether haptic feedback (Vibrate on tap) is enabled. The value is
* boolean (1 or 0).
+ *
+ * @deprecated Replaced by using {@link android.os.VibrationAttributes#USAGE_TOUCH} on
+ * vibrations. User settings are applied automatically by the service and should not be
+ * applied by individual apps.
*/
+ @Deprecated
@Readable
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index c5bc99d042d7..45b65e551305 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -177,6 +177,10 @@ public class HapticFeedbackConstants {
* Flag for {@link View#performHapticFeedback(int, int)
* View.performHapticFeedback(int, int)}: Ignore the global setting
* for whether to perform haptic feedback, do it always.
+ *
+ * @deprecated Starting from {@link android.os.Build.VERSION_CODES#TIRAMISU} only privileged
+ * apps can ignore user settings for touch feedback.
*/
+ @Deprecated
public static final int FLAG_IGNORE_GLOBAL_SETTING = 0x0002;
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f91776eaf259..f8ccde4cf4d9 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1028,15 +1028,6 @@ public class LockPatternUtils {
}
/**
- * @return Whether tactile feedback for the pattern is enabled.
- */
- @UnsupportedAppUsage
- public boolean isTactileFeedbackEnabled() {
- return Settings.System.getIntForUser(mContentResolver,
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
- }
-
- /**
* Set and store the lockout deadline, meaning the user can't attempt their unlock
* pattern until the deadline has passed.
* @return the chosen deadline.
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 3994fbdca2df..2b6b933c6886 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -139,7 +139,6 @@ public class LockPatternView extends View {
private boolean mInputEnabled = true;
@UnsupportedAppUsage
private boolean mInStealthMode = false;
- private boolean mEnableHapticFeedback = true;
@UnsupportedAppUsage
private boolean mPatternInProgress = false;
private boolean mFadePattern = true;
@@ -401,13 +400,6 @@ public class LockPatternView extends View {
}
/**
- * @return Whether the view has tactile feedback enabled.
- */
- public boolean isTactileFeedbackEnabled() {
- return mEnableHapticFeedback;
- }
-
- /**
* Set whether the view is in stealth mode. If true, there will be no
* visible feedback as the user enters the pattern.
*
@@ -427,17 +419,6 @@ public class LockPatternView extends View {
}
/**
- * Set whether the view will use tactile feedback. If true, there will be
- * tactile feedback as the user enters the pattern.
- *
- * @param tactileFeedbackEnabled Whether tactile feedback is enabled
- */
- @UnsupportedAppUsage
- public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) {
- mEnableHapticFeedback = tactileFeedbackEnabled;
- }
-
- /**
* Set the call back for pattern detection.
* @param onPatternListener The call back.
*/
@@ -783,11 +764,9 @@ public class LockPatternView extends View {
addCellToPattern(fillInGapCell);
}
addCellToPattern(cell);
- if (mEnableHapticFeedback) {
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
- | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
+ | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
return cell;
}
return null;
@@ -1462,7 +1441,7 @@ public class LockPatternView extends View {
return new SavedState(superState,
patternString,
mPatternDisplayMode.ordinal(),
- mInputEnabled, mInStealthMode, mEnableHapticFeedback);
+ mInputEnabled, mInStealthMode);
}
@Override
@@ -1475,7 +1454,6 @@ public class LockPatternView extends View {
mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
mInputEnabled = ss.isInputEnabled();
mInStealthMode = ss.isInStealthMode();
- mEnableHapticFeedback = ss.isTactileFeedbackEnabled();
}
/**
@@ -1487,20 +1465,18 @@ public class LockPatternView extends View {
private final int mDisplayMode;
private final boolean mInputEnabled;
private final boolean mInStealthMode;
- private final boolean mTactileFeedbackEnabled;
/**
* Constructor called from {@link LockPatternView#onSaveInstanceState()}
*/
@UnsupportedAppUsage
private SavedState(Parcelable superState, String serializedPattern, int displayMode,
- boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
+ boolean inputEnabled, boolean inStealthMode) {
super(superState);
mSerializedPattern = serializedPattern;
mDisplayMode = displayMode;
mInputEnabled = inputEnabled;
mInStealthMode = inStealthMode;
- mTactileFeedbackEnabled = tactileFeedbackEnabled;
}
/**
@@ -1513,7 +1489,6 @@ public class LockPatternView extends View {
mDisplayMode = in.readInt();
mInputEnabled = (Boolean) in.readValue(null);
mInStealthMode = (Boolean) in.readValue(null);
- mTactileFeedbackEnabled = (Boolean) in.readValue(null);
}
public String getSerializedPattern() {
@@ -1532,10 +1507,6 @@ public class LockPatternView extends View {
return mInStealthMode;
}
- public boolean isTactileFeedbackEnabled(){
- return mTactileFeedbackEnabled;
- }
-
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
@@ -1543,7 +1514,6 @@ public class LockPatternView extends View {
dest.writeInt(mDisplayMode);
dest.writeValue(mInputEnabled);
dest.writeValue(mInStealthMode);
- dest.writeValue(mTactileFeedbackEnabled);
}
@SuppressWarnings({ "unused", "hiding" }) // Found using reflection
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index 5e6f3a46de7d..11566d9a026d 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -22,10 +22,9 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.media.AudioAttributes;
-import android.os.UserHandle;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
import android.os.Vibrator;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
@@ -68,10 +67,8 @@ public class SlidingTab extends ViewGroup {
private boolean mHoldLeftOnTransition = true;
private boolean mHoldRightOnTransition = true;
- private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
+ private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
private OnTriggerListener mOnTriggerListener;
private int mGrabbedState = OnTriggerListener.NO_HANDLE;
@@ -834,16 +831,12 @@ public class SlidingTab extends ViewGroup {
* Triggers haptic feedback.
*/
private synchronized void vibrate(long duration) {
- final boolean hapticEnabled = Settings.System.getIntForUser(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
- UserHandle.USER_CURRENT) != 0;
- if (hapticEnabled) {
- if (mVibrator == null) {
- mVibrator = (android.os.Vibrator) getContext()
- .getSystemService(Context.VIBRATOR_SERVICE);
- }
- mVibrator.vibrate(duration, VIBRATION_ATTRIBUTES);
+ if (mVibrator == null) {
+ mVibrator = getContext().getSystemService(Vibrator.class);
}
+ mVibrator.vibrate(
+ VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE),
+ TOUCH_VIBRATION_ATTRIBUTES);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt
index 9e012598554b..aac1d0626d30 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt
@@ -17,13 +17,10 @@ package com.android.wm.shell.common.magnetictarget
import android.annotation.SuppressLint
import android.content.Context
-import android.database.ContentObserver
import android.graphics.PointF
-import android.os.Handler
-import android.os.UserHandle
+import android.os.VibrationAttributes
import android.os.VibrationEffect
import android.os.Vibrator
-import android.provider.Settings
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
@@ -147,6 +144,8 @@ abstract class MagnetizedObject<T : Any>(
private val velocityTracker: VelocityTracker = VelocityTracker.obtain()
private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+ private val vibrationAttributes: VibrationAttributes = VibrationAttributes.createForUsage(
+ VibrationAttributes.USAGE_TOUCH)
private var touchDown = PointF()
private var touchSlop = 0
@@ -268,10 +267,6 @@ abstract class MagnetizedObject<T : Any>(
*/
var flungIntoTargetSpringConfig = springConfig
- init {
- initHapticSettingObserver(context)
- }
-
/**
* Adds the provided MagneticTarget to this object. The object will now be attracted to the
* target if it strays within its magnetic field or is flung towards it.
@@ -468,8 +463,8 @@ abstract class MagnetizedObject<T : Any>(
/** Plays the given vibration effect if haptics are enabled. */
@SuppressLint("MissingPermission")
private fun vibrateIfEnabled(effectId: Int) {
- if (hapticsEnabled && systemHapticsEnabled) {
- vibrator.vibrate(VibrationEffect.createPredefined(effectId))
+ if (hapticsEnabled) {
+ vibrator.vibrate(VibrationEffect.createPredefined(effectId), vibrationAttributes)
}
}
@@ -622,44 +617,6 @@ abstract class MagnetizedObject<T : Any>(
}
companion object {
-
- /**
- * Whether the HAPTIC_FEEDBACK_ENABLED setting is true.
- *
- * We put it in the companion object because we need to register a settings observer and
- * [MagnetizedObject] doesn't have an obvious lifecycle so we don't have a good time to
- * remove that observer. Since this settings is shared among all instances we just let all
- * instances read from this value.
- */
- private var systemHapticsEnabled = false
- private var hapticSettingObserverInitialized = false
-
- private fun initHapticSettingObserver(context: Context) {
- if (hapticSettingObserverInitialized) {
- return
- }
-
- val hapticSettingObserver =
- object : ContentObserver(Handler.getMain()) {
- override fun onChange(selfChange: Boolean) {
- systemHapticsEnabled =
- Settings.System.getIntForUser(
- context.contentResolver,
- Settings.System.HAPTIC_FEEDBACK_ENABLED,
- 0,
- UserHandle.USER_CURRENT) != 0
- }
- }
-
- context.contentResolver.registerContentObserver(
- Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED),
- true /* notifyForDescendants */, hapticSettingObserver)
-
- // Trigger the observer once to initialize systemHapticsEnabled.
- hapticSettingObserver.onChange(false /* selfChange */)
- hapticSettingObserverInitialized = true
- }
-
/**
* Magnetizes the given view. Magnetized views are attracted to one or more magnetic
* targets. Magnetic targets attract objects that are dragged near them, and hold them there
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index cc6df45c598f..d02b8752469a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -30,7 +30,6 @@ import com.android.systemui.R;
*/
public abstract class KeyguardAbsKeyInputView extends KeyguardInputView {
protected View mEcaView;
- protected boolean mEnableHaptics;
// To avoid accidental lockout due to events while the device in in the pocket, ignore
// any passwords with length less than or equal to this length.
@@ -45,10 +44,6 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView {
super(context, attrs);
}
- void setEnableHaptics(boolean enableHaptics) {
- mEnableHaptics = enableHaptics;
- }
-
protected abstract int getPasswordTextViewId();
protected abstract void resetState();
@@ -80,11 +75,9 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView {
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
- if (mEnableHaptics) {
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
- | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
+ | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
public void setKeyDownListener(KeyDownListener keyDownListener) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 1c4559eb0364..f86d08de87fc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -98,7 +98,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
protected void onViewAttached() {
super.onViewAttached();
mView.setKeyDownListener(mKeyDownListener);
- mView.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
mEmergencyButtonController.setEmergencyButtonCallback(mEmergencyButtonCallback);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 94e07b713915..238acd5db621 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -224,8 +224,6 @@ public class KeyguardPatternViewController
mLockPatternView.setSaveEnabled(false);
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
KeyguardUpdateMonitor.getCurrentUser()));
- // vibrate mode will be the same for the life of this screen
- mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
mLockPatternView.setOnTouchListener((v, event) -> {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mFalsingCollector.avoidGesture();
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index e79ea9a44843..a5a3f80d07b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -213,10 +213,8 @@ public class NumPadKey extends ViewGroup {
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
- if (mLockPatternUtils.isTactileFeedbackEnabled()) {
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
- | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
+ | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
index ab8162f9464d..11498dbc0b83 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
@@ -107,6 +107,5 @@ public class AuthCredentialPatternView extends AuthCredentialView {
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
mLockPatternView.setInStealthMode(
!mLockPatternUtils.isVisiblePatternEnabled(mUserId));
- mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index ea90bdd940a7..6c3a9093fa98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -17,14 +17,10 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.database.ContentObserver;
-import android.media.AudioAttributes;
import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.UserHandle;
+import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
-import android.provider.Settings;
import com.android.systemui.dagger.SysUISingleton;
@@ -37,19 +33,8 @@ public class VibratorHelper {
private final Vibrator mVibrator;
private final Context mContext;
- private boolean mHapticFeedbackEnabled;
- private static final AudioAttributes STATUS_BAR_VIBRATION_ATTRIBUTES =
- new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
-
- final private ContentObserver mVibrationObserver = new ContentObserver(Handler.getMain()) {
- @Override
- public void onChange(boolean selfChange) {
- updateHapticFeedBackEnabled();
- }
- };
+ private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
/**
*/
@@ -57,23 +42,11 @@ public class VibratorHelper {
public VibratorHelper(Context context) {
mContext = context;
mVibrator = context.getSystemService(Vibrator.class);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED), true,
- mVibrationObserver);
- mVibrationObserver.onChange(false /* selfChange */);
}
public void vibrate(final int effectId) {
- if (mHapticFeedbackEnabled) {
- AsyncTask.execute(() ->
- mVibrator.vibrate(VibrationEffect.get(effectId, false /* fallback */),
- STATUS_BAR_VIBRATION_ATTRIBUTES));
- }
- }
-
- private void updateHapticFeedBackEnabled() {
- mHapticFeedbackEnabled = Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) != 0;
+ AsyncTask.execute(() ->
+ mVibrator.vibrate(VibrationEffect.get(effectId, false /* fallback */),
+ TOUCH_VIBRATION_ATTRIBUTES));
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 57ae36ed906b..0ea936e35a37 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4384,12 +4384,6 @@ public class AudioService extends IAudioService.Stub
if (!mHasVibrator) {
return false;
}
- final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
- if (hapticsDisabled) {
- return false;
- }
-
if (effect == null) {
return false;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 28f65cf6d1a0..7dd942507a16 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5401,18 +5401,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!mVibrator.hasVibrator()) {
return false;
}
- final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
- if (hapticsDisabled && !always) {
- return false;
- }
-
VibrationEffect effect = getVibrationEffect(effectId);
if (effect == null) {
return false;
}
-
- mVibrator.vibrate(uid, packageName, effect, reason, getVibrationAttributes(effectId));
+ VibrationAttributes attrs = getVibrationAttributes(effectId);
+ if (always) {
+ attrs = new VibrationAttributes.Builder(attrs)
+ .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
+ .build();
+ }
+ mVibrator.vibrate(uid, packageName, effect, reason, attrs);
return true;
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java
index f481772d7a7f..a528f063e875 100644
--- a/services/core/java/com/android/server/vibrator/VibrationScaler.java
+++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java
@@ -74,6 +74,12 @@ final class VibrationScaler {
public int getExternalVibrationScale(int usageHint) {
int defaultIntensity = mSettingsController.getDefaultIntensity(usageHint);
int currentIntensity = mSettingsController.getCurrentIntensity(usageHint);
+
+ if (currentIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ // Bypassing user settings, or it has changed between checking and scaling. Use default.
+ return SCALE_NONE;
+ }
+
int scaleLevel = currentIntensity - defaultIntensity;
if (scaleLevel >= SCALE_VERY_LOW && scaleLevel <= SCALE_VERY_HIGH) {
@@ -97,6 +103,12 @@ final class VibrationScaler {
public <T extends VibrationEffect> T scale(VibrationEffect effect, int usageHint) {
int defaultIntensity = mSettingsController.getDefaultIntensity(usageHint);
int currentIntensity = mSettingsController.getCurrentIntensity(usageHint);
+
+ if (currentIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ // Bypassing user settings, or it has changed between checking and scaling. Use default.
+ currentIntensity = defaultIntensity;
+ }
+
int newEffectStrength = intensityToEffectStrength(currentIntensity);
effect = effect.applyEffectStrength(newEffectStrength).resolve(mDefaultVibrationAmplitude);
ScaleLevel scale = mScaleLevels.get(currentIntensity - defaultIntensity);
@@ -121,6 +133,12 @@ final class VibrationScaler {
*/
public PrebakedSegment scale(PrebakedSegment prebaked, int usageHint) {
int currentIntensity = mSettingsController.getCurrentIntensity(usageHint);
+
+ if (currentIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ // Bypassing user settings, or it has changed between checking and scaling. Use default.
+ currentIntensity = mSettingsController.getDefaultIntensity(usageHint);
+ }
+
int newEffectStrength = intensityToEffectStrength(currentIntensity);
return prebaked.applyEffectStrength(newEffectStrength);
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index df6ffa2bd009..c54d490b5162 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -315,7 +315,9 @@ final class VibrationSettings {
}
int intensity = getCurrentIntensity(usage);
- if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ if ((intensity == Vibrator.VIBRATION_INTENSITY_OFF)
+ && !attrs.isFlagSet(
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) {
return Vibration.Status.IGNORED_FOR_SETTINGS;
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 27566b301a6e..a95b6c955d63 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -80,6 +80,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private static final boolean DEBUG = false;
private static final VibrationAttributes DEFAULT_ATTRIBUTES =
new VibrationAttributes.Builder().build();
+ private static final int ATTRIBUTES_ALL_BYPASS_FLAGS =
+ VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY
+ | VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
/** Lifecycle responsible for initializing this class at the right system server phases. */
public static class Lifecycle extends SystemService {
@@ -975,12 +978,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
usage = VibrationAttributes.USAGE_TOUCH;
}
int flags = attrs.getFlags();
- if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
+ if ((flags & ATTRIBUTES_ALL_BYPASS_FLAGS) != 0) {
if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
|| hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
|| hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
- // Remove bypass policy flag from attributes if the app does not have permissions.
- flags &= ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+ // Remove bypass flags from attributes if the app does not have permissions.
+ flags &= ~ATTRIBUTES_ALL_BYPASS_FLAGS;
}
}
if ((usage == attrs.getUsage()) && (flags == attrs.getFlags())) {
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
index 6369dbc6b171..81677101c139 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -133,13 +133,14 @@ public class VibrationScalerTest {
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- // Unexpected vibration intensity will be treated as SCALE_NONE.
+ // Vibration setting being bypassed will use default setting and not scale.
assertEquals(IExternalVibratorService.SCALE_NONE,
mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
}
@Test
public void scale_withPrebakedSegment_setsEffectStrengthBasedOnSettings() {
+ setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
PrebakedSegment effect = new PrebakedSegment(VibrationEffect.EFFECT_CLICK,
/* shouldFallback= */ false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
@@ -158,35 +159,33 @@ public class VibrationScalerTest {
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
- // Unexpected intensity setting will be mapped to STRONG.
- assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
+ // Vibration setting being bypassed will use default setting.
+ assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
}
@Test
public void scale_withPrebakedEffect_setsEffectStrengthBasedOnSettings() {
+ setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_LOW);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
VibrationEffect effect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
- PrebakedSegment scaled = getFirstSegment(mVibrationScaler.scale(
- effect, USAGE_NOTIFICATION));
+ PrebakedSegment scaled =
+ getFirstSegment(mVibrationScaler.scale(effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
VIBRATION_INTENSITY_MEDIUM);
- scaled = getFirstSegment(mVibrationScaler.scale(
- effect, USAGE_NOTIFICATION));
+ scaled = getFirstSegment(mVibrationScaler.scale(effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
- scaled = getFirstSegment(mVibrationScaler.scale(
- effect, USAGE_NOTIFICATION));
+ scaled = getFirstSegment(mVibrationScaler.scale(effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
- scaled = getFirstSegment(mVibrationScaler.scale(
- effect, USAGE_NOTIFICATION));
- // Unexpected intensity setting will be mapped to STRONG.
- assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
+ scaled = getFirstSegment(mVibrationScaler.scale(effect, USAGE_NOTIFICATION));
+ // Vibration setting being bypassed will use default setting.
+ assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index ff59d0f22c3c..2c22419d1372 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -330,6 +330,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -363,6 +365,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -376,6 +380,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -389,6 +395,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -402,6 +410,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -419,6 +429,8 @@ public class VibrationSettingsTest {
} else {
assertVibrationNotIgnoredForUsage(usage);
}
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
}
}
@@ -522,9 +534,17 @@ public class VibrationSettingsTest {
}
private void assertVibrationNotIgnoredForUsage(@VibrationAttributes.Usage int usage) {
+ assertVibrationNotIgnoredForUsageAndFlags(usage, /* flags= */ 0);
+ }
+
+ private void assertVibrationNotIgnoredForUsageAndFlags(@VibrationAttributes.Usage int usage,
+ @VibrationAttributes.Flag int flags) {
assertNull(errorMessageForUsage(usage),
mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(usage)));
+ new VibrationAttributes.Builder()
+ .setUsage(usage)
+ .setFlags(flags, VibrationAttributes.FLAG_ALL_SUPPORTED)
+ .build()));
}
private String errorMessageForUsage(int usage) {
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index b0bdaf084b1a..ab86e295e28a 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -1207,6 +1207,33 @@ public class VibratorManagerServiceTest {
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
}
+ @Test
+ public void onExternalVibration_withBypassMuteAudioFlag_ignoresUserSettings() {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+ Vibrator.VIBRATION_INTENSITY_OFF);
+ AudioAttributes audioAttrs = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ALARM)
+ .build();
+ AudioAttributes flaggedAudioAttrs = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ALARM)
+ .setFlags(AudioAttributes.FLAG_BYPASS_MUTE)
+ .build();
+ createSystemReadyService();
+
+ int scale = mExternalVibratorService.onExternalVibrationStart(
+ new ExternalVibration(UID, PACKAGE_NAME, audioAttrs,
+ mock(IExternalVibrationController.class)));
+ assertEquals(IExternalVibratorService.SCALE_MUTE, scale);
+
+ createSystemReadyService();
+ scale = mExternalVibratorService.onExternalVibrationStart(
+ new ExternalVibration(UID, PACKAGE_NAME, flaggedAudioAttrs,
+ mock(IExternalVibrationController.class)));
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
+ }
+
private VibrationEffectSegment expectedPrebaked(int effectId) {
return new PrebakedSegment(effectId, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
}