diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java index 6441eeb4571..bc8c6005806 100644 --- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java @@ -73,11 +73,11 @@ public abstract class VibrationIntensityPreferenceController extends SliderPrefe mSettingsContentObserver.onDisplayPreference(this, preference); preference.setEnabled(mPreferenceConfig.isPreferenceEnabled()); preference.setSummaryProvider(unused -> mPreferenceConfig.getSummary()); - // TODO: remove setContinuousUpdates and replace with a different way to play the haptic - // preview without relying on the setting being propagated to the service. - preference.setContinuousUpdates(true); preference.setMin(getMin()); preference.setMax(getMax()); + // 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. + preference.setContinuousUpdates(true); } @Override diff --git a/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java b/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java index 726bbc1f054..02e89269209 100644 --- a/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationMainSwitchPreferenceController.java @@ -23,6 +23,8 @@ import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; +import android.os.VibrationAttributes; +import android.os.Vibrator; import android.provider.Settings; import com.android.settings.R; @@ -42,9 +44,11 @@ public class VibrationMainSwitchPreferenceController extends SettingsMainSwitchP implements LifecycleObserver, OnStart, OnStop { private final ContentObserver mSettingObserver; + private final Vibrator mVibrator; public VibrationMainSwitchPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); + mVibrator = context.getSystemService(Vibrator.class); mSettingObserver = new ContentObserver(new Handler(/* async= */ true)) { @Override public void onChange(boolean selfChange, Uri uri) { @@ -79,9 +83,17 @@ public class VibrationMainSwitchPreferenceController extends SettingsMainSwitchP @Override public boolean setChecked(boolean isChecked) { - return Settings.System.putInt(mContext.getContentResolver(), + boolean success = Settings.System.putInt(mContext.getContentResolver(), VibrationPreferenceConfig.MAIN_SWITCH_SETTING_KEY, isChecked ? ON : OFF); + + if (success && isChecked) { + // Play a haptic as preview for the main toggle only when touch feedback is enabled. + VibrationPreferenceConfig.playVibrationPreview( + mVibrator, VibrationAttributes.USAGE_TOUCH); + } + + return success; } @Override diff --git a/src/com/android/settings/accessibility/VibrationPreferenceConfig.java b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java index 9208b188c49..b4be5281a0c 100644 --- a/src/com/android/settings/accessibility/VibrationPreferenceConfig.java +++ b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java @@ -49,6 +49,8 @@ public abstract class VibrationPreferenceConfig { * all device vibrations. */ public static final String MAIN_SWITCH_SETTING_KEY = Settings.System.VIBRATE_ON; + private static final VibrationEffect PREVIEW_VIBRATION_EFFECT = + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK); protected final ContentResolver mContentResolver; private final AudioManager mAudioManager; @@ -56,14 +58,22 @@ public abstract class VibrationPreferenceConfig { private final String mSettingKey; private final String mRingerModeSilentSummary; private final int mDefaultIntensity; - private final VibrationAttributes mVibrationAttributes; + private final VibrationAttributes mPreviewVibrationAttributes; /** Returns true if the user setting for enabling device vibrations is enabled. */ public static boolean isMainVibrationSwitchEnabled(ContentResolver contentResolver) { return Settings.System.getInt(contentResolver, MAIN_SWITCH_SETTING_KEY, ON) == ON; } - public VibrationPreferenceConfig(Context context, String settingKey, int vibrationUsage) { + /** Play a vibration effect with intensity just selected by the user. */ + public static void playVibrationPreview(Vibrator vibrator, + @VibrationAttributes.Usage int vibrationUsage) { + vibrator.vibrate(PREVIEW_VIBRATION_EFFECT, + createPreviewVibrationAttributes(vibrationUsage)); + } + + public VibrationPreferenceConfig(Context context, String settingKey, + @VibrationAttributes.Usage int vibrationUsage) { mContentResolver = context.getContentResolver(); mVibrator = context.getSystemService(Vibrator.class); mAudioManager = context.getSystemService(AudioManager.class); @@ -71,9 +81,7 @@ public abstract class VibrationPreferenceConfig { R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary); mSettingKey = settingKey; mDefaultIntensity = mVibrator.getDefaultVibrationIntensity(vibrationUsage); - mVibrationAttributes = new VibrationAttributes.Builder() - .setUsage(vibrationUsage) - .build(); + mPreviewVibrationAttributes = createPreviewVibrationAttributes(vibrationUsage); } /** Returns the setting key for this setting preference. */ @@ -118,8 +126,7 @@ public abstract class VibrationPreferenceConfig { /** Play a vibration effect with intensity just selected by the user. */ public void playVibrationPreview() { - mVibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), - mVibrationAttributes); + mVibrator.vibrate(PREVIEW_VIBRATION_EFFECT, mPreviewVibrationAttributes); } private boolean isRingerModeSilent() { @@ -128,6 +135,16 @@ public abstract class VibrationPreferenceConfig { return mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT; } + private static VibrationAttributes createPreviewVibrationAttributes( + @VibrationAttributes.Usage int vibrationUsage) { + return new VibrationAttributes.Builder() + .setUsage(vibrationUsage) + // Enforce fresh settings to be applied for the preview vibration, as they + // are played immediately after the new user values are set. + .setFlags(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE) + .build(); + } + /** {@link ContentObserver} for a setting described by a {@link VibrationPreferenceConfig}. */ public static final class SettingObserver extends ContentObserver { private static final Uri MAIN_SWITCH_SETTING_URI = diff --git a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java index 8d1b43ee926..149bed35373 100644 --- a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java @@ -124,6 +124,12 @@ public class VibrationRampingRingerTogglePreferenceController if (isRingVibrationEnabled()) { // Don't update ramping ringer setting value if ring vibration is disabled. mAudioManager.setRampingRingerEnabled(isChecked); + + if (isChecked) { + // Vibrate when toggle is enabled for consistency with all the other toggle/slides + // in the same screen. + mRingVibrationPreferenceConfig.playVibrationPreview(); + } } return true; }