Rename color transform to color mode and persist the value.

Also, standardize on a set of possible modes for the displays to
enter and separate the configuration of the color mode from the
configuration of the display mode.

Bug: 29044347

Change-Id: I6af0a7d1f11bc72d4cefc380f115c1fb00788864
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 93da3e5..826eb74 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -354,9 +354,9 @@
         }
     }
 
-    public void requestColorTransform(int displayId, int colorTransformId) {
+    public void requestColorMode(int displayId, int colorMode) {
         try {
-            mDm.requestColorTransform(displayId, colorTransformId);
+            mDm.requestColorMode(displayId, colorMode);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 8a1abf1..f696c8d 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -59,8 +59,8 @@
     // No permissions required.
     WifiDisplayStatus getWifiDisplayStatus();
 
-    // Requires CONFIGURE_DISPLAY_COLOR_TRANSFORM
-    void requestColorTransform(int displayId, int colorTransformId);
+    // Requires CONFIGURE_DISPLAY_COLOR_MODE
+    void requestColorMode(int displayId, int colorMode);
 
     // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
     // MediaProjection token for certain combinations of flags.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 8c49009..899ae49 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -36,7 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
-import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM;
+import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
 
 /**
  * Provides information about the size and density of a logical display.
@@ -284,6 +284,27 @@
      */
     public static final int STATE_DOZE_SUSPEND = 4;
 
+    /* The color mode constants defined below must be kept in sync with the ones in
+     * system/graphics.h */
+
+    /**
+     * Display color mode: The current color mode is unknown or invalid.
+     * @hide
+     */
+    public static final int COLOR_MODE_INVALID = -1;
+
+    /**
+     * Display color mode: The default or native gamut of the display.
+     * @hide
+     */
+    public static final int COLOR_MODE_DEFAULT = 0;
+
+    /**
+     * Display color mode: SRGB
+     * @hide
+     */
+    public static final int COLOR_MODE_SRGB = 7;
+
     /**
      * Internal method to create a display.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
@@ -696,33 +717,22 @@
     }
 
     /**
-     * Request the display applies a color transform.
+     * Request the display applies a color mode.
      * @hide
      */
-    @RequiresPermission(CONFIGURE_DISPLAY_COLOR_TRANSFORM)
-    public void requestColorTransform(ColorTransform colorTransform) {
-        mGlobal.requestColorTransform(mDisplayId, colorTransform.getId());
+    @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE)
+    public void requestColorMode(int colorMode) {
+        mGlobal.requestColorMode(mDisplayId, colorMode);
     }
 
     /**
-     * Returns the active color transform of this display
+     * Returns the active color mode of this display
      * @hide
      */
-    public ColorTransform getColorTransform() {
+    public int getColorMode() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.getColorTransform();
-        }
-    }
-
-    /**
-     * Returns the default color transform of this display
-     * @hide
-     */
-    public ColorTransform getDefaultColorTransform() {
-        synchronized (this) {
-            updateDisplayInfoLocked();
-            return mDisplayInfo.getDefaultColorTransform();
+            return mDisplayInfo.colorMode;
         }
     }
 
@@ -737,14 +747,14 @@
     }
 
     /**
-     * Gets the supported color transforms of this device.
+     * Gets the supported color modes of this device.
      * @hide
      */
-    public ColorTransform[] getSupportedColorTransforms() {
+    public int[] getSupportedColorModes() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            ColorTransform[] transforms = mDisplayInfo.supportedColorTransforms;
-            return Arrays.copyOf(transforms, transforms.length);
+            int[] colorModes = mDisplayInfo.supportedColorModes;
+            return Arrays.copyOf(colorModes, colorModes.length);
         }
     }
 
@@ -1263,89 +1273,4 @@
             return 0;
         }
     }
-
-    /**
-     * A color transform supported by a given display.
-     *
-     * @see Display#getSupportedColorTransforms()
-     * @hide
-     */
-    public static final class ColorTransform implements Parcelable {
-        public static final ColorTransform[] EMPTY_ARRAY = new ColorTransform[0];
-
-        private final int mId;
-        private final int mColorTransform;
-
-        public ColorTransform(int id, int colorTransform) {
-            mId = id;
-            mColorTransform = colorTransform;
-        }
-
-        public int getId() {
-            return mId;
-        }
-
-        public int getColorTransform() {
-            return mColorTransform;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) {
-                return true;
-            }
-            if (!(other instanceof ColorTransform)) {
-                return false;
-            }
-            ColorTransform that = (ColorTransform) other;
-            return mId == that.mId
-                && mColorTransform == that.mColorTransform;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 1;
-            hash = hash * 17 + mId;
-            hash = hash * 17 + mColorTransform;
-            return hash;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder("{")
-                    .append("id=").append(mId)
-                    .append(", colorTransform=").append(mColorTransform)
-                    .append("}")
-                    .toString();
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        private ColorTransform(Parcel in) {
-            this(in.readInt(), in.readInt());
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int parcelableFlags) {
-            out.writeInt(mId);
-            out.writeInt(mColorTransform);
-        }
-
-        @SuppressWarnings("hiding")
-        public static final Parcelable.Creator<ColorTransform> CREATOR
-                = new Parcelable.Creator<ColorTransform>() {
-            @Override
-            public ColorTransform createFromParcel(Parcel in) {
-                return new ColorTransform(in);
-            }
-
-            @Override
-            public ColorTransform[] newArray(int size) {
-                return new ColorTransform[size];
-            }
-        };
-    }
 }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 8aeeffd..49c3c46 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -169,14 +169,11 @@
      */
     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
 
-    /** The active color transform. */
-    public int colorTransformId;
+    /** The active color mode. */
+    public int colorMode;
 
-    /** The default color transform. */
-    public int defaultColorTransformId;
-
-    /** The list of supported color transforms */
-    public Display.ColorTransform[] supportedColorTransforms = Display.ColorTransform.EMPTY_ARRAY;
+    /** The list of supported color modes */
+    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
 
     /** The display's HDR capabilities */
     public Display.HdrCapabilities hdrCapabilities;
@@ -291,8 +288,8 @@
                 && rotation == other.rotation
                 && modeId == other.modeId
                 && defaultModeId == other.defaultModeId
-                && colorTransformId == other.colorTransformId
-                && defaultColorTransformId == other.defaultColorTransformId
+                && colorMode == other.colorMode
+                && Objects.equal(supportedColorModes, other.supportedColorModes)
                 && Objects.equal(hdrCapabilities, other.hdrCapabilities)
                 && logicalDensityDpi == other.logicalDensityDpi
                 && physicalXDpi == other.physicalXDpi
@@ -332,10 +329,9 @@
         modeId = other.modeId;
         defaultModeId = other.defaultModeId;
         supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
-        colorTransformId = other.colorTransformId;
-        defaultColorTransformId = other.defaultColorTransformId;
-        supportedColorTransforms = Arrays.copyOf(
-                other.supportedColorTransforms, other.supportedColorTransforms.length);
+        colorMode = other.colorMode;
+        supportedColorModes = Arrays.copyOf(
+                other.supportedColorModes, other.supportedColorModes.length);
         hdrCapabilities = other.hdrCapabilities;
         logicalDensityDpi = other.logicalDensityDpi;
         physicalXDpi = other.physicalXDpi;
@@ -373,12 +369,11 @@
         for (int i = 0; i < nModes; i++) {
             supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
         }
-        colorTransformId = source.readInt();
-        defaultColorTransformId = source.readInt();
-        int nColorTransforms = source.readInt();
-        supportedColorTransforms = new Display.ColorTransform[nColorTransforms];
-        for (int i = 0; i < nColorTransforms; i++) {
-            supportedColorTransforms[i] = Display.ColorTransform.CREATOR.createFromParcel(source);
+        colorMode = source.readInt();
+        int nColorModes = source.readInt();
+        supportedColorModes = new int[nColorModes];
+        for (int i = 0; i < nColorModes; i++) {
+            supportedColorModes[i] = source.readInt();
         }
         hdrCapabilities = source.readParcelable(null);
         logicalDensityDpi = source.readInt();
@@ -418,11 +413,10 @@
         for (int i = 0; i < supportedModes.length; i++) {
             supportedModes[i].writeToParcel(dest, flags);
         }
-        dest.writeInt(colorTransformId);
-        dest.writeInt(defaultColorTransformId);
-        dest.writeInt(supportedColorTransforms.length);
-        for (int i = 0; i < supportedColorTransforms.length; i++) {
-            supportedColorTransforms[i].writeToParcel(dest, flags);
+        dest.writeInt(colorMode);
+        dest.writeInt(supportedColorModes.length);
+        for (int i = 0; i < supportedColorModes.length; i++) {
+            dest.writeInt(supportedColorModes[i]);
         }
         dest.writeParcelable(hdrCapabilities, flags);
         dest.writeInt(logicalDensityDpi);
@@ -496,24 +490,6 @@
         return result;
     }
 
-    public Display.ColorTransform getColorTransform() {
-        return findColorTransform(colorTransformId);
-    }
-
-    public Display.ColorTransform getDefaultColorTransform() {
-        return findColorTransform(defaultColorTransformId);
-    }
-
-    private Display.ColorTransform findColorTransform(int colorTransformId) {
-        for (int i = 0; i < supportedColorTransforms.length; i++) {
-            Display.ColorTransform colorTransform = supportedColorTransforms[i];
-            if (colorTransform.getId() == colorTransformId) {
-                return colorTransform;
-            }
-        }
-        throw new IllegalStateException("Unable to locate color transform: " + colorTransformId);
-    }
-
     public void getAppMetrics(DisplayMetrics outMetrics) {
         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
@@ -615,12 +591,10 @@
         sb.append(defaultModeId);
         sb.append(", modes ");
         sb.append(Arrays.toString(supportedModes));
-        sb.append(", colorTransformId ");
-        sb.append(colorTransformId);
-        sb.append(", defaultColorTransformId ");
-        sb.append(defaultColorTransformId);
-        sb.append(", supportedColorTransforms ");
-        sb.append(Arrays.toString(supportedColorTransforms));
+        sb.append(", colorMode ");
+        sb.append(colorMode);
+        sb.append(", supportedColorModes ");
+        sb.append(Arrays.toString(supportedColorModes));
         sb.append(", hdrCapabilities ");
         sb.append(hdrCapabilities);
         sb.append(", rotation ");
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index f1abca8..e778a7f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -82,6 +82,10 @@
             IBinder displayToken);
     private static native int nativeGetActiveConfig(IBinder displayToken);
     private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
+    private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
+    private static native int nativeGetActiveColorMode(IBinder displayToken);
+    private static native boolean nativeSetActiveColorMode(IBinder displayToken,
+            int colorMode);
     private static native void nativeSetDisplayPowerMode(
             IBinder displayToken, int mode);
     private static native void nativeDeferTransactionUntil(long nativeObject,
@@ -547,7 +551,6 @@
         public boolean secure;
         public long appVsyncOffsetNanos;
         public long presentationDeadlineNanos;
-        public int colorTransform;
 
         public PhysicalDisplayInfo() {
         }
@@ -571,8 +574,7 @@
                     && yDpi == other.yDpi
                     && secure == other.secure
                     && appVsyncOffsetNanos == other.appVsyncOffsetNanos
-                    && presentationDeadlineNanos == other.presentationDeadlineNanos
-                    && colorTransform == other.colorTransform;
+                    && presentationDeadlineNanos == other.presentationDeadlineNanos;
         }
 
         @Override
@@ -590,7 +592,6 @@
             secure = other.secure;
             appVsyncOffsetNanos = other.appVsyncOffsetNanos;
             presentationDeadlineNanos = other.presentationDeadlineNanos;
-            colorTransform = other.colorTransform;
         }
 
         // For debugging purposes
@@ -599,8 +600,7 @@
             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
                     + ", appVsyncOffset " + appVsyncOffsetNanos
-                    + ", bufferDeadline " + presentationDeadlineNanos
-                    + ", colorTransform " + colorTransform + "}";
+                    + ", bufferDeadline " + presentationDeadlineNanos + "}";
         }
     }
 
@@ -632,6 +632,27 @@
         return nativeSetActiveConfig(displayToken, id);
     }
 
+    public static int[] getDisplayColorModes(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeGetDisplayColorModes(displayToken);
+    }
+
+    public static int getActiveColorMode(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeGetActiveColorMode(displayToken);
+    }
+
+    public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        return nativeSetActiveColorMode(displayToken, colorMode);
+    }
+
     public static void setDisplayProjection(IBinder displayToken,
             int orientation, Rect layerStackRect, Rect displayRect) {
         if (displayToken == null) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index fa1313b..0d8a95c 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -32,6 +32,7 @@
 #include <jni.h>
 #include <memory>
 #include <stdio.h>
+#include <system/graphics.h>
 #include <ui/DisplayInfo.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/FrameStats.h>
@@ -58,7 +59,6 @@
     jfieldID secure;
     jfieldID appVsyncOffsetNanos;
     jfieldID presentationDeadlineNanos;
-    jfieldID colorTransform;
 } gPhysicalDisplayInfoClassInfo;
 
 static struct {
@@ -429,8 +429,6 @@
                 info.appVsyncOffset);
         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
                 info.presentationDeadline);
-        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.colorTransform,
-                info.colorTransform);
         env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
         env->DeleteLocalRef(infoObj);
     }
@@ -451,6 +449,43 @@
     return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
 }
 
+static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return NULL;
+    Vector<android_color_mode_t> colorModes;
+    if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR ||
+            colorModes.isEmpty()) {
+        return NULL;
+    }
+
+    jintArray colorModesArray = env->NewIntArray(colorModes.size());
+    if (colorModesArray == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return NULL;
+    }
+    jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
+    for (size_t i = 0; i < colorModes.size(); i++) {
+        colorModesArrayValues[i] = static_cast<jint>(colorModes[i]);
+    }
+    env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
+    return colorModesArray;
+}
+
+static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return -1;
+    return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
+}
+
+static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass,
+        jobject tokenObj, jint colorMode) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+    status_t err = SurfaceComposerClient::setActiveColorMode(token,
+            static_cast<android_color_mode_t>(colorMode));
+    return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
+}
+
 static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
     if (token == NULL) return;
@@ -715,6 +750,12 @@
             (void*)nativeGetActiveConfig },
     {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
             (void*)nativeSetActiveConfig },
+    {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
+            (void*)nativeGetDisplayColorModes},
+    {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I",
+            (void*)nativeGetActiveColorMode},
+    {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
+            (void*)nativeSetActiveColorMode},
     {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
             (void*)nativeGetHdrCapabilities },
     {"nativeClearContentFrameStats", "(J)Z",
@@ -757,8 +798,6 @@
             clazz, "appVsyncOffsetNanos", "J");
     gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env,
             clazz, "presentationDeadlineNanos", "J");
-    gPhysicalDisplayInfoClassInfo.colorTransform = GetFieldIDOrDie(env, clazz,
-            "colorTransform", "I");
 
     jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect");
     gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4b66f70..48dfdff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2508,11 +2508,10 @@
     <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
         android:protectionLevel="signature" />
 
-    <!-- Allows an application to control the color transforms applied to
-         displays system-wide.
+    <!-- Allows an application to control the color modes set for displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
-    <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
+    <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
         android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to control VPN.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 674a0d7..2835c6f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1825,28 +1825,6 @@
     -->
     <bool name="config_enableWifiDisplay">false</bool>
 
-    <!-- The color transform values that correspond to each respective configuration mode for the
-         built-in display, or -1 if the mode is unsupported by the device. The possible
-         configuration modes are:
-            1. Wide-gamut ("Vibrant")
-            2. Adobe RGB ("Natural")
-            3. sRGB ("Standard")
-
-        For example, if a device had Wide-gamut as color transform mode 1, sRGB mode as color
-        transform mode 7, and did not support Adobe RGB at all this would look like:
-
-            <integer-array name="config_colorTransforms">
-                <item>1</item>
-                <item>-1</item>
-                <item>7</item>
-            </integer-array>
-    -->
-    <integer-array name="config_colorTransforms">
-        <item>-1</item>
-        <item>-1</item>
-        <item>-1</item>
-    </integer-array>
-
     <!-- When true, local displays that do not contain any of their own content will automatically
          mirror the content of the default display. -->
     <bool name="config_localDisplaysMirrorContent">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3590ac8..38749f6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1142,7 +1142,6 @@
   <java-symbol type="array" name="config_telephonyHardware" />
   <java-symbol type="array" name="config_keySystemUuidMapping" />
   <java-symbol type="array" name="config_gpsParameters" />
-  <java-symbol type="array" name="config_colorTransforms" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
   <java-symbol type="drawable" name="default_lock_wallpaper" />