Merge "Hide haptic intensity settings for devices without enough dynamic range." into pi-dev am: 8c60fc69b7

am: 23460d03bc

Change-Id: I5c5e8a4157874f19abe28201fba772c72bc7f9d9
This commit is contained in:
Michael Wright
2018-05-25 19:17:33 -07:00
committed by android-build-merger
6 changed files with 184 additions and 49 deletions

View File

@@ -134,4 +134,9 @@
<!-- Whether or not to show the night light suggestion. --> <!-- Whether or not to show the night light suggestion. -->
<bool name="config_night_light_suggestion_enabled">true</bool> <bool name="config_night_light_suggestion_enabled">true</bool>
<!-- Whether or not the device is capable of multiple levels of vibration intensity.
Note that this is different from whether it can control the vibration amplitude as some
devices will be able to vary their amplitude but do not possess enough dynamic range to
have distinct intensity levels -->
<bool name="config_vibration_supports_multiple_intensities">false</bool>
</resources> </resources>

View File

@@ -781,17 +781,27 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
} }
private String getVibrationSummary(Context context, @VibrationIntensity int intensity) { private String getVibrationSummary(Context context, @VibrationIntensity int intensity) {
switch (intensity) { final boolean supportsMultipleIntensities = context.getResources().getBoolean(
case Vibrator.VIBRATION_INTENSITY_OFF: R.bool.config_vibration_supports_multiple_intensities);
return context.getString(R.string.accessibility_vibration_summary_off); if (supportsMultipleIntensities) {
case Vibrator.VIBRATION_INTENSITY_LOW: switch (intensity) {
return context.getString(R.string.accessibility_vibration_summary_low); case Vibrator.VIBRATION_INTENSITY_OFF:
case Vibrator.VIBRATION_INTENSITY_MEDIUM: return context.getString(R.string.accessibility_vibration_summary_off);
return context.getString(R.string.accessibility_vibration_summary_medium); case Vibrator.VIBRATION_INTENSITY_LOW:
case Vibrator.VIBRATION_INTENSITY_HIGH: return context.getString(R.string.accessibility_vibration_summary_low);
return context.getString(R.string.accessibility_vibration_summary_high); case Vibrator.VIBRATION_INTENSITY_MEDIUM:
default: return context.getString(R.string.accessibility_vibration_summary_medium);
return ""; 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);
}
} }
} }

View File

@@ -81,17 +81,27 @@ public abstract class VibrationIntensityPreferenceController extends BasePrefere
} }
public static CharSequence getIntensityString(Context context, int intensity) { public static CharSequence getIntensityString(Context context, int intensity) {
switch (intensity) { final boolean supportsMultipleIntensities = context.getResources().getBoolean(
case Vibrator.VIBRATION_INTENSITY_OFF: R.bool.config_vibration_supports_multiple_intensities);
return context.getText(R.string.accessibility_vibration_intensity_off); if (supportsMultipleIntensities) {
case Vibrator.VIBRATION_INTENSITY_LOW: switch (intensity) {
return context.getText(R.string.accessibility_vibration_intensity_low); case Vibrator.VIBRATION_INTENSITY_OFF:
case Vibrator.VIBRATION_INTENSITY_MEDIUM: return context.getString(R.string.accessibility_vibration_intensity_off);
return context.getText(R.string.accessibility_vibration_intensity_medium); case Vibrator.VIBRATION_INTENSITY_LOW:
case Vibrator.VIBRATION_INTENSITY_HIGH: return context.getString(R.string.accessibility_vibration_intensity_low);
return context.getText(R.string.accessibility_vibration_intensity_high); case Vibrator.VIBRATION_INTENSITY_MEDIUM:
default: return context.getString(R.string.accessibility_vibration_intensity_medium);
return ""; 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);
}
} }
} }

View File

@@ -55,28 +55,15 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm
final static String KEY_INTENSITY_MEDIUM = "intensity_medium"; final static String KEY_INTENSITY_MEDIUM = "intensity_medium";
@VisibleForTesting @VisibleForTesting
final static String KEY_INTENSITY_HIGH = "intensity_high"; 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<String, VibrationIntensityCandidateInfo> mCandidates; private final Map<String, VibrationIntensityCandidateInfo> mCandidates;
private final SettingsObserver mSettingsObserver; private final SettingsObserver mSettingsObserver;
public VibrationPreferenceFragment() { public VibrationPreferenceFragment() {
mCandidates = new ArrayMap<>(); 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(); mSettingsObserver = new SettingsObserver();
} }
@@ -84,6 +71,39 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mSettingsObserver.register(); 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 @Override
@@ -138,7 +158,10 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm
final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(), final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
getVibrationIntensitySetting(), getDefaultVibrationIntensity()); getVibrationIntensitySetting(), getDefaultVibrationIntensity());
for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) { 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(); return candidate.getKey();
} }
} }

View File

@@ -18,10 +18,12 @@ package com.android.settings.accessibility;
import static android.provider.Settings.System.NOTIFICATION_VIBRATION_INTENSITY; import static android.provider.Settings.System.NOTIFICATION_VIBRATION_INTENSITY;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.os.Vibrator; import android.os.Vibrator;
import android.provider.Settings; import android.provider.Settings;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -48,6 +50,7 @@ public class NotificationVibrationIntensityPreferenceControllerTest {
private LifecycleOwner mLifecycleOwner; private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle; private Lifecycle mLifecycle;
private Context mContext; private Context mContext;
private Resources mResources;
private NotificationVibrationIntensityPreferenceController mController; private NotificationVibrationIntensityPreferenceController mController;
private Preference mPreference; private Preference mPreference;
@@ -56,7 +59,11 @@ public class NotificationVibrationIntensityPreferenceControllerTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mLifecycleOwner = () -> mLifecycle; mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner); 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) { mController = new NotificationVibrationIntensityPreferenceController(mContext) {
@Override @Override
protected int getDefaultIntensity() { protected int getDefaultIntensity() {
@@ -68,7 +75,6 @@ public class NotificationVibrationIntensityPreferenceControllerTest {
mPreference.setSummary("Test"); mPreference.setSummary("Test");
when(mScreen.findPreference(mController.getPreferenceKey())) when(mScreen.findPreference(mController.getPreferenceKey()))
.thenReturn(mPreference); .thenReturn(mPreference);
mController.displayPreference(mScreen);
} }
@Test @Test
@@ -80,7 +86,10 @@ public class NotificationVibrationIntensityPreferenceControllerTest {
} }
@Test @Test
public void updateState_shouldRefreshSummary() { public void updateState_withMultipleIntensitySuport_shouldRefreshSummary() {
setSupportsMultipleIntensities(true);
showPreference();
Settings.System.putInt(mContext.getContentResolver(), Settings.System.putInt(mContext.getContentResolver(),
NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW); NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -105,4 +114,43 @@ public class NotificationVibrationIntensityPreferenceControllerTest {
assertThat(mPreference.getSummary()) assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_off)); .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);
}
} }

View File

@@ -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_LOW;
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_MEDIUM; 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_OFF;
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_ON;
import static com.google.common.truth.Truth.assertThat; 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.spy;
import static org.mockito.Mockito.when;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.os.UserManager; import android.os.UserManager;
import android.os.Vibrator; import android.os.Vibrator;
import android.provider.Settings; import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.accessibility.VibrationPreferenceFragment.VibrationIntensityCandidateInfo; import com.android.settings.accessibility.VibrationPreferenceFragment.VibrationIntensityCandidateInfo;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -58,12 +61,11 @@ public class VibrationPreferenceFragmentTest {
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH); INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH);
} }
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
private Context mContext; private Context mContext;
private Resources mResources;
private TestVibrationPreferenceFragment mFragment; private TestVibrationPreferenceFragment mFragment;
@Before @Before
@@ -71,16 +73,18 @@ public class VibrationPreferenceFragmentTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(); FakeFeatureFactory.setupForTest();
mContext = RuntimeEnvironment.application; mContext = spy(RuntimeEnvironment.application);
mResources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(mResources);
mFragment = spy(new TestVibrationPreferenceFragment()); mFragment = spy(new TestVibrationPreferenceFragment());
doReturn(mUserManager).when(mActivity).getSystemService(Context.USER_SERVICE); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
doReturn(mContext).when(mFragment).getContext();
mFragment.onAttach(mActivity);
} }
@Test @Test
public void changeIntensitySetting_shouldResultInCorrespondingKey() { public void changeIntensitySetting_shouldResultInCorrespondingKey() {
setSupportsMultipleIntensities(true);
mFragment.onAttach(mContext);
for (Map.Entry<Integer, String> entry : INTENSITY_TO_KEY.entrySet()) { for (Map.Entry<Integer, String> entry : INTENSITY_TO_KEY.entrySet()) {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.putInt(mContext.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_INTENSITY, entry.getKey()); 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 @Test
public void initialDefaultKey_shouldBeMedium() { public void initialDefaultKey_shouldBeMedium() {
setSupportsMultipleIntensities(true);
mFragment.onAttach(mContext);
assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_MEDIUM); 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 @Test
public void candidates_shouldBeSortedByIntensity() { public void candidates_shouldBeSortedByIntensity() {
setSupportsMultipleIntensities(true);
mFragment.onAttach(mContext);
final List<? extends CandidateInfo> candidates = mFragment.getCandidates(); final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
assertThat(candidates.size()).isEqualTo(INTENSITY_TO_KEY.size()); assertThat(candidates.size()).isEqualTo(INTENSITY_TO_KEY.size());
VibrationIntensityCandidateInfo prevCandidate = 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 { private class TestVibrationPreferenceFragment extends VibrationPreferenceFragment {
@Override @Override
protected int getPreferenceScreenResId() { protected int getPreferenceScreenResId() {
@@ -129,5 +163,10 @@ public class VibrationPreferenceFragmentTest {
protected int getDefaultVibrationIntensity() { protected int getDefaultVibrationIntensity() {
return Vibrator.VIBRATION_INTENSITY_MEDIUM; return Vibrator.VIBRATION_INTENSITY_MEDIUM;
} }
@Override
public Context getContext() {
return mContext;
}
} }
} }