diff options
-rw-r--r-- | api/current.txt | 14 | ||||
-rw-r--r-- | api/system-current.txt | 14 | ||||
-rw-r--r-- | api/test-current.txt | 14 | ||||
-rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 11 | ||||
-rw-r--r-- | core/java/android/content/res/Configuration.java | 175 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 3 | ||||
-rw-r--r-- | docs/html/guide/topics/resources/providing-resources.jd | 32 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 69 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 18 | ||||
-rw-r--r-- | libs/androidfw/tests/Config_test.cpp | 20 | ||||
-rw-r--r-- | tools/aapt/AaptConfig.cpp | 60 | ||||
-rw-r--r-- | tools/aapt/AaptConfig.h | 2 | ||||
-rw-r--r-- | tools/aapt/tests/AaptConfig_test.cpp | 30 | ||||
-rw-r--r-- | tools/aapt2/ConfigDescription.cpp | 73 | ||||
-rw-r--r-- | tools/aapt2/ConfigDescription_test.cpp | 30 |
15 files changed, 561 insertions, 4 deletions
diff --git a/api/current.txt b/api/current.txt index b3090cd5215a..be151aa7069f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9543,6 +9543,7 @@ package android.content.pm { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 3bc7be541497..bb1e9c8a1a5e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9940,6 +9940,7 @@ package android.content.pm { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 22c5581732f6..d485f20f4216 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -9568,6 +9568,7 @@ package android.content.pm { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 @@ package android.content.res { 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 298dc4eafa15..4bd091dae77e 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -566,6 +566,7 @@ public class ActivityInfo extends ComponentInfo CONFIG_SMALLEST_SCREEN_SIZE, CONFIG_DENSITY, CONFIG_LAYOUT_DIRECTION, + CONFIG_COLORIMETRY, CONFIG_FONT_SCALE, }) @Retention(RetentionPolicy.SOURCE) @@ -671,6 +672,12 @@ public class ActivityInfo extends ComponentInfo 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 @@ public class ActivityInfo extends ComponentInfo 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 @@ public class ActivityInfo extends ComponentInfo * {@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 65f49578071f..a81329d9ee67 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -101,6 +101,68 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration | (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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** + * 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 b9613949627c..d1a1d3e9352a 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 77e8d7720c61..021a07ecaa5b 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -565,6 +565,38 @@ which indicates whether the screen is long.</p> 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 a30c8497b0f8..a4bcc624ef31 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1907,6 +1907,8 @@ int ResTable_config::compare(const ResTable_config& o) const { 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 @@ int ResTable_config::compareLogical(const ResTable_config& o) const { 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 @@ int ResTable_config::diff(const ResTable_config& o) const { 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 @@ bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const { } } + 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 @@ bool ResTable_config::isBetterThan(const ResTable_config& o, } } + 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 @@ bool ResTable_config::match(const ResTable_config& settings) const { 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 @@ String8 ResTable_config::toString() const { 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 c118b57510f9..1e4aee9d18e7 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1146,11 +1146,26 @@ struct ResTable_config 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 @@ struct ResTable_config 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 778c7bfb2053..3e5aca7ab655 100644 --- a/libs/androidfw/tests/Config_test.cpp +++ b/libs/androidfw/tests/Config_test.cpp @@ -182,4 +182,24 @@ TEST(ConfigTest, RoundIsMoreSpecific) { 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 565d2f0a0549..d0026a28ba16 100644 --- a/tools/aapt/AaptConfig.cpp +++ b/tools/aapt/AaptConfig.cpp @@ -131,6 +131,22 @@ bool parse(const String8& str, ConfigDescription* out) { 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 @@ void applyVersionForCompatibility(ConfigDescription* config) { 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 @@ bool parseScreenRound(const char* name, ResTable_config* out) { 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 04c763f20d31..a6dd252281f5 100644 --- a/tools/aapt/AaptConfig.h +++ b/tools/aapt/AaptConfig.h @@ -61,6 +61,8 @@ bool parseScreenHeightDp(const char* str, android::ResTable_config* out = NULL); 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 8bb38bac6d42..23f61e9e4b70 100644 --- a/tools/aapt/tests/AaptConfig_test.cpp +++ b/tools/aapt/tests/AaptConfig_test.cpp @@ -98,3 +98,33 @@ TEST(AaptConfigTest, TestParsingRoundQualifier) { 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 c97d6d4876fd..5bea3ad1bbad 100644 --- a/tools/aapt2/ConfigDescription.cpp +++ b/tools/aapt2/ConfigDescription.cpp @@ -206,6 +206,52 @@ static bool parseScreenRound(const char* name, ResTable_config* out) { 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 @@ bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) { } } + 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 @@ void ConfigDescription::ApplyVersionForCompatibility( 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 @@ bool ConfigDescription::HasHigherPrecedenceThan( 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 @@ bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const { !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 793356861c1a..b88838ae26f5 100644 --- a/tools/aapt2/ConfigDescription_test.cpp +++ b/tools/aapt2/ConfigDescription_test.cpp @@ -102,6 +102,36 @@ TEST(ConfigDescriptionTest, TestParsingRoundQualifier) { 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)); |