Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2662afa authored by Ahmad Khalil's avatar Ahmad Khalil Committed by Android (Google) Code Review
Browse files

Merge "[Catalyst] Integrate vibration switches with main switch" into main

parents 95e184da ea65969f
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.accessibility
import android.content.Context
import android.os.VibrationAttributes.Usage
import android.os.Vibrator
import android.provider.Settings
import com.android.settings.R
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.KeyValueStoreDelegate
@@ -33,11 +34,20 @@ class VibrationIntensitySettingsStore(
    private val supportedIntensityLevels: Int = context.getSupportedVibrationIntensityLevels(),
) : KeyValueStoreDelegate {

    /** Returns true if the settings key should be enabled, false otherwise. */
    fun isPreferenceEnabled() =
        keyValueStoreDelegate.getBoolean(Settings.System.VIBRATE_ON) ?: true

    override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
        intensityToValue(valueType, defaultIntensity)

    override fun <T : Any> getValue(key: String, valueType: Class<T>) =
        if (isPreferenceEnabled()) {
            intensityToValue(valueType, keyValueStoreDelegate.getInt(key) ?: defaultIntensity)
        } else {
            // Preference must show intensity off when disabled, but value stored must be preserved.
            intensityToValue(valueType, Vibrator.VIBRATION_INTENSITY_OFF)
        }

    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) =
        keyValueStoreDelegate.setInt(key, value?.let { valueToIntensity(valueType, it) })
+20 −2
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@ import kotlin.math.min
 *
 * This implementation uses VibrationIntensitySettingsStore to save the vibration intensity value,
 * also playing a haptic preview on slider changes.
 *
 * This preference observes the state of the VibrationMainSwitchPreference in this fragment,
 * disabling and displaying intensity OFF this slider when the main switch is unchecked. This "off"
 * state should not be persisted, as the original user settings value must be preserved and restored
 * once the main switch is turned back on. This behavior reflects the actual system behavior that
 * restricts all vibrations when the main switch is off.
 */
// LINT.IfChange
open class VibrationIntensitySliderPreference(
@@ -43,6 +49,8 @@ open class VibrationIntensitySliderPreference(
    @StringRes override val summary: Int = 0,
) : IntRangeValuePreference, SliderPreferenceBinding, OnPreferenceChangeListener {

    private var storage: VibrationIntensitySettingsStore? = null

    override fun getMinValue(context: Context) = Vibrator.VIBRATION_INTENSITY_OFF

    override fun getMaxValue(context: Context) =
@@ -50,8 +58,15 @@ open class VibrationIntensitySliderPreference(

    override fun getIncrementStep(context: Context) = 1

    override fun storage(context: Context): KeyValueStore =
        VibrationIntensitySettingsStore(context, vibrationUsage)
    override fun storage(context: Context): KeyValueStore {
        if (storage == null) {
            storage = VibrationIntensitySettingsStore(context, vibrationUsage)
        }
        return storage!!
    }


    override fun dependencies(context: Context) = arrayOf(VibrationMainSwitchPreference.KEY)

    @CallSuper
    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
@@ -70,5 +85,8 @@ open class VibrationIntensitySliderPreference(
        }
        return true
    }

    @CallSuper
    override fun isEnabled(context: Context) = storage?.isPreferenceEnabled() ?: true
}
// LINT.ThenChange(VibrationIntensityPreferenceController.java)
+19 −2
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@ import com.android.settingslib.preference.SwitchPreferenceBinding
 *
 * This implementation uses VibrationIntensitySettingsStore to save the device default vibration
 * intensity value when the switch is turned on, also playing a haptic preview.
 *
 * This preference observes the state of the VibrationMainSwitchPreference in this fragment,
 * disabling and unchecking this switch when the main switch is unchecked. This "unchecked" state
 * should not be persisted, as the original user settings value must be preserved and restored once
 * the main switch is turned back on. This behavior reflects the actual system behavior that
 * restricts all vibrations when the main switch is off.
 */
// LINT.IfChange
open class VibrationIntensitySwitchPreference(
@@ -42,8 +48,16 @@ open class VibrationIntensitySwitchPreference(
    OnPreferenceChangeListener,
    SwitchPreferenceBinding {

    override fun storage(context: Context): KeyValueStore =
        VibrationIntensitySettingsStore(context, vibrationUsage)
    private var storage: VibrationIntensitySettingsStore? = null

    override fun storage(context: Context): KeyValueStore {
        if (storage == null) {
            storage = VibrationIntensitySettingsStore(context, vibrationUsage)
        }
        return storage!!
    }

    override fun dependencies(context: Context) = arrayOf(VibrationMainSwitchPreference.KEY)

    @CallSuper
    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
@@ -57,5 +71,8 @@ open class VibrationIntensitySwitchPreference(
        }
        return true
    }

    @CallSuper
    override fun isEnabled(context: Context) = storage?.isPreferenceEnabled() ?: true
}
// LINT.ThenChange(VibrationTogglePreferenceController.java)
+5 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
@Config(shadows = [ShadowAudioManager::class])
class VibrationIntensityScreenTest : CatalystScreenTestCase() {
    private lateinit var mockVibrator: Vibrator
    private lateinit var vibratorMock: Vibrator

    private val resourcesSpy: Resources =
        spy((ApplicationProvider.getApplicationContext() as Context).resources)
@@ -50,7 +50,7 @@ class VibrationIntensityScreenTest : CatalystScreenTestCase() {
        object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
            override fun getSystemService(name: String): Any? =
                when {
                    name == VIBRATOR_SERVICE -> mockVibrator
                    name == VIBRATOR_SERVICE -> vibratorMock
                    else -> super.getSystemService(name)
                }

@@ -74,7 +74,7 @@ class VibrationIntensityScreenTest : CatalystScreenTestCase() {

    @Test
    fun isAvailable_noVibrator_unavailable() {
        mockVibrator = mock { on { hasVibrator() } doReturn false }
        vibratorMock = mock { on { hasVibrator() } doReturn false }
        resourcesSpy.stub {
            on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 3
        }
@@ -83,7 +83,7 @@ class VibrationIntensityScreenTest : CatalystScreenTestCase() {

    @Test
    fun isAvailable_hasVibratorAndSingleIntensityLevel_unavailable() {
        mockVibrator = mock { on { hasVibrator() } doReturn true }
        vibratorMock = mock { on { hasVibrator() } doReturn true }
        resourcesSpy.stub {
            on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 1
        }
@@ -92,7 +92,7 @@ class VibrationIntensityScreenTest : CatalystScreenTestCase() {

    @Test
    fun isAvailable_hasVibratorAndMultipleIntensityLevels_available() {
        mockVibrator = mock { on { hasVibrator() } doReturn true }
        vibratorMock = mock { on { hasVibrator() } doReturn true }
        resourcesSpy.stub {
            on { getInteger(R.integer.config_vibration_supported_intensity_levels) } doReturn 2
        }
+32 −0
Original line number Diff line number Diff line
@@ -44,6 +44,28 @@ class VibrationIntensitySettingsStoreTest {
        supportedIntensityLevels = SUPPORTED_INTENSITIES,
    )

    @Test
    fun isPreferenceEnabled_returnsVibrateOnSettingOrTrue() {
        settingsStore.setBoolean(Settings.System.VIBRATE_ON, null)
        assertThat(store.isPreferenceEnabled()).isTrue()

        settingsStore.setBoolean(Settings.System.VIBRATE_ON, true)
        assertThat(store.isPreferenceEnabled()).isTrue()

        settingsStore.setBoolean(Settings.System.VIBRATE_ON, false)
        assertThat(store.isPreferenceEnabled()).isFalse()
    }

    @Test
    fun getValue_preferenceDisabledByMainSwitch_returnsIntensityOffAndPreservesValue() {
        settingsStore.setBoolean(Settings.System.VIBRATE_ON, false)
        setIntValue(Vibrator.VIBRATION_INTENSITY_HIGH)

        assertThat(settingsStore.getInt(KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH)
        assertThat(store.getBoolean(KEY)).isFalse()
        assertThat(store.getInt(KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
    }

    @Test
    fun getValue_valueNull_returnDefaultIntensity() {
        setIntValue(null)
@@ -98,6 +120,16 @@ class VibrationIntensitySettingsStoreTest {
        assertThat(store.getInt(KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
    }

    @Test
    fun getValue_preferenceDisabled_returnOffAndPreservesValue() {
        settingsStore.setBoolean(Settings.System.VIBRATE_ON, false)
        setBooleanValue(true)

        assertThat(settingsStore.getInt(KEY)).isEqualTo(DEFAULT_INTENSITY)
        assertThat(store.getBoolean(KEY)).isFalse()
        assertThat(store.getInt(KEY)).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
    }

    @Test
    fun setValue_updatesCorrectly() {
        setBooleanValue(null)
Loading