diff --git a/res/values/strings.xml b/res/values/strings.xml index ec72321ced8..70a47fe66da 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5457,6 +5457,8 @@ Vibration & haptics Control the vibration strength for different usages + + Setting disabled because device is set to silent Calls diff --git a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java index 98fd5f2315c..05dc7840155 100644 --- a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java @@ -37,6 +37,12 @@ public class HapticFeedbackIntensityPreferenceController VibrationAttributes.USAGE_TOUCH); } + @Override + public boolean isRestrictedByRingerModeSilent() { + // Touch feedback is disabled when the phone is in silent mode. + return true; + } + @Override public int readIntensity() { final int hapticFeedbackEnabled = Settings.System.getInt(mContentResolver, diff --git a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java index cee45f6065d..951d322b98e 100644 --- a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java @@ -32,6 +32,12 @@ public class NotificationVibrationIntensityPreferenceController super(context, Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VibrationAttributes.USAGE_NOTIFICATION); } + + @Override + public boolean isRestrictedByRingerModeSilent() { + // Notifications never vibrate when the phone is in silent mode. + return true; + } } public NotificationVibrationIntensityPreferenceController(Context context, diff --git a/src/com/android/settings/accessibility/RingVibrationPreferenceConfig.java b/src/com/android/settings/accessibility/RingVibrationPreferenceConfig.java index da446d77ac8..f4ec7473d16 100644 --- a/src/com/android/settings/accessibility/RingVibrationPreferenceConfig.java +++ b/src/com/android/settings/accessibility/RingVibrationPreferenceConfig.java @@ -35,6 +35,12 @@ public class RingVibrationPreferenceConfig extends VibrationPreferenceConfig { mAudioManager = context.getSystemService(AudioManager.class); } + @Override + public boolean isRestrictedByRingerModeSilent() { + // Incoming calls never vibrate when the phone is in silent mode. + return true; + } + @Override public int readIntensity() { final int vibrateWhenRinging = Settings.System.getInt(mContentResolver, diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java index b3e8168af87..6441eeb4571 100644 --- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java @@ -58,12 +58,12 @@ public abstract class VibrationIntensityPreferenceController extends SliderPrefe @Override public void onStart() { - mSettingsContentObserver.register(mContext.getContentResolver()); + mSettingsContentObserver.register(mContext); } @Override public void onStop() { - mSettingsContentObserver.unregister(mContext.getContentResolver()); + mSettingsContentObserver.unregister(mContext); } @Override @@ -72,6 +72,7 @@ public abstract class VibrationIntensityPreferenceController extends SliderPrefe final SeekBarPreference preference = screen.findPreference(getPreferenceKey()); mSettingsContentObserver.onDisplayPreference(this, preference); preference.setEnabled(mPreferenceConfig.isPreferenceEnabled()); + preference.setSummaryProvider(unused -> mPreferenceConfig.getSummary()); // TODO: remove setContinuousUpdates and replace with a different way to play the haptic // preview without relying on the setting being propagated to the service. preference.setContinuousUpdates(true); diff --git a/src/com/android/settings/accessibility/VibrationPreferenceConfig.java b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java index 1b0b1635456..9208b188c49 100644 --- a/src/com/android/settings/accessibility/VibrationPreferenceConfig.java +++ b/src/com/android/settings/accessibility/VibrationPreferenceConfig.java @@ -18,9 +18,13 @@ package com.android.settings.accessibility; import static com.android.settings.accessibility.AccessibilityUtil.State.ON; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.database.ContentObserver; +import android.media.AudioManager; import android.net.Uri; import android.os.Handler; import android.os.VibrationAttributes; @@ -28,8 +32,10 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings; +import androidx.annotation.Nullable; import androidx.preference.Preference; +import com.android.settings.R; import com.android.settingslib.core.AbstractPreferenceController; /** @@ -45,8 +51,10 @@ public abstract class VibrationPreferenceConfig { public static final String MAIN_SWITCH_SETTING_KEY = Settings.System.VIBRATE_ON; protected final ContentResolver mContentResolver; + private final AudioManager mAudioManager; private final Vibrator mVibrator; private final String mSettingKey; + private final String mRingerModeSilentSummary; private final int mDefaultIntensity; private final VibrationAttributes mVibrationAttributes; @@ -58,6 +66,9 @@ public abstract class VibrationPreferenceConfig { public VibrationPreferenceConfig(Context context, String settingKey, int vibrationUsage) { mContentResolver = context.getContentResolver(); mVibrator = context.getSystemService(Vibrator.class); + mAudioManager = context.getSystemService(AudioManager.class); + mRingerModeSilentSummary = context.getString( + R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary); mSettingKey = settingKey; mDefaultIntensity = mVibrator.getDefaultVibrationIntensity(vibrationUsage); mVibrationAttributes = new VibrationAttributes.Builder() @@ -70,9 +81,24 @@ public abstract class VibrationPreferenceConfig { return mSettingKey; } + /** Returns the summary string for this setting preference. */ + @Nullable + public CharSequence getSummary() { + return isRestrictedByRingerModeSilent() && isRingerModeSilent() + ? mRingerModeSilentSummary : null; + } + /** Returns true if this setting preference is enabled for user update. */ public boolean isPreferenceEnabled() { - return isMainVibrationSwitchEnabled(mContentResolver); + return isMainVibrationSwitchEnabled(mContentResolver) + && (!isRestrictedByRingerModeSilent() || !isRingerModeSilent()); + } + + /** + * Returns true if this setting preference should be disabled when the device is in silent mode. + */ + public boolean isRestrictedByRingerModeSilent() { + return false; } /** Returns the default intensity to be displayed when the setting value is not set. */ @@ -96,12 +122,23 @@ public abstract class VibrationPreferenceConfig { mVibrationAttributes); } + private boolean isRingerModeSilent() { + // AudioManager.isSilentMode() also returns true when ringer mode is VIBRATE. + // The vibration preferences are only disabled when the ringer mode is SILENT. + return mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT; + } + /** {@link ContentObserver} for a setting described by a {@link VibrationPreferenceConfig}. */ public static final class SettingObserver extends ContentObserver { private static final Uri MAIN_SWITCH_SETTING_URI = Settings.System.getUriFor(MAIN_SWITCH_SETTING_KEY); + private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER = + new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); private final Uri mUri; + @Nullable + private final BroadcastReceiver mRingerModeChangeReceiver; + private AbstractPreferenceController mPreferenceController; private Preference mPreference; @@ -109,35 +146,63 @@ public abstract class VibrationPreferenceConfig { public SettingObserver(VibrationPreferenceConfig preferenceConfig) { super(new Handler(/* async= */ true)); mUri = Settings.System.getUriFor(preferenceConfig.getSettingKey()); + + if (preferenceConfig.isRestrictedByRingerModeSilent()) { + // If this preference is restricted by AudioManager.getRingerModeInternal() result + // for the device mode, then listen to changes in that value using the broadcast + // intent action INTERNAL_RINGER_MODE_CHANGED_ACTION. + mRingerModeChangeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { + notifyChange(); + } + } + }; + } else { + // No need to register a receiver if this preference is not affected by ringer mode. + mRingerModeChangeReceiver = null; + } } @Override public void onChange(boolean selfChange, Uri uri) { - if (mPreferenceController == null || mPreference == null) { - // onDisplayPreference not triggered yet, nothing to update. - return; - } if (mUri.equals(uri) || MAIN_SWITCH_SETTING_URI.equals(uri)) { + notifyChange(); + } + } + + private void notifyChange() { + if (mPreferenceController != null && mPreference != null) { mPreferenceController.updateState(mPreference); } } /** - * Register this observer to given {@link ContentResolver}, to be called from lifecycle + * Register this observer to given {@link Context}, to be called from lifecycle * {@code onStart} method. */ - public void register(ContentResolver contentResolver) { - contentResolver.registerContentObserver(mUri, /* notifyForDescendants= */ false, this); - contentResolver.registerContentObserver(MAIN_SWITCH_SETTING_URI, - /* notifyForDescendants= */ false, this); + public void register(Context context) { + if (mRingerModeChangeReceiver != null) { + context.registerReceiver(mRingerModeChangeReceiver, + INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER); + } + context.getContentResolver().registerContentObserver( + mUri, /* notifyForDescendants= */ false, this); + context.getContentResolver().registerContentObserver( + MAIN_SWITCH_SETTING_URI, /* notifyForDescendants= */ false, this); } /** - * Unregister this observer from given {@link ContentResolver}, to be called from lifecycle + * Unregister this observer from given {@link Context}, to be called from lifecycle * {@code onStop} method. */ - public void unregister(ContentResolver contentResolver) { - contentResolver.unregisterContentObserver(this); + public void unregister(Context context) { + if (mRingerModeChangeReceiver != null) { + context.unregisterReceiver(mRingerModeChangeReceiver); + } + context.getContentResolver().unregisterContentObserver(this); } /** diff --git a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java index 37a0257cb20..8d1b43ee926 100644 --- a/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceController.java @@ -93,7 +93,7 @@ public class VibrationRampingRingerTogglePreferenceController @Override public void onStart() { - mRingSettingObserver.register(mContext.getContentResolver()); + mRingSettingObserver.register(mContext); mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER), /* notifyForDescendants= */ false, @@ -102,7 +102,7 @@ public class VibrationRampingRingerTogglePreferenceController @Override public void onStop() { - mRingSettingObserver.unregister(mContext.getContentResolver()); + mRingSettingObserver.unregister(mContext); mContext.getContentResolver().unregisterContentObserver(mSettingObserver); } diff --git a/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java index 8f158cc04b5..c60158daac1 100644 --- a/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationTogglePreferenceController.java @@ -45,12 +45,12 @@ public abstract class VibrationTogglePreferenceController extends TogglePreferen @Override public void onStart() { - mSettingsContentObserver.register(mContext.getContentResolver()); + mSettingsContentObserver.register(mContext); } @Override public void onStop() { - mSettingsContentObserver.unregister(mContext.getContentResolver()); + mSettingsContentObserver.unregister(mContext); } @Override @@ -66,6 +66,7 @@ public abstract class VibrationTogglePreferenceController extends TogglePreferen super.updateState(preference); if (preference != null) { preference.setEnabled(mPreferenceConfig.isPreferenceEnabled()); + preference.setSummary(mPreferenceConfig.getSummary()); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java index 2273a3ed2fd..9d87c93c1df 100644 --- a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -48,6 +50,7 @@ public class HapticFeedbackIntensityPreferenceControllerTest { private static final int ON = 1; @Mock private PreferenceScreen mScreen; + @Mock private AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -59,7 +62,9 @@ public class HapticFeedbackIntensityPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new HapticFeedbackIntensityPreferenceController(mContext, PREFERENCE_KEY, Vibrator.VIBRATION_INTENSITY_HIGH); @@ -88,6 +93,54 @@ public class HapticFeedbackIntensityPreferenceControllerTest { .isEqualTo(mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH)); } + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + // TODO(b/136805769): summary is broken in SeekBarPreference, enable this once fixed +// assertThat(mPreference.getSummary()).isNotNull(); +// assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( +// R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void updateState_hapticFeedbackDisabled_shouldDisplayAlwaysOff() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, OFF); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + } + @Test public void updateState_shouldDisplayIntensityInSliderPosition() { updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); diff --git a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java index f992b0ef029..3e8aeac6b59 100644 --- a/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/HapticFeedbackTogglePreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -29,6 +31,7 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -48,6 +51,7 @@ public class HapticFeedbackTogglePreferenceControllerTest { private static final int ON = 1; @Mock private PreferenceScreen mScreen; + @Mock AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -59,7 +63,9 @@ public class HapticFeedbackTogglePreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new HapticFeedbackTogglePreferenceController(mContext, PREFERENCE_KEY); mLifecycle.addObserver(mController); @@ -84,6 +90,54 @@ public class HapticFeedbackTogglePreferenceControllerTest { assertThat(mPreference.isChecked()).isTrue(); } + + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.getSummary()).isNotNull(); + assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( + R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void updateState_hapticFeedbackDisabled_shouldDisplayAlwaysOff() { + updateSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, OFF); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + } + @Test public void updateState_shouldDisplayOnOffState() { updateSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java index d0be8b57c6a..9533c5389de 100644 --- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -46,6 +48,7 @@ public class NotificationVibrationIntensityPreferenceControllerTest { private static final String PREFERENCE_KEY = "preference_key"; @Mock private PreferenceScreen mScreen; + @Mock private AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -57,7 +60,9 @@ public class NotificationVibrationIntensityPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new NotificationVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY, Vibrator.VIBRATION_INTENSITY_HIGH); @@ -86,6 +91,34 @@ public class NotificationVibrationIntensityPreferenceControllerTest { mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION)); } + + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + // TODO(b/136805769): summary is broken in SeekBarPreference, enable this once fixed +// assertThat(mPreference.getSummary()).isNotNull(); +// assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( +// R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + @Test public void updateState_shouldDisplayIntensityInSliderPosition() { updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java index adf94361b3c..4b6f686fa1b 100644 --- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationTogglePreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -29,6 +31,7 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -46,6 +49,7 @@ public class NotificationVibrationTogglePreferenceControllerTest { private static final String PREFERENCE_KEY = "preference_key"; @Mock private PreferenceScreen mScreen; + @Mock private AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -57,7 +61,9 @@ public class NotificationVibrationTogglePreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new NotificationVibrationTogglePreferenceController(mContext, PREFERENCE_KEY); mLifecycle.addObserver(mController); @@ -82,6 +88,32 @@ public class NotificationVibrationTogglePreferenceControllerTest { assertThat(mPreference.isChecked()).isTrue(); } + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.getSummary()).isNotNull(); + assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( + R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + @Test public void updateState_shouldDisplayOnOffState() { updateSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java index d891926c418..2bffaf4d011 100644 --- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -49,6 +51,7 @@ public class RingVibrationIntensityPreferenceControllerTest { private static final int ON = 1; @Mock private PreferenceScreen mScreen; + @Mock private AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -60,7 +63,9 @@ public class RingVibrationIntensityPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new RingVibrationIntensityPreferenceController(mContext, PREFERENCE_KEY, Vibrator.VIBRATION_INTENSITY_HIGH); @@ -89,6 +94,55 @@ public class RingVibrationIntensityPreferenceControllerTest { mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)); } + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + // TODO(b/136805769): summary is broken in SeekBarPreference, enable this once fixed +// assertThat(mPreference.getSummary()).isNotNull(); +// assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( +// R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_LOW); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void updateState_vibrateWhenRingingAndRampingRingerOff_shouldDisplayAlwaysOff() { + when(mAudioManager.isRampingRingerEnabled()).thenReturn(false); + updateSetting(Settings.System.VIBRATE_WHEN_RINGING, OFF); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); + } + @Test public void updateState_shouldDisplayIntensityInSliderPosition() { updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); @@ -109,7 +163,6 @@ public class RingVibrationIntensityPreferenceControllerTest { assertThat(mPreference.getProgress()).isEqualTo(Vibrator.VIBRATION_INTENSITY_OFF); } - @Test @Ignore public void setProgress_updatesIntensityAndDependentSettings() throws Exception { diff --git a/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java index 8e85c86d901..08ad1cdade1 100644 --- a/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/RingVibrationTogglePreferenceControllerTest.java @@ -18,9 +18,11 @@ 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.media.AudioManager; import android.os.VibrationAttributes; import android.os.Vibrator; import android.provider.Settings; @@ -29,6 +31,7 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -48,6 +51,7 @@ public class RingVibrationTogglePreferenceControllerTest { private static final int ON = 1; @Mock private PreferenceScreen mScreen; + @Mock private AudioManager mAudioManager; private Lifecycle mLifecycle; private Context mContext; @@ -59,7 +63,9 @@ public class RingVibrationTogglePreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mLifecycle = new Lifecycle(() -> mLifecycle); - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mVibrator = mContext.getSystemService(Vibrator.class); mController = new RingVibrationTogglePreferenceController(mContext, PREFERENCE_KEY); mLifecycle.addObserver(mController); @@ -84,6 +90,54 @@ public class RingVibrationTogglePreferenceControllerTest { assertThat(mPreference.isChecked()).isTrue(); } + @Test + public void updateState_ringerModeUpdates_shouldPreserveSettingAndDisplaySummary() { + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.getSummary()).isNotNull(); + assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString( + R.string.accessibility_vibration_setting_disabled_for_silent_mode_summary)); + assertThat(mPreference.isEnabled()).isFalse(); + + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isTrue(); + assertThat(mPreference.getSummary()).isNull(); + assertThat(mPreference.isEnabled()).isTrue(); + } + + @Test + public void updateState_vibrateWhenRingingAndRampingRingerOff_shouldDisplayAlwaysOff() { + when(mAudioManager.isRampingRingerEnabled()).thenReturn(false); + updateSetting(Settings.System.VIBRATE_WHEN_RINGING, OFF); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + + updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.isChecked()).isFalse(); + } + @Test public void updateState_shouldDisplayOnOffState() { updateSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java index 1f2c0d9fcf5..9e3113053cc 100644 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationRampingRingerTogglePreferenceControllerTest.java @@ -70,6 +70,7 @@ public class VibrationRampingRingerTogglePreferenceControllerTest { mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); mController = new VibrationRampingRingerTogglePreferenceController(mContext, PREFERENCE_KEY, mDeviceConfigProvider); mLifecycle.addObserver(mController);