diff --git a/res/values/strings.xml b/res/values/strings.xml index 12f398b9f2b..32719495ab1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5565,8 +5565,10 @@ Longer Auto click time - + Vibration & haptics + + Control the vibration strength for different usages Calls @@ -5736,33 +5738,6 @@ %1$s seconds - - Ring %1$s, notification %2$s, touch %3$s - - - Ring & notification set to off - - - Ring & notification set to low - - - Ring & notification set to medium - - - Ring & notification set to high - - - Off - - - Low - - - Medium - - - High - Settings @@ -8427,6 +8402,8 @@ haptics, vibrate, screen, sensitivity haptics, vibrate, phone, call, sensitivity, ring + + haptics, vibrate, phone, call, ring, gradually haptics, vibrate, sensitivity diff --git a/res/xml/accessibility_notification_vibration_settings.xml b/res/xml/accessibility_notification_vibration_settings.xml deleted file mode 100644 index b37d3636db1..00000000000 --- a/res/xml/accessibility_notification_vibration_settings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - diff --git a/res/xml/accessibility_ring_vibration_settings.xml b/res/xml/accessibility_ring_vibration_settings.xml deleted file mode 100644 index 078f76c2ce8..00000000000 --- a/res/xml/accessibility_ring_vibration_settings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml index d836e24d9c7..dcf3fc2b6e7 100644 --- a/res/xml/accessibility_settings.xml +++ b/res/xml/accessibility_settings.xml @@ -110,7 +110,8 @@ android:persistent="false" android:title="@string/accessibility_vibration_settings_title" settings:controller="com.android.settings.accessibility.VibrationPreferenceController" - settings:keywords="@string/keywords_vibration"/> + settings:keywords="@string/keywords_vibration" + android:summary="@string/accessibility_vibration_settings_summary"/> diff --git a/res/xml/accessibility_touch_vibration_settings.xml b/res/xml/accessibility_touch_vibration_settings.xml deleted file mode 100644 index ed8f550a8b9..00000000000 --- a/res/xml/accessibility_touch_vibration_settings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - diff --git a/res/xml/accessibility_vibration_intensity_settings.xml b/res/xml/accessibility_vibration_intensity_settings.xml new file mode 100644 index 00000000000..d9a97f09aa9 --- /dev/null +++ b/res/xml/accessibility_vibration_intensity_settings.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/accessibility_vibration_settings.xml b/res/xml/accessibility_vibration_settings.xml index ff106110946..18cd7184b16 100644 --- a/res/xml/accessibility_vibration_settings.xml +++ b/res/xml/accessibility_vibration_settings.xml @@ -17,25 +17,23 @@ - + app:keywords="@string/keywords_ring_vibration" + app:controller="com.android.settings.accessibility.RingVibrationTogglePreferenceController" /> - + @@ -43,12 +41,11 @@ android:key="accessibility_notification_alarm_vibration_category" android:title="@string/accessibility_notification_alarm_vibration_category_title"> - + app:keywords="@string/keywords_notification_vibration" + app:controller="com.android.settings.accessibility.NotificationVibrationTogglePreferenceController" /> @@ -56,12 +53,11 @@ android:key="accessibility_interactive_haptics_category" android:title="@string/accessibility_interactive_haptics_category_title"> - + app:keywords="@string/keywords_touch_vibration" + app:controller="com.android.settings.accessibility.HapticFeedbackTogglePreferenceController" /> diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java index 4030e0dd777..8e8c7e45039 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettings.java +++ b/src/com/android/settings/accessibility/AccessibilitySettings.java @@ -294,11 +294,6 @@ public class AccessibilitySettings extends DashboardFragment { return info.loadDescription(context.getPackageManager()); } - static boolean isRampingRingerEnabled(final Context context) { - return Settings.System.getInt( - context.getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, 0) == 1; - } - @VisibleForTesting void onContentChanged() { // If the fragment is visible then update preferences immediately, else set the flag then diff --git a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java index f3e9b83bbcc..99d2bf5a199 100644 --- a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java @@ -16,31 +16,66 @@ package com.android.settings.accessibility; +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + import android.content.Context; import android.os.VibrationAttributes; +import android.os.Vibrator; import android.provider.Settings; -import androidx.annotation.VisibleForTesting; - +/** Preference controller for haptic feedback intensity */ public class HapticFeedbackIntensityPreferenceController extends VibrationIntensityPreferenceController { - @VisibleForTesting - static final String PREF_KEY = "touch_vibration_preference_screen"; + /** General configuration for haptic feedback intensity settings. */ + public static final class HapticFeedbackVibrationPreferenceConfig + extends VibrationPreferenceConfig { - public HapticFeedbackIntensityPreferenceController(Context context) { - super(context, PREF_KEY, Settings.System.HAPTIC_FEEDBACK_INTENSITY, - Settings.System.HAPTIC_FEEDBACK_ENABLED); + public HapticFeedbackVibrationPreferenceConfig(Context context) { + super(context, Settings.System.HAPTIC_FEEDBACK_INTENSITY, + VibrationAttributes.USAGE_TOUCH); + } + + @Override + public int readIntensity() { + final int hapticFeedbackEnabled = Settings.System.getInt(mContentResolver, + Settings.System.HAPTIC_FEEDBACK_ENABLED, ON); + + if (hapticFeedbackEnabled == OFF) { + // HAPTIC_FEEDBACK_ENABLED is deprecated but should still be applied if the user has + // turned it off already. + return Vibrator.VIBRATION_INTENSITY_OFF; + } + + return super.readIntensity(); + } + + @Override + public boolean updateIntensity(int intensity) { + final boolean success = super.updateIntensity(intensity); + final boolean isIntensityOff = intensity == Vibrator.VIBRATION_INTENSITY_OFF; + + Settings.System.putInt(mContentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, + isIntensityOff ? OFF : ON); + // HAPTIC_FEEDBACK_ENABLED is deprecated but should still reflect the intensity setting. + + // HARDWARE_HAPTIC_FEEDBACK_INTENSITY is dependent on this setting, but should not be + // disabled by it. + Settings.System.putInt(mContentResolver, + Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, + isIntensityOff ? getDefaultIntensity() : intensity); + + return success; + } + } + + public HapticFeedbackIntensityPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey, new HapticFeedbackVibrationPreferenceConfig(context)); } @Override public int getAvailabilityStatus() { return AVAILABLE; } - - @Override - protected int getDefaultIntensity() { - return mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH); - } - } diff --git a/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceController.java b/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceController.java new file mode 100644 index 00000000000..fdaf14048fe --- /dev/null +++ b/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceController.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 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 com.android.settings.accessibility.HapticFeedbackIntensityPreferenceController.HapticFeedbackVibrationPreferenceConfig; + +/** Preference controller for haptic feedback with only a toggle for on/off states. */ +public class HapticFeedbackTogglePreferenceController extends VibrationTogglePreferenceController { + + public HapticFeedbackTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey, new HapticFeedbackVibrationPreferenceConfig(context)); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } +} diff --git a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java index eb396ac87b7..31ae1873dc2 100644 --- a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java @@ -20,25 +20,27 @@ import android.content.Context; import android.os.VibrationAttributes; import android.provider.Settings; -import androidx.annotation.VisibleForTesting; - +/** Preference controller for notification vibration intensity */ public class NotificationVibrationIntensityPreferenceController extends VibrationIntensityPreferenceController { - @VisibleForTesting - static final String PREF_KEY = "notification_vibration_preference_screen"; + /** General configuration for notification vibration intensity settings. */ + public static final class NotificationVibrationPreferenceConfig + extends VibrationPreferenceConfig { - public NotificationVibrationIntensityPreferenceController(Context context) { - super(context, PREF_KEY, Settings.System.NOTIFICATION_VIBRATION_INTENSITY, ""); + public NotificationVibrationPreferenceConfig(Context context) { + super(context, Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + VibrationAttributes.USAGE_NOTIFICATION); + } + } + + public NotificationVibrationIntensityPreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey, new NotificationVibrationPreferenceConfig(context)); } @Override public int getAvailabilityStatus() { return AVAILABLE; } - - @Override - protected int getDefaultIntensity() { - return mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION); - } } diff --git a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java deleted file mode 100644 index e1d9d47df34..00000000000 --- a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2018 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.app.settings.SettingsEnums; -import android.media.AudioAttributes; -import android.os.VibrationAttributes; -import android.os.Vibrator; -import android.provider.Settings; - -import com.android.settings.R; - -/** - * Fragment for picking accessibility shortcut service - */ -public class NotificationVibrationPreferenceFragment extends VibrationPreferenceFragment { - @Override - public int getMetricsCategory() { - return SettingsEnums.ACCESSIBILITY_VIBRATION_NOTIFICATION; - } - - @Override - protected int getPreferenceScreenResId() { - return R.xml.accessibility_notification_vibration_settings; - } - - /** - * Get the setting string of the vibration intensity setting this preference is dealing with. - */ - @Override - protected String getVibrationIntensitySetting() { - return Settings.System.NOTIFICATION_VIBRATION_INTENSITY; - } - - @Override - protected String getVibrationEnabledSetting() { - return ""; - } - - @Override - protected int getPreviewVibrationAudioAttributesUsage() { - return AudioAttributes.USAGE_NOTIFICATION; - } - - @Override - protected int getDefaultVibrationIntensity() { - Vibrator vibrator = getContext().getSystemService(Vibrator.class); - return vibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION); - } -} diff --git a/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceController.java new file mode 100644 index 00000000000..2dc02a162e8 --- /dev/null +++ b/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceController.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 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 com.android.settings.accessibility.NotificationVibrationIntensityPreferenceController.NotificationVibrationPreferenceConfig; + +/** Preference controller for notification vibration with only a toggle for on/off states. */ +public class NotificationVibrationTogglePreferenceController + extends VibrationTogglePreferenceController { + + public NotificationVibrationTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey, new NotificationVibrationPreferenceConfig(context)); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } +} diff --git a/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java index 75cbefb4d52..1ddcf2bf726 100644 --- a/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java @@ -16,30 +16,63 @@ package com.android.settings.accessibility; +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + import android.content.Context; +import android.media.AudioManager; import android.os.VibrationAttributes; +import android.os.Vibrator; import android.provider.Settings; -import androidx.annotation.VisibleForTesting; - +/** Preference controller for ringtone vibration intensity */ public class RingVibrationIntensityPreferenceController extends VibrationIntensityPreferenceController { - @VisibleForTesting - static final String PREF_KEY = "ring_vibration_preference_screen"; + /** General configuration for ringtone vibration intensity settings. */ + public static final class RingVibrationPreferenceConfig extends VibrationPreferenceConfig { + private final AudioManager mAudioManager; - public RingVibrationIntensityPreferenceController(Context context) { - super(context, PREF_KEY, Settings.System.RING_VIBRATION_INTENSITY, - Settings.System.VIBRATE_WHEN_RINGING, /* supportRampingRinger= */ true); + public RingVibrationPreferenceConfig(Context context) { + super(context, Settings.System.RING_VIBRATION_INTENSITY, + VibrationAttributes.USAGE_RINGTONE); + mAudioManager = context.getSystemService(AudioManager.class); + } + + @Override + public int readIntensity() { + final int vibrateWhenRinging = Settings.System.getInt(mContentResolver, + Settings.System.VIBRATE_WHEN_RINGING, ON); + + if ((vibrateWhenRinging == OFF) + && !mAudioManager.isRampingRingerEnabled()) { + // VIBRATE_WHEN_RINGING is deprecated but should still be applied if the user has + // turned it off and has not enabled the ramping ringer (old three-state setting). + return Vibrator.VIBRATION_INTENSITY_OFF; + } + + return super.readIntensity(); + } + + @Override + public boolean updateIntensity(int intensity) { + final boolean success = super.updateIntensity(intensity); + + // VIBRATE_WHEN_RINGING is deprecated but should still reflect the intensity setting. + // Ramping ringer is independent of the ring intensity and should not be affected. + Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, + (intensity == Vibrator.VIBRATION_INTENSITY_OFF) ? OFF : ON); + + return success; + } + } + + public RingVibrationIntensityPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey, new RingVibrationPreferenceConfig(context)); } @Override public int getAvailabilityStatus() { return AVAILABLE; } - - @Override - protected int getDefaultIntensity() { - return mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE); - } } diff --git a/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java deleted file mode 100644 index aa3e313804a..00000000000 --- a/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2018 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.app.settings.SettingsEnums; -import android.media.AudioAttributes; -import android.os.VibrationAttributes; -import android.os.Vibrator; -import android.provider.Settings; - -import com.android.settings.R; - -/** - * Fragment for picking accessibility shortcut service - */ -public class RingVibrationPreferenceFragment extends VibrationPreferenceFragment { - @Override - public int getMetricsCategory() { - return SettingsEnums.ACCESSIBILITY_VIBRATION_RING; - } - - @Override - protected int getPreferenceScreenResId() { - return R.xml.accessibility_ring_vibration_settings; - } - - /** - * Get the setting string of the vibration intensity setting this preference is dealing with. - */ - @Override - protected String getVibrationIntensitySetting() { - return Settings.System.RING_VIBRATION_INTENSITY; - } - - @Override - protected String getVibrationEnabledSetting() { - if (AccessibilitySettings.isRampingRingerEnabled(getContext())) { - return Settings.System.APPLY_RAMPING_RINGER; - } else { - return Settings.System.VIBRATE_WHEN_RINGING; - } - } - - @Override - protected int getPreviewVibrationAudioAttributesUsage() { - return AudioAttributes.USAGE_NOTIFICATION_RINGTONE; - } - - @Override - protected int getDefaultVibrationIntensity() { - Vibrator vibrator = getContext().getSystemService(Vibrator.class); - return vibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE); - } -} diff --git a/src/com/android/settings/accessibility/RingVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/RingVibrationTogglePreferenceController.java new file mode 100644 index 00000000000..e68b6cead7b --- /dev/null +++ b/src/com/android/settings/accessibility/RingVibrationTogglePreferenceController.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 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 com.android.settings.accessibility.RingVibrationIntensityPreferenceController.RingVibrationPreferenceConfig; + +/** Preference controller for ringtone vibration with only a toggle for on/off states. */ +public class RingVibrationTogglePreferenceController extends VibrationTogglePreferenceController { + + public RingVibrationTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey, new RingVibrationPreferenceConfig(context)); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } +} diff --git a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java deleted file mode 100644 index b1bd8473df9..00000000000 --- a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2018 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.app.settings.SettingsEnums; -import android.media.AudioAttributes; -import android.os.VibrationAttributes; -import android.os.Vibrator; -import android.provider.Settings; - -import com.android.settings.R; - -/** - * Fragment for picking accessibility shortcut service - */ -public class TouchVibrationPreferenceFragment extends VibrationPreferenceFragment { - @Override - public int getMetricsCategory() { - return SettingsEnums.ACCESSIBILITY_VIBRATION_TOUCH; - } - - @Override - protected int getPreferenceScreenResId() { - return R.xml.accessibility_touch_vibration_settings; - } - - /** - * Get the setting string of the vibration intensity setting this preference is dealing with. - */ - @Override - protected String getVibrationIntensitySetting() { - return Settings.System.HAPTIC_FEEDBACK_INTENSITY; - } - - @Override - protected String getVibrationEnabledSetting() { - return Settings.System.HAPTIC_FEEDBACK_ENABLED; - } - - @Override - protected int getDefaultVibrationIntensity() { - Vibrator vibrator = getContext().getSystemService(Vibrator.class); - return vibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH); - } - - @Override - protected int getPreviewVibrationAudioAttributesUsage() { - return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; - } -} diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java index 9d7117640cd..e35b42c83a8 100644 --- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java @@ -17,116 +17,80 @@ package com.android.settings.accessibility; import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; import android.os.Vibrator; -import android.provider.Settings; -import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.SliderPreferenceController; +import com.android.settings.widget.SeekBarPreference; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; -public abstract class VibrationIntensityPreferenceController extends BasePreferenceController +/** + * Abstract preference controller for a vibration intensity setting, that displays multiple + * intensity levels to the user as a slider. + */ +public abstract class VibrationIntensityPreferenceController extends SliderPreferenceController implements LifecycleObserver, OnStart, OnStop { - protected final Vibrator mVibrator; - private final SettingObserver mSettingsContentObserver; - private final String mSettingKey; - private final String mEnabledKey; - private final boolean mSupportRampingRinger; + protected final VibrationPreferenceConfig mPreferenceConfig; + private final VibrationPreferenceConfig.SettingObserver mSettingsContentObserver; - private Preference mPreference; - - public VibrationIntensityPreferenceController(Context context, String prefkey, - String settingKey, String enabledKey, boolean supportRampingRinger) { + protected VibrationIntensityPreferenceController(Context context, String prefkey, + VibrationPreferenceConfig preferenceConfig) { super(context, prefkey); - mVibrator = mContext.getSystemService(Vibrator.class); - mSettingKey = settingKey; - mEnabledKey = enabledKey; - mSupportRampingRinger= supportRampingRinger; - mSettingsContentObserver = new SettingObserver(settingKey) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateState(mPreference); - } - }; - } - - public VibrationIntensityPreferenceController(Context context, String prefkey, - String settingKey, String enabledKey) { - this(context, prefkey, settingKey, enabledKey, /* supportRampingRinger= */ false); + mPreferenceConfig = preferenceConfig; + mSettingsContentObserver = new VibrationPreferenceConfig.SettingObserver( + preferenceConfig); } @Override public void onStart() { - mContext.getContentResolver().registerContentObserver( - mSettingsContentObserver.uri, - false /* notifyForDescendants */, - mSettingsContentObserver); + mSettingsContentObserver.register(mContext.getContentResolver()); } @Override public void onStop() { - mContext.getContentResolver().unregisterContentObserver(mSettingsContentObserver); + mSettingsContentObserver.unregister(mContext.getContentResolver()); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mPreference = screen.findPreference(getPreferenceKey()); + final SeekBarPreference preference = screen.findPreference(getPreferenceKey()); + mSettingsContentObserver.onDisplayPreference(this, preference); + // TODO: remove this 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()); } @Override - public CharSequence getSummary() { - final int intensity = Settings.System.getInt(mContext.getContentResolver(), - mSettingKey, getDefaultIntensity()); - final boolean enabled = (Settings.System.getInt(mContext.getContentResolver(), - mEnabledKey, 1) == 1) || - (mSupportRampingRinger && AccessibilitySettings.isRampingRingerEnabled(mContext)); - return getIntensityString(mContext, enabled ? intensity : Vibrator.VIBRATION_INTENSITY_OFF); + public int getMin() { + return Vibrator.VIBRATION_INTENSITY_OFF; } - public static CharSequence getIntensityString(Context context, int intensity) { - final boolean supportsMultipleIntensities = context.getResources().getBoolean( - R.bool.config_vibration_supports_multiple_intensities); - if (supportsMultipleIntensities) { - switch (intensity) { - case Vibrator.VIBRATION_INTENSITY_OFF: - return context.getString(R.string.accessibility_vibration_intensity_off); - case Vibrator.VIBRATION_INTENSITY_LOW: - return context.getString(R.string.accessibility_vibration_intensity_low); - case Vibrator.VIBRATION_INTENSITY_MEDIUM: - return context.getString(R.string.accessibility_vibration_intensity_medium); - case Vibrator.VIBRATION_INTENSITY_HIGH: - return context.getString(R.string.accessibility_vibration_intensity_high); - default: - return ""; - } - } else { - if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { - return context.getString(R.string.switch_off_text); - } else { - return context.getString(R.string.switch_on_text); - } - } + @Override + public int getMax() { + return Vibrator.VIBRATION_INTENSITY_HIGH; } - protected abstract int getDefaultIntensity(); + @Override + public int getSliderPosition() { + final int position = mPreferenceConfig.readIntensity(); + return Math.min(position, getMax()); + } - private static class SettingObserver extends ContentObserver { + @Override + public boolean setSliderPosition(int position) { + final boolean success = mPreferenceConfig.updateIntensity(position); - public final Uri uri; - - public SettingObserver(String settingKey) { - super(new Handler(Looper.getMainLooper())); - uri = Settings.System.getUriFor(settingKey); + if (success && (position != Vibrator.VIBRATION_INTENSITY_OFF)) { + mPreferenceConfig.playVibrationPreview(); } + + return success; } } diff --git a/src/com/android/settings/accessibility/VibrationPreferenceConfig.java b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java new file mode 100644 index 00000000000..aa59554b64a --- /dev/null +++ b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022 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.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.provider.Settings; + +import androidx.preference.Preference; + +import com.android.settingslib.core.AbstractPreferenceController; + +/** + * Vibration intensity settings configuration to be shared between different preference + * controllers that handle the same setting key. + */ +public abstract class VibrationPreferenceConfig { + + protected final ContentResolver mContentResolver; + private final Vibrator mVibrator; + private final String mSettingKey; + private final int mDefaultIntensity; + private final VibrationAttributes mVibrationAttributes; + + public VibrationPreferenceConfig(Context context, String settingKey, int vibrationUsage) { + mContentResolver = context.getContentResolver(); + mVibrator = context.getSystemService(Vibrator.class); + mSettingKey = settingKey; + mDefaultIntensity = mVibrator.getDefaultVibrationIntensity(vibrationUsage); + mVibrationAttributes = new VibrationAttributes.Builder() + .setUsage(vibrationUsage) + .build(); + } + + /** Return the setting key for this setting preference. */ + public String getSettingKey() { + return mSettingKey; + } + + /** Returns the default intensity to be displayed when the setting value is not set. */ + public int getDefaultIntensity() { + return mDefaultIntensity; + } + + /** Reads setting value for corresponding {@link VibrationPreferenceConfig} */ + public int readIntensity() { + return Settings.System.getInt(mContentResolver, mSettingKey, mDefaultIntensity); + } + + /** Update setting value for corresponding {@link VibrationPreferenceConfig} */ + public boolean updateIntensity(int intensity) { + return Settings.System.putInt(mContentResolver, mSettingKey, intensity); + } + + /** Play a vibration effect with intensity just selected by the user. */ + public void playVibrationPreview() { + mVibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), + mVibrationAttributes); + } + + /** {@link ContentObserver} for a setting described by a {@link VibrationPreferenceConfig}. */ + public static final class SettingObserver extends ContentObserver { + private final Uri mUri; + private AbstractPreferenceController mPreferenceController; + private Preference mPreference; + + /** Creates observer for given preference. */ + public SettingObserver(VibrationPreferenceConfig preferenceConfig) { + super(new Handler(/* async= */ true)); + mUri = Settings.System.getUriFor(preferenceConfig.getSettingKey()); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (mUri.equals(uri) && mPreferenceController != null && mPreference != null) { + mPreferenceController.updateState(mPreference); + } + } + + /** + * Register this observer to given {@link ContentResolver}, to be called from lifecycle + * {@code onStart} method. + */ + public void register(ContentResolver contentResolver) { + contentResolver.registerContentObserver(mUri, /* notifyForDescendants= */ false, this); + } + + /** + * Unregister this observer from given {@link ContentResolver}, to be called from lifecycle + * {@code onStop} method. + */ + public void unregister(ContentResolver contentResolver) { + contentResolver.unregisterContentObserver(this); + } + + /** + * Binds this observer to given controller and preference, once it has been displayed to the + * user. + */ + public void onDisplayPreference(AbstractPreferenceController controller, + Preference preference) { + mPreferenceController = controller; + mPreference = preference; + } + } +} diff --git a/src/com/android/settings/accessibility/VibrationPreferenceController.java b/src/com/android/settings/accessibility/VibrationPreferenceController.java deleted file mode 100644 index b36106d5db1..00000000000 --- a/src/com/android/settings/accessibility/VibrationPreferenceController.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2019 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 com.android.settings.R; -import com.android.settings.core.BasePreferenceController; - -public class VibrationPreferenceController extends BasePreferenceController { - - private final Vibrator mVibrator; - - public VibrationPreferenceController(Context context, String preferenceKey) { - super(context, preferenceKey); - mVibrator = mContext.getSystemService(Vibrator.class); - } - - @Override - public int getAvailabilityStatus() { - return AVAILABLE; - } - - @Override - public CharSequence getSummary() { - int ringIntensity = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.RING_VIBRATION_INTENSITY, - mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)); - if (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, 0) == 0 - && !AccessibilitySettings.isRampingRingerEnabled(mContext)) { - ringIntensity = Vibrator.VIBRATION_INTENSITY_OFF; - } - final CharSequence ringIntensityString = - VibrationIntensityPreferenceController.getIntensityString(mContext, ringIntensity); - - final int notificationIntensity = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.NOTIFICATION_VIBRATION_INTENSITY, - mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION)); - final CharSequence notificationIntensityString = - VibrationIntensityPreferenceController.getIntensityString(mContext, - notificationIntensity); - - int touchIntensity = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_INTENSITY, - mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH)); - if (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) { - touchIntensity = Vibrator.VIBRATION_INTENSITY_OFF; - } - final CharSequence touchIntensityString = - VibrationIntensityPreferenceController.getIntensityString(mContext, touchIntensity); - - if (ringIntensity == touchIntensity && ringIntensity == notificationIntensity) { - return ringIntensityString; - } else { - return mContext.getString(R.string.accessibility_vibration_summary, ringIntensityString, - notificationIntensityString, touchIntensityString); - } - } -} diff --git a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java deleted file mode 100644 index 2ef8f660079..00000000000 --- a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2018 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 static android.os.Vibrator.VibrationIntensity; - -import android.content.Context; -import android.database.ContentObserver; -import android.graphics.drawable.Drawable; -import android.media.AudioAttributes; -import android.net.Uri; -import android.os.Handler; -import android.os.VibrationEffect; -import android.os.Vibrator; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; - -import androidx.annotation.VisibleForTesting; - -import com.android.settings.R; -import com.android.settings.widget.RadioButtonPickerFragment; -import com.android.settingslib.widget.CandidateInfo; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -/** - * Fragment for changing vibration settings. - */ -public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragment { - private static final String TAG = "VibrationPreferenceFragment"; - - @VisibleForTesting - final static String KEY_INTENSITY_OFF = "intensity_off"; - @VisibleForTesting - final static String KEY_INTENSITY_LOW = "intensity_low"; - @VisibleForTesting - final static String KEY_INTENSITY_MEDIUM = "intensity_medium"; - @VisibleForTesting - final static String KEY_INTENSITY_HIGH = "intensity_high"; - // KEY_INTENSITY_ON is only used when the device doesn't support multiple intensity levels. - @VisibleForTesting - final static String KEY_INTENSITY_ON = "intensity_on"; - - private final Map mCandidates; - private final SettingsObserver mSettingsObserver; - - public VibrationPreferenceFragment() { - mCandidates = new ArrayMap<>(); - mSettingsObserver = new SettingsObserver(); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - mSettingsObserver.register(); - if (mCandidates.isEmpty()) { - loadCandidates(context); - } - } - - private void loadCandidates(Context context) { - final boolean supportsMultipleIntensities = context.getResources().getBoolean( - R.bool.config_vibration_supports_multiple_intensities); - if (supportsMultipleIntensities) { - mCandidates.put(KEY_INTENSITY_OFF, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF, - R.string.accessibility_vibration_intensity_off, - Vibrator.VIBRATION_INTENSITY_OFF)); - mCandidates.put(KEY_INTENSITY_LOW, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_LOW, - R.string.accessibility_vibration_intensity_low, - Vibrator.VIBRATION_INTENSITY_LOW)); - mCandidates.put(KEY_INTENSITY_MEDIUM, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_MEDIUM, - R.string.accessibility_vibration_intensity_medium, - Vibrator.VIBRATION_INTENSITY_MEDIUM)); - mCandidates.put(KEY_INTENSITY_HIGH, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_HIGH, - R.string.accessibility_vibration_intensity_high, - Vibrator.VIBRATION_INTENSITY_HIGH)); - } else { - mCandidates.put(KEY_INTENSITY_OFF, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF, - R.string.switch_off_text, Vibrator.VIBRATION_INTENSITY_OFF)); - mCandidates.put(KEY_INTENSITY_ON, - new VibrationIntensityCandidateInfo(KEY_INTENSITY_ON, - R.string.switch_on_text, getDefaultVibrationIntensity())); - } - } - - private boolean hasVibrationEnabledSetting() { - return !TextUtils.isEmpty(getVibrationEnabledSetting()); - } - - private void updateSettings(VibrationIntensityCandidateInfo candidate) { - boolean vibrationEnabled = candidate.getIntensity() != Vibrator.VIBRATION_INTENSITY_OFF; - if (hasVibrationEnabledSetting()) { - // Update vibration enabled setting - final String vibrationEnabledSetting = getVibrationEnabledSetting(); - final boolean wasEnabled = TextUtils.equals( - vibrationEnabledSetting, Settings.System.APPLY_RAMPING_RINGER) - ? true - : (Settings.System.getInt( - getContext().getContentResolver(), vibrationEnabledSetting, 1) == 1); - if (vibrationEnabled != wasEnabled) { - if (vibrationEnabledSetting.equals(Settings.System.APPLY_RAMPING_RINGER)) { - Settings.Global.putInt(getContext().getContentResolver(), - vibrationEnabledSetting, 0); - } else { - Settings.System.putInt(getContext().getContentResolver(), - vibrationEnabledSetting, vibrationEnabled ? 1 : 0); - } - - int previousIntensity = Settings.System.getInt(getContext().getContentResolver(), - getVibrationIntensitySetting(), 0); - if (vibrationEnabled && previousIntensity == candidate.getIntensity()) { - // We can't play preview effect here for all cases because that causes a data - // race (VibratorService may access intensity settings before these settings - // are updated). But we can't just play it in intensity settings update - // observer, because the intensity settings are not changed if we turn the - // vibration off, then on. - // - // In this case we sould play the preview here. - // To be refactored in b/132952771 - playVibrationPreview(); - } - } - } - // There are two conditions that need to change the intensity. - // First: Vibration is enabled and we are changing its strength. - // Second: There is no setting to enable this vibration, change the intensity directly. - if (vibrationEnabled || !hasVibrationEnabledSetting()) { - // Update vibration intensity setting - Settings.System.putInt(getContext().getContentResolver(), - getVibrationIntensitySetting(), candidate.getIntensity()); - } - } - - @Override - public void onDetach() { - super.onDetach(); - mSettingsObserver.unregister(); - } - - /** - * Get the setting string of the vibration intensity setting this preference is dealing with. - */ - protected abstract String getVibrationIntensitySetting(); - - /** - * Get the setting string of the vibration enabledness setting this preference is dealing with. - */ - protected abstract String getVibrationEnabledSetting(); - - /** - * Get the default intensity for the desired setting. - */ - protected abstract int getDefaultVibrationIntensity(); - - /** - * When a new vibration intensity is selected by the user. - */ - protected void onVibrationIntensitySelected(int intensity) { } - - /** - * Play a vibration effect with intensity just selected by user - */ - protected void playVibrationPreview() { - Vibrator vibrator = getContext().getSystemService(Vibrator.class); - VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); - AudioAttributes.Builder builder = new AudioAttributes.Builder(); - builder.setUsage(getPreviewVibrationAudioAttributesUsage()); - vibrator.vibrate(effect, builder.build()); - } - - /** - * Get the AudioAttributes usage for vibration preview. - */ - protected int getPreviewVibrationAudioAttributesUsage() { - return AudioAttributes.USAGE_UNKNOWN; - } - - @Override - protected List getCandidates() { - List candidates = new ArrayList<>(mCandidates.values()); - candidates.sort( - Comparator.comparing(VibrationIntensityCandidateInfo::getIntensity).reversed()); - return candidates; - } - - @Override - protected String getDefaultKey() { - int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(), - getVibrationIntensitySetting(), getDefaultVibrationIntensity()); - final String vibrationEnabledSetting = getVibrationEnabledSetting(); - final boolean vibrationEnabled = TextUtils.equals( - vibrationEnabledSetting, Settings.System.APPLY_RAMPING_RINGER) - ? true - : (Settings.System.getInt( - getContext().getContentResolver(), vibrationEnabledSetting, 1) == 1); - if (!vibrationEnabled) { - vibrationIntensity = Vibrator.VIBRATION_INTENSITY_OFF; - } - for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) { - final boolean matchesIntensity = candidate.getIntensity() == vibrationIntensity; - final boolean matchesOn = candidate.getKey().equals(KEY_INTENSITY_ON) - && vibrationIntensity != Vibrator.VIBRATION_INTENSITY_OFF; - if (matchesIntensity || matchesOn) { - return candidate.getKey(); - } - } - return null; - } - - @Override - protected boolean setDefaultKey(String key) { - VibrationIntensityCandidateInfo candidate = mCandidates.get(key); - if (candidate == null) { - Log.e(TAG, "Tried to set unknown intensity (key=" + key + ")!"); - return false; - } - updateSettings(candidate); - onVibrationIntensitySelected(candidate.getIntensity()); - return true; - } - - @VisibleForTesting - class VibrationIntensityCandidateInfo extends CandidateInfo { - private String mKey; - private int mLabelId; - @VibrationIntensity - private int mIntensity; - - public VibrationIntensityCandidateInfo(String key, int labelId, int intensity) { - super(true /* enabled */); - mKey = key; - mLabelId = labelId; - mIntensity = intensity; - } - - @Override - public CharSequence loadLabel() { - return getContext().getString(mLabelId); - } - - @Override - public Drawable loadIcon() { - return null; - } - - @Override - public String getKey() { - return mKey; - } - - public int getIntensity() { - return mIntensity; - } - } - - private class SettingsObserver extends ContentObserver { - public SettingsObserver() { - super(new Handler()); - } - - public void register() { - getContext().getContentResolver().registerContentObserver( - Settings.System.getUriFor(getVibrationIntensitySetting()), false, this); - } - - public void unregister() { - getContext().getContentResolver().unregisterContentObserver(this); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - updateCandidates(); - playVibrationPreview(); - } - } -} diff --git a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java new file mode 100644 index 00000000000..4a865386b1a --- /dev/null +++ b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2022 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.database.ContentObserver; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.os.VibrationAttributes; +import android.os.Vibrator; +import android.provider.DeviceConfig; +import android.provider.Settings; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import com.google.common.annotations.VisibleForTesting; + +/** + * Preference controller for the ramping ringer setting key, controlled via {@link AudioManager}. + * + *

This preference depends on the {@link Settings.System#RING_VIBRATION_INTENSITY}, and it will + * be disabled and display the unchecked state when the ring intensity is set to OFF. The actual + * ramping ringer setting will not be overwritten when the ring intensity is turned off, so the + * user original value will be naturally restored when the ring intensity is enabled again. + */ +public class VibrationRampingRingerTogglePreferenceController + extends TogglePreferenceController implements LifecycleObserver, OnStart, OnStop { + + @VisibleForTesting + static final String DEVICE_CONFIG_KEY = "ramping_ringer_enabled"; + + private final ContentObserver mSettingObserver; + private final Vibrator mVibrator; + private final AudioManager mAudioManager; + + private Preference mPreference; + + public VibrationRampingRingerTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mVibrator = context.getSystemService(Vibrator.class); + mAudioManager = context.getSystemService(AudioManager.class); + mSettingObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + updateState(mPreference); + } + }; + } + + @Override + public int getAvailabilityStatus() { + final boolean rampingRingerEnabledOnTelephonyConfig = + DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY, DEVICE_CONFIG_KEY, false); + return (Utils.isVoiceCapable(mContext) && !rampingRingerEnabledOnTelephonyConfig) + ? AVAILABLE + : UNSUPPORTED_ON_DEVICE; + } + + @Override + public void onStart() { + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER), + /* notifyForDescendants= */ false, + mSettingObserver); + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY), + /* notifyForDescendants= */ false, + mSettingObserver); + } + + @Override + public void onStop() { + mContext.getContentResolver().unregisterContentObserver(mSettingObserver); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + mPreference.setEnabled(isRingVibrationEnabled()); + } + + @Override + public boolean isChecked() { + return isRingVibrationEnabled() && mAudioManager.isRampingRingerEnabled(); + } + + @Override + public boolean setChecked(boolean isChecked) { + if (isRingVibrationEnabled()) { + // Don't update ramping ringer setting value if ring vibration is disabled. + mAudioManager.setRampingRingerEnabled(isChecked); + } + return true; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_accessibility; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (preference != null) { + preference.setEnabled(isRingVibrationEnabled()); + } + } + + private boolean isRingVibrationEnabled() { + final int ringIntensity = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.RING_VIBRATION_INTENSITY, + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)); + return ringIntensity != Vibrator.VIBRATION_INTENSITY_OFF; + } +} diff --git a/src/com/android/settings/accessibility/VibrationSettings.java b/src/com/android/settings/accessibility/VibrationSettings.java index 90ee11cf57d..277cfee09a3 100644 --- a/src/com/android/settings/accessibility/VibrationSettings.java +++ b/src/com/android/settings/accessibility/VibrationSettings.java @@ -41,7 +41,11 @@ public class VibrationSettings extends DashboardFragment { @Override protected int getPreferenceScreenResId() { - return R.xml.accessibility_vibration_settings; + final boolean supportsMultipleIntensities = getContext().getResources().getBoolean( + R.bool.config_vibration_supports_multiple_intensities); + return supportsMultipleIntensities + ? R.xml.accessibility_vibration_intensity_settings + : R.xml.accessibility_vibration_settings; } @Override diff --git a/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java new file mode 100644 index 00000000000..5278b662b36 --- /dev/null +++ b/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022 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.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +/** Abstract preference controller for a vibration intensity setting, that has only ON/OFF states */ +public abstract class VibrationTogglePreferenceController extends TogglePreferenceController + implements LifecycleObserver, OnStart, OnStop { + + protected final VibrationPreferenceConfig mPreferenceConfig; + private final VibrationPreferenceConfig.SettingObserver mSettingsContentObserver; + + protected VibrationTogglePreferenceController(Context context, String preferenceKey, + VibrationPreferenceConfig preferenceConfig) { + super(context, preferenceKey); + mPreferenceConfig = preferenceConfig; + mSettingsContentObserver = new VibrationPreferenceConfig.SettingObserver( + preferenceConfig); + } + + @Override + public void onStart() { + mSettingsContentObserver.register(mContext.getContentResolver()); + } + + @Override + public void onStop() { + mSettingsContentObserver.unregister(mContext.getContentResolver()); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + final Preference preference = screen.findPreference(getPreferenceKey()); + mSettingsContentObserver.onDisplayPreference(this, preference); + } + + @Override + public boolean isChecked() { + final int position = mPreferenceConfig.readIntensity(); + return position != Vibrator.VIBRATION_INTENSITY_OFF; + } + + @Override + public boolean setChecked(boolean isChecked) { + final int newIntensity = isChecked + ? mPreferenceConfig.getDefaultIntensity() + : Vibrator.VIBRATION_INTENSITY_OFF; + final boolean success = mPreferenceConfig.updateIntensity(newIntensity); + + if (success && isChecked) { + mPreferenceConfig.playVibrationPreview(); + } + + return success; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_accessibility; + } +} diff --git a/src/com/android/settings/notification/app/VibrationPreferenceController.java b/src/com/android/settings/notification/app/VibrationPreferenceController.java index bfbe768600f..34d1a543b56 100644 --- a/src/com/android/settings/notification/app/VibrationPreferenceController.java +++ b/src/com/android/settings/notification/app/VibrationPreferenceController.java @@ -25,7 +25,6 @@ import androidx.preference.Preference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.notification.NotificationBackend; -import com.android.settings.notification.app.NotificationPreferenceController; import com.android.settingslib.RestrictedSwitchPreference; public class VibrationPreferenceController extends NotificationPreferenceController @@ -36,7 +35,7 @@ public class VibrationPreferenceController extends NotificationPreferenceControl public VibrationPreferenceController(Context context, NotificationBackend backend) { super(context, backend); - mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + mVibrator = context.getSystemService(Vibrator.class); } @Override diff --git a/src/com/android/settings/sound/VibrateForCallsPreferenceController.java b/src/com/android/settings/sound/VibrateForCallsPreferenceController.java deleted file mode 100644 index 58c6ba5e707..00000000000 --- a/src/com/android/settings/sound/VibrateForCallsPreferenceController.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2020 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.sound; - -import android.content.Context; -import android.provider.DeviceConfig; -import android.provider.Settings; - -import androidx.annotation.VisibleForTesting; - -import com.android.settings.R; -import com.android.settings.Utils; -import com.android.settings.core.BasePreferenceController; - -/** - * Controller for vibrate for calls settings. - */ -public class VibrateForCallsPreferenceController extends BasePreferenceController { - - private static final int ON = 1; - private static final int OFF = 0; - @VisibleForTesting - static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled"; - - public VibrateForCallsPreferenceController(Context context, String preferenceKey) { - super(context, preferenceKey); - } - - @Override - @AvailabilityStatus - public int getAvailabilityStatus() { - return Utils.isVoiceCapable(mContext) && !DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_TELEPHONY, RAMPING_RINGER_ENABLED, false) - ? AVAILABLE - : UNSUPPORTED_ON_DEVICE; - } - - @Override - public CharSequence getSummary() { - if (Settings.System.getInt( - mContext.getContentResolver(), - Settings.System.APPLY_RAMPING_RINGER, OFF) == ON) { - return mContext.getText(R.string.vibrate_when_ringing_option_ramping_ringer); - } else if (Settings.System.getInt( - mContext.getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, OFF) == ON) { - return mContext.getText(R.string.vibrate_when_ringing_option_always_vibrate); - } else { - return mContext.getText(R.string.vibrate_when_ringing_option_never_vibrate); - } - } -} diff --git a/src/com/android/settings/sound/VibrateForCallsPreferenceFragment.java b/src/com/android/settings/sound/VibrateForCallsPreferenceFragment.java deleted file mode 100644 index a769de15ee8..00000000000 --- a/src/com/android/settings/sound/VibrateForCallsPreferenceFragment.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2019 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.sound; - -import android.app.settings.SettingsEnums; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; - -import androidx.annotation.VisibleForTesting; - -import com.android.settings.R; -import com.android.settings.widget.RadioButtonPickerFragment; -import com.android.settingslib.widget.CandidateInfo; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Fragment for changing vibrate for calls options. - */ -public class VibrateForCallsPreferenceFragment extends RadioButtonPickerFragment { - private static final String TAG = "VibrateForCallsPreferenceFragment"; - - @VisibleForTesting - static final String KEY_NEVER_VIBRATE = "never_vibrate"; - @VisibleForTesting - static final String KEY_ALWAYS_VIBRATE = "always_vibrate"; - @VisibleForTesting - static final String KEY_RAMPING_RINGER = "ramping_ringer"; - - private static final int ON = 1; - private static final int OFF = 0; - - private final Map mCandidates; - - public VibrateForCallsPreferenceFragment() { - mCandidates = new ArrayMap<>(); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - loadCandidates(context); - } - - private void loadCandidates(Context context) { - mCandidates.put(KEY_NEVER_VIBRATE, - new VibrateForCallsCandidateInfo( - KEY_NEVER_VIBRATE, R.string.vibrate_when_ringing_option_never_vibrate)); - mCandidates.put(KEY_ALWAYS_VIBRATE, - new VibrateForCallsCandidateInfo( - KEY_ALWAYS_VIBRATE, R.string.vibrate_when_ringing_option_always_vibrate)); - mCandidates.put(KEY_RAMPING_RINGER, - new VibrateForCallsCandidateInfo( - KEY_RAMPING_RINGER, R.string.vibrate_when_ringing_option_ramping_ringer)); - } - - private void updateSettings(VibrateForCallsCandidateInfo candidate) { - final String key = candidate.getKey(); - if (TextUtils.equals(key, KEY_ALWAYS_VIBRATE)) { - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, ON); - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, OFF); - } else if (TextUtils.equals(key, KEY_RAMPING_RINGER)) { - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, ON); - } else { - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt( - getContext().getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, OFF); - } - } - - @Override - protected List getCandidates() { - final List candidates = new ArrayList<>(); - candidates.add(mCandidates.get(KEY_NEVER_VIBRATE)); - candidates.add(mCandidates.get(KEY_ALWAYS_VIBRATE)); - candidates.add(mCandidates.get(KEY_RAMPING_RINGER)); - return candidates; - } - - @Override - protected String getDefaultKey() { - if (Settings.System.getInt( - getContext().getContentResolver(), - Settings.System.APPLY_RAMPING_RINGER, OFF) == ON) { - return KEY_RAMPING_RINGER; - } else if (Settings.System.getInt( - getContext().getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, OFF) == ON) { - return KEY_ALWAYS_VIBRATE; - } else { - return KEY_NEVER_VIBRATE; - } - } - - @Override - protected boolean setDefaultKey(String key) { - final VibrateForCallsCandidateInfo candidate = mCandidates.get(key); - if (candidate == null) { - Log.e(TAG, "Unknown vibrate for calls candidate (key = " + key + ")!"); - return false; - } - updateSettings(candidate); - return true; - } - - @Override - protected int getPreferenceScreenResId() { - return R.xml.vibrate_for_calls_settings; - } - - @Override - public int getMetricsCategory() { - return SettingsEnums.VIBRATE_FOR_CALLS; - } - - @VisibleForTesting - class VibrateForCallsCandidateInfo extends CandidateInfo { - private final String mKey; - private final int mLabelId; - - VibrateForCallsCandidateInfo(String key, int labelId) { - super(true /* enabled */); - mKey = key; - mLabelId = labelId; - } - - @Override - public CharSequence loadLabel() { - return getContext().getString(mLabelId); - } - - @Override - public Drawable loadIcon() { - return null; - } - - @Override - public String getKey() { - return mKey; - } - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java index c9f1b660cae..d1c59f708c9 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java @@ -52,7 +52,6 @@ import androidx.test.core.app.ApplicationProvider; import com.android.internal.content.PackageMonitor; import com.android.settings.R; import com.android.settings.testutils.XmlTestUtils; -import com.android.settings.testutils.shadow.ShadowDeviceConfig; import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settingslib.RestrictedPreference; @@ -143,22 +142,6 @@ public class AccessibilitySettingsTest { assertThat(indexableRawList).isNull(); } - @Test - @Config(shadows = {ShadowDeviceConfig.class}) - public void isRampingRingerEnabled_settingsFlagOn_Enabled() { - Settings.System.putInt( - mContext.getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, ON); - assertThat(AccessibilitySettings.isRampingRingerEnabled(mContext)).isTrue(); - } - - @Test - @Config(shadows = {ShadowDeviceConfig.class}) - public void isRampingRingerEnabled_settingsFlagOff_Disabled() { - Settings.System.putInt( - mContext.getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, OFF); - assertThat(AccessibilitySettings.isRampingRingerEnabled(mContext)).isFalse(); - } - @Test public void getServiceSummary_serviceCrash_showsStopped() { mServiceInfo.crashed = true; diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java index a454831ad25..4e8b3f63773 100644 --- a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java @@ -18,42 +18,136 @@ package com.android.settings.accessibility; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + import android.content.Context; +import android.os.VibrationAttributes; +import android.os.Vibrator; +import android.provider.Settings; import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; import com.android.settings.core.BasePreferenceController; +import com.android.settings.widget.SeekBarPreference; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class HapticFeedbackIntensityPreferenceControllerTest { + private static final String PREFERENCE_KEY = "preference_key"; + private static final int OFF = 0; + private static final int ON = 1; + + @Mock + private PreferenceScreen mScreen; + private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; private Context mContext; + private Vibrator mVibrator; private HapticFeedbackIntensityPreferenceController mController; + private SeekBarPreference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); - mContext = RuntimeEnvironment.application; - mController = new HapticFeedbackIntensityPreferenceController(mContext); + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new HapticFeedbackIntensityPreferenceController(mContext, PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SeekBarPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); } @Test public void verifyConstants() { - assertThat(mController.getPreferenceKey()) - .isEqualTo(HapticFeedbackIntensityPreferenceController.PREF_KEY); + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.AVAILABLE); + assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + } + + @Test + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_INTENSITY, /* value= */ null); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()) + .isEqualTo(mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH)); + } + + @Test + public void updateState_shouldDisplayIntensityInSliderPosition() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + } + + @Test + public void setProgress_updatesIntensityAndDependentSettings() throws Exception { + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); + } + + private void showPreference() { + mController.displayPreference(mScreen); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java new file mode 100644 index 00000000000..25455f46a4c --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 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 static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.VibrationAttributes; +import android.os.Vibrator; +import android.provider.Settings; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class HapticFeedbackTogglePreferenceControllerTest { + + private static final String PREFERENCE_KEY = "preference_key"; + private static final int OFF = 0; + private static final int ON = 1; + + @Mock + private PreferenceScreen mScreen; + + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private Context mContext; + private Vibrator mVibrator; + private HapticFeedbackTogglePreferenceController mController; + private SwitchPreference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new HapticFeedbackTogglePreferenceController(mContext, PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SwitchPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); + } + + @Test + public void verifyConstants() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_INTENSITY, /* value= */ null); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void updateState_shouldDisplayOnOffState() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void setChecked_updatesIntensityAndDependentSettings() throws Exception { + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + mPreference.setChecked(true); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH)); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(ON); + + mPreference.setChecked(false); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)).isEqualTo(OFF); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); + } + + private void showPreference() { + mController.displayPreference(mScreen); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java index 41accfb4d99..9dbd6d11016 100644 --- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java @@ -16,24 +16,22 @@ package com.android.settings.accessibility; -import static android.provider.Settings.System.NOTIFICATION_VIBRATION_INTENSITY; - import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; -import android.content.res.Resources; +import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; import androidx.lifecycle.LifecycleOwner; -import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; -import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.widget.SeekBarPreference; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; @@ -42,115 +40,105 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class NotificationVibrationIntensityPreferenceControllerTest { + private static final String PREFERENCE_KEY = "preference_key"; + @Mock private PreferenceScreen mScreen; private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; private Context mContext; - private Resources mResources; + private Vibrator mVibrator; private NotificationVibrationIntensityPreferenceController mController; - private Preference mPreference; + private SeekBarPreference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); - mContext = spy(RuntimeEnvironment.application); - mResources = spy(mContext.getResources()); - when(mContext.getResources()).thenReturn(mResources); - when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities)) - .thenReturn(true); - mController = new NotificationVibrationIntensityPreferenceController(mContext) { - @Override - protected int getDefaultIntensity() { - return 10; - } - }; + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new NotificationVibrationIntensityPreferenceController(mContext, + PREFERENCE_KEY); mLifecycle.addObserver(mController); - mPreference = new Preference(mContext); - mPreference.setSummary("Test"); - when(mScreen.findPreference(mController.getPreferenceKey())) - .thenReturn(mPreference); + mPreference = new SeekBarPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); } @Test public void verifyConstants() { - assertThat(mController.getPreferenceKey()) - .isEqualTo(NotificationVibrationIntensityPreferenceController.PREF_KEY); + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.AVAILABLE); + assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); } @Test - public void updateState_withMultipleIntensitySuport_shouldRefreshSummary() { - setSupportsMultipleIntensities(true); - showPreference(); - - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.NOTIFICATION_VIBRATION_INTENSITY, /* value= */ null); mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_low)); - - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); - mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_high)); - - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM); - mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_medium)); - - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); - mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_off)); + assertThat(mPreference.getProgress()).isEqualTo( + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION)); } @Test - public void updateState_withoutMultipleIntensitySupport_shouldRefreshSummary() { - setSupportsMultipleIntensities(false); - showPreference(); - - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + public void updateState_shouldDisplayIntensityInSliderPosition() { + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_HIGH); mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.switch_on_text)); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.switch_on_text)); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM); + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_LOW); mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.switch_on_text)); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); - Settings.System.putInt(mContext.getContentResolver(), - NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_OFF); mController.updateState(mPreference); - assertThat(mPreference.getSummary()) - .isEqualTo(mContext.getString(R.string.switch_off_text)); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); } - private void setSupportsMultipleIntensities(boolean hasSupport) { - when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities)) - .thenReturn(hasSupport); + + @Test + public void setProgress_updatesIntensitySetting() throws Exception { + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); } private void showPreference() { diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java new file mode 100644 index 00000000000..d40d77905aa --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 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 static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.VibrationAttributes; +import android.os.Vibrator; +import android.provider.Settings; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class NotificationVibrationTogglePreferenceControllerTest { + + private static final String PREFERENCE_KEY = "preference_key"; + + @Mock + private PreferenceScreen mScreen; + + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private Context mContext; + private Vibrator mVibrator; + private NotificationVibrationTogglePreferenceController mController; + private SwitchPreference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new NotificationVibrationTogglePreferenceController(mContext, PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SwitchPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); + } + + @Test + public void verifyConstants() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.NOTIFICATION_VIBRATION_INTENSITY, /* value= */ null); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void updateState_shouldDisplayOnOffState() { + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void setChecked_updatesIntensityAndDependentSettings() throws Exception { + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + mPreference.setChecked(true); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)).isEqualTo( + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION)); + + mPreference.setChecked(false); + assertThat(readSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); + } + + private void showPreference() { + mController.displayPreference(mScreen); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java index bd2206fc6fc..4e1730e0e01 100644 --- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java @@ -16,20 +16,24 @@ package com.android.settings.accessibility; -import static com.android.settings.core.BasePreferenceController.AVAILABLE; - import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.content.Context; import android.os.VibrationAttributes; import android.os.Vibrator; +import android.provider.Settings; +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.widget.SeekBarPreference; +import com.android.settingslib.core.lifecycle.Lifecycle; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,30 +44,112 @@ import org.robolectric.RobolectricTestRunner; /** Tests for {@link RingVibrationIntensityPreferenceController}. */ @RunWith(RobolectricTestRunner.class) public class RingVibrationIntensityPreferenceControllerTest { - @Mock - private Vibrator mVibrator; + private static final String PREFERENCE_KEY = "preference_key"; + private static final int OFF = 0; + private static final int ON = 1; + + @Mock + private PreferenceScreen mScreen; + + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private Context mContext; + private Vibrator mVibrator; private RingVibrationIntensityPreferenceController mController; + private SeekBarPreference mPreference; @Before - public void setUp() throws Exception { + public void setUp() { MockitoAnnotations.initMocks(this); - - final Context mContext = spy(ApplicationProvider.getApplicationContext()); - doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class); - mController = new RingVibrationIntensityPreferenceController(mContext); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new RingVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SeekBarPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); } @Test - public void getAvailabilityStatus_available() { - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + public void verifyConstants() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + assertThat(mController.getMin()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(mController.getMax()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); } @Test - public void getDefaultIntensity_success() { - doReturn(/* toBeReturned= */ 5).when(mVibrator).getDefaultVibrationIntensity( - eq(VibrationAttributes.USAGE_RINGTONE)); + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.RING_VIBRATION_INTENSITY, /* value= */ null); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo( + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)); + } - assertThat(mController.getDefaultIntensity()).isEqualTo(/* expected= */ 5); + @Test + public void updateState_shouldDisplayIntensityInSliderPosition() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + } + + + @Test + public void setProgress_updatesIntensityAndDependentSettings() throws Exception { + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_MEDIUM); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_MEDIUM); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_HIGH); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_HIGH); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON); + + mPreference.setProgress(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); + } + + private void showPreference() { + mController.displayPreference(mScreen); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationPreferenceFragmentTest.java deleted file mode 100644 index e2b1051d25d..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationPreferenceFragmentTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import android.content.Context; -import android.provider.Settings; - -import com.android.settings.testutils.shadow.ShadowDeviceConfig; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -@RunWith(RobolectricTestRunner.class) -public class RingVibrationPreferenceFragmentTest { - - private Context mContext; - private RingVibrationPreferenceFragment mFragment; - - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - mFragment = spy(new RingVibrationPreferenceFragment()); - doReturn(mContext).when(mFragment).getContext(); - } - - @Test - @Config(shadows = {ShadowDeviceConfig.class}) - public void getVibrationEnabledSetting_rampingRingerEnabled_returnApplyRampingRinger() { - // Turn on both flags to enable ramping ringer. - Settings.System.putInt( - mContext.getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, 1 /* ON */); - assertThat(mFragment.getVibrationEnabledSetting()).isEqualTo( - Settings.System.APPLY_RAMPING_RINGER); - } - - @Test - public void getVibrationEnabledSetting_rampingRingerDisabled_returnVibrationWhenRinging() { - // Turn off Settings.System.APPLY_RAMPING_RINGER to disable ramping ringer. - Settings.System.putInt( - mContext.getContentResolver(), Settings.System.APPLY_RAMPING_RINGER, 0 /* OFF */); - assertThat(mFragment.getVibrationEnabledSetting()).isEqualTo( - Settings.System.VIBRATE_WHEN_RINGING); - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java new file mode 100644 index 00000000000..2d1c69c3c73 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 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 static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.VibrationAttributes; +import android.os.Vibrator; +import android.provider.Settings; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class RingVibrationTogglePreferenceControllerTest { + + private static final String PREFERENCE_KEY = "preference_key"; + private static final int OFF = 0; + private static final int ON = 1; + + @Mock + private PreferenceScreen mScreen; + + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private Context mContext; + private Vibrator mVibrator; + private RingVibrationTogglePreferenceController mController; + private SwitchPreference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mContext = spy(ApplicationProvider.getApplicationContext()); + mVibrator = mContext.getSystemService(Vibrator.class); + mController = new RingVibrationTogglePreferenceController(mContext, PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SwitchPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); + } + + @Test + public void verifyConstants() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void missingSetting_shouldReturnDefault() { + Settings.System.putString(mContext.getContentResolver(), + Settings.System.RING_VIBRATION_INTENSITY, /* value= */ null); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void updateState_shouldDisplayOnOffState() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void setChecked_updatesIntensityAndDependentSettings() throws Exception { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + mPreference.setChecked(true); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)).isEqualTo( + mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(ON); + + mPreference.setChecked(false); + assertThat(readSetting(Settings.System.RING_VIBRATION_INTENSITY)) + .isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + assertThat(readSetting(Settings.System.VIBRATE_WHEN_RINGING)).isEqualTo(OFF); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private int readSetting(String settingKey) throws Settings.SettingNotFoundException { + return Settings.System.getInt(mContext.getContentResolver(), settingKey); + } + + private void showPreference() { + mController.displayPreference(mScreen); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java deleted file mode 100644 index e4d0f4577e4..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceControllerTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat; - -import android.content.Context; -import android.os.Vibrator; -import android.provider.Settings; - -import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class VibrationPreferenceControllerTest { - - private static final String VIBRATION_ON = "On"; - private static final String VIBRATION_OFF = "Off"; - - private Context mContext; - private VibrationPreferenceController mController; - - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - mController = new VibrationPreferenceController(mContext, "vibration_pref"); - } - - @Test - public void getAvailabilityStatus_byDefault_shouldReturnAvailable() { - assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.AVAILABLE); - } - - @Test - public void getSummary_disabledVibration_shouldReturnOffSummary() { - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); - final String expectedResult = mContext.getString(R.string.switch_off_text); - - assertThat(mController.getSummary()).isEqualTo(expectedResult); - } - - @Test - public void getSummary_enabledSomeVibration_shouldReturnVibrationOnSummary() { - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, 1); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM); - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_ENABLED, 1); - final String expectedResult = mContext.getString(R.string.accessibility_vibration_summary, - VIBRATION_ON /* ring */, - VIBRATION_OFF /* notification */, - VIBRATION_ON /* touch */); - - assertThat(mController.getSummary()).isEqualTo(expectedResult); - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java deleted file mode 100644 index 9f83f72850d..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2018 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 static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_HIGH; -import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_LOW; -import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_MEDIUM; -import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_OFF; -import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_ON; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.res.Resources; -import android.os.UserManager; -import android.os.Vibrator; -import android.provider.Settings; - -import com.android.settings.R; -import com.android.settings.accessibility.VibrationPreferenceFragment - .VibrationIntensityCandidateInfo; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settingslib.widget.CandidateInfo; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@RunWith(RobolectricTestRunner.class) -public class VibrationPreferenceFragmentTest { - - private static final Map INTENSITY_TO_KEY = new HashMap<>(4); - static { - INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_OFF, KEY_INTENSITY_OFF); - INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_LOW, KEY_INTENSITY_LOW); - INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_MEDIUM, KEY_INTENSITY_MEDIUM); - INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH); - } - - @Mock - private UserManager mUserManager; - - private Context mContext; - private Resources mResources; - private TestVibrationPreferenceFragment mFragment; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - FakeFeatureFactory.setupForTest(); - - mContext = spy(RuntimeEnvironment.application); - mResources = spy(mContext.getResources()); - when(mContext.getResources()).thenReturn(mResources); - - mFragment = spy(new TestVibrationPreferenceFragment()); - when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); - } - - @Test - public void changeIntensitySetting_shouldResultInCorrespondingKey() { - setSupportsMultipleIntensities(true); - mFragment.onAttach(mContext); - for (Map.Entry entry : INTENSITY_TO_KEY.entrySet()) { - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_INTENSITY, entry.getKey()); - assertThat(mFragment.getDefaultKey()).isEqualTo(entry.getValue()); - } - } - - @Test - public void changeIntensitySetting_WithoutMultipleIntensitySupport_shouldResultInOn() { - setSupportsMultipleIntensities(false); - mFragment.onAttach(mContext); - for (int intensity : INTENSITY_TO_KEY.keySet()) { - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.HAPTIC_FEEDBACK_INTENSITY, intensity); - final String expectedKey = intensity == Vibrator.VIBRATION_INTENSITY_OFF - ? KEY_INTENSITY_OFF - : KEY_INTENSITY_ON; - assertThat(mFragment.getDefaultKey()).isEqualTo(expectedKey); - } - } - - @Test - public void initialDefaultKey_shouldBeMedium() { - setSupportsMultipleIntensities(true); - mFragment.onAttach(mContext); - assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_MEDIUM); - } - - @Test - public void initialDefaultKey_WithoutMultipleIntensitySupport_shouldBeOn() { - setSupportsMultipleIntensities(false); - mFragment.onAttach(mContext); - assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_ON); - } - - @Test - public void candidates_shouldBeSortedByIntensity() { - setSupportsMultipleIntensities(true); - mFragment.onAttach(mContext); - final List candidates = mFragment.getCandidates(); - assertThat(candidates.size()).isEqualTo(INTENSITY_TO_KEY.size()); - VibrationIntensityCandidateInfo prevCandidate = - (VibrationIntensityCandidateInfo) candidates.get(0); - for (int i = 1; i < candidates.size(); i++) { - VibrationIntensityCandidateInfo candidate = - (VibrationIntensityCandidateInfo) candidates.get(i); - assertThat(candidate.getIntensity()).isLessThan(prevCandidate.getIntensity()); - } - } - - private void setSupportsMultipleIntensities(boolean hasSupport) { - when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities)) - .thenReturn(hasSupport); - } - - private class TestVibrationPreferenceFragment extends VibrationPreferenceFragment { - @Override - protected int getPreferenceScreenResId() { - return 0; - } - - @Override - public int getMetricsCategory() { - return 0; - } - - /** - * Get the setting string of the vibration intensity setting this preference is dealing with. - */ - @Override - protected String getVibrationIntensitySetting() { - return Settings.System.HAPTIC_FEEDBACK_INTENSITY; - } - - @Override - protected String getVibrationEnabledSetting() { - return ""; - } - - @Override - protected int getDefaultVibrationIntensity() { - return Vibrator.VIBRATION_INTENSITY_MEDIUM; - } - - @Override - public Context getContext() { - return mContext; - } - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java new file mode 100644 index 00000000000..08831c8f9e5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 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 static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.media.AudioManager; +import android.os.Vibrator; +import android.provider.DeviceConfig; +import android.provider.Settings; +import android.telephony.TelephonyManager; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class VibrationRampingRingerTogglePreferenceControllerTest { + + private static final String PREFERENCE_KEY = "preference_key"; + + @Mock + private PreferenceScreen mScreen; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private AudioManager mAudioManager; + + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private Context mContext; + private VibrationRampingRingerTogglePreferenceController mController; + private SwitchPreference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + mController = new VibrationRampingRingerTogglePreferenceController(mContext, + PREFERENCE_KEY); + mLifecycle.addObserver(mController); + mPreference = new SwitchPreference(mContext); + mPreference.setSummary("Test summary"); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + showPreference(); + } + + @Test + public void verifyConstants() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); + } + + @Test + public void getAvailabilityStatus_notVoiceCapable_returnUnsupportedOnDevice() { + when(mTelephonyManager.isVoiceCapable()).thenReturn(false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, + VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "false", false); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_rampingRingerEnabled_returnUnsupportedOnDevice() { + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, + VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "true", false); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_voiceCapableAndRampingRingerDisabled_returnAvailable() { + when(mTelephonyManager.isVoiceCapable()).thenReturn(true); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, + VibrationRampingRingerTogglePreferenceController.DEVICE_CONFIG_KEY, "false", false); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void updateState_withRingDisabled_shouldReturnFalseForCheckedAndEnabled() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + when(mAudioManager.isRampingRingerEnabled()).thenReturn(true); + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void updateState_withRingEnabled_shouldReturnTheSettingStateAndAlwaysEnabled() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + when(mAudioManager.isRampingRingerEnabled()).thenReturn(true, false); + + mController.updateState(mPreference); + assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isChecked()).isTrue(); + + mController.updateState(mPreference); + assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void setChecked_withRingDisabled_ignoresUpdates() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + + mPreference.setChecked(true); + mPreference.setChecked(false); + verify(mAudioManager, never()).setRampingRingerEnabled(anyBoolean()); + } + + @Test + public void setChecked_withRingEnabled_updatesSetting() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + + mPreference.setChecked(true); + verify(mAudioManager).setRampingRingerEnabled(true); + + mPreference.setChecked(false); + verify(mAudioManager).setRampingRingerEnabled(false); + } + + private void updateSetting(String key, int value) { + Settings.System.putInt(mContext.getContentResolver(), key, value); + } + + private void showPreference() { + mController.displayPreference(mScreen); + } +} diff --git a/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceControllerTest.java deleted file mode 100644 index 1f4ba96f7a9..00000000000 --- a/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceControllerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2020 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.sound; - -import static com.android.settings.core.BasePreferenceController.AVAILABLE; -import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.ContentResolver; -import android.content.Context; -import android.provider.DeviceConfig; -import android.provider.Settings; -import android.telephony.TelephonyManager; - -import com.android.settings.R; -import com.android.settings.testutils.shadow.ShadowDeviceConfig; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -@RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowDeviceConfig.class}) -public class VibrateForCallsPreferenceControllerTest { - - private static final int OFF = 0; - private static final int ON = 1; - private Context mContext; - private ContentResolver mContentResolver; - @Mock - private TelephonyManager mTelephonyManager; - private VibrateForCallsPreferenceController mController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - mContentResolver = mContext.getContentResolver(); - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - mController = new VibrateForCallsPreferenceController( - mContext, VibrateForCallsPreferenceController.RAMPING_RINGER_ENABLED); - } - - @Test - public void getAvailabilityStatus_notVoiceCapable_returnUnsupportedOnDevice() { - when(mTelephonyManager.isVoiceCapable()).thenReturn(false); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, - VibrateForCallsPreferenceController.RAMPING_RINGER_ENABLED, "false", false); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); - } - - @Test - public void getAvailabilityStatus_rampingRingerEnabled_returnUnsupportedOnDevice() { - when(mTelephonyManager.isVoiceCapable()).thenReturn(true); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, - VibrateForCallsPreferenceController.RAMPING_RINGER_ENABLED, "true", false); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); - } - - @Test - public void getAvailabilityStatus_voiceCapableAndRampingRingerDisabled_returnAvailable() { - when(mTelephonyManager.isVoiceCapable()).thenReturn(true); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_TELEPHONY, - VibrateForCallsPreferenceController.RAMPING_RINGER_ENABLED, "false", false); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); - } - - @Test - public void getSummary_applyRampingRinger_rampingRingerSummary() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, ON); - - assertThat(mController.getSummary()).isEqualTo( - mContext.getText(R.string.vibrate_when_ringing_option_ramping_ringer)); - } - - @Test - public void getSummary_enableVibrateWhenRinging_alwaysVibrateSummary() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, ON); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF); - - assertThat(mController.getSummary()).isEqualTo( - mContext.getText(R.string.vibrate_when_ringing_option_always_vibrate)); - } - - @Test - public void getSummary_notApplyRampingRingerDisableVibrateWhenRinging_neverVibrateSummary() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF); - - assertThat(mController.getSummary()).isEqualTo( - mContext.getText(R.string.vibrate_when_ringing_option_never_vibrate)); - } -} diff --git a/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceFragmentTest.java deleted file mode 100644 index 889e5a6f9d6..00000000000 --- a/tests/robotests/src/com/android/settings/sound/VibrateForCallsPreferenceFragmentTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2020 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.sound; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import android.content.ContentResolver; -import android.content.Context; -import android.provider.Settings; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class VibrateForCallsPreferenceFragmentTest { - - private static final int OFF = 0; - private static final int ON = 1; - private Context mContext; - private ContentResolver mContentResolver; - private VibrateForCallsPreferenceFragment mFragment; - - @Before - public void setUp() { - mContext = spy(RuntimeEnvironment.application); - mContentResolver = mContext.getContentResolver(); - mFragment = spy(new VibrateForCallsPreferenceFragment()); - doReturn(mContext).when(mFragment).getContext(); - mFragment.onAttach(mContext); - } - - @Test - public void getDefaultKey_applyRampingRinger_keyRampingRinger() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, ON); - - assertThat(mFragment.getDefaultKey()).isEqualTo( - VibrateForCallsPreferenceFragment.KEY_RAMPING_RINGER); - } - - @Test - public void getDefaultKey_enableVibrateWhenRinging_keyAlwaysVibrate() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, ON); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF); - - assertThat(mFragment.getDefaultKey()).isEqualTo( - VibrateForCallsPreferenceFragment.KEY_ALWAYS_VIBRATE); - } - - @Test - public void getDefaultKey_notApplyRampingRingerDisableVibrateWhenRinging_keyNeverVibrate() { - Settings.System.putInt(mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF); - Settings.System.putInt(mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF); - - assertThat(mFragment.getDefaultKey()).isEqualTo( - VibrateForCallsPreferenceFragment.KEY_NEVER_VIBRATE); - } - - @Test - public void setDefaultKey_keyRampingRinger_applyRampingRingerDisableVibrateWhenRinging() { - mFragment.setDefaultKey(VibrateForCallsPreferenceFragment.KEY_RAMPING_RINGER); - - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF)).isEqualTo(ON); - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF)).isEqualTo(OFF); - } - - @Test - public void setDefaultKey_keyAlwaysVibrate_notApplyRampingRingerEnableVibrateWhenRinging() { - mFragment.setDefaultKey(VibrateForCallsPreferenceFragment.KEY_ALWAYS_VIBRATE); - - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF)).isEqualTo(OFF); - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF)).isEqualTo(ON); - } - - @Test - public void setDefaultKey_keyNeverVibrate_notApplyRampingRingerDisableVibrateWhenRinging() { - mFragment.setDefaultKey(VibrateForCallsPreferenceFragment.KEY_NEVER_VIBRATE); - - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.APPLY_RAMPING_RINGER, OFF)).isEqualTo(OFF); - assertThat(Settings.System.getInt( - mContentResolver, Settings.System.VIBRATE_WHEN_RINGING, OFF)).isEqualTo(OFF); - } -}