Apply VIBRATE_ON settings in vibrator service
Apply main switch toggle from "Vibration & haptics" settings screeen to
disable all vibrations except for accessibility usage and the ones with
bypass flag (e.g. broadcasted alers from CellBroadcastAlertAudio.
Fix: 30028435
Test: VibrationSettingsTest
Change-Id: Ia8a0e5e952ce2e1055b6c63fc5801546b635d39a
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index fbe2170..2f2158d 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -97,7 +97,7 @@
optional int32 status = 6;
}
-// Next id: 24
+// Next id: 25
message VibratorManagerServiceDumpProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
repeated int32 vibrator_ids = 1;
@@ -106,6 +106,7 @@
optional VibrationProto current_external_vibration = 4;
optional bool vibrator_under_external_control = 5;
optional bool low_power_mode = 6;
+ optional bool vibrate_on = 24;
optional int32 alarm_intensity = 18;
optional int32 alarm_default_intensity = 19;
optional int32 haptic_feedback_intensity = 7;
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index c54d490..6c5d952 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -97,6 +97,15 @@
USAGE_ALARM,
USAGE_COMMUNICATION_REQUEST));
+ /**
+ * Usage allowed for vibrations when {@link Settings.System#VIBRATE_ON} is disabled.
+ *
+ * <p>The only allowed usage is accessibility, which is applied when the user enables talkback.
+ * Other usages that must ignore this setting should use
+ * {@link VibrationAttributes#FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF}.
+ */
+ private static final int VIBRATE_ON_DISABLED_USAGE_ALLOWED = USAGE_ACCESSIBILITY;
+
/** Listener for changes on vibration settings. */
interface OnVibratorSettingsChanged {
/** Callback triggered when any of the vibrator settings change. */
@@ -127,6 +136,8 @@
private SparseIntArray mCurrentVibrationIntensities = new SparseIntArray();
@GuardedBy("mLock")
private boolean mBatterySaverMode;
+ @GuardedBy("mLock")
+ private boolean mVibrateOn;
VibrationSettings(Context context, Handler handler) {
this(context, handler, new VibrationConfig(context.getResources()));
@@ -199,6 +210,7 @@
// Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
+ registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_ON));
registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
registerSettingsObserver(Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER));
registerSettingsObserver(Settings.System.getUriFor(
@@ -314,11 +326,14 @@
return Vibration.Status.IGNORED_FOR_POWER;
}
- int intensity = getCurrentIntensity(usage);
- if ((intensity == Vibrator.VIBRATION_INTENSITY_OFF)
- && !attrs.isFlagSet(
- VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) {
- return Vibration.Status.IGNORED_FOR_SETTINGS;
+ if (!attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) {
+ if (!mVibrateOn && (VIBRATE_ON_DISABLED_USAGE_ALLOWED != usage)) {
+ return Vibration.Status.IGNORED_FOR_SETTINGS;
+ }
+
+ if (getCurrentIntensity(usage) == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return Vibration.Status.IGNORED_FOR_SETTINGS;
+ }
}
if (!shouldVibrateForRingerModeLocked(usage)) {
@@ -357,6 +372,7 @@
void updateSettings() {
synchronized (mLock) {
mVibrateInputDevices = loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
+ mVibrateOn = loadSystemSetting(Settings.System.VIBRATE_ON, 1) > 0;
int alarmIntensity = toIntensity(
loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1),
@@ -437,8 +453,9 @@
+ "mVibratorConfig=" + mVibrationConfig
+ ", mVibrateInputDevices=" + mVibrateInputDevices
+ ", mBatterySaverMode=" + mBatterySaverMode
- + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
+ + ", mVibrateOn=" + mVibrateOn
+ ", mVibrationIntensities=" + vibrationIntensitiesString
+ + ", mProcStatesCache=" + mUidObserver.mProcStatesCache
+ '}';
}
}
@@ -446,6 +463,8 @@
/** Write current settings into given {@link ProtoOutputStream}. */
public void dumpProto(ProtoOutputStream proto) {
synchronized (mLock) {
+ proto.write(VibratorManagerServiceDumpProto.VIBRATE_ON, mVibrateOn);
+ proto.write(VibratorManagerServiceDumpProto.LOW_POWER_MODE, mBatterySaverMode);
proto.write(VibratorManagerServiceDumpProto.ALARM_INTENSITY,
getCurrentIntensity(USAGE_ALARM));
proto.write(VibratorManagerServiceDumpProto.ALARM_DEFAULT_INTENSITY,
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 2c22419..5d4ffbb 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -319,6 +319,34 @@
}
}
+
+ @Test
+ public void shouldIgnoreVibration_vibrateOnDisabled_ignoresUsagesNotAccessibility() {
+ setUserSetting(Settings.System.VIBRATE_ON, 0);
+
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_ACCESSIBILITY) {
+ assertVibrationNotIgnoredForUsage(usage);
+ } else {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ }
+ assertVibrationNotIgnoredForUsageAndFlags(usage,
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF);
+ }
+ }
+
+ @Test
+ public void shouldIgnoreVibration_vibrateOnEnabledOrUnset_allowsAnyUsage() {
+ deleteUserSetting(Settings.System.VIBRATE_ON);
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+
+ setUserSetting(Settings.System.VIBRATE_ON, 1);
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
@Test
public void shouldIgnoreVibration_withRingSettingsOff_disableRingtoneVibrations() {
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
@@ -560,10 +588,17 @@
when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
}
+ private void deleteUserSetting(String settingName) {
+ Settings.System.putStringForUser(
+ mContextSpy.getContentResolver(), settingName, null, UserHandle.USER_CURRENT);
+ // FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
+ mVibrationSettings.updateSettings();
+ }
+
private void setUserSetting(String settingName, int value) {
Settings.System.putIntForUser(
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
- // FakeSettingsProvider don't support testing triggering ContentObserver yet.
+ // FakeSettingsProvider doesn't support testing triggering ContentObserver yet.
mVibrationSettings.updateSettings();
}