From 3dbaac6e7156763cdfffd29cff35a3b6b941a8e5 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 25 May 2018 22:57:03 +0100 Subject: [PATCH] Hide haptic intensity settings for devices without enough dynamic range. Despite our hope, devices prior to P18 just don't have the dynamic range to give three distinct vibration intensity settings. Given this, only show an on / off toggle for devices by default unless they explicitly opt-in to multiple intensity levels. Test: m -j RunSettingsRoboTests Bug: 80243632 Change-Id: I14ece855cf20f9fa44b0648d28f89c0053be5c5f --- res/values/config.xml | 5 ++ .../accessibility/AccessibilitySettings.java | 32 +++++++---- ...ibrationIntensityPreferenceController.java | 32 +++++++---- .../VibrationPreferenceFragment.java | 57 +++++++++++++------ ...tionIntensityPreferenceControllerTest.java | 54 +++++++++++++++++- .../VibrationPreferenceFragmentTest.java | 53 ++++++++++++++--- 6 files changed, 184 insertions(+), 49 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index 8e55ea95e36..f46134f301b 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -134,4 +134,9 @@ true + + false diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java index 72e485e7c81..4ddcc31bf27 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettings.java +++ b/src/com/android/settings/accessibility/AccessibilitySettings.java @@ -779,17 +779,27 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements } private String getVibrationSummary(Context context, @VibrationIntensity int intensity) { - switch (intensity) { - case Vibrator.VIBRATION_INTENSITY_OFF: - return context.getString(R.string.accessibility_vibration_summary_off); - case Vibrator.VIBRATION_INTENSITY_LOW: - return context.getString(R.string.accessibility_vibration_summary_low); - case Vibrator.VIBRATION_INTENSITY_MEDIUM: - return context.getString(R.string.accessibility_vibration_summary_medium); - case Vibrator.VIBRATION_INTENSITY_HIGH: - return context.getString(R.string.accessibility_vibration_summary_high); - default: - return ""; + 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_summary_off); + case Vibrator.VIBRATION_INTENSITY_LOW: + return context.getString(R.string.accessibility_vibration_summary_low); + case Vibrator.VIBRATION_INTENSITY_MEDIUM: + return context.getString(R.string.accessibility_vibration_summary_medium); + case Vibrator.VIBRATION_INTENSITY_HIGH: + return context.getString(R.string.accessibility_vibration_summary_high); + default: + return ""; + } + } else { + if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { + return context.getString(R.string.switch_on_text); + } else { + return context.getString(R.string.switch_off_text); + } } } diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java index 9c81afa2f16..3fbb1230a50 100644 --- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java +++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java @@ -81,17 +81,27 @@ public abstract class VibrationIntensityPreferenceController extends BasePrefere } public static CharSequence getIntensityString(Context context, int intensity) { - switch (intensity) { - case Vibrator.VIBRATION_INTENSITY_OFF: - return context.getText(R.string.accessibility_vibration_intensity_off); - case Vibrator.VIBRATION_INTENSITY_LOW: - return context.getText(R.string.accessibility_vibration_intensity_low); - case Vibrator.VIBRATION_INTENSITY_MEDIUM: - return context.getText(R.string.accessibility_vibration_intensity_medium); - case Vibrator.VIBRATION_INTENSITY_HIGH: - return context.getText(R.string.accessibility_vibration_intensity_high); - default: - return ""; + 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); + } } } diff --git a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java index e911b612e37..f02c4747c96 100644 --- a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java @@ -53,28 +53,15 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm 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<>(); - 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)); mSettingsObserver = new SettingsObserver(); } @@ -82,6 +69,39 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm 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())); + } } @Override @@ -118,7 +138,10 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(), getVibrationIntensitySetting(), getDefaultVibrationIntensity()); for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) { - if (candidate.getIntensity() == vibrationIntensity) { + 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(); } } diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java index 067f015e85e..aa9efc51f88 100644 --- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java @@ -18,10 +18,12 @@ 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.arch.lifecycle.LifecycleOwner; import android.content.Context; +import android.content.res.Resources; import android.os.Vibrator; import android.provider.Settings; import android.support.v7.preference.Preference; @@ -48,6 +50,7 @@ public class NotificationVibrationIntensityPreferenceControllerTest { private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; private Context mContext; + private Resources mResources; private NotificationVibrationIntensityPreferenceController mController; private Preference mPreference; @@ -56,7 +59,11 @@ public class NotificationVibrationIntensityPreferenceControllerTest { MockitoAnnotations.initMocks(this); mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); - mContext = RuntimeEnvironment.application; + 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() { @@ -68,7 +75,6 @@ public class NotificationVibrationIntensityPreferenceControllerTest { mPreference.setSummary("Test"); when(mScreen.findPreference(mController.getPreferenceKey())) .thenReturn(mPreference); - mController.displayPreference(mScreen); } @Test @@ -80,7 +86,10 @@ public class NotificationVibrationIntensityPreferenceControllerTest { } @Test - public void updateState_shouldRefreshSummary() { + public void updateState_withMultipleIntensitySuport_shouldRefreshSummary() { + setSupportsMultipleIntensities(true); + showPreference(); + Settings.System.putInt(mContext.getContentResolver(), NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); mController.updateState(mPreference); @@ -105,4 +114,43 @@ public class NotificationVibrationIntensityPreferenceControllerTest { assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_off)); } + + @Test + public void updateState_withoutMultipleIntensitySupport_shouldRefreshSummary() { + setSupportsMultipleIntensities(false); + showPreference(); + + Settings.System.putInt(mContext.getContentResolver(), + NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getString(R.string.switch_on_text)); + + Settings.System.putInt(mContext.getContentResolver(), + NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getString(R.string.switch_on_text)); + + Settings.System.putInt(mContext.getContentResolver(), + NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getString(R.string.switch_on_text)); + + Settings.System.putInt(mContext.getContentResolver(), + NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF); + mController.updateState(mPreference); + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getString(R.string.switch_off_text)); + } + + private void setSupportsMultipleIntensities(boolean hasSupport) { + when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities)) + .thenReturn(hasSupport); + } + + private void showPreference() { + mController.displayPreference(mScreen); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java index 8550cf98916..ecd2ff9ce57 100644 --- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java @@ -20,16 +20,19 @@ import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY 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.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.app.Activity; 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.settings.testutils.SettingsRobolectricTestRunner; @@ -58,12 +61,11 @@ public class VibrationPreferenceFragmentTest { INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH); } - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Activity mActivity; @Mock private UserManager mUserManager; private Context mContext; + private Resources mResources; private TestVibrationPreferenceFragment mFragment; @Before @@ -71,16 +73,18 @@ public class VibrationPreferenceFragmentTest { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(); - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); + mResources = spy(mContext.getResources()); + when(mContext.getResources()).thenReturn(mResources); mFragment = spy(new TestVibrationPreferenceFragment()); - doReturn(mUserManager).when(mActivity).getSystemService(Context.USER_SERVICE); - doReturn(mContext).when(mFragment).getContext(); - mFragment.onAttach(mActivity); + 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()); @@ -88,13 +92,38 @@ public class VibrationPreferenceFragmentTest { } } + @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 = @@ -106,6 +135,11 @@ public class VibrationPreferenceFragmentTest { } } + 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() { @@ -129,5 +163,10 @@ public class VibrationPreferenceFragmentTest { protected int getDefaultVibrationIntensity() { return Vibrator.VIBRATION_INTENSITY_MEDIUM; } + + @Override + public Context getContext() { + return mContext; + } } }