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);