Merge "Hide display white balance setting depending on accessibility" into qt-dev
diff --git a/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java b/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
index dc569aa..6fc0b0e 100644
--- a/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
+++ b/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
@@ -13,17 +13,34 @@
*/
package com.android.settings.display;
+import android.app.ActivityManager;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings.Secure;
+import android.provider.Settings.System;
import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+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.android.settings.core.TogglePreferenceController;
-public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController {
+public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController
+ implements LifecycleObserver, OnStart, OnStop {
private ColorDisplayManager mColorDisplayManager;
+ @VisibleForTesting
+ ContentObserver mContentObserver;
+ private Preference mPreference;
public DisplayWhiteBalancePreferenceController(Context context, String key) {
super(context, key);
@@ -31,12 +48,8 @@
@Override
public int getAvailabilityStatus() {
- // Display white balance is only valid in linear light space. COLOR_MODE_SATURATED implies
- // unmanaged color mode, and hence unknown color processing conditions.
- return ColorDisplayManager.isDisplayWhiteBalanceAvailable(mContext) &&
- getColorDisplayManager().getColorMode() !=
- ColorDisplayManager.COLOR_MODE_SATURATED ?
- AVAILABLE : DISABLED_FOR_USER;
+ return getColorDisplayManager().isDisplayWhiteBalanceAvailable(mContext) ?
+ AVAILABLE : DISABLED_FOR_USER;
}
@Override
@@ -49,6 +62,50 @@
return getColorDisplayManager().setDisplayWhiteBalanceEnabled(isChecked);
}
+ @Override
+ public void onStart() {
+ if (!isAvailable()) {
+ return;
+ }
+
+ final ContentResolver cr = mContext.getContentResolver();
+ mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateVisibility();
+ }
+ };
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+ cr.registerContentObserver(
+ System.getUriFor(System.DISPLAY_COLOR_MODE),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+
+ updateVisibility();
+ }
+
+ @Override
+ public void onStop() {
+ if (mContentObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ mContentObserver = null;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
@VisibleForTesting
ColorDisplayManager getColorDisplayManager() {
if (mColorDisplayManager == null) {
@@ -56,4 +113,17 @@
}
return mColorDisplayManager;
}
+
+ @VisibleForTesting
+ void updateVisibility() {
+ if (mPreference != null) {
+ ColorDisplayManager cdm = getColorDisplayManager();
+
+ // Display white balance is only valid in linear light space. COLOR_MODE_SATURATED
+ // implies unmanaged color mode, and hence unknown color processing conditions.
+ // We also disallow display white balance when color accessibility features are enabled.
+ mPreference.setVisible(cdm.getColorMode() != ColorDisplayManager.COLOR_MODE_SATURATED &&
+ !cdm.areAccessibilityTransformsEnabled(mContext));
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
index d0dbc0b..dfc13de 100644
--- a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
@@ -1,16 +1,27 @@
package com.android.settings.display;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.Context;
import android.hardware.display.ColorDisplayManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -27,6 +38,15 @@
@Mock
private ColorDisplayManager mColorDisplayManager;
+ private ContentResolver mContentResolver;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private Preference mPreference;
+
+ private final String PREFERENCE_KEY = "display_white_balance";
@After
public void tearDown() {
@@ -36,17 +56,21 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = spy(new DisplayWhiteBalancePreferenceController(RuntimeEnvironment.application,
- "display_white_balance"));
+
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
+ when(mScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
+
+ mController = spy(new DisplayWhiteBalancePreferenceController(mContext, PREFERENCE_KEY));
doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
}
@Test
- public void isAvailable_configuredAvailable() {
+ public void isAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+
assertThat(mController.isAvailable()).isTrue();
}
@@ -54,20 +78,7 @@
public void isAvailable_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
- assertThat(mController.isAvailable()).isFalse();
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
- assertThat(mController.isAvailable()).isFalse();
-
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
}
@@ -94,4 +105,101 @@
when(mColorDisplayManager.isDisplayWhiteBalanceEnabled()).thenReturn(false);
assertThat(mController.isChecked()).isFalse();
}
+
+ @Test
+ public void onStart_configuredUnavailable() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
+ mController.displayPreference(mScreen);
+ mController.onStart();
+ assertThat(mController.mContentObserver).isNull();
+ }
+
+ @Test
+ public void onStart_configuredAvailable() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ toggleAccessibilityInversion(false);
+ toggleAccessibilityDaltonizer(false);
+
+ mController.displayPreference(mScreen);
+ mController.onStart();
+ assertThat(mController.mContentObserver).isNotNull();
+ }
+
+ @Test
+ public void visibility_configuredAvailableAccessibilityToggled() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ mController.displayPreference(mScreen);
+
+ // Accessibility features disabled
+ toggleAccessibilityInversion(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ toggleAccessibilityDaltonizer(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ // Accessibility features enabled one by one
+ toggleAccessibilityInversion(true);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ toggleAccessibilityDaltonizer(true);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ // Accessibility features disabled one by one
+ toggleAccessibilityInversion(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ // Daltonizer is still enabled, so we expect the preference to still be invisible
+ verify(mPreference).setVisible(false);
+
+ // Now both a11y features are disabled, so we expect the preference to become visible
+ toggleAccessibilityDaltonizer(false);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+ }
+
+ @Test
+ public void visibility_configuredAvailableColorModeChanged() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ mController.displayPreference(mScreen);
+
+ // Non-Saturated color mode selected
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ // Saturated color mode selected
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ // Switch back to non-Saturated color mode
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+ }
+
+ private void toggleAccessibilityInversion(boolean enable) {
+ Settings.Secure.putInt(mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, enable ? 1 : 0);
+ }
+
+ private void toggleAccessibilityDaltonizer(boolean enable) {
+ Settings.Secure.putInt(mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, enable ? 1 : 0);
+ }
}