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

Commit bad3a1a9 authored by Lais Andrade's avatar Lais Andrade
Browse files

[Catalyst] Integrate vibration deprecated settings

Update ring and touch preferences to also update dependent and
deprecated settings when the main intensity settings are updated.

Added tests to cover the switch <-> dependent settings integrated behavior.

NO_IFTTT=migration ongoing, no need to update legacy controllers

Bug: 390338213
Flag: com.android.settings.flags.catalyst_vibration_intensity_screen_25q4
Test: [Ring|Touch]VibrationIntensitySwitchPreferenceTest
Change-Id: I23b3e996afa6d225180b45f5643ef6423cc7110e
parent 0d45de73
Loading
Loading
Loading
Loading
+64 −8
Original line number Diff line number Diff line
@@ -22,7 +22,10 @@ import android.content.IntentFilter
import android.media.AudioManager
import android.os.VibrationAttributes.Usage
import android.os.Vibrator
import android.os.Vibrator.VIBRATION_INTENSITY_OFF
import android.provider.Settings.System
import com.android.settings.R
import com.android.settings.accessibility.AccessibilityUtil.State
import com.android.settingslib.datastore.AbstractKeyedDataObservable
import com.android.settingslib.datastore.HandlerExecutor
import com.android.settingslib.datastore.KeyValueStore
@@ -65,14 +68,21 @@ class VibrationIntensitySettingsStore(

    override fun <T : Any> getValue(key: String, valueType: Class<T>) =
        if (isPreferenceEnabled()) {
            intensityToValue(valueType, keyValueStoreDelegate.getInt(key) ?: defaultIntensity)
            getFromDeprecatedValue(key, valueType)
                ?: 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)
            intensityToValue(valueType, VIBRATION_INTENSITY_OFF)
        }

    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) =
        keyValueStoreDelegate.setInt(key, value?.let { valueToIntensity(valueType, it) })
    override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
        val intensity = value?.let { valueToIntensity(valueType, it) };
        keyValueStoreDelegate.setInt(key, intensity)
        setDependentValues(key, intensity)
    }

    override fun onFirstObserverAdded() {
        ringerModeBroadcastReceiver = object : BroadcastReceiver() {
@@ -118,7 +128,7 @@ class VibrationIntensitySettingsStore(
            as T?

    private fun intensityToBooleanValue(intensity: Int): Boolean? =
        intensity != Vibrator.VIBRATION_INTENSITY_OFF
        intensity != VIBRATION_INTENSITY_OFF

    private fun intensityToIntValue(intensity: Int): Int? = min(intensity, supportedIntensityLevels)

@@ -130,11 +140,11 @@ class VibrationIntensitySettingsStore(
        }

    private fun booleanValueToIntensity(value: Boolean): Int? =
        if (value) defaultIntensity else Vibrator.VIBRATION_INTENSITY_OFF
        if (value) defaultIntensity else VIBRATION_INTENSITY_OFF

    private fun intValueToIntensity(value: Int): Int? =
        if (value == Vibrator.VIBRATION_INTENSITY_OFF) {
            Vibrator.VIBRATION_INTENSITY_OFF
        if (value == VIBRATION_INTENSITY_OFF) {
            VIBRATION_INTENSITY_OFF
        } else if (supportedIntensityLevels == 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.
@@ -147,6 +157,52 @@ class VibrationIntensitySettingsStore(
            // the highest vibration intensity, skipping intermediate values in the scale.
            Vibrator.VIBRATION_INTENSITY_HIGH
        }

    /**
     * Load intensity based on deprecated settings for given key.
     *
     * <p>This is required to support users that have only set this preference before its
     * deprecation, to make sure the settings are preserved after its deprecation.
     */
    @Suppress("DEPRECATION") // Loading deprecated settings key to maintain support.
    private fun <T: Any> getFromDeprecatedValue(key: String, valueType: Class<T>): T? {
        when (key) {
            System.HAPTIC_FEEDBACK_INTENSITY -> {
                if (keyValueStoreDelegate.getInt(System.HAPTIC_FEEDBACK_ENABLED) == State.OFF) {
                    // This is deprecated but should still be applied if the user has turned it off.
                    return intensityToValue(valueType, VIBRATION_INTENSITY_OFF)
                }
            }
        }
        return null
    }

    /** Set dependent/deprecated settings based on new intensity value being set for given key. */
    @Suppress("DEPRECATION") // Updating deprecated settings key to maintain support.
    private fun setDependentValues(key: String, intensity: Int?) {
        when (key) {
            System.RING_VIBRATION_INTENSITY -> {
                // This is deprecated but should still reflect the intensity setting.
                // Ramping ringer is independent of the ring intensity and should not be affected.
                keyValueStoreDelegate.setBoolean(
                    System.VIBRATE_WHEN_RINGING,
                    intensity?.let { it != VIBRATION_INTENSITY_OFF },
                )
            }
            System.HAPTIC_FEEDBACK_INTENSITY -> {
                // This is dependent on this setting, but should not be disabled by it.
                keyValueStoreDelegate.setInt(
                    System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
                    intensity?.let { if (it == VIBRATION_INTENSITY_OFF) defaultIntensity else it },
                )
                // This is deprecated but should still reflect the intensity setting.
                keyValueStoreDelegate.setInt(
                    System.HAPTIC_FEEDBACK_ENABLED,
                    intensity?.let { if (it == VIBRATION_INTENSITY_OFF) State.OFF else State.ON }
                )
            }
        }
    }
}

/** Returns the device default vibration intensity for given usage. */
+36 −0
Original line number Diff line number Diff line
@@ -15,9 +15,45 @@
 */
package com.android.settings.accessibility

import android.os.Vibrator
import android.provider.Settings
import com.android.settingslib.datastore.SettingsSystemStore
import com.google.common.truth.Truth.assertThat
import org.junit.Test

// LINT.IfChange
class RingVibrationIntensitySliderPreferenceTest : VibrationIntensitySliderPreferenceTestCase() {
    override val hasRingerModeDependency = true
    override val preference = RingVibrationIntensitySliderPreference(context)

    @Test
    fun setValue_updatesVibrateWhenRinging() {
        setSupportedLevels(3)
        setDefaultIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        setValue(Vibrator.VIBRATION_INTENSITY_HIGH)
        setVibrateWhenRinging(null)
        val widget = createWidget()

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH)
        assertThat(getStoredVibrateWhenRinging()).isNull()

        widget.value = Vibrator.VIBRATION_INTENSITY_OFF

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
        assertThat(getStoredVibrateWhenRinging()).isFalse()

        widget.value = Vibrator.VIBRATION_INTENSITY_LOW

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW)
        assertThat(getStoredVibrateWhenRinging()).isTrue()
    }

    @Suppress("DEPRECATION")
    private fun getStoredVibrateWhenRinging() =
        SettingsSystemStore.get(context).getBoolean(Settings.System.VIBRATE_WHEN_RINGING)

    @Suppress("DEPRECATION")
    private fun setVibrateWhenRinging(value: Boolean?) =
        SettingsSystemStore.get(context).setBoolean(Settings.System.VIBRATE_WHEN_RINGING, value)
}
// LINT.ThenChange(RingVibrationIntensityPreferenceControllerTest.java)
+33 −0
Original line number Diff line number Diff line
@@ -15,9 +15,42 @@
 */
package com.android.settings.accessibility

import android.provider.Settings
import com.android.settingslib.datastore.SettingsSystemStore
import com.google.common.truth.Truth.assertThat
import org.junit.Test

// LINT.IfChange
class RingVibrationIntensitySwitchPreferenceTest : VibrationIntensitySwitchPreferenceTestCase() {
    override val hasRingerModeDependency = true
    override val preference = RingVibrationIntensitySwitchPreference(context)

    @Test
    fun click_updatesVibrateWhenRinging() {
        setValue(null)
        setVibrateWhenRinging(null)
        val widget = createWidget()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredVibrateWhenRinging()).isNull()

        widget.performClick()

        assertThat(widget.isChecked).isFalse()
        assertThat(getStoredVibrateWhenRinging()).isFalse()

        widget.performClick()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredVibrateWhenRinging()).isTrue()
    }

    @Suppress("DEPRECATION")
    private fun getStoredVibrateWhenRinging() =
        SettingsSystemStore.get(context).getBoolean(Settings.System.VIBRATE_WHEN_RINGING)

    @Suppress("DEPRECATION")
    private fun setVibrateWhenRinging(value: Boolean?) =
        SettingsSystemStore.get(context).setBoolean(Settings.System.VIBRATE_WHEN_RINGING, value)
}
// LINT.ThenChange(RingVibrationTogglePreferenceControllerTest.java)
+100 −0
Original line number Diff line number Diff line
@@ -15,9 +15,109 @@
 */
package com.android.settings.accessibility

import android.os.Vibrator
import android.provider.Settings
import com.android.settings.accessibility.AccessibilityUtil.State
import com.android.settingslib.datastore.SettingsSystemStore
import com.google.common.truth.Truth.assertThat
import org.junit.Test

// LINT.IfChange
class TouchVibrationIntensitySliderPreferenceTest : VibrationIntensitySliderPreferenceTestCase() {
    override val hasRingerModeDependency = false
    override val preference = TouchVibrationIntensitySliderPreference(context)

    @Test
    fun state_valueTrueAndHapticFeedbackEnabledFalse_enabledAndUnchecked() {
        setSupportedLevels(3)
        setDefaultIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        setValue(Vibrator.VIBRATION_INTENSITY_HIGH)
        setHapticFeedbackEnabled(false)
        val widget = createWidget()

        assertThat(widget.isEnabled).isTrue()
        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
    }

    @Test
    fun state_valueFalseAndHapticFeedbackEnabledTrue_enabledAndUnchecked() {
        setSupportedLevels(3)
        setDefaultIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        setValue(Vibrator.VIBRATION_INTENSITY_OFF)
        setHapticFeedbackEnabled(true)
        val widget = createWidget()

        assertThat(widget.isEnabled).isTrue()
        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
    }

    @Test
    fun setValue_withHapticFeedbackEnabled_updatesDeprecatedSetting() {
        setSupportedLevels(3)
        setDefaultIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        setValue(null)
        setHapticFeedbackEnabled(null)
        val widget = createWidget()

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        assertThat(getStoredHapticFeedbackEnabled()).isNull()

        widget.value = Vibrator.VIBRATION_INTENSITY_OFF

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
        assertThat(getStoredHapticFeedbackEnabled()).isFalse()

        widget.value = Vibrator.VIBRATION_INTENSITY_HIGH

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH)
        assertThat(getStoredHapticFeedbackEnabled()).isTrue()
    }

    @Test
    fun setValue_withHardwareFeedback_updatesDependentSetting() {
        setSupportedLevels(3)
        setDefaultIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        setValue(null)
        setHardwareFeedbackIntensity(null)
        val widget = createWidget()

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM)
        assertThat(getStoredHardwareFeedbackIntensity()).isNull()

        widget.value = Vibrator.VIBRATION_INTENSITY_OFF

        // Hardware feedback intensity is not turned off by this preference
        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF)
        assertThat(getStoredHardwareFeedbackIntensity())
            .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM)

        widget.value = Vibrator.VIBRATION_INTENSITY_LOW

        assertThat(widget.value).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW)
        assertThat(getStoredHardwareFeedbackIntensity())
            .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW)
    }

    private fun getStoredHardwareFeedbackIntensity() =
        SettingsSystemStore.get(context).getInt(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY)

    @Suppress("DEPRECATION")
    private fun getStoredHapticFeedbackEnabled() =
        SettingsSystemStore.get(context).getInt(Settings.System.HAPTIC_FEEDBACK_ENABLED)?.let {
            it == State.ON
        }

    @Suppress("DEPRECATION")
    private fun setHapticFeedbackEnabled(value: Boolean?) =
        SettingsSystemStore.get(context).setInt(
            Settings.System.HAPTIC_FEEDBACK_ENABLED,
            value?.let { if (it) State.ON else State.OFF },
        )

    private fun setHardwareFeedbackIntensity(value: Int?) =
        SettingsSystemStore.get(context).setInt(
            Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
            value,
        )
}
// LINT.ThenChange(HapticFeedbackIntensityPreferenceControllerTest.java)
+91 −0
Original line number Diff line number Diff line
@@ -15,9 +15,100 @@
 */
package com.android.settings.accessibility

import android.os.Vibrator
import android.provider.Settings
import com.android.settingslib.datastore.SettingsSystemStore
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub

// LINT.IfChange
class TouchVibrationIntensitySwitchPreferenceTest : VibrationIntensitySwitchPreferenceTestCase() {
    override val hasRingerModeDependency = false
    override val preference = TouchVibrationIntensitySwitchPreference(context)

    @Test
    fun state_valueTrueAndHapticFeedbackEnabledFalse_enabledAndUnchecked() {
        setValue(true)
        setHapticFeedbackEnabled(false)
        val widget = createWidget()

        assertThat(widget.isEnabled).isTrue()
        assertThat(widget.isChecked).isFalse()
    }

    @Test
    fun state_valueFalseAndHapticFeedbackEnabledTrue_enabledAndUnchecked() {
        setValue(false)
        setHapticFeedbackEnabled(true)
        val widget = createWidget()

        assertThat(widget.isEnabled).isTrue()
        assertThat(widget.isChecked).isFalse()
    }

    @Test
    fun click_withHapticFeedbackEnabled_updatesDeprecatedSetting() {
        setValue(null)
        setHapticFeedbackEnabled(null)
        val widget = createWidget()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredHapticFeedbackEnabled()).isNull()

        widget.performClick()

        assertThat(widget.isChecked).isFalse()
        assertThat(getStoredHapticFeedbackEnabled()).isFalse()

        widget.performClick()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredHapticFeedbackEnabled()).isTrue()
    }

    @Test
    fun click_withHardwareFeedback_updatesDependentSetting() {
        val defaultIntensity = Vibrator.VIBRATION_INTENSITY_HIGH
        vibratorSpy.stub {
            on { getDefaultVibrationIntensity(any()) } doReturn defaultIntensity
        }
        setValue(null)
        setHardwareFeedbackIntensity(null)
        val widget = createWidget()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredHardwareFeedbackIntensity()).isNull()

        widget.performClick()

        // Hardware feedback intensity is not turned off by this preference
        assertThat(widget.isChecked).isFalse()
        assertThat(getStoredHardwareFeedbackIntensity()).isEqualTo(defaultIntensity)

        widget.performClick()

        assertThat(widget.isChecked).isTrue()
        assertThat(getStoredHardwareFeedbackIntensity()).isEqualTo(defaultIntensity)
    }

    private fun getStoredHardwareFeedbackIntensity() =
        SettingsSystemStore.get(context).getInt(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY)

    @Suppress("DEPRECATION")
    private fun getStoredHapticFeedbackEnabled() =
        SettingsSystemStore.get(context).getBoolean(Settings.System.HAPTIC_FEEDBACK_ENABLED)

    @Suppress("DEPRECATION")
    private fun setHapticFeedbackEnabled(value: Boolean?) =
        SettingsSystemStore.get(context).setBoolean(Settings.System.HAPTIC_FEEDBACK_ENABLED, value)

    private fun setHardwareFeedbackIntensity(value: Int?) =
        SettingsSystemStore.get(context).setInt(
            Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
            value,
        )
}
// LINT.ThenChange(HapticFeedbackTogglePreferenceControllerTest.java)
Loading