| /* |
| * Copyright (C) 2025 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.Usage |
| import android.os.Vibrator |
| import androidx.annotation.CallSuper |
| import androidx.annotation.StringRes |
| import androidx.preference.Preference |
| import androidx.preference.Preference.OnPreferenceChangeListener |
| import com.android.settingslib.datastore.KeyValueStore |
| import com.android.settingslib.metadata.IntRangeValuePreference |
| import com.android.settingslib.metadata.PreferenceMetadata |
| import com.android.settingslib.metadata.PreferenceSummaryProvider |
| import com.android.settingslib.widget.SliderPreference |
| import com.android.settingslib.widget.SliderPreferenceBinding |
| import kotlin.math.min |
| |
| /** |
| * SliderPreference for vibration intensity. |
| * |
| * 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( |
| context: Context, |
| override val key: String, |
| @Usage val vibrationUsage: Int, |
| @StringRes override val title: Int = 0, |
| @StringRes override val summary: Int = 0, |
| val hasRingerModeDependency: Boolean = false, |
| ) : |
| IntRangeValuePreference, |
| PreferenceSummaryProvider, |
| SliderPreferenceBinding, |
| OnPreferenceChangeListener { |
| |
| private val storage by lazy { |
| VibrationIntensitySettingsStore( |
| context, |
| vibrationUsage, |
| hasRingerModeDependency, |
| key |
| ) |
| } |
| |
| override fun getMinValue(context: Context) = Vibrator.VIBRATION_INTENSITY_OFF |
| |
| override fun getMaxValue(context: Context) = |
| min(Vibrator.VIBRATION_INTENSITY_HIGH, context.getSupportedVibrationIntensityLevels()) |
| |
| override fun getIncrementStep(context: Context) = 1 |
| |
| override fun storage(context: Context): KeyValueStore = storage |
| |
| override fun dependencies(context: Context) = storage.dependencies() |
| |
| override fun getSummary(context: Context) = storage.getSummary() |
| |
| override fun createWidget(context: Context) = SliderPreference(context) |
| |
| @CallSuper |
| override fun bind(preference: Preference, metadata: PreferenceMetadata) { |
| super.bind(preference, metadata) |
| preference.onPreferenceChangeListener = this |
| (preference as SliderPreference).apply { |
| // Haptics previews played by the Settings app don't bypass user settings to be played. |
| // The sliders continuously updates the intensity value so the previews can apply them. |
| updatesContinuously = true |
| } |
| } |
| |
| override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { |
| val intensity = newValue as Int |
| // must make new value effective before preview |
| (preference as SliderPreference).value = intensity |
| if (intensity != Vibrator.VIBRATION_INTENSITY_OFF) { |
| preference.context.playVibrationSettingsPreview(vibrationUsage) |
| } |
| return false // value has been updated |
| } |
| |
| @CallSuper override fun isEnabled(context: Context) = storage.isPreferenceEnabled() |
| } |
| // LINT.ThenChange(VibrationIntensityPreferenceController.java) |