Introduce alarm and media vibration intensity settings

Introduce toggles and sliders to configure the alarm and media
vibrations in the "Vibration & haptics" settings app.

Also update the multiple intensities configuration flag into a integer,
where the device can specify how many distinct levels are supported.
Follow existing implementation to map the intensities to higher setting
values.

Bug: 198346559
Bug: 207477604
Test: [Alarm|Media]Vibration[Intensity|Toggle]PreferenceControllerTest
Change-Id: Ie3d570b72ba1229e613ecf0c45fac81233529e32
diff --git a/res/values/config.xml b/res/values/config.xml
index fe9f42d..7a2f641 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -197,11 +197,24 @@
     <!-- Whether or not to show the night light suggestion. -->
     <bool name="config_night_light_suggestion_enabled">true</bool>
 
-    <!-- Whether or not the device is capable of multiple levels of vibration intensity.
-         Note that this is different from whether it can control the vibration amplitude as some
-         devices will be able to vary their amplitude but do not possess enough dynamic range to
-         have distinct intensity levels -->
-    <bool name="config_vibration_supports_multiple_intensities">false</bool>
+    <!-- The number of vibration intensity levels supported by the device.
+
+         Note that this should correspond to the ability to vary the vibration amplitude, with
+         enough dynamic range to have at least as many distinct intensity levels as defined here.
+
+         Supported values are 1, 2, 3. If '1', the settings app will use a toggle for the settings,
+         otherwise a slider. If '3', the settings app maps intensities directly to the levels
+         supported by the Vibrator HAL APIs. If '2', then the levels will be mapped to
+         VIBRATION_INTENSITY_LOW and VIBRATION_INTENSITY_HIGH, which gives the most range for
+         scaling vibrations. The medium intensity will be skipped.
+
+         The default intensity values are configured at
+         frameworks/base/core/res/res/values/config.xml's config_default[type]VibrationIntensity.
+         Make sure that each default intensity value is consistent with the supported levels set
+         here. If this settings supports only 2 levels, for example, then the default intensity
+         should be either LOW (1) or HIGH (3).
+    -->
+    <integer name="config_vibration_supported_intensity_levels">1</integer>
 
     <!--
         Whether or not the homepage should be powered by legacy suggestion (versus contextual cards)
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 73a0de8..7520c91 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5457,6 +5457,10 @@
     <string name="accessibility_notification_alarm_vibration_category_title">Notifications and alarms</string>
     <!-- Title for the category of preferences to configure device vibrations triggered by user interaction with the device. [CHAR LIMIT=NONE] -->
     <string name="accessibility_interactive_haptics_category_title">Interactive haptics</string>
+    <!-- Title for preference for configuring alarm vibrations. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_alarm_vibration_title">Alarm vibration</string>
+    <!-- Title for preference for configuring media vibrations (e.g. vibrations played together with animations, music, videos, etc). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_media_vibration_title">Media vibration</string>
     <!-- Title for accessibility preference for configuring ring vibrations. [CHAR LIMIT=NONE] -->
     <string name="accessibility_ring_vibration_title">Ring vibration</string>
     <!-- Title for accessibility preference for configuring notification vibrations. -->
@@ -8238,7 +8242,11 @@
     <!-- List of synonyms for ring vibration setting (changes whether your phone vibrates when it rings), used to match in settings search [CHAR LIMIT=NONE] -->
     <string name="keywords_ramping_ringer_vibration">haptics, vibrate, phone, call, ring, gradually</string>
     <!-- List of synonyms for notification vibration setting (changes whether your phone vibrates when it shows a notification), used to match in settings search [CHAR LIMIT=NONE] -->
-    <string name="keywords_notification_vibration">haptics, vibrate, sensitivity</string>
+    <string name="keywords_notification_vibration">haptics, vibrate, sensitivity, notification</string>
+    <!-- List of synonyms for alarm vibration setting (changes whether your phone vibrates when an alarm goes off), used to match in settings search [CHAR LIMIT=NONE] -->
+    <string name="keywords_alarm_vibration">haptics, vibrate, sensitivity, alarm</string>
+    <!-- List of synonyms for media vibration setting (changes whether your phone vibrates as part of a music, animation, video, etc), used to match in settings search [CHAR LIMIT=NONE] -->
+    <string name="keywords_media_vibration">haptics, vibrate, sensitivity, media</string>
     <!-- List of synonyms for vibration and haptics setting, used to match in settings search [CHAR LIMIT=NONE] -->
     <string name="keywords_vibration">haptics, vibrate, vibration</string>
     <!-- Battery Saver: Search terms for sticky battery saver preference [CHAR_LIMIT=NONE] -->
diff --git a/res/xml/accessibility_vibration_intensity_settings.xml b/res/xml/accessibility_vibration_intensity_settings.xml
index d9a97f0..7982268 100644
--- a/res/xml/accessibility_vibration_intensity_settings.xml
+++ b/res/xml/accessibility_vibration_intensity_settings.xml
@@ -47,6 +47,12 @@
             app:keywords="@string/keywords_notification_vibration"
             app:controller="com.android.settings.accessibility.NotificationVibrationIntensityPreferenceController" />
 
+        <com.android.settings.widget.SeekBarPreference
+            android:key="alarm_vibration_preference_screen"
+            android:title="@string/accessibility_alarm_vibration_title"
+            app:keywords="@string/keywords_alarm_vibration"
+            app:controller="com.android.settings.accessibility.AlarmVibrationIntensityPreferenceController" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
@@ -59,6 +65,12 @@
             app:keywords="@string/keywords_touch_vibration"
             app:controller="com.android.settings.accessibility.HapticFeedbackIntensityPreferenceController" />
 
+        <com.android.settings.widget.SeekBarPreference
+            android:key="media_vibration_preference_screen"
+            android:title="@string/accessibility_media_vibration_title"
+            app:keywords="@string/keywords_media_vibration"
+            app:controller="com.android.settings.accessibility.MediaVibrationIntensityPreferenceController" />
+
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/accessibility_vibration_settings.xml b/res/xml/accessibility_vibration_settings.xml
index 18cd718..af78433 100644
--- a/res/xml/accessibility_vibration_settings.xml
+++ b/res/xml/accessibility_vibration_settings.xml
@@ -47,6 +47,12 @@
             app:keywords="@string/keywords_notification_vibration"
             app:controller="com.android.settings.accessibility.NotificationVibrationTogglePreferenceController" />
 
+        <SwitchPreference
+            android:key="alarm_vibration_preference_screen"
+            android:title="@string/accessibility_alarm_vibration_title"
+            app:keywords="@string/keywords_alarm_vibration"
+            app:controller="com.android.settings.accessibility.AlarmVibrationTogglePreferenceController" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
@@ -59,6 +65,12 @@
             app:keywords="@string/keywords_touch_vibration"
             app:controller="com.android.settings.accessibility.HapticFeedbackTogglePreferenceController" />
 
+        <SwitchPreference
+            android:key="media_vibration_preference_screen"
+            android:title="@string/accessibility_media_vibration_title"
+            app:keywords="@string/keywords_media_vibration"
+            app:controller="com.android.settings.accessibility.MediaVibrationTogglePreferenceController" />
+
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceController.java
new file mode 100644
index 0000000..9e60f21
--- /dev/null
+++ b/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceController.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.provider.Settings;
+
+/** Preference controller for alarm vibration intensity */
+public class AlarmVibrationIntensityPreferenceController
+        extends VibrationIntensityPreferenceController {
+
+    /** General configuration for alarm vibration intensity settings. */
+    public static final class AlarmVibrationPreferenceConfig extends VibrationPreferenceConfig {
+
+        public AlarmVibrationPreferenceConfig(Context context) {
+            super(context, Settings.System.ALARM_VIBRATION_INTENSITY,
+                    VibrationAttributes.USAGE_ALARM);
+        }
+    }
+
+    public AlarmVibrationIntensityPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey, new AlarmVibrationPreferenceConfig(context));
+    }
+
+    protected AlarmVibrationIntensityPreferenceController(Context context, String preferenceKey,
+            int supportedIntensityLevels) {
+        super(context, preferenceKey, new AlarmVibrationPreferenceConfig(context),
+                supportedIntensityLevels);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceController.java
new file mode 100644
index 0000000..63281dd
--- /dev/null
+++ b/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceController.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+
+import com.android.settings.accessibility.AlarmVibrationIntensityPreferenceController.AlarmVibrationPreferenceConfig;
+
+/** Preference controller for alarm vibration with only a toggle for on/off states. */
+public class AlarmVibrationTogglePreferenceController extends VibrationTogglePreferenceController {
+
+    public AlarmVibrationTogglePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey, new AlarmVibrationPreferenceConfig(context));
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
index 99d2bf5..98fd5f2 100644
--- a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
@@ -74,6 +74,12 @@
         super(context, preferenceKey, new HapticFeedbackVibrationPreferenceConfig(context));
     }
 
+    protected HapticFeedbackIntensityPreferenceController(Context context, String preferenceKey,
+            int supportedIntensityLevels) {
+        super(context, preferenceKey, new HapticFeedbackVibrationPreferenceConfig(context),
+                supportedIntensityLevels);
+    }
+
     @Override
     public int getAvailabilityStatus() {
         return AVAILABLE;
diff --git a/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceController.java
new file mode 100644
index 0000000..0678e58
--- /dev/null
+++ b/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceController.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.provider.Settings;
+
+/** Preference controller for am vibration intensity */
+public class MediaVibrationIntensityPreferenceController
+        extends VibrationIntensityPreferenceController {
+
+    /** General configuration for alarm vibration intensity settings. */
+    public static final class MediaVibrationPreferenceConfig extends VibrationPreferenceConfig {
+
+        public MediaVibrationPreferenceConfig(Context context) {
+            super(context, Settings.System.MEDIA_VIBRATION_INTENSITY,
+                    VibrationAttributes.USAGE_MEDIA);
+        }
+    }
+
+    public MediaVibrationIntensityPreferenceController(Context context,
+            String preferenceKey) {
+        super(context, preferenceKey, new MediaVibrationPreferenceConfig(context));
+    }
+
+    protected MediaVibrationIntensityPreferenceController(Context context, String preferenceKey,
+            int supportedIntensityLevels) {
+        super(context, preferenceKey, new MediaVibrationPreferenceConfig(context),
+                supportedIntensityLevels);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceController.java
new file mode 100644
index 0000000..f7b0e39
--- /dev/null
+++ b/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceController.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+
+import com.android.settings.accessibility.MediaVibrationIntensityPreferenceController.MediaVibrationPreferenceConfig;
+
+/** Preference controller for alarm vibration with only a toggle for on/off states. */
+public class MediaVibrationTogglePreferenceController extends VibrationTogglePreferenceController {
+
+    public MediaVibrationTogglePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey, new MediaVibrationPreferenceConfig(context));
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
index 31ae187..cee45f6 100644
--- a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
@@ -39,6 +39,12 @@
         super(context, preferenceKey, new NotificationVibrationPreferenceConfig(context));
     }
 
+    protected NotificationVibrationIntensityPreferenceController(Context context,
+            String preferenceKey, int supportedIntensityLevels) {
+        super(context, preferenceKey, new NotificationVibrationPreferenceConfig(context),
+                supportedIntensityLevels);
+    }
+
     @Override
     public int getAvailabilityStatus() {
         return AVAILABLE;
diff --git a/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java
index 1ddcf2b..894d818 100644
--- a/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java
@@ -71,6 +71,12 @@
         super(context, preferenceKey, new RingVibrationPreferenceConfig(context));
     }
 
+    protected RingVibrationIntensityPreferenceController(Context context, String preferenceKey,
+            int supportedIntensityLevels) {
+        super(context, preferenceKey, new RingVibrationPreferenceConfig(context),
+                supportedIntensityLevels);
+    }
+
     @Override
     public int getAvailabilityStatus() {
         return AVAILABLE;
diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
index e35b42c..ef15f06 100644
--- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
@@ -21,6 +21,7 @@
 
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -36,13 +37,22 @@
 
     protected final VibrationPreferenceConfig mPreferenceConfig;
     private final VibrationPreferenceConfig.SettingObserver mSettingsContentObserver;
+    private final int mMaxIntensity;
 
     protected VibrationIntensityPreferenceController(Context context, String prefkey,
             VibrationPreferenceConfig preferenceConfig) {
+        this(context, prefkey, preferenceConfig,
+                context.getResources().getInteger(
+                        R.integer.config_vibration_supported_intensity_levels));
+    }
+
+    protected VibrationIntensityPreferenceController(Context context, String prefkey,
+            VibrationPreferenceConfig preferenceConfig, int supportedIntensityLevels) {
         super(context, prefkey);
         mPreferenceConfig = preferenceConfig;
         mSettingsContentObserver = new VibrationPreferenceConfig.SettingObserver(
                 preferenceConfig);
+        mMaxIntensity = Math.min(Vibrator.VIBRATION_INTENSITY_HIGH, supportedIntensityLevels);
     }
 
     @Override
@@ -74,7 +84,7 @@
 
     @Override
     public int getMax() {
-        return Vibrator.VIBRATION_INTENSITY_HIGH;
+        return mMaxIntensity;
     }
 
     @Override
@@ -85,7 +95,8 @@
 
     @Override
     public boolean setSliderPosition(int position) {
-        final boolean success = mPreferenceConfig.updateIntensity(position);
+        final int intensity = calculateVibrationIntensity(position);
+        final boolean success = mPreferenceConfig.updateIntensity(intensity);
 
         if (success && (position != Vibrator.VIBRATION_INTENSITY_OFF)) {
             mPreferenceConfig.playVibrationPreview();
@@ -93,4 +104,19 @@
 
         return success;
     }
+
+    private int calculateVibrationIntensity(int position) {
+        int maxPosition = getMax();
+        if (position >= maxPosition) {
+            if (maxPosition == 1) {
+                // If there is only one intensity available besides OFF, then use the device default
+                // intensity to ensure no scaling will ever happen in the platform.
+                return mPreferenceConfig.getDefaultIntensity();
+            }
+            // If the settings granularity is lower than the platform's then map the max position to
+            // the highest vibration intensity, skipping intermediate values in the scale.
+            return Vibrator.VIBRATION_INTENSITY_HIGH;
+        }
+        return position;
+    }
 }
diff --git a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java
index 4a86538..21a5e36 100644
--- a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java
+++ b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java
@@ -21,7 +21,6 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.VibrationAttributes;
 import android.os.Vibrator;
 import android.provider.DeviceConfig;
@@ -37,8 +36,6 @@
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
 
-import com.google.common.annotations.VisibleForTesting;
-
 /**
  * Preference controller for the ramping ringer setting key, controlled via {@link AudioManager}.
  *
@@ -50,9 +47,15 @@
 public class VibrationRampingRingerTogglePreferenceController
         extends TogglePreferenceController implements LifecycleObserver, OnStart, OnStop {
 
-    @VisibleForTesting
-    static final String DEVICE_CONFIG_KEY = "ramping_ringer_enabled";
+    /** Wrapper around static {@link DeviceConfig} accessor for testing. */
+    protected static class DeviceConfigProvider {
+        public boolean isRampingRingerEnabledOnTelephonyConfig() {
+            return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY,
+                    "ramping_ringer_enabled", false);
+        }
+    }
 
+    private final DeviceConfigProvider mDeviceConfigProvider;
     private final ContentObserver mSettingObserver;
     private final Vibrator mVibrator;
     private final AudioManager mAudioManager;
@@ -60,10 +63,16 @@
     private Preference mPreference;
 
     public VibrationRampingRingerTogglePreferenceController(Context context, String preferenceKey) {
+        this(context, preferenceKey, new DeviceConfigProvider());
+    }
+
+    protected VibrationRampingRingerTogglePreferenceController(Context context,
+            String preferenceKey, DeviceConfigProvider deviceConfigProvider) {
         super(context, preferenceKey);
+        mDeviceConfigProvider = deviceConfigProvider;
         mVibrator = context.getSystemService(Vibrator.class);
         mAudioManager = context.getSystemService(AudioManager.class);
-        mSettingObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+        mSettingObserver = new ContentObserver(new Handler(/* async= */ true)) {
             @Override
             public void onChange(boolean selfChange, Uri uri) {
                 updateState(mPreference);
@@ -74,7 +83,7 @@
     @Override
     public int getAvailabilityStatus() {
         final boolean rampingRingerEnabledOnTelephonyConfig =
-                DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY, DEVICE_CONFIG_KEY, false);
+                mDeviceConfigProvider.isRampingRingerEnabledOnTelephonyConfig();
         return (Utils.isVoiceCapable(mContext) && !rampingRingerEnabledOnTelephonyConfig)
                 ? AVAILABLE
                 : UNSUPPORTED_ON_DEVICE;
diff --git a/src/com/android/settings/accessibility/VibrationSettings.java b/src/com/android/settings/accessibility/VibrationSettings.java
index 277cfee..1bf75f7 100644
--- a/src/com/android/settings/accessibility/VibrationSettings.java
+++ b/src/com/android/settings/accessibility/VibrationSettings.java
@@ -41,9 +41,9 @@
 
     @Override
     protected int getPreferenceScreenResId() {
-        final boolean supportsMultipleIntensities = getContext().getResources().getBoolean(
-                R.bool.config_vibration_supports_multiple_intensities);
-        return supportsMultipleIntensities
+        final int supportedIntensities = getContext().getResources().getInteger(
+                R.integer.config_vibration_supported_intensity_levels);
+        return supportedIntensities > 1
                 ? R.xml.accessibility_vibration_intensity_settings
                 : R.xml.accessibility_vibration_settings;
     }
diff --git a/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceControllerTest.java
new file mode 100644
index 0000000..22e2b8a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationIntensityPreferenceControllerTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AlarmVibrationIntensityPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock private PreferenceScreen mScreen;
+
+    private Lifecycle mLifecycle;
+    private Context mContext;
+    private Vibrator mVibrator;
+    private AlarmVibrationIntensityPreferenceController mController;
+    private SeekBarPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
+        mVibrator = mContext.getSystemService(Vibrator.class);
+        mController = new AlarmVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY,
+                Vibrator.VIBRATION_INTENSITY_HIGH);
+        mLifecycle.addObserver(mController);
+        mPreference = new SeekBarPreference(mContext);
+        mPreference.setSummary("Test summary");
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void verifyConstants() {
+        assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+        assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    @Test
+    public void missingSetting_shouldReturnDefault() {
+        Settings.System.putString(mContext.getContentResolver(),
+                Settings.System.ALARM_VIBRATION_INTENSITY, /* value= */ null);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getProgress()).isEqualTo(
+                mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
+    }
+
+    @Test
+    public void updateState_shouldDisplayIntensityInSliderPosition() {
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+                Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+
+    @Test
+    public void setProgress_updatesIntensitySetting() throws Exception {
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    private void updateSetting(String key, int value) {
+        Settings.System.putInt(mContext.getContentResolver(), key, value);
+    }
+
+    private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceControllerTest.java
new file mode 100644
index 0000000..82d65f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AlarmVibrationTogglePreferenceControllerTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AlarmVibrationTogglePreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock private PreferenceScreen mScreen;
+
+    private Lifecycle mLifecycle;
+    private Context mContext;
+    private Vibrator mVibrator;
+    private AlarmVibrationTogglePreferenceController mController;
+    private SwitchPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
+        mVibrator = mContext.getSystemService(Vibrator.class);
+        mController = new AlarmVibrationTogglePreferenceController(mContext, PREFERENCE_KEY);
+        mLifecycle.addObserver(mController);
+        mPreference = new SwitchPreference(mContext);
+        mPreference.setSummary("Test summary");
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void verifyConstants() {
+        assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void missingSetting_shouldReturnDefault() {
+        Settings.System.putString(mContext.getContentResolver(),
+                Settings.System.ALARM_VIBRATION_INTENSITY, /* value= */ null);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_shouldDisplayOnOffState() {
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+                Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_updatesIntensityAndDependentSettings() throws Exception {
+        updateSetting(Settings.System.ALARM_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+
+        mController.setChecked(true);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY)).isEqualTo(
+                mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
+
+        mController.setChecked(false);
+        assertThat(readSetting(Settings.System.ALARM_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+    private void updateSetting(String key, int value) {
+        Settings.System.putInt(mContext.getContentResolver(), key, value);
+    }
+
+    private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java
index 4e8b3f6..dbd14b0 100644
--- a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -48,10 +46,8 @@
     private static final int OFF = 0;
     private static final int ON = 1;
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -61,16 +57,16 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
-        mController = new HapticFeedbackIntensityPreferenceController(mContext, PREFERENCE_KEY);
+        mController = new HapticFeedbackIntensityPreferenceController(mContext, PREFERENCE_KEY,
+                Vibrator.VIBRATION_INTENSITY_HIGH);
         mLifecycle.addObserver(mController);
         mPreference = new SeekBarPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -113,27 +109,27 @@
 
     @Test
     public void setProgress_updatesIntensityAndDependentSettings() throws Exception {
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF);
@@ -146,8 +142,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java
index 25455f4..cf8371a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 import androidx.test.core.app.ApplicationProvider;
@@ -48,10 +46,8 @@
     private static final int OFF = 0;
     private static final int ON = 1;
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -61,16 +57,15 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
         mController = new HapticFeedbackTogglePreferenceController(mContext, PREFERENCE_KEY);
         mLifecycle.addObserver(mController);
         mPreference = new SwitchPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -114,12 +109,12 @@
         mController.updateState(mPreference);
         assertThat(mPreference.isChecked()).isFalse();
 
-        mPreference.setChecked(true);
+        mController.setChecked(true);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH));
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON);
 
-        mPreference.setChecked(false);
+        mController.setChecked(false);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF);
@@ -132,8 +127,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceControllerTest.java
new file mode 100644
index 0000000..0a9f242
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MediaVibrationIntensityPreferenceControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+/** Test for {@link MediaVibrationIntensityPreferenceController}. */
+@RunWith(RobolectricTestRunner.class)
+public class MediaVibrationIntensityPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock private PreferenceScreen mScreen;
+
+    private Lifecycle mLifecycle;
+    private Context mContext;
+    private Vibrator mVibrator;
+    private MediaVibrationIntensityPreferenceController mController;
+    private SeekBarPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
+        mVibrator = mContext.getSystemService(Vibrator.class);
+        mController = new MediaVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY,
+                Vibrator.VIBRATION_INTENSITY_HIGH);
+        mLifecycle.addObserver(mController);
+        mPreference = new SeekBarPreference(mContext);
+        mPreference.setSummary("Test summary");
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void verifyConstants() {
+        assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+        assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    @Test
+    public void missingSetting_shouldReturnDefault() {
+        Settings.System.putString(mContext.getContentResolver(),
+                Settings.System.MEDIA_VIBRATION_INTENSITY, /* value= */ null);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getProgress()).isEqualTo(
+                mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_MEDIA));
+    }
+
+    @Test
+    public void updateState_shouldDisplayIntensityInSliderPosition() {
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
+                Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+
+    @Test
+    public void setProgress_updatesIntensitySetting() throws Exception {
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    private void updateSetting(String key, int value) {
+        Settings.System.putInt(mContext.getContentResolver(), key, value);
+    }
+
+    private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceControllerTest.java
new file mode 100644
index 0000000..7923cca
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MediaVibrationTogglePreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+/** Test for {@link MediaVibrationIntensityPreferenceController}. */
+@RunWith(RobolectricTestRunner.class)
+public class MediaVibrationTogglePreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock private PreferenceScreen mScreen;
+
+    private Lifecycle mLifecycle;
+    private Context mContext;
+    private Vibrator mVibrator;
+    private MediaVibrationTogglePreferenceController mController;
+    private SwitchPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
+        mVibrator = mContext.getSystemService(Vibrator.class);
+        mController = new MediaVibrationTogglePreferenceController(mContext, PREFERENCE_KEY);
+        mLifecycle.addObserver(mController);
+        mPreference = new SwitchPreference(mContext);
+        mPreference.setSummary("Test summary");
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void verifyConstants() {
+        assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY);
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void missingSetting_shouldReturnDefault() {
+        Settings.System.putString(mContext.getContentResolver(),
+                Settings.System.MEDIA_VIBRATION_INTENSITY, /* value= */ null);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_shouldDisplayOnOffState() {
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
+                Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_updatesIntensityAndDependentSettings() throws Exception {
+        updateSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+
+        mController.setChecked(true);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY)).isEqualTo(
+                mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_MEDIA));
+
+        mController.setChecked(false);
+        assertThat(readSetting(Settings.System.MEDIA_VIBRATION_INTENSITY))
+                .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+    private void updateSetting(String key, int value) {
+        Settings.System.putInt(mContext.getContentResolver(), key, value);
+    }
+
+    private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
index 9dbd6d1..b7b9366 100644
--- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -46,10 +44,8 @@
 
     private static final String PREFERENCE_KEY = "preference_key";
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -59,17 +55,16 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
         mController = new NotificationVibrationIntensityPreferenceController(mContext,
-                PREFERENCE_KEY);
+                PREFERENCE_KEY, Vibrator.VIBRATION_INTENSITY_HIGH);
         mLifecycle.addObserver(mController);
         mPreference = new SeekBarPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -116,19 +111,19 @@
 
     @Test
     public void setProgress_updatesIntensitySetting() throws Exception {
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
     }
@@ -140,8 +135,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java
index d40d779..b786c3d 100644
--- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 import androidx.test.core.app.ApplicationProvider;
@@ -46,10 +44,8 @@
 
     private static final String PREFERENCE_KEY = "preference_key";
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -59,16 +55,15 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
         mController = new NotificationVibrationTogglePreferenceController(mContext, PREFERENCE_KEY);
         mLifecycle.addObserver(mController);
         mPreference = new SwitchPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -116,11 +111,11 @@
         mController.updateState(mPreference);
         assertThat(mPreference.isChecked()).isFalse();
 
-        mPreference.setChecked(true);
+        mController.setChecked(true);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)).isEqualTo(
                 mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION));
 
-        mPreference.setChecked(false);
+        mController.setChecked(false);
         assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
     }
@@ -132,8 +127,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java
index 4e1730e..8863126 100644
--- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -49,10 +47,8 @@
     private static final int OFF = 0;
     private static final int ON = 1;
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -62,16 +58,16 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
-        mController = new RingVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY);
+        mController = new RingVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY,
+                Vibrator.VIBRATION_INTENSITY_HIGH);
         mLifecycle.addObserver(mController);
         mPreference = new SeekBarPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -115,27 +111,27 @@
 
     @Test
     public void setProgress_updatesIntensityAndDependentSettings() throws Exception {
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON);
 
-        mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF);
+        mController.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF);
@@ -148,8 +144,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java
index 2d1c69c..b368494 100644
--- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -26,7 +25,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 import androidx.test.core.app.ApplicationProvider;
@@ -48,10 +46,8 @@
     private static final int OFF = 0;
     private static final int ON = 1;
 
-    @Mock
-    private PreferenceScreen mScreen;
+    @Mock private PreferenceScreen mScreen;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private Vibrator mVibrator;
@@ -61,16 +57,15 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        mContext = spy(ApplicationProvider.getApplicationContext());
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
         mVibrator = mContext.getSystemService(Vibrator.class);
         mController = new RingVibrationTogglePreferenceController(mContext, PREFERENCE_KEY);
         mLifecycle.addObserver(mController);
         mPreference = new SwitchPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -114,12 +109,12 @@
         mController.updateState(mPreference);
         assertThat(mPreference.isChecked()).isFalse();
 
-        mPreference.setChecked(true);
+        mController.setChecked(true);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)).isEqualTo(
                 mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE));
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON);
 
-        mPreference.setChecked(false);
+        mController.setChecked(false);
         assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY))
                 .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
         assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF);
@@ -132,8 +127,4 @@
     private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
         return Settings.System.getInt(mContext.getContentResolver(), settingKey);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityPreferenceControllerTest.java
new file mode 100644
index 0000000..ba48f66
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityPreferenceControllerTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.widget.SeekBarPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class VibrationIntensityPreferenceControllerTest {
+
+    private static final String SETTING_KEY = Settings.System.NOTIFICATION_VIBRATION_INTENSITY;
+    private static final int VIBRATION_USAGE = VibrationAttributes.USAGE_NOTIFICATION;
+
+    /** Basic implementation of preference controller to test generic behavior. */
+    private static class TestPreferenceController extends VibrationIntensityPreferenceController {
+
+        TestPreferenceController(Context context, int supportedIntensityLevels) {
+            super(context, "preference_key",
+                    new VibrationPreferenceConfig(context, SETTING_KEY, VIBRATION_USAGE) {},
+                    supportedIntensityLevels);
+        }
+
+        @Override
+        public int getAvailabilityStatus() {
+            return AVAILABLE;
+        }
+    }
+
+    @Mock private PreferenceScreen mScreen;
+
+    private Lifecycle mLifecycle;
+    private Context mContext;
+    private Vibrator mVibrator;
+    private SeekBarPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mContext = ApplicationProvider.getApplicationContext();
+        mVibrator = mContext.getSystemService(Vibrator.class);
+    }
+
+    @Test
+    public void missingSetting_shouldReturnDefault() {
+        VibrationIntensityPreferenceController controller = createPreferenceController(3);
+        Settings.System.putString(mContext.getContentResolver(), SETTING_KEY, null);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress())
+                .isEqualTo(mVibrator.getDefaultVibrationIntensity(VIBRATION_USAGE));
+    }
+
+    @Test
+    public void updateState_allLevelsSupported_shouldDisplayIntensityInSliderPosition() {
+        VibrationIntensityPreferenceController controller = createPreferenceController(3);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_LOW);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_OFF);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+    @Test
+    public void updateState_twoLevelsSupported_shouldDisplayMediumAndHighAtLastPosition() {
+        VibrationIntensityPreferenceController controller = createPreferenceController(2);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_LOW);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_OFF);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+    @Test
+    public void updateState_oneLevelSupported_shouldDisplayAllAtLastPosition() {
+        VibrationIntensityPreferenceController controller = createPreferenceController(1);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_HIGH);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_LOW);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        updateSetting(SETTING_KEY, Vibrator.VIBRATION_INTENSITY_OFF);
+        controller.updateState(mPreference);
+        assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+    }
+
+    @Test
+    public void setProgress_allSupportedPositions_updatesIntensitySetting() throws Exception {
+        VibrationIntensityPreferenceController controller = createPreferenceController(3);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    @Test
+    public void setProgress_twoSupportedPositions_updatesMediumPositionToHigh() throws Exception {
+        VibrationIntensityPreferenceController controller = createPreferenceController(2);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH);
+    }
+
+    @Test
+    public void setProgress_oneSupportedPosition_updatesOnPositionsToDeviceDefault()
+            throws Exception {
+        int defaultIntensity = mVibrator.getDefaultVibrationIntensity(VIBRATION_USAGE);
+        VibrationIntensityPreferenceController controller = createPreferenceController(1);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_OFF);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_LOW);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(defaultIntensity);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(defaultIntensity);
+
+        controller.setSliderPosition(Vibrator.VIBRATION_INTENSITY_HIGH);
+        assertThat(readSetting(SETTING_KEY)).isEqualTo(defaultIntensity);
+    }
+
+    private void updateSetting(String key, int value) {
+        Settings.System.putInt(mContext.getContentResolver(), key, value);
+    }
+
+    private int readSetting(String settingKey) throws Settings.SettingNotFoundException {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey);
+    }
+
+    private VibrationIntensityPreferenceController createPreferenceController(
+            int supportedIntensityLevels) {
+        VibrationIntensityPreferenceController controller =
+                new TestPreferenceController(mContext, supportedIntensityLevels);
+        mLifecycle.addObserver(controller);
+        mPreference = new SeekBarPreference(mContext);
+        mPreference.setSummary("Test summary");
+        when(mScreen.findPreference(controller.getPreferenceKey())).thenReturn(mPreference);
+        controller.displayPreference(mScreen);
+        return controller;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java
index 08831c8..efd1281 100644
--- a/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java
@@ -30,11 +30,9 @@
 import android.content.Context;
 import android.media.AudioManager;
 import android.os.Vibrator;
-import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 
-import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 import androidx.test.core.app.ApplicationProvider;
@@ -53,14 +51,12 @@
 
     private static final String PREFERENCE_KEY = "preference_key";
 
-    @Mock
-    private PreferenceScreen mScreen;
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private AudioManager mAudioManager;
+    @Mock private PreferenceScreen mScreen;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private AudioManager mAudioManager;
+    @Mock private VibrationRampingRingerTogglePreferenceController.DeviceConfigProvider
+            mDeviceConfigProvider;
 
-    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private Context mContext;
     private VibrationRampingRingerTogglePreferenceController mController;
@@ -69,18 +65,17 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
+        mLifecycle = new Lifecycle(() -> mLifecycle);
         mContext = spy(ApplicationProvider.getApplicationContext());
         when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
         when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
         mController = new VibrationRampingRingerTogglePreferenceController(mContext,
-                PREFERENCE_KEY);
+                PREFERENCE_KEY, mDeviceConfigProvider);
         mLifecycle.addObserver(mController);
         mPreference = new SwitchPreference(mContext);
         mPreference.setSummary("Test summary");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        showPreference();
+        mController.displayPreference(mScreen);
     }
 
     @Test
@@ -91,8 +86,7 @@
     @Test
     public void getAvailabilityStatus_notVoiceCapable_returnUnsupportedOnDevice() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY,
-                VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "false", false);
+        when(mDeviceConfigProvider.isRampingRingerEnabledOnTelephonyConfig()).thenReturn(false);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
@@ -100,8 +94,7 @@
     @Test
     public void getAvailabilityStatus_rampingRingerEnabled_returnUnsupportedOnDevice() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY,
-                VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "true", false);
+        when(mDeviceConfigProvider.isRampingRingerEnabledOnTelephonyConfig()).thenReturn(true);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
@@ -109,8 +102,7 @@
     @Test
     public void getAvailabilityStatus_voiceCapableAndRampingRingerDisabled_returnAvailable() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY,
-                VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "false", false);
+        when(mDeviceConfigProvider.isRampingRingerEnabledOnTelephonyConfig()).thenReturn(false);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
@@ -143,8 +135,8 @@
     public void setChecked_withRingDisabled_ignoresUpdates() {
         updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
 
-        mPreference.setChecked(true);
-        mPreference.setChecked(false);
+        mController.setChecked(true);
+        mController.setChecked(false);
         verify(mAudioManager, never()).setRampingRingerEnabled(anyBoolean());
     }
 
@@ -152,18 +144,14 @@
     public void setChecked_withRingEnabled_updatesSetting() {
         updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
 
-        mPreference.setChecked(true);
+        mController.setChecked(true);
         verify(mAudioManager).setRampingRingerEnabled(true);
 
-        mPreference.setChecked(false);
+        mController.setChecked(false);
         verify(mAudioManager).setRampingRingerEnabled(false);
     }
 
     private void updateSetting(String key, int value) {
         Settings.System.putInt(mContext.getContentResolver(), key, value);
     }
-
-    private void showPreference() {
-        mController.displayPreference(mScreen);
-    }
 }