Disable user control of color mode depending on Accessibility

The Accessibility settings for color inversion and color correction are
incompatible with some color modes. When either of these settings is
enabled, disable GUI color mode controls.

Bug: 68856024
Change-Id: I12fad22190283bac38592b94e88d865d3af978ad
This commit is contained in:
Daniel Solomon
2018-03-30 18:11:38 -07:00
parent 21926abed2
commit a1687df27b
2 changed files with 103 additions and 20 deletions

View File

@@ -16,6 +16,7 @@ package com.android.settings.display;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import com.android.internal.app.ColorDisplayController; import com.android.internal.app.ColorDisplayController;
@@ -24,13 +25,15 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.CandidateInfo;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public class ColorModePreferenceFragment extends RadioButtonPickerFragment { public class ColorModePreferenceFragment extends RadioButtonPickerFragment
implements ColorDisplayController.Callback {
@VisibleForTesting @VisibleForTesting
static final String KEY_COLOR_MODE_NATURAL = "color_mode_natural"; static final String KEY_COLOR_MODE_NATURAL = "color_mode_natural";
@@ -48,6 +51,16 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mController = new ColorDisplayController(context); mController = new ColorDisplayController(context);
mController.setListener(this);
}
@Override
public void onDetach() {
super.onDetach();
if (mController != null) {
mController.setListener(null);
mController = null;
}
} }
@Override @Override
@@ -71,15 +84,16 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
@Override @Override
protected List<? extends CandidateInfo> getCandidates() { protected List<? extends CandidateInfo> getCandidates() {
Context c = getContext(); Context c = getContext();
final boolean enabled = !mController.getAccessibilityTransformActivated();
return Arrays.asList( return Arrays.asList(
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_natural), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_natural),
KEY_COLOR_MODE_NATURAL), KEY_COLOR_MODE_NATURAL, enabled),
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_boosted), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_boosted),
KEY_COLOR_MODE_BOOSTED), KEY_COLOR_MODE_BOOSTED, enabled),
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_saturated), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_saturated),
KEY_COLOR_MODE_SATURATED), KEY_COLOR_MODE_SATURATED, enabled),
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_automatic), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_automatic),
KEY_COLOR_MODE_AUTOMATIC) KEY_COLOR_MODE_AUTOMATIC, enabled)
); );
} }
@@ -120,8 +134,8 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
private final CharSequence mLabel; private final CharSequence mLabel;
private final String mKey; private final String mKey;
ColorModeCandidateInfo(CharSequence label, String key) { ColorModeCandidateInfo(CharSequence label, String key, boolean enabled) {
super(true); super(enabled);
mLabel = label; mLabel = label;
mKey = key; mKey = key;
} }
@@ -142,4 +156,18 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
} }
} }
@Override
public void onAccessibilityTransformChanged(boolean state) {
// Disable controls when a11y transforms are enabled, and vice versa
final PreferenceScreen screen = getPreferenceScreen();
if (screen != null) {
final int count = screen.getPreferenceCount();
for (int i = 0; i < count; i++) {
final Preference pref = screen.getPreference(i);
if (pref instanceof RadioButtonPreference) {
pref.setEnabled(!state);
}
}
}
}
} }

View File

@@ -16,8 +16,10 @@
package com.android.settings.display; package com.android.settings.display;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -32,6 +34,7 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.CandidateInfo;
import org.junit.Before; import org.junit.Before;
@@ -39,11 +42,11 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@@ -54,11 +57,14 @@ public class ColorModePreferenceFragmentTest {
@Mock @Mock
private ColorDisplayController mController; private ColorDisplayController mController;
@Mock
private PreferenceScreen mScreen;
@Before @Before
public void setup() { public void setup() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mFragment = spy(new ColorModePreferenceFragment()); mFragment = spy(new ColorModePreferenceFragmentTestable(mScreen));
ReflectionHelpers.setField(mFragment, "mController", mController); ReflectionHelpers.setField(mFragment, "mController", mController);
} }
@@ -86,7 +92,7 @@ public class ColorModePreferenceFragmentTest {
@Test @Test
public void getKey_natural() { public void getKey_natural() {
Mockito.when(mController.getColorMode()) when(mController.getColorMode())
.thenReturn(ColorDisplayController.COLOR_MODE_NATURAL); .thenReturn(ColorDisplayController.COLOR_MODE_NATURAL);
assertThat(mFragment.getDefaultKey()) assertThat(mFragment.getDefaultKey())
@@ -95,7 +101,7 @@ public class ColorModePreferenceFragmentTest {
@Test @Test
public void getKey_boosted() { public void getKey_boosted() {
Mockito.when(mController.getColorMode()) when(mController.getColorMode())
.thenReturn(ColorDisplayController.COLOR_MODE_BOOSTED); .thenReturn(ColorDisplayController.COLOR_MODE_BOOSTED);
assertThat(mFragment.getDefaultKey()) assertThat(mFragment.getDefaultKey())
@@ -104,7 +110,7 @@ public class ColorModePreferenceFragmentTest {
@Test @Test
public void getKey_saturated() { public void getKey_saturated() {
Mockito.when(mController.getColorMode()) when(mController.getColorMode())
.thenReturn(ColorDisplayController.COLOR_MODE_SATURATED); .thenReturn(ColorDisplayController.COLOR_MODE_SATURATED);
assertThat(mFragment.getDefaultKey()) assertThat(mFragment.getDefaultKey())
@@ -141,15 +147,64 @@ public class ColorModePreferenceFragmentTest {
@Test @Test
public void addStaticPreferences_shouldAddPreviewImage() { public void addStaticPreferences_shouldAddPreviewImage() {
PreferenceScreen mockPreferenceScreen = Mockito.mock(PreferenceScreen.class); PreferenceScreen mockPreferenceScreen = mock(PreferenceScreen.class);
LayoutPreference mockPreview = Mockito.mock(LayoutPreference.class); LayoutPreference mockPreview = mock(LayoutPreference.class);
ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(Preference.class); ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(Preference.class);
mFragment.configureAndInstallPreview(mockPreview, mockPreferenceScreen); mFragment.configureAndInstallPreview(mockPreview, mockPreferenceScreen);
Mockito.verify(mockPreview, times(1)).setSelectable(false); verify(mockPreview, times(1)).setSelectable(false);
Mockito.verify(mockPreferenceScreen, times(1)).addPreference(preferenceCaptor.capture()); verify(mockPreferenceScreen, times(1)).addPreference(preferenceCaptor.capture());
assertThat(preferenceCaptor.getValue()).isEqualTo(mockPreview); assertThat(preferenceCaptor.getValue()).isEqualTo(mockPreview);
} }
@Test
public void onAccessibilityTransformChanged_toggles() {
final int radioPrefsCount = 3;
List<RadioButtonPreference> radioPrefs = new ArrayList<>();
for (int i = 0; i < radioPrefsCount; i++) {
radioPrefs.add(mock(RadioButtonPreference.class));
}
when(mScreen.getPreferenceCount()).thenReturn(radioPrefs.size());
when(mScreen.getPreference(anyInt())).thenAnswer(invocation -> {
final Object[] args = invocation.getArguments();
return radioPrefs.get((int) args[0]);
});
mFragment.onAccessibilityTransformChanged(true /* state */);
for (int i = 0; i < radioPrefsCount; i++) {
verify(radioPrefs.get(i)).setEnabled(false);
}
mFragment.onAccessibilityTransformChanged(false /* state */);
for (int i = 0; i < radioPrefsCount; i++) {
verify(radioPrefs.get(i)).setEnabled(true);
}
}
private static class ColorModePreferenceFragmentTestable
extends ColorModePreferenceFragment {
private final PreferenceScreen mPreferenceScreen;
private ColorModePreferenceFragmentTestable(PreferenceScreen screen) {
mPreferenceScreen = screen;
}
/**
* A method to return a mock PreferenceScreen.
* A real ColorModePreferenceFragment calls super.getPreferenceScreen() to get its
* PreferenceScreen handle, which internally dereferenced a PreferenceManager. But in this
* test scenario, the PreferenceManager object is uninitialized, so we need to supply the
* PreferenceScreen directly.
*
* @return a mock PreferenceScreen
*/
@Override
public PreferenceScreen getPreferenceScreen() {
return mPreferenceScreen;
}
}
} }