From 08a7f6a5e7a2822cf766d1141149a1a6a4faa051 Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Wed, 20 Nov 2024 12:13:24 +0000 Subject: [PATCH] [Catalyst] Vibration and haptics main switch migration - Migrate "Use Vibration & haptics" main toggle in vibration settings screen. - Add screen for VibrationScreen dashboard fragment NO_IFTTT=introducing preference metadata files, no change in preference controllers required. Bug: 368360218 Flag: com.android.settings.flags.catalyst_vibration_intensity_screen Test: VibrationIntensityScreenTest VibrationScreenTest VibrationMainSwitchPreferenceTest Change-Id: I1dee7fdd59e093bd2dd12204554fe5198e7b76b4 --- ...ssibility_vibration_intensity_settings.xml | 2 +- res/xml/accessibility_vibration_settings.xml | 2 +- .../accessibility/VibrationIntensityScreen.kt | 21 +++- .../VibrationMainSwitchPreference.kt | 100 ++++++++++++++++++ ...brationMainSwitchPreferenceController.java | 2 + .../VibrationPreferenceController.java | 5 + .../settings/accessibility/VibrationScreen.kt | 69 ++++++++++++ .../accessibility/VibrationSettings.java | 7 ++ .../VibrationIntensityScreenTest.kt | 54 ++++++++++ ...ionMainSwitchPreferenceControllerTest.java | 2 + .../VibrationMainSwitchPreferenceTest.kt | 77 ++++++++++++++ .../VibrationPreferenceControllerTest.java | 5 + .../accessibility/VibrationScreenTest.kt | 90 ++++++++++++++++ 13 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt create mode 100644 src/com/android/settings/accessibility/VibrationScreen.kt create mode 100644 tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceTest.kt create mode 100644 tests/robotests/src/com/android/settings/accessibility/VibrationScreenTest.kt diff --git a/res/xml/accessibility_vibration_intensity_settings.xml b/res/xml/accessibility_vibration_intensity_settings.xml index f9a5578c517..ba1bd83da94 100644 --- a/res/xml/accessibility_vibration_intensity_settings.xml +++ b/res/xml/accessibility_vibration_intensity_settings.xml @@ -20,7 +20,7 @@ android:title="@string/accessibility_vibration_settings_title"> diff --git a/res/xml/accessibility_vibration_settings.xml b/res/xml/accessibility_vibration_settings.xml index 3ce92a6e303..be45659b310 100644 --- a/res/xml/accessibility_vibration_settings.xml +++ b/res/xml/accessibility_vibration_settings.xml @@ -20,7 +20,7 @@ android:title="@string/accessibility_vibration_settings_title"> diff --git a/src/com/android/settings/accessibility/VibrationIntensityScreen.kt b/src/com/android/settings/accessibility/VibrationIntensityScreen.kt index 5d7d4fbfe45..0a372308066 100644 --- a/src/com/android/settings/accessibility/VibrationIntensityScreen.kt +++ b/src/com/android/settings/accessibility/VibrationIntensityScreen.kt @@ -19,18 +19,32 @@ import android.content.Context import androidx.fragment.app.Fragment import com.android.settings.R import com.android.settings.flags.Flags +import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator +/** + * Accessibility settings for vibration intensities. + */ +// TODO(b/368360218): investigate if we still need this screen once we finish the migration. +// We might be able to consolidate this into VibrationScreen with PreferenceHierarchy choosing +// between toggle or slider preferences based on device config, depending on how overlays are done. +// LINT.IfChange @ProvidePreferenceScreen -class VibrationIntensityScreen : PreferenceScreenCreator { +class VibrationIntensityScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider { override val key: String get() = KEY override val title: Int get() = R.string.accessibility_vibration_settings_title + override val keywords: Int + get() = R.string.keywords_vibration + + override fun isAvailable(context: Context) = + context.isVibratorAvailable() && context.getSupportedVibrationIntensityLevels() > 1 + override fun isFlagEnabled(context: Context): Boolean = Flags.catalystVibrationIntensityScreen() override fun hasCompleteHierarchy() = false @@ -38,9 +52,12 @@ class VibrationIntensityScreen : PreferenceScreenCreator { override fun fragmentClass(): Class? = VibrationIntensitySettingsFragment::class.java - override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) { + +VibrationMainSwitchPreference() + } companion object { const val KEY = "vibration_intensity_screen" } } +// LINT.ThenChange(VibrationPreferenceController.java) diff --git a/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt new file mode 100644 index 00000000000..70a0033d57a --- /dev/null +++ b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2024 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.os.Vibrator +import android.provider.Settings +import android.widget.CompoundButton +import android.widget.CompoundButton.OnCheckedChangeListener +import com.android.settings.R +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.KeyedObservableDelegate +import com.android.settingslib.datastore.SettingsStore +import com.android.settingslib.datastore.SettingsSystemStore +import com.android.settingslib.metadata.MainSwitchPreference +import com.android.settingslib.metadata.PreferenceLifecycleContext +import com.android.settingslib.metadata.PreferenceLifecycleProvider +import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.preference.MainSwitchPreferenceBinding + +/** + * Accessibility settings for vibration. + */ +// LINT.IfChange +class VibrationMainSwitchPreference : MainSwitchPreference( + key = Settings.System.VIBRATE_ON, + title = R.string.accessibility_vibration_primary_switch_title, +), PreferenceLifecycleProvider, OnCheckedChangeListener { + override val keywords: Int + get() = R.string.keywords_accessibility_vibration_primary_switch + + lateinit var vibrator: Vibrator + + override fun storage(context: Context): KeyValueStore = + VibrationMainSwitchToggleStorage(SettingsSystemStore.get(context)) + + override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun onResume(context: PreferenceLifecycleContext) { + vibrator = context.getSystemService(Vibrator::class.java) + context.findPreference(key) + ?.addOnSwitchChangeListener(this) + } + + override fun onPause(context: PreferenceLifecycleContext) { + context.findPreference(key) + ?.removeOnSwitchChangeListener(this) + } + + override fun onCheckedChanged(button: CompoundButton, isChecked: Boolean) { + if (isChecked) { + // Play a haptic as preview for the main toggle only when touch feedback is enabled. + VibrationPreferenceConfig.playVibrationPreview( + vibrator, VibrationAttributes.USAGE_TOUCH + ) + } + } + + /** Provides SettingsStore for vibration main switch with custom default value. */ + @Suppress("UNCHECKED_CAST") + private class VibrationMainSwitchToggleStorage( + private val settingsStore: SettingsStore, + ) : KeyedObservableDelegate(settingsStore), KeyValueStore { + + override fun contains(key: String) = settingsStore.contains(key) + + override fun getDefaultValue(key: String, valueType: Class) = + DEFAULT_VALUE as T + + override fun getValue(key: String, valueType: Class) = + (settingsStore.getBoolean(key) ?: DEFAULT_VALUE) as T + + override fun setValue(key: String, valueType: Class, value: T?) { + settingsStore.setBoolean(key, value as Boolean?) + } + } + + companion object { + const val DEFAULT_VALUE = true + } +} +// LINT.ThenChange(VibrationMainSwitchPreferenceController.java) diff --git a/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java b/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java index 5b553e3df61..0f2fb77a98a 100644 --- a/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java @@ -41,6 +41,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop; * will disable the entire settings screen once the settings is turned OFF. All device haptics will * be disabled by this setting, except the flagged alerts and accessibility touch feedback. */ +// LINT.IfChange public class VibrationMainSwitchPreferenceController extends SettingsMainSwitchPreferenceController implements LifecycleObserver, OnStart, OnStop { @@ -106,3 +107,4 @@ public class VibrationMainSwitchPreferenceController extends SettingsMainSwitchP return R.string.menu_key_accessibility; } } +// LINT.ThenChange(VibrationMainSwitchPreference.kt) diff --git a/src/com/android/settings/accessibility/VibrationPreferenceController.java b/src/com/android/settings/accessibility/VibrationPreferenceController.java index 092ff6945d1..e84543db997 100644 --- a/src/com/android/settings/accessibility/VibrationPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationPreferenceController.java @@ -31,6 +31,7 @@ import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SubSettingLauncher; /** Controller for "Vibration & haptics" settings page. */ +// LINT.IfChange public class VibrationPreferenceController extends BasePreferenceController { private final boolean mHasVibrator; @@ -79,3 +80,7 @@ public class VibrationPreferenceController extends BasePreferenceController { } +// LINT.ThenChange( +// VibrationIntensityScreenTest.kt, +// VibrationScreenTest.kt, +// ) diff --git a/src/com/android/settings/accessibility/VibrationScreen.kt b/src/com/android/settings/accessibility/VibrationScreen.kt new file mode 100644 index 00000000000..63a7c4492a1 --- /dev/null +++ b/src/com/android/settings/accessibility/VibrationScreen.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 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.Vibrator +import androidx.fragment.app.Fragment +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.metadata.PreferenceAvailabilityProvider +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +/** + * Accessibility settings for vibration. + */ +// LINT.IfChange +@ProvidePreferenceScreen +class VibrationScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider { + override val key: String + get() = KEY + + override val title: Int + get() = R.string.accessibility_vibration_settings_title + + override val keywords: Int + get() = R.string.keywords_vibration + + override fun isAvailable(context: Context) = + context.isVibratorAvailable() && context.getSupportedVibrationIntensityLevels() == 1 + + override fun isFlagEnabled(context: Context): Boolean = Flags.catalystVibrationIntensityScreen() + + override fun hasCompleteHierarchy() = false + + override fun fragmentClass(): Class? = VibrationSettings::class.java + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) { + +VibrationMainSwitchPreference() + } + + companion object { + const val KEY = "vibration_screen" + } +} + +/** Returns true if the device has a system vibrator, false otherwise. */ +fun Context.isVibratorAvailable(): Boolean = + getSystemService(Vibrator::class.java).hasVibrator() + +/** Returns the number of vibration intensity levels supported by this device. */ +fun Context.getSupportedVibrationIntensityLevels(): Int = + resources.getInteger(R.integer.config_vibration_supported_intensity_levels) + +// LINT.ThenChange(VibrationPreferenceController.java) diff --git a/src/com/android/settings/accessibility/VibrationSettings.java b/src/com/android/settings/accessibility/VibrationSettings.java index 48393d9394c..11e1ddde5b4 100644 --- a/src/com/android/settings/accessibility/VibrationSettings.java +++ b/src/com/android/settings/accessibility/VibrationSettings.java @@ -20,6 +20,8 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Vibrator; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.settings.R; @@ -35,6 +37,11 @@ public class VibrationSettings extends DashboardFragment { private static final String TAG = "VibrationSettings"; + @Override + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { + return VibrationScreen.KEY; + } + @Override public int getMetricsCategory() { return SettingsEnums.ACCESSIBILITY_VIBRATION; diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityScreenTest.kt b/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityScreenTest.kt index 99851de6ac2..40ed9a3dda8 100644 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityScreenTest.kt +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationIntensityScreenTest.kt @@ -15,15 +15,40 @@ */ package com.android.settings.accessibility +import android.content.Context +import android.content.ContextWrapper +import android.content.res.Resources +import android.os.Vibrator +import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.flags.Flags +import com.android.settings.R import com.android.settingslib.preference.CatalystScreenTestCase import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.stub +// LINT.IfChange @RunWith(AndroidJUnit4::class) class VibrationIntensityScreenTest : CatalystScreenTestCase() { + private lateinit var vibrator: Vibrator + + private val resourcesSpy: Resources = + spy((ApplicationProvider.getApplicationContext() as Context).resources) + + private val context: Context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when { + name == getSystemServiceName(Vibrator::class.java) -> vibrator + else -> super.getSystemService(name) + } + override fun getResources(): Resources = resourcesSpy + } override val preferenceScreenCreator = VibrationIntensityScreen() @@ -34,4 +59,33 @@ class VibrationIntensityScreenTest : CatalystScreenTestCase() { fun key() { assertThat(preferenceScreenCreator.key).isEqualTo(VibrationIntensityScreen.KEY) } + + @Test + fun isAvailable_noVibrator_unavailable() { + vibrator = mock { on { hasVibrator() } doReturn false } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 3 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isFalse() + } + + @Test + fun isAvailable_hasVibratorAndSingleIntensityLevel_unavailable() { + vibrator = mock { on { hasVibrator() } doReturn true } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 1 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isFalse() + } + + @Test + fun isAvailable_hasVibratorAndMultipleIntensityLevels_available() { + vibrator = mock { on { hasVibrator() } doReturn true } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 2 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isTrue() + } } +// LINT.ThenChange(VibrationPreferenceControllerTest.java) + diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceControllerTest.java index 6f5700347a7..9caa211ebfa 100644 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceControllerTest.java @@ -41,6 +41,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; /** Tests for {@link VibrationMainSwitchPreferenceController}. */ +// LINT.IfChange @RunWith(RobolectricTestRunner.class) public class VibrationMainSwitchPreferenceControllerTest { @@ -104,3 +105,4 @@ public class VibrationMainSwitchPreferenceControllerTest { return Settings.System.getInt(mContext.getContentResolver(), settingKey); } } +// LINT.ThenChange(VibrationMainSwitchPreferenceTest.kt) diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceTest.kt b/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceTest.kt new file mode 100644 index 00000000000..fd781bc33d5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 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.provider.Settings.System.VIBRATE_ON +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.preference.createAndBindWidget +import com.android.settingslib.widget.MainSwitchPreference +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +// LINT.IfChange +@RunWith(AndroidJUnit4::class) +class VibrationMainSwitchPreferenceTest { + private val context: Context = ApplicationProvider.getApplicationContext() + private val preference = VibrationMainSwitchPreference() + + @Test + fun checked_valueUnset_returnDefaultTrue() { + setVibrateOn(null) + + assertThat(getMainSwitchPreference().isChecked).isTrue() + } + + @Test + fun checked_valueEnabled_returnTrue() { + setVibrateOn(true) + + assertThat(getMainSwitchPreference().isChecked).isTrue() + } + + @Test + fun checked_valueDisabled_returnFalse() { + setVibrateOn(false) + + assertThat(getMainSwitchPreference().isChecked).isFalse() + } + + @Test + fun click_updatesCorrectly() { + setVibrateOn(null) + val widget = getMainSwitchPreference() + + assertThat(widget.isChecked).isTrue() + + widget.performClick() + + assertThat(widget.isChecked).isFalse() + + widget.performClick() + + assertThat(widget.isChecked).isTrue() + } + + private fun getMainSwitchPreference(): MainSwitchPreference = + preference.createAndBindWidget(context) + + private fun setVibrateOn(enabled: Boolean?) = + preference.storage(context).setValue(VIBRATE_ON, Boolean::class.javaObjectType, enabled) +} +// LINT.ThenChange(VibrationMainSwitchPreferenceControllerTest.java) diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java index 59ed48638d0..a0481e5eda5 100644 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java @@ -46,6 +46,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; +// LINT.IfChange @RunWith(RobolectricTestRunner.class) public class VibrationPreferenceControllerTest { private static final String PREFERENCE_KEY = "preference_key"; @@ -158,3 +159,7 @@ public class VibrationPreferenceControllerTest { return controller; } } +// LINT.ThenChange( +// VibrationIntensityScreenTest.kt, +// VibrationScreenTest.kt, +// ) diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationScreenTest.kt b/tests/robotests/src/com/android/settings/accessibility/VibrationScreenTest.kt new file mode 100644 index 00000000000..c6e5265a52c --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationScreenTest.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2024 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.content.ContextWrapper +import android.content.res.Resources +import android.os.Vibrator +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.flags.Flags +import com.android.settings.R +import com.android.settingslib.preference.CatalystScreenTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.stub + +// LINT.IfChange +@RunWith(AndroidJUnit4::class) +class VibrationScreenTest : CatalystScreenTestCase() { + private lateinit var vibrator: Vibrator + + private val resourcesSpy: Resources = + spy((ApplicationProvider.getApplicationContext() as Context).resources) + + private val context: Context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when { + name == getSystemServiceName(Vibrator::class.java) -> vibrator + else -> super.getSystemService(name) + } + override fun getResources(): Resources = resourcesSpy + } + + override val preferenceScreenCreator = VibrationScreen() + + override val flagName: String + get() = Flags.FLAG_CATALYST_VIBRATION_INTENSITY_SCREEN + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(VibrationScreen.KEY) + } + + @Test + fun isAvailable_noVibrator_unavailable() { + vibrator = mock { on { hasVibrator() } doReturn false } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 1 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isFalse() + } + + @Test + fun isAvailable_hasVibratorAndMultipleIntensityLevels_unavailable() { + vibrator = mock { on { hasVibrator() } doReturn true } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 3 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isFalse() + } + + @Test + fun isAvailable_hasVibratorAndSingleIntensityLevel_available() { + vibrator = mock { on { hasVibrator() } doReturn true } + resourcesSpy.stub { + on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 1 + } + assertThat(preferenceScreenCreator.isAvailable(context)).isTrue() + } +} +// LINT.ThenChange(VibrationPreferenceControllerTest.java)