| Screen orientation |
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index a30c8497b0f84..a4bcc624ef311 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 c118b57510f99..1e4aee9d18e7f 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 778c7bfb2053f..3e5aca7ab6552 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 565d2f0a0549e..d0026a28ba168 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 04c763f20d310..a6dd252281f56 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 8bb38bac6d425..23f61e9e4b704 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 c97d6d4876fdf..5bea3ad1bbade 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 793356861c1a0..b88838ae26f52 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));
|