summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-03-07 19:39:13 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-03-07 19:39:13 +0000
commitd5b9bcb60d7d20e3e32edcef7d9b235e0ccccf82 (patch)
tree8943af3865523559f65eeb676eb57d80aecc92d8 /libs
parentf214b4cccba33d66cf52e1896a09e57704c4dae1 (diff)
parent28879bbfe89dc4bf2067a7183975ecffb82f68e6 (diff)
downloadframeworks_base-d5b9bcb60d7d20e3e32edcef7d9b235e0ccccf82.zip
frameworks_base-d5b9bcb60d7d20e3e32edcef7d9b235e0ccccf82.tar.gz
frameworks_base-d5b9bcb60d7d20e3e32edcef7d9b235e0ccccf82.tar.bz2
am 28879bbf: am be57fca4: Merge "Extended locales in AAPT / AssetManager."
* commit '28879bbfe89dc4bf2067a7183975ecffb82f68e6': Extended locales in AAPT / AssetManager.
Diffstat (limited to 'libs')
-rw-r--r--libs/androidfw/AssetManager.cpp30
-rw-r--r--libs/androidfw/ResourceTypes.cpp95
-rw-r--r--libs/androidfw/tests/ResourceTypes_test.cpp35
3 files changed, 114 insertions, 46 deletions
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 5069958..b4d482a 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -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();
@@ -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);
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 0c356b6..efb589a 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -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 {
@@ -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);
}
@@ -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
@@ -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;
@@ -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) {
@@ -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);
}
}
}
@@ -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++) {
@@ -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();
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ResourceTypes_test.cpp
index eadfe00..4888b4a 100644
--- a/libs/androidfw/tests/ResourceTypes_test.cpp
+++ b/libs/androidfw/tests/ResourceTypes_test.cpp
@@ -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.