diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e25572645b45b..6c57d88501d92 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -86,6 +86,7 @@ import android.util.MemoryIntArray;
import android.view.textservice.TextServicesManager;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.ColorDisplayController;
import com.android.internal.widget.ILockSettings;
import java.io.IOException;
@@ -3147,7 +3148,9 @@ public final class Settings {
public static final String DISPLAY_COLOR_MODE = "display_color_mode";
private static final Validator DISPLAY_COLOR_MODE_VALIDATOR =
- new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
+ new SettingsValidators.InclusiveIntegerRangeValidator(
+ ColorDisplayController.COLOR_MODE_NATURAL,
+ ColorDisplayController.COLOR_MODE_AUTOMATIC);
/**
* The amount of time in milliseconds before the device goes to sleep or begins
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index f1539eeb1260e..6cc964bf16ed2 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -82,7 +82,7 @@ public final class ColorDisplayController {
public static final int AUTO_MODE_TWILIGHT = 2;
@Retention(RetentionPolicy.SOURCE)
- @IntDef({ COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED })
+ @IntDef({ COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED, COLOR_MODE_AUTOMATIC })
public @interface ColorMode {}
/**
@@ -103,12 +103,12 @@ public final class ColorDisplayController {
* @see #setColorMode(int)
*/
public static final int COLOR_MODE_SATURATED = 2;
-
/**
- * See com.android.server.display.DisplayTransformManager.
+ * Color mode with automatic colors.
+ *
+ * @see #setColorMode(int)
*/
- private static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
- private static final String PERSISTENT_PROPERTY_NATIVE_MODE = "persist.sys.sf.native_mode";
+ public static final int COLOR_MODE_AUTOMATIC = 3;
private final Context mContext;
private final int mUserId;
@@ -361,6 +361,41 @@ public final class ColorDisplayController {
Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, colorTemperature, mUserId);
}
+ /**
+ * Get the current color mode from system properties, or return -1.
+ *
+ * See com.android.server.display.DisplayTransformManager.
+ */
+ private @ColorMode int getCurrentColorModeFromSystemProperties() {
+ int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
+ if (displayColorSetting == 0) {
+ return "1.0".equals(SystemProperties.get("persist.sys.sf.color_saturation"))
+ ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
+ } else if (displayColorSetting == 1) {
+ return COLOR_MODE_SATURATED;
+ } else if (displayColorSetting == 2) {
+ return COLOR_MODE_AUTOMATIC;
+ } else {
+ return -1;
+ }
+ }
+
+ private boolean isColorModeAvailable(@ColorMode int colorMode) {
+ // SATURATED is always allowed
+ if (colorMode == COLOR_MODE_SATURATED) {
+ return true;
+ }
+
+ final int[] availableColorModes = mContext.getResources().getIntArray(
+ R.array.config_availableColorModes);
+ for (int mode : availableColorModes) {
+ if (mode == colorMode) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Get the current color mode.
*/
@@ -369,17 +404,27 @@ public final class ColorDisplayController {
return COLOR_MODE_SATURATED;
}
- final int colorMode = System.getIntForUser(mContext.getContentResolver(),
+ int colorMode = System.getIntForUser(mContext.getContentResolver(),
System.DISPLAY_COLOR_MODE, -1, mUserId);
- if (colorMode < COLOR_MODE_NATURAL || colorMode > COLOR_MODE_SATURATED) {
+ if (colorMode == -1) {
// There still might be a legacy system property controlling color mode that we need to
// respect.
- if ("1".equals(SystemProperties.get(PERSISTENT_PROPERTY_NATIVE_MODE))) {
- return COLOR_MODE_SATURATED;
- }
- return "1.0".equals(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
- ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
+ colorMode = getCurrentColorModeFromSystemProperties();
}
+
+ // This happens when a color mode is no longer available (e.g., after system update or B&R)
+ // or the device does not support any color mode.
+ if (!isColorModeAvailable(colorMode)) {
+ if (colorMode == COLOR_MODE_BOOSTED && isColorModeAvailable(COLOR_MODE_NATURAL)) {
+ colorMode = COLOR_MODE_NATURAL;
+ } else if (colorMode == COLOR_MODE_SATURATED
+ && isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
+ colorMode = COLOR_MODE_AUTOMATIC;
+ } else {
+ colorMode = COLOR_MODE_SATURATED;
+ }
+ }
+
return colorMode;
}
@@ -389,7 +434,7 @@ public final class ColorDisplayController {
* @param colorMode the color mode
*/
public void setColorMode(@ColorMode int colorMode) {
- if (colorMode < COLOR_MODE_NATURAL || colorMode > COLOR_MODE_SATURATED) {
+ if (!isColorModeAvailable(colorMode)) {
throw new IllegalArgumentException("Invalid colorMode: " + colorMode);
}
System.putIntForUser(mContext.getContentResolver(), System.DISPLAY_COLOR_MODE, colorMode,
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 54864f36c40a3..5c80d4d265635 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -948,6 +948,16 @@
- -0.198650895
+
+
+
+
+
+
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 37035c3a343c7..030c91532135e 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -293,7 +293,7 @@ public final class ColorDisplayService extends SystemService
mColorMatrixAnimator.cancel();
}
- setCoefficientMatrix(getContext(), mode == ColorDisplayController.COLOR_MODE_SATURATED);
+ setCoefficientMatrix(getContext(), DisplayTransformManager.isColorModeNative(mode));
setMatrix(mController.getColorTemperature(), mMatrixNight);
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
index a94f049f7ef82..57d88e1907204 100644
--- a/services/core/java/com/android/server/display/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -60,14 +60,24 @@ public class DisplayTransformManager {
private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014;
private static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
- private static final String PERSISTENT_PROPERTY_NATIVE_MODE = "persist.sys.sf.native_mode";
+ private static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode";
+ /**
+ * SurfaceFlinger global saturation factor.
+ */
private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022;
- private static final int SURFACE_FLINGER_TRANSACTION_NATIVE_MODE = 1023;
+ /**
+ * SurfaceFlinger display color (managed, unmanaged, etc.).
+ */
+ private static final int SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR = 1023;
private static final float COLOR_SATURATION_NATURAL = 1.0f;
private static final float COLOR_SATURATION_BOOSTED = 1.1f;
+ private static final int DISPLAY_COLOR_MANAGED = 0;
+ private static final int DISPLAY_COLOR_UNMANAGED = 1;
+ private static final int DISPLAY_COLOR_ENHANCED = 2;
+
/**
* Map of level -> color transformation matrix.
*/
@@ -220,20 +230,37 @@ public class DisplayTransformManager {
}
}
+ /**
+ * Return true when colors are stretched from the working color space to the
+ * native color space.
+ */
public static boolean isNativeModeEnabled() {
- return SystemProperties.getBoolean(PERSISTENT_PROPERTY_NATIVE_MODE, false);
+ return SystemProperties.getInt(PERSISTENT_PROPERTY_DISPLAY_COLOR,
+ DISPLAY_COLOR_MANAGED) != DISPLAY_COLOR_MANAGED;
+ }
+
+ /**
+ * Return true when the specified colorMode stretches colors from the
+ * working color space to the native color space.
+ */
+ public static boolean isColorModeNative(int colorMode) {
+ return !(colorMode == ColorDisplayController.COLOR_MODE_NATURAL ||
+ colorMode == ColorDisplayController.COLOR_MODE_BOOSTED);
}
public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
if (colorMode == ColorDisplayController.COLOR_MODE_NATURAL) {
applySaturation(COLOR_SATURATION_NATURAL);
- setNativeMode(false);
+ setDisplayColor(DISPLAY_COLOR_MANAGED);
} else if (colorMode == ColorDisplayController.COLOR_MODE_BOOSTED) {
applySaturation(COLOR_SATURATION_BOOSTED);
- setNativeMode(false);
+ setDisplayColor(DISPLAY_COLOR_MANAGED);
} else if (colorMode == ColorDisplayController.COLOR_MODE_SATURATED) {
applySaturation(COLOR_SATURATION_NATURAL);
- setNativeMode(true);
+ setDisplayColor(DISPLAY_COLOR_UNMANAGED);
+ } else if (colorMode == ColorDisplayController.COLOR_MODE_AUTOMATIC) {
+ applySaturation(COLOR_SATURATION_NATURAL);
+ setDisplayColor(DISPLAY_COLOR_ENHANCED);
}
setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix);
@@ -265,17 +292,17 @@ public class DisplayTransformManager {
/**
* Toggles native mode on/off in SurfaceFlinger.
*/
- private void setNativeMode(boolean enabled) {
- SystemProperties.set(PERSISTENT_PROPERTY_NATIVE_MODE, enabled ? "1" : "0");
+ private void setDisplayColor(int color) {
+ SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, Integer.toString(color));
final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
if (flinger != null) {
final Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
- data.writeInt(enabled ? 1 : 0);
+ data.writeInt(color);
try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_NATIVE_MODE, data, null, 0);
+ flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to set native mode", ex);
+ Log.e(TAG, "Failed to set display color", ex);
} finally {
data.recycle();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 04554efccfe7f..10dfdf2a982e1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7489,7 +7489,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean hasWideColorGamutSupport() {
return mHasWideColorGamutSupport &&
- !SystemProperties.getBoolean("persist.sys.sf.native_mode", false);
+ SystemProperties.getInt("persist.sys.sf.native_mode", 0) != 1;
}
void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
diff --git a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
index 43701e900ab1e..c004074d241b5 100644
--- a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
@@ -898,6 +898,10 @@ public class ColorDisplayServiceTest {
@Test
public void accessibility_colorInversion_transformActivated() {
+ if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
+ return;
+ }
+
setAccessibilityColorInversion(true);
setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
@@ -909,6 +913,10 @@ public class ColorDisplayServiceTest {
@Test
public void accessibility_colorCorrection_transformActivated() {
+ if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
+ return;
+ }
+
setAccessibilityColorCorrection(true);
setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
@@ -920,6 +928,10 @@ public class ColorDisplayServiceTest {
@Test
public void accessibility_all_transformActivated() {
+ if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
+ return;
+ }
+
setAccessibilityColorCorrection(true);
setAccessibilityColorInversion(true);
setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);
@@ -932,6 +944,10 @@ public class ColorDisplayServiceTest {
@Test
public void accessibility_none_transformActivated() {
+ if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
+ return;
+ }
+
setAccessibilityColorCorrection(false);
setAccessibilityColorInversion(false);
setColorMode(ColorDisplayController.COLOR_MODE_NATURAL);