Add wide color gamut and HDR resource qualifiers

Bug: 32984164
Test: Config_test, AaptConfig_test and aapt2_tests
Change-Id: Ie9c82bfe2d36b1d6180ee223250ab5bb2ce90dd4
diff --git a/api/current.txt b/api/current.txt
index b3090cd..be151aa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9543,6 +9543,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -10537,7 +10538,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -10547,6 +10550,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -10612,6 +10625,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
diff --git a/api/system-current.txt b/api/system-current.txt
index 3bc7be5..bb1e9c8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9940,6 +9940,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -11055,7 +11056,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -11065,6 +11068,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -11130,6 +11143,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
diff --git a/api/test-current.txt b/api/test-current.txt
index 22c5581..d485f20 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -9568,6 +9568,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -10569,7 +10570,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -10579,6 +10582,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -10644,6 +10657,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 298dc4e..4bd091d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -566,6 +566,7 @@
                     CONFIG_SMALLEST_SCREEN_SIZE,
                     CONFIG_DENSITY,
                     CONFIG_LAYOUT_DIRECTION,
+                    CONFIG_COLORIMETRY,
                     CONFIG_FONT_SCALE,
             })
     @Retention(RetentionPolicy.SOURCE)
@@ -671,6 +672,12 @@
     public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the change to the display color gamut or dynamic
+     * range. Set from the {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_COLORIMETRY = 0x4000;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle asset path changes.  Set from the {@link android.R.attr#configChanges}
      * attribute. This is not a core resource configuration, but a higher-level value, so its
      * constant starts at the high bits.
@@ -706,6 +713,7 @@
         Configuration.NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,   // SMALLEST SCREEN SIZE
         Configuration.NATIVE_CONFIG_DENSITY,                // DENSITY
         Configuration.NATIVE_CONFIG_LAYOUTDIR,              // LAYOUT DIRECTION
+        Configuration.NATIVE_CONFIG_COLORIMETRY,            // COLORIMETRY
     };
 
     /**
@@ -761,7 +769,8 @@
      * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
      * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
      * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT},
-     * {@link #CONFIG_DENSITY}, and {@link #CONFIG_LAYOUT_DIRECTION}.
+     * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION} and
+     * {@link #CONFIG_COLORIMETRY}.
      * Set from the {@link android.R.attr#configChanges} attribute.
      */
     public int configChanges;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 65f4957..a81329d 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -101,6 +101,68 @@
      */
     public boolean userSetLocale;
 
+
+    /** Constant for {@link #colorimetry}: bits that encode whether the screen is wide gamut. */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 0x3;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that it is unknown whether or not the screen is wide gamut.
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that the screen is not wide gamut.
+     * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 0x1;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that the screen is wide gamut.
+     * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 0x2;
+
+    /** Constant for {@link #colorimetry}: bits that encode whether the dynamic range of the screen. */
+    public static final int COLORIMETRY_HDR_MASK = 0xc;
+    /** Constant for {@link #colorimetry}: bits shift to get the screen dynamic range. */
+    public static final int COLORIMETRY_HDR_SHIFT = 2;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that it is unknown whether or not the screen is HDR.
+     */
+    public static final int COLORIMETRY_HDR_UNDEFINED = 0x0;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that the screen is not HDR (low/standard dynamic range).
+     * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_HDR_NO = 0x1 << COLORIMETRY_HDR_SHIFT;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that the screen is HDR (dynamic range).
+     * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_HDR_YES = 0x2 << COLORIMETRY_HDR_SHIFT;
+
+    /** Constant for {@link #colorimetry}: a value indicating that colorimetry is undefined */
+    @SuppressWarnings("PointlessBitwiseExpression")
+    public static final int COLORIMETRY_UNDEFINED = COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED |
+            COLORIMETRY_HDR_UNDEFINED;
+
+    /**
+     * Bit mask of for color capabilities of the screen. Currently there are two fields:
+     * <p>The {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
+     * the screen. They may be one of
+     * {@link #COLORIMETRY_WIDE_COLOR_GAMUT_NO} or {@link #COLORIMETRY_WIDE_COLOR_GAMUT_YES}.</p>
+     *
+     * <p>The {@link #COLORIMETRY_HDR_MASK} defines the dynamic range of the screen. They may be
+     * one of {@link #COLORIMETRY_HDR_NO} or {@link #COLORIMETRY_HDR_YES}.</p>
+     *
+     * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+     * Multiple Screens</a> for more information.</p>
+     */
+    public int colorimetry;
+
     /** Constant for {@link #screenLayout}: bits that encode the size. */
     public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
@@ -331,6 +393,9 @@
         if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
             list.add("CONFIG_SCREEN_LAYOUT");
         }
+        if ((diff & ActivityInfo.CONFIG_COLORIMETRY) != 0) {
+            list.add("CONFIG_COLORIMETRY");
+        }
         if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
             list.add("CONFIG_UI_MODE");
         }
@@ -711,6 +776,7 @@
                     NATIVE_CONFIG_UI_MODE,
                     NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
                     NATIVE_CONFIG_LAYOUTDIR,
+                    NATIVE_CONFIG_COLORIMETRY,
             })
     @Retention(RetentionPolicy.SOURCE)
     public @interface NativeConfig {}
@@ -747,6 +813,8 @@
     public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
     /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
     public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
+    /** @hide Native-specific bit mask for COLORIMETRY config ; DO NOT USE UNLESS YOU ARE SURE.*/
+    public static final int NATIVE_CONFIG_COLORIMETRY = 0x10000;
 
     /**
      * <p>Construct an invalid Configuration. This state is only suitable for constructing a
@@ -805,6 +873,7 @@
         navigationHidden = o.navigationHidden;
         orientation = o.orientation;
         screenLayout = o.screenLayout;
+        colorimetry = o.colorimetry;
         uiMode = o.uiMode;
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
@@ -885,6 +954,20 @@
             default: sb.append(" layoutLong=");
                     sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
         }
+        switch ((colorimetry&COLORIMETRY_HDR_MASK)) {
+            case COLORIMETRY_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
+            case COLORIMETRY_HDR_NO: /* ldr is not interesting to print */ break;
+            case COLORIMETRY_HDR_YES: sb.append(" hdr"); break;
+            default: sb.append(" dynamicRange=");
+                sb.append(colorimetry&COLORIMETRY_HDR_MASK); break;
+        }
+        switch ((colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            case COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
+            case COLORIMETRY_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
+            case COLORIMETRY_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
+            default: sb.append(" wideColorGamut=");
+                sb.append(colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK); break;
+        }
         switch (orientation) {
             case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
             case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
@@ -976,6 +1059,7 @@
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_UNDEFINED;
+        colorimetry = COLORIMETRY_UNDEFINED;
         uiMode = UI_MODE_TYPE_UNDEFINED;
         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
@@ -1111,6 +1195,23 @@
                 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
         }
 
+        if (((delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                     COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED)
+                && (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)
+                != (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+            colorimetry = (colorimetry & ~COLORIMETRY_WIDE_COLOR_GAMUT_MASK)
+                    | (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK);
+        }
+
+        if (((delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED)
+                && (delta.colorimetry & COLORIMETRY_HDR_MASK)
+                != (colorimetry & COLORIMETRY_HDR_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+            colorimetry = (colorimetry & ~COLORIMETRY_HDR_MASK)
+                    | (delta.colorimetry & COLORIMETRY_HDR_MASK);
+        }
+
         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
                 && uiMode != delta.uiMode) {
             changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -1260,6 +1361,19 @@
                 getScreenLayoutNoDirection(delta.screenLayout)) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
+        if ((compareUndefined ||
+                     (delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED)
+                && (colorimetry & COLORIMETRY_HDR_MASK) !=
+                        (delta.colorimetry & COLORIMETRY_HDR_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+        }
+        if ((compareUndefined ||
+                     (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                             COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED)
+                && (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                        (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+        }
         if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
                 && uiMode != delta.uiMode) {
             changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -1371,6 +1485,7 @@
         dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
+        dest.writeInt(colorimetry);
         dest.writeInt(uiMode);
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
@@ -1405,6 +1520,7 @@
         navigationHidden = source.readInt();
         orientation = source.readInt();
         screenLayout = source.readInt();
+        colorimetry = source.readInt();
         uiMode = source.readInt();
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
@@ -1486,6 +1602,8 @@
         if (n != 0) return n;
         n = this.orientation - that.orientation;
         if (n != 0) return n;
+        n = this.colorimetry - that.colorimetry;
+        if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
         if (n != 0) return n;
         n = this.uiMode - that.uiMode;
@@ -1531,6 +1649,7 @@
         result = 31 * result + navigationHidden;
         result = 31 * result + orientation;
         result = 31 * result + screenLayout;
+        result = 31 * result + colorimetry;
         result = 31 * result + uiMode;
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
@@ -1639,6 +1758,24 @@
     }
 
     /**
+     * Return whether the screen has a wide color gamut.
+     *
+     * @return true if the screen has a wide color gamut, false otherwise
+     */
+    public boolean isScreenWideColorGamut() {
+        return (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) == COLORIMETRY_WIDE_COLOR_GAMUT_YES;
+    }
+
+    /**
+     * Return whether the screen has a high dynamic range.
+     *
+     * @return true if the screen has a high dynamic range, false otherwise
+     */
+    public boolean isScreenHdr() {
+        return (colorimetry & COLORIMETRY_HDR_MASK) == COLORIMETRY_HDR_YES;
+    }
+
+    /**
      *
      * @hide
      */
@@ -1770,6 +1907,28 @@
                 break;
         }
 
+        switch (config.colorimetry & Configuration.COLORIMETRY_HDR_MASK) {
+            case Configuration.COLORIMETRY_HDR_YES:
+                parts.add("highdr");
+                break;
+            case Configuration.COLORIMETRY_HDR_NO:
+                parts.add("lowdr");
+                break;
+            default:
+                break;
+        }
+
+        switch (config.colorimetry & Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_MASK) {
+            case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_YES:
+                parts.add("widecg");
+                break;
+            case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_NO:
+                parts.add("nowidecg");
+                break;
+            default:
+                break;
+        }
+
         switch (config.orientation) {
             case Configuration.ORIENTATION_LANDSCAPE:
                 parts.add("land");
@@ -1995,6 +2154,16 @@
             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
         }
 
+        if ((base.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                (change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            delta.colorimetry |= change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK;
+        }
+
+        if ((base.colorimetry & COLORIMETRY_HDR_MASK) !=
+                (change.colorimetry & COLORIMETRY_HDR_MASK)) {
+            delta.colorimetry |= change.colorimetry & COLORIMETRY_HDR_MASK;
+        }
+
         if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
             delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
         }
@@ -2037,6 +2206,7 @@
     private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
     private static final String XML_ATTR_ORIENTATION = "ori";
     private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
+    private static final String XML_ATTR_COLORIMETRY = "clrMtry";
     private static final String XML_ATTR_UI_MODE = "ui";
     private static final String XML_ATTR_SCREEN_WIDTH = "width";
     private static final String XML_ATTR_SCREEN_HEIGHT = "height";
@@ -2079,6 +2249,8 @@
                 ORIENTATION_UNDEFINED);
         configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
                 SCREENLAYOUT_UNDEFINED);
+        configOut.colorimetry = XmlUtils.readIntAttribute(parser, XML_ATTR_COLORIMETRY,
+                COLORIMETRY_UNDEFINED);
         configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
         configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
                 SCREEN_WIDTH_DP_UNDEFINED);
@@ -2141,6 +2313,9 @@
         if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
             XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
         }
+        if (config.colorimetry != COLORIMETRY_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_COLORIMETRY, config.colorimetry);
+        }
         if (config.uiMode != 0) {
             XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
         }
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b961394..d1a1d3e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -843,6 +843,9 @@
         <flag name="density" value="0x1000" />
         <!-- The layout direction has changed. For example going from LTR to RTL. -->
         <flag name="layoutDirection" value="0x2000" />
+        <!-- The colorimetry capabilities of the screen have changed (color gamut
+             or dynamic range). -->
+        <flag name="colorimetry" value="0x4000" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 77e8d77..021a07e 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -565,6 +565,38 @@
 method, which indicates whether the screen is round.</p>
       </td>
     </tr>
+    <tr id="WideColorGamutQualifier">
+      <td>Wide Color Gamut</td>
+      <td>
+        <code>widecg</code><br/>
+        <code>nowidecg</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code widecg}: Displays with a wide color gamut such as Display P3 or AdobeRGB</li>
+          <li>{@code nowidecg}: Displays with a narrow color gamut such as sRGB</li>
+        </ul>
+        <p><em>Added in API level 26.</em></p>
+        <p>Also see the {@link android.content.res.Configuration#isScreenWideColorGamut()} configuration
+        method, which indicates whether the screen has a wide color gamut.</p>
+      </td>
+    </tr>
+    <tr id="HDRQualifier">
+      <td>High Dynamic Range (HDR)</td>
+      <td>
+        <code>highdr</code><br/>
+        <code>lowdr</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code highdr}: Displays with a high-dynamic range</li>
+          <li>{@code lowdr}: Displays with a low/standard dynamic range</li>
+        </ul>
+        <p><em>Added in API level 26.</em></p>
+        <p>Also see the {@link android.content.res.Configuration#isScreenHdr()} configuration
+        method, which indicates whether the screen has a HDR capabilities.</p>
+      </td>
+    </tr>
     <tr id="OrientationQualifier">
       <td>Screen orientation</td>
       <td>
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index a30c849..a4bcc62 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1907,6 +1907,8 @@
     if (diff != 0) return diff;
     diff = (int32_t)(screenLayout2 - o.screenLayout2);
     if (diff != 0) return diff;
+    diff = (int32_t)(colorimetry - o.colorimetry);
+    if (diff != 0) return diff;
     diff = (int32_t)(uiMode - o.uiMode);
     if (diff != 0) return diff;
     diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp);
@@ -1967,6 +1969,9 @@
     if (screenLayout2 != o.screenLayout2) {
         return screenLayout2 < o.screenLayout2 ? -1 : 1;
     }
+    if (colorimetry != o.colorimetry) {
+        return colorimetry < o.colorimetry ? -1 : 1;
+    }
     if (uiMode != o.uiMode) {
         return uiMode < o.uiMode ? -1 : 1;
     }
@@ -1992,6 +1997,8 @@
     if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) diffs |= CONFIG_LAYOUTDIR;
     if ((screenLayout & ~MASK_LAYOUTDIR) != (o.screenLayout & ~MASK_LAYOUTDIR)) diffs |= CONFIG_SCREEN_LAYOUT;
     if ((screenLayout2 & MASK_SCREENROUND) != (o.screenLayout2 & MASK_SCREENROUND)) diffs |= CONFIG_SCREEN_ROUND;
+    if ((colorimetry & MASK_WIDE_COLOR_GAMUT) != (o.colorimetry & MASK_WIDE_COLOR_GAMUT)) diffs |= CONFIG_COLORIMETRY;
+    if ((colorimetry & MASK_HDR) != (o.colorimetry & MASK_HDR)) diffs |= CONFIG_COLORIMETRY;
     if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
     if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
@@ -2103,6 +2110,17 @@
         }
     }
 
+    if (colorimetry || o.colorimetry) {
+        if (((colorimetry^o.colorimetry) & MASK_HDR) != 0) {
+            if (!(colorimetry & MASK_HDR)) return false;
+            if (!(o.colorimetry & MASK_HDR)) return true;
+        }
+        if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0) {
+            if (!(colorimetry & MASK_WIDE_COLOR_GAMUT)) return false;
+            if (!(o.colorimetry & MASK_WIDE_COLOR_GAMUT)) return true;
+        }
+    }
+
     if (orientation != o.orientation) {
         if (!orientation) return false;
         if (!o.orientation) return true;
@@ -2390,6 +2408,17 @@
             }
         }
 
+        if (colorimetry || o.colorimetry) {
+            if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0 &&
+                    (requested->colorimetry & MASK_WIDE_COLOR_GAMUT)) {
+                return colorimetry & MASK_WIDE_COLOR_GAMUT;
+            }
+            if (((colorimetry^o.colorimetry) & MASK_HDR) != 0 &&
+                    (requested->colorimetry & MASK_HDR)) {
+                return colorimetry & MASK_HDR;
+            }
+        }
+
         if ((orientation != o.orientation) && requested->orientation) {
             return (orientation);
         }
@@ -2639,6 +2668,18 @@
         if (screenRound != 0 && screenRound != setScreenRound) {
             return false;
         }
+
+        const int hdr = colorimetry & MASK_HDR;
+        const int setHdr = settings.colorimetry & MASK_HDR;
+        if (hdr != 0 && hdr != setHdr) {
+            return false;
+        }
+
+        const int wideColorGamut = colorimetry & MASK_WIDE_COLOR_GAMUT;
+        const int setWideColorGamut = settings.colorimetry & MASK_WIDE_COLOR_GAMUT;
+        if (wideColorGamut != 0 && wideColorGamut != setWideColorGamut) {
+            return false;
+        }
     }
 
     if (screenSizeDp != 0) {
@@ -2959,6 +3000,34 @@
                 break;
         }
     }
+    if ((colorimetry&MASK_HDR) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (colorimetry&MASK_HDR) {
+            case ResTable_config::HDR_NO:
+                res.append("lowdr");
+                break;
+            case ResTable_config::HDR_YES:
+                res.append("highdr");
+                break;
+            default:
+                res.appendFormat("hdr=%d", dtohs(colorimetry&MASK_HDR));
+                break;
+        }
+    }
+    if ((colorimetry&MASK_WIDE_COLOR_GAMUT) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (colorimetry&MASK_WIDE_COLOR_GAMUT) {
+            case ResTable_config::WIDE_COLOR_GAMUT_NO:
+                res.append("nowidecg");
+                break;
+            case ResTable_config::WIDE_COLOR_GAMUT_YES:
+                res.append("widecg");
+                break;
+            default:
+                res.appendFormat("wideColorGamut=%d", dtohs(colorimetry&MASK_WIDE_COLOR_GAMUT));
+                break;
+        }
+    }
     if (orientation != ORIENTATION_ANY) {
         if (res.size() > 0) res.append("-");
         switch (orientation) {
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index c118b57..1e4aee9 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1146,11 +1146,26 @@
         SCREENROUND_YES = ACONFIGURATION_SCREENROUND_YES,
     };
 
+    enum {
+        // colorimetry bits for wide-color gamut/narrow-color gamut.
+        MASK_WIDE_COLOR_GAMUT = 0x03,
+        WIDE_COLOR_GAMUT_ANY = ACONFIGURATION_WIDE_COLOR_GAMUT_ANY,
+        WIDE_COLOR_GAMUT_NO = ACONFIGURATION_WIDE_COLOR_GAMUT_NO,
+        WIDE_COLOR_GAMUT_YES = ACONFIGURATION_WIDE_COLOR_GAMUT_YES,
+
+        // colorimetry bits for HDR/LDR.
+        MASK_HDR = 0x0c,
+        SHIFT_COLORIMETRY_HDR = 2,
+        HDR_ANY = ACONFIGURATION_HDR_ANY << SHIFT_COLORIMETRY_HDR,
+        HDR_NO = ACONFIGURATION_HDR_NO << SHIFT_COLORIMETRY_HDR,
+        HDR_YES = ACONFIGURATION_HDR_YES << SHIFT_COLORIMETRY_HDR,
+    };
+
     // An extension of screenConfig.
     union {
         struct {
             uint8_t screenLayout2;      // Contains round/notround qualifier.
-            uint8_t screenConfigPad1;   // Reserved padding.
+            uint8_t colorimetry;        // Wide-gamut, HDR, etc.
             uint16_t screenConfigPad2;  // Reserved padding.
         };
         uint32_t screenConfig2;
@@ -1193,6 +1208,7 @@
         CONFIG_UI_MODE = ACONFIGURATION_UI_MODE,
         CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR,
         CONFIG_SCREEN_ROUND = ACONFIGURATION_SCREEN_ROUND,
+        CONFIG_COLORIMETRY = ACONFIGURATION_COLORIMETRY,
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
index 778c7bf..3e5aca7 100644
--- a/libs/androidfw/tests/Config_test.cpp
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -182,4 +182,24 @@
   EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
 }
 
+TEST(ConfigTest, ScreenIsWideGamut) {
+  ResTable_config defaultConfig;
+  memset(&defaultConfig, 0, sizeof(defaultConfig));
+
+  ResTable_config wideGamutConfig = defaultConfig;
+  wideGamutConfig.colorimetry = ResTable_config::WIDE_COLOR_GAMUT_YES;
+
+  EXPECT_EQ(defaultConfig.diff(wideGamutConfig), ResTable_config::CONFIG_COLORIMETRY);
+}
+
+TEST(ConfigTest, ScreenIsHdr) {
+  ResTable_config defaultConfig;
+  memset(&defaultConfig, 0, sizeof(defaultConfig));
+
+  ResTable_config hdrConfig = defaultConfig;
+  hdrConfig.colorimetry = ResTable_config::HDR_YES;
+
+  EXPECT_EQ(defaultConfig.diff(hdrConfig), ResTable_config::CONFIG_COLORIMETRY);
+}
+
 }  // namespace android.
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index 565d2f0..d0026a2 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -131,6 +131,22 @@
         part = parts[index].string();
     }
 
+    if (parseWideColorGamut(part, &config)) {
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index].string();
+    }
+
+    if (parseHdr(part, &config)) {
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index].string();
+    }
+
     if (parseOrientation(part, &config)) {
         index++;
         if (index == N) {
@@ -250,7 +266,9 @@
 
     uint16_t minSdk = 0;
     if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
-                == ResTable_config::UI_MODE_TYPE_VR_HEADSET) {
+                == ResTable_config::UI_MODE_TYPE_VR_HEADSET
+            || config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT
+            || config->colorimetry & ResTable_config::MASK_HDR) {
         minSdk = SDK_O;
     } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
         minSdk = SDK_MNC;
@@ -431,6 +449,46 @@
     return false;
 }
 
+bool parseWideColorGamut(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_ANY;
+        return true;
+    } else if (strcmp(name, "widecg") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_YES;
+        return true;
+    } else if (strcmp(name, "nowidecg") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_NO;
+        return true;
+    }
+    return false;
+}
+
+bool parseHdr(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_ANY;
+        return true;
+    } else if (strcmp(name, "highdr") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_YES;
+        return true;
+    } else if (strcmp(name, "lowdr") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_NO;
+        return true;
+    }
+    return false;
+}
+
 bool parseOrientation(const char* name, ResTable_config* out) {
     if (strcmp(name, kWildcardName) == 0) {
         if (out) out->orientation = out->ORIENTATION_ANY;
diff --git a/tools/aapt/AaptConfig.h b/tools/aapt/AaptConfig.h
index 04c763f..a6dd252 100644
--- a/tools/aapt/AaptConfig.h
+++ b/tools/aapt/AaptConfig.h
@@ -61,6 +61,8 @@
 bool parseScreenLayoutSize(const char* str, android::ResTable_config* out = NULL);
 bool parseScreenLayoutLong(const char* str, android::ResTable_config* out = NULL);
 bool parseScreenRound(const char* name, android::ResTable_config* out = NULL);
+bool parseWideColorGamut(const char* name, android::ResTable_config* out = NULL);
+bool parseHdr(const char* name, android::ResTable_config* out = NULL);
 bool parseOrientation(const char* str, android::ResTable_config* out = NULL);
 bool parseUiModeType(const char* str, android::ResTable_config* out = NULL);
 bool parseUiModeNight(const char* str, android::ResTable_config* out = NULL);
diff --git a/tools/aapt/tests/AaptConfig_test.cpp b/tools/aapt/tests/AaptConfig_test.cpp
index 8bb38ba..23f61e9 100644
--- a/tools/aapt/tests/AaptConfig_test.cpp
+++ b/tools/aapt/tests/AaptConfig_test.cpp
@@ -98,3 +98,33 @@
     EXPECT_EQ(SDK_MNC, config.sdkVersion);
     EXPECT_EQ(String8("notround-v23"), config.toString());
 }
+
+TEST(AaptConfigTest, WideColorGamutQualifier) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("widecg", &config));
+    EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES,
+              config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("widecg-v26"), config.toString());
+
+    EXPECT_TRUE(TestParse("nowidecg", &config));
+    EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO,
+              config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("nowidecg-v26"), config.toString());
+}
+
+TEST(AaptConfigTest, HdrQualifier) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("highdr", &config));
+    EXPECT_EQ(android::ResTable_config::HDR_YES,
+              config.colorimetry & android::ResTable_config::MASK_HDR);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("highdr-v26"), config.toString());
+
+    EXPECT_TRUE(TestParse("lowdr", &config));
+    EXPECT_EQ(android::ResTable_config::HDR_NO,
+              config.colorimetry & android::ResTable_config::MASK_HDR);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("lowdr-v26"), config.toString());
+}
\ No newline at end of file
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
index c97d6d4..5bea3ad 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -206,6 +206,52 @@
   return false;
 }
 
+static bool parseWideColorGamut(const char* name, ResTable_config* out) {
+  if (strcmp(name, kWildcardName) == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_ANY;
+    return true;
+  } else if (strcmp(name, "widecg") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_YES;
+    return true;
+  } else if (strcmp(name, "nowidecg") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_NO;
+    return true;
+  }
+  return false;
+}
+
+static bool parseHdr(const char* name, ResTable_config* out) {
+  if (strcmp(name, kWildcardName) == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_ANY;
+    return true;
+  } else if (strcmp(name, "highdr") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_YES;
+    return true;
+  } else if (strcmp(name, "lowdr") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_NO;
+    return true;
+  }
+  return false;
+}
+
 static bool parseOrientation(const char* name, ResTable_config* out) {
   if (strcmp(name, kWildcardName) == 0) {
     if (out) out->orientation = out->ORIENTATION_ANY;
@@ -687,6 +733,20 @@
     }
   }
 
+  if (parseWideColorGamut(part_iter->c_str(), &config)) {
+    ++part_iter;
+    if (part_iter == parts_end) {
+      goto success;
+    }
+  }
+
+  if (parseHdr(part_iter->c_str(), &config)) {
+    ++part_iter;
+    if (part_iter == parts_end) {
+      goto success;
+    }
+  }
+
   if (parseOrientation(part_iter->c_str(), &config)) {
     ++part_iter;
     if (part_iter == parts_end) {
@@ -779,7 +839,9 @@
     ConfigDescription* config) {
   uint16_t min_sdk = 0;
   if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
-                == ResTable_config::UI_MODE_TYPE_VR_HEADSET) {
+                == ResTable_config::UI_MODE_TYPE_VR_HEADSET ||
+            config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT ||
+            config->colorimetry & ResTable_config::MASK_HDR) {
         min_sdk = SDK_O;
   } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
     min_sdk = SDK_MARSHMALLOW;
@@ -850,6 +912,12 @@
   if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) {
     return !(o.screenLayout2 & MASK_SCREENROUND);
   }
+  if ((colorimetry | o.colorimetry) & MASK_HDR) {
+    return !(o.colorimetry & MASK_HDR);
+  }
+  if ((colorimetry | o.colorimetry) & MASK_WIDE_COLOR_GAMUT) {
+    return !(o.colorimetry & MASK_WIDE_COLOR_GAMUT);
+  }
   if (orientation || o.orientation) return (!o.orientation);
   if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) {
     return !(o.uiMode & MASK_UI_MODE_TYPE);
@@ -896,6 +964,9 @@
          !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) ||
          !pred(screenLayout2 & MASK_SCREENROUND,
                o.screenLayout2 & MASK_SCREENROUND) ||
+         !pred(colorimetry & MASK_HDR, o.colorimetry & MASK_HDR) ||
+         !pred(colorimetry & MASK_WIDE_COLOR_GAMUT,
+               o.colorimetry & MASK_WIDE_COLOR_GAMUT) ||
          !pred(orientation, o.orientation) ||
          !pred(touchscreen, o.touchscreen) ||
          !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) ||
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
index 7933568..b88838a 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -102,6 +102,36 @@
   EXPECT_EQ(std::string("notround-v23"), config.toString().string());
 }
 
+TEST(ConfigDescriptionTest, TestWideColorGamutQualifier) {
+  ConfigDescription config;
+  EXPECT_TRUE(TestParse("widecg", &config));
+  EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES,
+            config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("widecg-v26"), config.toString().string());
+
+  EXPECT_TRUE(TestParse("nowidecg", &config));
+  EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO,
+            config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("nowidecg-v26"), config.toString().string());
+}
+
+TEST(ConfigDescriptionTest, TestHdrQualifier) {
+  ConfigDescription config;
+  EXPECT_TRUE(TestParse("highdr", &config));
+  EXPECT_EQ(android::ResTable_config::HDR_YES,
+            config.colorimetry & android::ResTable_config::MASK_HDR);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("highdr-v26"), config.toString().string());
+
+  EXPECT_TRUE(TestParse("lowdr", &config));
+  EXPECT_EQ(android::ResTable_config::HDR_NO,
+            config.colorimetry & android::ResTable_config::MASK_HDR);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("lowdr-v26"), config.toString().string());
+}
+
 TEST(ConfigDescriptionTest, ParseVrAttribute) {
   ConfigDescription config;
   EXPECT_TRUE(TestParse("vrheadset", &config));