Add ability to select composition color space for a given color mode

Add the ability to specify a desired display composition color space
(sRGB, P3, etc.) for a given color mode (Natural, Boosted, etc.).
If no composition color space is specified, the composition color space
is unchanged.

Bug: 137140317
Bug: 137053654
Test: atest FrameworksMockingServicesTests:DisplayTransformManagerTest
Test: atest FrameworksServicesTests:ColorDisplayServiceTest
Change-Id: I37b01fa160d3965cea341781c0aa656f57e0f68f
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 2e5aafe..7fb5b19 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -63,6 +63,8 @@
 import android.provider.Settings.System;
 import android.util.MathUtils;
 import android.util.Slog;
+import android.util.SparseIntArray;
+import android.view.Display;
 import android.view.SurfaceControl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
@@ -171,6 +173,11 @@
 
     private NightDisplayAutoMode mNightDisplayAutoMode;
 
+    /**
+     * Map of color modes -> display composition colorspace
+     */
+    private SparseIntArray mColorModeCompositionColorSpaces = null;
+
     public ColorDisplayService(Context context) {
         super(context);
         mHandler = new TintHandler(DisplayThread.get().getLooper());
@@ -267,6 +274,30 @@
         return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1;
     }
 
+    private void setUpDisplayCompositionColorSpaces(Resources res) {
+        mColorModeCompositionColorSpaces = null;
+
+        final int[] colorModes = res.getIntArray(R.array.config_displayCompositionColorModes);
+        if (colorModes == null) {
+            return;
+        }
+
+        final int[] compSpaces = res.getIntArray(R.array.config_displayCompositionColorSpaces);
+        if (compSpaces == null) {
+            return;
+        }
+
+        if (colorModes.length != compSpaces.length) {
+            Slog.e(TAG, "Number of composition color spaces doesn't match specified color modes");
+            return;
+        }
+
+        mColorModeCompositionColorSpaces = new SparseIntArray(colorModes.length);
+        for (int i = 0; i < colorModes.length; i++) {
+            mColorModeCompositionColorSpaces.put(colorModes[i], compSpaces[i]);
+        }
+    }
+
     private void setUp() {
         Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);
 
@@ -359,6 +390,8 @@
         onAccessibilityInversionChanged();
         onAccessibilityDaltonizerChanged();
 
+        setUpDisplayCompositionColorSpaces(getContext().getResources());
+
         // Set the color mode, if valid, and immediately apply the updated tint matrix based on the
         // existing activated state. This ensures consistency of tint across the color mode change.
         onDisplayColorModeChanged(getColorModeInternal());
@@ -450,6 +483,14 @@
         }
     }
 
+    private int getCompositionColorSpace(int mode) {
+        if (mColorModeCompositionColorSpaces == null) {
+            return Display.COLOR_MODE_INVALID;
+        }
+
+        return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID);
+    }
+
     private void onDisplayColorModeChanged(int mode) {
         if (mode == NOT_SET) {
             return;
@@ -470,7 +511,8 @@
         // DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent
         // on the state of DisplayTransformManager.
         final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
-        dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
+        dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(),
+                getCompositionColorSpace(mode));
 
         if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
             updateDisplayWhiteBalanceStatus();