Loading core/java/android/content/res/Resources.java +1 −4 Original line number Diff line number Diff line Loading @@ -1569,10 +1569,7 @@ public class Resources { String locale = null; if (mConfiguration.locale != null) { locale = mConfiguration.locale.getLanguage(); if (mConfiguration.locale.getCountry() != null) { locale += "-" + mConfiguration.locale.getCountry(); } locale = mConfiguration.locale.toLanguageTag(); } int width, height; if (mMetrics.widthPixels >= mMetrics.heightPixels) { Loading include/androidfw/ResourceTypes.h +27 −14 Original line number Diff line number Diff line Loading @@ -1053,7 +1053,7 @@ struct ResTable_config // The ISO-15924 short name for the script corresponding to this // configuration. (eg. Hant, Latn, etc.). Interpreted in conjunction with // the locale field // the locale field. char localeScript[4]; // A single BCP-47 variant subtag. Will vary in length between 5 and 8 Loading Loading @@ -1118,14 +1118,23 @@ struct ResTable_config bool match(const ResTable_config& settings) const; // Get the string representation of the locale component of this // Config. This will contain the language along with the prefixed script, // region and variant of this config, separated by underscores. // Config. The maximum size of this representation will be // |RESTABLE_MAX_LOCALE_LEN| (including a terminating '\0'). // // 'r' is the region prefix, 's' is the script prefix and 'v' is the // variant prefix. // // Example: en_rUS, en_sLatn_rUS, en_vPOSIX. void getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const; // Example: en-US, en-Latn-US, en-POSIX. void getBcp47Locale(char* out) const; // Sets the values of language, region, script and variant to the // well formed BCP-47 locale contained in |in|. The input locale is // assumed to be valid and no validation is performed. void setBcp47Locale(const char* in); inline void clearLocale() { locale = 0; memset(localeScript, 0, sizeof(localeScript)); memset(localeVariant, 0, sizeof(localeVariant)); } // Get the 2 or 3 letter language code of this configuration. Trailing // bytes are set to '\0'. size_t unpackLanguage(char language[4]) const; Loading @@ -1133,12 +1142,16 @@ struct ResTable_config // bytes are set to '\0'. size_t unpackRegion(char region[4]) const; // Sets the language code of this configuration from |language|. If |language| // is a 2 letter code, the trailing byte is expected to be '\0'. void packLanguage(const char language[3]); // Sets the region code of this configuration from |region|. If |region| // is a 2 letter code, the trailing byte is expected to be '\0'. void packRegion(const char region[3]); // Sets the language code of this configuration to the first three // chars at |language|. // // If |language| is a 2 letter code, the trailing byte must be '\0' or // the BCP-47 separator '-'. void packLanguage(const char* language); // Sets the region code of this configuration to the first three bytes // at |region|. If |region| is a 2 letter code, the trailing byte must be '\0' // or the BCP-47 separator '-'. void packRegion(const char* region); // Returns a positive integer if this config is more specific than |o| // with respect to their locales, a negative integer if |o| is more specific Loading libs/androidfw/AssetManager.cpp +6 −24 Original line number Diff line number Diff line Loading @@ -386,17 +386,8 @@ void AssetManager::setConfiguration(const ResTable_config& config, const char* l if (locale) { setLocaleLocked(locale); } else if (config.language[0] != 0) { char spec[9]; spec[0] = config.language[0]; spec[1] = config.language[1]; if (config.country[0] != 0) { spec[2] = '_'; spec[3] = config.country[0]; spec[4] = config.country[1]; spec[5] = 0; } else { spec[3] = 0; } char spec[RESTABLE_MAX_LOCALE_LEN]; config.getBcp47Locale(spec); setLocaleLocked(spec); } else { updateResourceParamsLocked(); Loading Loading @@ -668,20 +659,11 @@ void AssetManager::updateResourceParamsLocked() const return; } size_t llen = mLocale ? strlen(mLocale) : 0; mConfig->language[0] = 0; mConfig->language[1] = 0; mConfig->country[0] = 0; mConfig->country[1] = 0; if (llen >= 2) { mConfig->language[0] = mLocale[0]; mConfig->language[1] = mLocale[1]; } if (llen >= 5) { mConfig->country[0] = mLocale[3]; mConfig->country[1] = mLocale[4]; if (mLocale) { mConfig->setBcp47Locale(mLocale); } else { mConfig->clearLocale(); } mConfig->size = sizeof(*mConfig); res->setParameters(mConfig); } Loading libs/androidfw/ResourceTypes.cpp +73 −22 Original line number Diff line number Diff line Loading @@ -1592,9 +1592,9 @@ void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) { return 0; } /* static */ void packLanguageOrRegion(const char in[3], const char base, /* static */ void packLanguageOrRegion(const char* in, const char base, char out[2]) { if (in[2] == 0) { if (in[2] == 0 || in[2] == '-') { out[0] = in[0]; out[1] = in[1]; } else { Loading @@ -1608,11 +1608,11 @@ void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) { } void ResTable_config::packLanguage(const char language[3]) { void ResTable_config::packLanguage(const char* language) { packLanguageOrRegion(language, 'a', this->language); } void ResTable_config::packRegion(const char region[3]) { void ResTable_config::packRegion(const char* region) { packLanguageOrRegion(region, '0', this->country); } Loading Loading @@ -2320,7 +2320,7 @@ bool ResTable_config::match(const ResTable_config& settings) const { return true; } void ResTable_config::getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const { void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const { memset(str, 0, RESTABLE_MAX_LOCALE_LEN); // This represents the "any" locale value, which has traditionally been Loading @@ -2331,34 +2331,83 @@ void ResTable_config::getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const { size_t charsWritten = 0; if (language[0]) { unpackLanguage(str); charsWritten += unpackLanguage(str); } if (country[0]) { if (localeScript[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = 'r'; str[charsWritten++] = '-'; } charsWritten += unpackRegion(str + charsWritten); memcpy(str + charsWritten, localeScript, sizeof(localeScript)); charsWritten += sizeof(localeScript); } if (localeScript[0]) { if (country[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = '_s'; str[charsWritten++] = '-'; } memcpy(str + charsWritten, localeScript, sizeof(localeScript)); charsWritten += unpackRegion(str + charsWritten); } if (localeVariant[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = 'v'; str[charsWritten++] = '-'; } memcpy(str + charsWritten, localeVariant, sizeof(localeVariant)); } } /* static */ inline bool assignLocaleComponent(ResTable_config* config, const char* start, size_t size) { switch (size) { case 0: return false; case 2: case 3: config->language[0] ? config->packRegion(start) : config->packLanguage(start); break; case 4: config->localeScript[0] = toupper(start[0]); for (size_t i = 1; i < 4; ++i) { config->localeScript[i] = tolower(start[i]); } break; case 5: case 6: case 7: case 8: for (size_t i = 0; i < size; ++i) { config->localeVariant[i] = tolower(start[i]); } break; default: return false; } return true; } void ResTable_config::setBcp47Locale(const char* in) { locale = 0; memset(localeScript, 0, sizeof(localeScript)); memset(localeVariant, 0, sizeof(localeVariant)); const char* separator = in; const char* start = in; while ((separator = strchr(start, '-')) != NULL) { const size_t size = separator - start; if (!assignLocaleComponent(this, start, size)) { fprintf(stderr, "Invalid BCP-47 locale string: %s", in); } start = (separator + 1); } const size_t size = in + strlen(in) - start; assignLocaleComponent(this, start, size); } String8 ResTable_config::toString() const { String8 res; Loading @@ -2371,7 +2420,7 @@ String8 ResTable_config::toString() const { res.appendFormat("%dmnc", dtohs(mnc)); } char localeStr[RESTABLE_MAX_LOCALE_LEN]; getLocale(localeStr); getBcp47Locale(localeStr); res.append(localeStr); if ((screenLayout&MASK_LAYOUTDIR) != 0) { Loading Loading @@ -5126,18 +5175,20 @@ void ResTable::getConfigurations(Vector<ResTable_config>* configs) const const size_t L = type->configs.size(); for (size_t l=0; l<L; l++) { const ResTable_type* config = type->configs[l]; const ResTable_config* cfg = &config->config; ResTable_config cfg; memset(&cfg, 0, sizeof(ResTable_config)); cfg.copyFromDtoH(config->config); // only insert unique const size_t M = configs->size(); size_t m; for (m=0; m<M; m++) { if (0 == (*configs)[m].compare(*cfg)) { if (0 == (*configs)[m].compare(cfg)) { break; } } // if we didn't find it if (m == M) { configs->add(*cfg); configs->add(cfg); } } } Loading @@ -5155,7 +5206,7 @@ void ResTable::getLocales(Vector<String8>* locales) const char locale[RESTABLE_MAX_LOCALE_LEN]; for (size_t i=0; i<I; i++) { configs[i].getLocale(locale); configs[i].getBcp47Locale(locale); const size_t J = locales->size(); size_t j; for (j=0; j<J; j++) { Loading Loading @@ -5815,7 +5866,7 @@ void ResTable::print(bool inclValues) const } #if 0 char localeStr[RESTABLE_MAX_LOCALE_LEN]; mParams.getLocale(localeStr); mParams.getBcp47Locale(localeStr); printf("mParams=%s,\n" localeStr); #endif size_t pgCount = mPackageGroups.size(); Loading libs/androidfw/tests/ResourceTypes_test.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -146,5 +146,40 @@ TEST(ResourceTypesTest, IsMoreSpecificThan) { EXPECT_TRUE(r.isMoreSpecificThan(l)); } TEST(ResourceTypesTest, setLocale) { ResTable_config test; test.setBcp47Locale("en-US"); EXPECT_EQ('e', test.language[0]); EXPECT_EQ('n', test.language[1]); EXPECT_EQ('U', test.country[0]); EXPECT_EQ('S', test.country[1]); EXPECT_EQ(0, test.localeScript[0]); EXPECT_EQ(0, test.localeVariant[0]); test.setBcp47Locale("eng-419"); char out[4] = { 1, 1, 1, 1}; test.unpackLanguage(out); EXPECT_EQ('e', out[0]); EXPECT_EQ('n', out[1]); EXPECT_EQ('g', out[2]); EXPECT_EQ(0, out[3]); memset(out, 1, 4); test.unpackRegion(out); EXPECT_EQ('4', out[0]); EXPECT_EQ('1', out[1]); EXPECT_EQ('9', out[2]); test.setBcp47Locale("en-Latn-419"); memset(out, 1, 4); EXPECT_EQ('e', test.language[0]); EXPECT_EQ('n', test.language[1]); EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); test.unpackRegion(out); EXPECT_EQ('4', out[0]); EXPECT_EQ('1', out[1]); EXPECT_EQ('9', out[2]); } } // namespace android. Loading
core/java/android/content/res/Resources.java +1 −4 Original line number Diff line number Diff line Loading @@ -1569,10 +1569,7 @@ public class Resources { String locale = null; if (mConfiguration.locale != null) { locale = mConfiguration.locale.getLanguage(); if (mConfiguration.locale.getCountry() != null) { locale += "-" + mConfiguration.locale.getCountry(); } locale = mConfiguration.locale.toLanguageTag(); } int width, height; if (mMetrics.widthPixels >= mMetrics.heightPixels) { Loading
include/androidfw/ResourceTypes.h +27 −14 Original line number Diff line number Diff line Loading @@ -1053,7 +1053,7 @@ struct ResTable_config // The ISO-15924 short name for the script corresponding to this // configuration. (eg. Hant, Latn, etc.). Interpreted in conjunction with // the locale field // the locale field. char localeScript[4]; // A single BCP-47 variant subtag. Will vary in length between 5 and 8 Loading Loading @@ -1118,14 +1118,23 @@ struct ResTable_config bool match(const ResTable_config& settings) const; // Get the string representation of the locale component of this // Config. This will contain the language along with the prefixed script, // region and variant of this config, separated by underscores. // Config. The maximum size of this representation will be // |RESTABLE_MAX_LOCALE_LEN| (including a terminating '\0'). // // 'r' is the region prefix, 's' is the script prefix and 'v' is the // variant prefix. // // Example: en_rUS, en_sLatn_rUS, en_vPOSIX. void getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const; // Example: en-US, en-Latn-US, en-POSIX. void getBcp47Locale(char* out) const; // Sets the values of language, region, script and variant to the // well formed BCP-47 locale contained in |in|. The input locale is // assumed to be valid and no validation is performed. void setBcp47Locale(const char* in); inline void clearLocale() { locale = 0; memset(localeScript, 0, sizeof(localeScript)); memset(localeVariant, 0, sizeof(localeVariant)); } // Get the 2 or 3 letter language code of this configuration. Trailing // bytes are set to '\0'. size_t unpackLanguage(char language[4]) const; Loading @@ -1133,12 +1142,16 @@ struct ResTable_config // bytes are set to '\0'. size_t unpackRegion(char region[4]) const; // Sets the language code of this configuration from |language|. If |language| // is a 2 letter code, the trailing byte is expected to be '\0'. void packLanguage(const char language[3]); // Sets the region code of this configuration from |region|. If |region| // is a 2 letter code, the trailing byte is expected to be '\0'. void packRegion(const char region[3]); // Sets the language code of this configuration to the first three // chars at |language|. // // If |language| is a 2 letter code, the trailing byte must be '\0' or // the BCP-47 separator '-'. void packLanguage(const char* language); // Sets the region code of this configuration to the first three bytes // at |region|. If |region| is a 2 letter code, the trailing byte must be '\0' // or the BCP-47 separator '-'. void packRegion(const char* region); // Returns a positive integer if this config is more specific than |o| // with respect to their locales, a negative integer if |o| is more specific Loading
libs/androidfw/AssetManager.cpp +6 −24 Original line number Diff line number Diff line Loading @@ -386,17 +386,8 @@ void AssetManager::setConfiguration(const ResTable_config& config, const char* l if (locale) { setLocaleLocked(locale); } else if (config.language[0] != 0) { char spec[9]; spec[0] = config.language[0]; spec[1] = config.language[1]; if (config.country[0] != 0) { spec[2] = '_'; spec[3] = config.country[0]; spec[4] = config.country[1]; spec[5] = 0; } else { spec[3] = 0; } char spec[RESTABLE_MAX_LOCALE_LEN]; config.getBcp47Locale(spec); setLocaleLocked(spec); } else { updateResourceParamsLocked(); Loading Loading @@ -668,20 +659,11 @@ void AssetManager::updateResourceParamsLocked() const return; } size_t llen = mLocale ? strlen(mLocale) : 0; mConfig->language[0] = 0; mConfig->language[1] = 0; mConfig->country[0] = 0; mConfig->country[1] = 0; if (llen >= 2) { mConfig->language[0] = mLocale[0]; mConfig->language[1] = mLocale[1]; } if (llen >= 5) { mConfig->country[0] = mLocale[3]; mConfig->country[1] = mLocale[4]; if (mLocale) { mConfig->setBcp47Locale(mLocale); } else { mConfig->clearLocale(); } mConfig->size = sizeof(*mConfig); res->setParameters(mConfig); } Loading
libs/androidfw/ResourceTypes.cpp +73 −22 Original line number Diff line number Diff line Loading @@ -1592,9 +1592,9 @@ void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) { return 0; } /* static */ void packLanguageOrRegion(const char in[3], const char base, /* static */ void packLanguageOrRegion(const char* in, const char base, char out[2]) { if (in[2] == 0) { if (in[2] == 0 || in[2] == '-') { out[0] = in[0]; out[1] = in[1]; } else { Loading @@ -1608,11 +1608,11 @@ void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) { } void ResTable_config::packLanguage(const char language[3]) { void ResTable_config::packLanguage(const char* language) { packLanguageOrRegion(language, 'a', this->language); } void ResTable_config::packRegion(const char region[3]) { void ResTable_config::packRegion(const char* region) { packLanguageOrRegion(region, '0', this->country); } Loading Loading @@ -2320,7 +2320,7 @@ bool ResTable_config::match(const ResTable_config& settings) const { return true; } void ResTable_config::getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const { void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const { memset(str, 0, RESTABLE_MAX_LOCALE_LEN); // This represents the "any" locale value, which has traditionally been Loading @@ -2331,34 +2331,83 @@ void ResTable_config::getLocale(char str[RESTABLE_MAX_LOCALE_LEN]) const { size_t charsWritten = 0; if (language[0]) { unpackLanguage(str); charsWritten += unpackLanguage(str); } if (country[0]) { if (localeScript[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = 'r'; str[charsWritten++] = '-'; } charsWritten += unpackRegion(str + charsWritten); memcpy(str + charsWritten, localeScript, sizeof(localeScript)); charsWritten += sizeof(localeScript); } if (localeScript[0]) { if (country[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = '_s'; str[charsWritten++] = '-'; } memcpy(str + charsWritten, localeScript, sizeof(localeScript)); charsWritten += unpackRegion(str + charsWritten); } if (localeVariant[0]) { if (charsWritten) { str[charsWritten++] = '_'; str[charsWritten++] = 'v'; str[charsWritten++] = '-'; } memcpy(str + charsWritten, localeVariant, sizeof(localeVariant)); } } /* static */ inline bool assignLocaleComponent(ResTable_config* config, const char* start, size_t size) { switch (size) { case 0: return false; case 2: case 3: config->language[0] ? config->packRegion(start) : config->packLanguage(start); break; case 4: config->localeScript[0] = toupper(start[0]); for (size_t i = 1; i < 4; ++i) { config->localeScript[i] = tolower(start[i]); } break; case 5: case 6: case 7: case 8: for (size_t i = 0; i < size; ++i) { config->localeVariant[i] = tolower(start[i]); } break; default: return false; } return true; } void ResTable_config::setBcp47Locale(const char* in) { locale = 0; memset(localeScript, 0, sizeof(localeScript)); memset(localeVariant, 0, sizeof(localeVariant)); const char* separator = in; const char* start = in; while ((separator = strchr(start, '-')) != NULL) { const size_t size = separator - start; if (!assignLocaleComponent(this, start, size)) { fprintf(stderr, "Invalid BCP-47 locale string: %s", in); } start = (separator + 1); } const size_t size = in + strlen(in) - start; assignLocaleComponent(this, start, size); } String8 ResTable_config::toString() const { String8 res; Loading @@ -2371,7 +2420,7 @@ String8 ResTable_config::toString() const { res.appendFormat("%dmnc", dtohs(mnc)); } char localeStr[RESTABLE_MAX_LOCALE_LEN]; getLocale(localeStr); getBcp47Locale(localeStr); res.append(localeStr); if ((screenLayout&MASK_LAYOUTDIR) != 0) { Loading Loading @@ -5126,18 +5175,20 @@ void ResTable::getConfigurations(Vector<ResTable_config>* configs) const const size_t L = type->configs.size(); for (size_t l=0; l<L; l++) { const ResTable_type* config = type->configs[l]; const ResTable_config* cfg = &config->config; ResTable_config cfg; memset(&cfg, 0, sizeof(ResTable_config)); cfg.copyFromDtoH(config->config); // only insert unique const size_t M = configs->size(); size_t m; for (m=0; m<M; m++) { if (0 == (*configs)[m].compare(*cfg)) { if (0 == (*configs)[m].compare(cfg)) { break; } } // if we didn't find it if (m == M) { configs->add(*cfg); configs->add(cfg); } } } Loading @@ -5155,7 +5206,7 @@ void ResTable::getLocales(Vector<String8>* locales) const char locale[RESTABLE_MAX_LOCALE_LEN]; for (size_t i=0; i<I; i++) { configs[i].getLocale(locale); configs[i].getBcp47Locale(locale); const size_t J = locales->size(); size_t j; for (j=0; j<J; j++) { Loading Loading @@ -5815,7 +5866,7 @@ void ResTable::print(bool inclValues) const } #if 0 char localeStr[RESTABLE_MAX_LOCALE_LEN]; mParams.getLocale(localeStr); mParams.getBcp47Locale(localeStr); printf("mParams=%s,\n" localeStr); #endif size_t pgCount = mPackageGroups.size(); Loading
libs/androidfw/tests/ResourceTypes_test.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -146,5 +146,40 @@ TEST(ResourceTypesTest, IsMoreSpecificThan) { EXPECT_TRUE(r.isMoreSpecificThan(l)); } TEST(ResourceTypesTest, setLocale) { ResTable_config test; test.setBcp47Locale("en-US"); EXPECT_EQ('e', test.language[0]); EXPECT_EQ('n', test.language[1]); EXPECT_EQ('U', test.country[0]); EXPECT_EQ('S', test.country[1]); EXPECT_EQ(0, test.localeScript[0]); EXPECT_EQ(0, test.localeVariant[0]); test.setBcp47Locale("eng-419"); char out[4] = { 1, 1, 1, 1}; test.unpackLanguage(out); EXPECT_EQ('e', out[0]); EXPECT_EQ('n', out[1]); EXPECT_EQ('g', out[2]); EXPECT_EQ(0, out[3]); memset(out, 1, 4); test.unpackRegion(out); EXPECT_EQ('4', out[0]); EXPECT_EQ('1', out[1]); EXPECT_EQ('9', out[2]); test.setBcp47Locale("en-Latn-419"); memset(out, 1, 4); EXPECT_EQ('e', test.language[0]); EXPECT_EQ('n', test.language[1]); EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4)); test.unpackRegion(out); EXPECT_EQ('4', out[0]); EXPECT_EQ('1', out[1]); EXPECT_EQ('9', out[2]); } } // namespace android.