Merge "Extended locales in AAPT / AssetManager."
This commit is contained in:
@ -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) {
|
||||
|
@ -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
|
||||
@ -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;
|
||||
@ -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
|
||||
|
@ -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 (mLocale) {
|
||||
mConfig->setBcp47Locale(mLocale);
|
||||
} else {
|
||||
mConfig->clearLocale();
|
||||
}
|
||||
if (llen >= 5) {
|
||||
mConfig->country[0] = mLocale[3];
|
||||
mConfig->country[1] = mLocale[4];
|
||||
}
|
||||
mConfig->size = sizeof(*mConfig);
|
||||
|
||||
res->setParameters(mConfig);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
if (country[0]) {
|
||||
if (charsWritten) {
|
||||
str[charsWritten++] = '_';
|
||||
str[charsWritten++] = 'r';
|
||||
}
|
||||
charsWritten += unpackRegion(str + charsWritten);
|
||||
charsWritten += unpackLanguage(str);
|
||||
}
|
||||
|
||||
if (localeScript[0]) {
|
||||
if (charsWritten) {
|
||||
str[charsWritten++] = '_';
|
||||
str[charsWritten++] = '_s';
|
||||
str[charsWritten++] = '-';
|
||||
}
|
||||
memcpy(str + charsWritten, localeScript, sizeof(localeScript));
|
||||
charsWritten += sizeof(localeScript);
|
||||
}
|
||||
|
||||
if (country[0]) {
|
||||
if (charsWritten) {
|
||||
str[charsWritten++] = '-';
|
||||
}
|
||||
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();
|
||||
|
@ -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.
|
||||
|
@ -149,205 +149,506 @@ static bool isHidden(const char *root, const char *path)
|
||||
// =========================================================================
|
||||
// =========================================================================
|
||||
|
||||
status_t
|
||||
AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
|
||||
/* static */ void AaptLocaleValue::splitAndLowerCase(const char* const chars,
|
||||
Vector<String8>* parts, const char separator) {
|
||||
const char *p = chars;
|
||||
const char *q;
|
||||
while (NULL != (q = strchr(p, separator))) {
|
||||
String8 val(p, q - p);
|
||||
val.toLower();
|
||||
parts->add(val);
|
||||
p = q+1;
|
||||
}
|
||||
|
||||
if (p < chars + strlen(chars)) {
|
||||
String8 val(p);
|
||||
val.toLower();
|
||||
parts->add(val);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
inline bool isAlpha(const String8& string) {
|
||||
const size_t length = string.length();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
if (!isalpha(string[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
inline bool isNumber(const String8& string) {
|
||||
const size_t length = string.length();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
if (!isdigit(string[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AaptLocaleValue::setLanguage(const char* languageChars) {
|
||||
size_t i = 0;
|
||||
while ((*languageChars) != '\0') {
|
||||
language[i++] = tolower(*languageChars);
|
||||
languageChars++;
|
||||
}
|
||||
}
|
||||
|
||||
void AaptLocaleValue::setRegion(const char* regionChars) {
|
||||
size_t i = 0;
|
||||
while ((*regionChars) != '\0') {
|
||||
region[i++] = toupper(*regionChars);
|
||||
regionChars++;
|
||||
}
|
||||
}
|
||||
|
||||
void AaptLocaleValue::setScript(const char* scriptChars) {
|
||||
size_t i = 0;
|
||||
while ((*scriptChars) != '\0') {
|
||||
if (i == 0) {
|
||||
script[i++] = toupper(*scriptChars);
|
||||
} else {
|
||||
script[i++] = tolower(*scriptChars);
|
||||
}
|
||||
scriptChars++;
|
||||
}
|
||||
}
|
||||
|
||||
void AaptLocaleValue::setVariant(const char* variantChars) {
|
||||
size_t i = 0;
|
||||
while ((*variantChars) != '\0') {
|
||||
variant[i++] = *variantChars;
|
||||
variantChars++;
|
||||
}
|
||||
}
|
||||
|
||||
bool AaptLocaleValue::initFromFilterString(const String8& str) {
|
||||
// A locale (as specified in the filter) is an underscore separated name such
|
||||
// as "en_US", "en_Latn_US", or "en_US_POSIX".
|
||||
Vector<String8> parts;
|
||||
splitAndLowerCase(str.string(), &parts, '_');
|
||||
|
||||
const int numTags = parts.size();
|
||||
bool valid = false;
|
||||
if (numTags >= 1) {
|
||||
const String8& lang = parts[0];
|
||||
if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
|
||||
setLanguage(lang.string());
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid || numTags == 1) {
|
||||
return valid;
|
||||
}
|
||||
|
||||
// At this point, valid == true && numTags > 1.
|
||||
const String8& part2 = parts[1];
|
||||
if ((part2.length() == 2 && isAlpha(part2)) ||
|
||||
(part2.length() == 3 && isNumber(part2))) {
|
||||
setRegion(part2.string());
|
||||
} else if (part2.length() == 4 && isAlpha(part2)) {
|
||||
setScript(part2.string());
|
||||
} else if (part2.length() >= 5 && part2.length() <= 8) {
|
||||
setVariant(part2.string());
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid || numTags == 2) {
|
||||
return valid;
|
||||
}
|
||||
|
||||
// At this point, valid == true && numTags > 1.
|
||||
const String8& part3 = parts[2];
|
||||
if (((part3.length() == 2 && isAlpha(part3)) ||
|
||||
(part3.length() == 3 && isNumber(part3))) && script[0]) {
|
||||
setRegion(part3.string());
|
||||
} else if (part3.length() >= 5 && part3.length() <= 8) {
|
||||
setVariant(part3.string());
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid || numTags == 3) {
|
||||
return valid;
|
||||
}
|
||||
|
||||
const String8& part4 = parts[3];
|
||||
if (part4.length() >= 5 && part4.length() <= 8) {
|
||||
setVariant(part4.string());
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid || numTags > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
|
||||
const int size = parts.size();
|
||||
int currentIndex = startIndex;
|
||||
|
||||
String8 part = parts[currentIndex];
|
||||
if (part[0] == 'b' && part[1] == '+') {
|
||||
// This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
|
||||
// except that the separator is "+" and not "-".
|
||||
Vector<String8> subtags;
|
||||
AaptLocaleValue::splitAndLowerCase(part.string(), &subtags, '+');
|
||||
subtags.removeItemsAt(0);
|
||||
if (subtags.size() == 1) {
|
||||
setLanguage(subtags[0]);
|
||||
} else if (subtags.size() == 2) {
|
||||
setLanguage(subtags[0]);
|
||||
|
||||
// The second tag can either be a region, a variant or a script.
|
||||
switch (subtags[1].size()) {
|
||||
case 2:
|
||||
case 3:
|
||||
setRegion(subtags[1]);
|
||||
break;
|
||||
case 4:
|
||||
setScript(subtags[1]);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
setVariant(subtags[1]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n",
|
||||
part.string());
|
||||
return -1;
|
||||
}
|
||||
} else if (subtags.size() == 3) {
|
||||
// The language is always the first subtag.
|
||||
setLanguage(subtags[0]);
|
||||
|
||||
// The second subtag can either be a script or a region code.
|
||||
// If its size is 4, it's a script code, else it's a region code.
|
||||
bool hasRegion = false;
|
||||
if (subtags[1].size() == 4) {
|
||||
setScript(subtags[1]);
|
||||
} else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
|
||||
setRegion(subtags[1]);
|
||||
hasRegion = true;
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n", part.string());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The third tag can either be a region code (if the second tag was
|
||||
// a script), else a variant code.
|
||||
if (subtags[2].size() > 4) {
|
||||
setVariant(subtags[2]);
|
||||
} else {
|
||||
setRegion(subtags[2]);
|
||||
}
|
||||
} else if (subtags.size() == 4) {
|
||||
setLanguage(subtags[0]);
|
||||
setScript(subtags[1]);
|
||||
setRegion(subtags[2]);
|
||||
setVariant(subtags[3]);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name: %s\n", part.string());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ++currentIndex;
|
||||
} else {
|
||||
if ((part.length() == 2 || part.length() == 3) && isAlpha(part)) {
|
||||
setLanguage(part);
|
||||
if (++currentIndex == size) {
|
||||
return size;
|
||||
}
|
||||
} else {
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
part = parts[currentIndex];
|
||||
if (part.string()[0] == 'r' && part.length() == 3) {
|
||||
setRegion(part.string() + 1);
|
||||
if (++currentIndex == size) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
|
||||
String8 AaptLocaleValue::toDirName() const {
|
||||
String8 dirName("");
|
||||
if (language[0]) {
|
||||
dirName += language;
|
||||
} else {
|
||||
return dirName;
|
||||
}
|
||||
|
||||
if (script[0]) {
|
||||
dirName += "-s";
|
||||
dirName += script;
|
||||
}
|
||||
|
||||
if (region[0]) {
|
||||
dirName += "-r";
|
||||
dirName += region;
|
||||
}
|
||||
|
||||
if (variant[0]) {
|
||||
dirName += "-v";
|
||||
dirName += variant;
|
||||
}
|
||||
|
||||
return dirName;
|
||||
}
|
||||
|
||||
void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
|
||||
config.unpackLanguage(language);
|
||||
config.unpackRegion(region);
|
||||
if (config.localeScript[0]) {
|
||||
memcpy(script, config.localeScript, sizeof(config.localeScript));
|
||||
}
|
||||
|
||||
if (config.localeVariant[0]) {
|
||||
memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
|
||||
}
|
||||
}
|
||||
|
||||
void AaptLocaleValue::writeTo(ResTable_config* out) const {
|
||||
out->packLanguage(language);
|
||||
out->packRegion(region);
|
||||
|
||||
if (script[0]) {
|
||||
memcpy(out->localeScript, script, sizeof(out->localeScript));
|
||||
}
|
||||
|
||||
if (variant[0]) {
|
||||
memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */ bool
|
||||
AaptGroupEntry::parseFilterNamePart(const String8& part, int* axis, AxisValue* value)
|
||||
{
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(ResTable_config));
|
||||
|
||||
// IMSI - MCC
|
||||
if (getMccName(part.string(), &config)) {
|
||||
*axis = AXIS_MCC;
|
||||
*value = config.mcc;
|
||||
return 0;
|
||||
value->intValue = config.mcc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// IMSI - MNC
|
||||
if (getMncName(part.string(), &config)) {
|
||||
*axis = AXIS_MNC;
|
||||
*value = config.mnc;
|
||||
return 0;
|
||||
value->intValue = config.mnc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// locale - language
|
||||
if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
|
||||
*axis = AXIS_LANGUAGE;
|
||||
*value = part[1] << 8 | part[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// locale - language_REGION
|
||||
if (part.length() == 5 && isalpha(part[0]) && isalpha(part[1])
|
||||
&& part[2] == '_' && isalpha(part[3]) && isalpha(part[4])) {
|
||||
*axis = AXIS_LANGUAGE;
|
||||
*value = (part[4] << 24) | (part[3] << 16) | (part[1] << 8) | (part[0]);
|
||||
return 0;
|
||||
if (value->localeValue.initFromFilterString(part)) {
|
||||
*axis = AXIS_LOCALE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// layout direction
|
||||
if (getLayoutDirectionName(part.string(), &config)) {
|
||||
*axis = AXIS_LAYOUTDIR;
|
||||
*value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
|
||||
return 0;
|
||||
value->intValue = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// smallest screen dp width
|
||||
if (getSmallestScreenWidthDpName(part.string(), &config)) {
|
||||
*axis = AXIS_SMALLESTSCREENWIDTHDP;
|
||||
*value = config.smallestScreenWidthDp;
|
||||
return 0;
|
||||
value->intValue = config.smallestScreenWidthDp;
|
||||
return true;
|
||||
}
|
||||
|
||||
// screen dp width
|
||||
if (getScreenWidthDpName(part.string(), &config)) {
|
||||
*axis = AXIS_SCREENWIDTHDP;
|
||||
*value = config.screenWidthDp;
|
||||
return 0;
|
||||
value->intValue = config.screenWidthDp;
|
||||
return true;
|
||||
}
|
||||
|
||||
// screen dp height
|
||||
if (getScreenHeightDpName(part.string(), &config)) {
|
||||
*axis = AXIS_SCREENHEIGHTDP;
|
||||
*value = config.screenHeightDp;
|
||||
return 0;
|
||||
value->intValue = config.screenHeightDp;
|
||||
return true;
|
||||
}
|
||||
|
||||
// screen layout size
|
||||
if (getScreenLayoutSizeName(part.string(), &config)) {
|
||||
*axis = AXIS_SCREENLAYOUTSIZE;
|
||||
*value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
|
||||
return 0;
|
||||
value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// screen layout long
|
||||
if (getScreenLayoutLongName(part.string(), &config)) {
|
||||
*axis = AXIS_SCREENLAYOUTLONG;
|
||||
*value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
|
||||
return 0;
|
||||
value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
|
||||
return true;
|
||||
}
|
||||
|
||||
// orientation
|
||||
if (getOrientationName(part.string(), &config)) {
|
||||
*axis = AXIS_ORIENTATION;
|
||||
*value = config.orientation;
|
||||
return 0;
|
||||
value->intValue = config.orientation;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ui mode type
|
||||
if (getUiModeTypeName(part.string(), &config)) {
|
||||
*axis = AXIS_UIMODETYPE;
|
||||
*value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
|
||||
return 0;
|
||||
value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ui mode night
|
||||
if (getUiModeNightName(part.string(), &config)) {
|
||||
*axis = AXIS_UIMODENIGHT;
|
||||
*value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
|
||||
return 0;
|
||||
value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
|
||||
return true;
|
||||
}
|
||||
|
||||
// density
|
||||
if (getDensityName(part.string(), &config)) {
|
||||
*axis = AXIS_DENSITY;
|
||||
*value = config.density;
|
||||
return 0;
|
||||
value->intValue = config.density;
|
||||
return true;
|
||||
}
|
||||
|
||||
// touchscreen
|
||||
if (getTouchscreenName(part.string(), &config)) {
|
||||
*axis = AXIS_TOUCHSCREEN;
|
||||
*value = config.touchscreen;
|
||||
return 0;
|
||||
value->intValue = config.touchscreen;
|
||||
return true;
|
||||
}
|
||||
|
||||
// keyboard hidden
|
||||
if (getKeysHiddenName(part.string(), &config)) {
|
||||
*axis = AXIS_KEYSHIDDEN;
|
||||
*value = config.inputFlags;
|
||||
return 0;
|
||||
value->intValue = config.inputFlags;
|
||||
return true;
|
||||
}
|
||||
|
||||
// keyboard
|
||||
if (getKeyboardName(part.string(), &config)) {
|
||||
*axis = AXIS_KEYBOARD;
|
||||
*value = config.keyboard;
|
||||
return 0;
|
||||
value->intValue = config.keyboard;
|
||||
return true;
|
||||
}
|
||||
|
||||
// navigation hidden
|
||||
if (getNavHiddenName(part.string(), &config)) {
|
||||
*axis = AXIS_NAVHIDDEN;
|
||||
*value = config.inputFlags;
|
||||
value->intValue = config.inputFlags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// navigation
|
||||
if (getNavigationName(part.string(), &config)) {
|
||||
*axis = AXIS_NAVIGATION;
|
||||
*value = config.navigation;
|
||||
return 0;
|
||||
value->intValue = config.navigation;
|
||||
return true;
|
||||
}
|
||||
|
||||
// screen size
|
||||
if (getScreenSizeName(part.string(), &config)) {
|
||||
*axis = AXIS_SCREENSIZE;
|
||||
*value = config.screenSize;
|
||||
return 0;
|
||||
value->intValue = config.screenSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
// version
|
||||
if (getVersionName(part.string(), &config)) {
|
||||
*axis = AXIS_VERSION;
|
||||
*value = config.version;
|
||||
return 0;
|
||||
value->intValue = config.version;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AxisValue
|
||||
AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
|
||||
{
|
||||
AxisValue value;
|
||||
switch (axis) {
|
||||
case AXIS_MCC:
|
||||
return config.mcc;
|
||||
value.intValue = config.mcc;
|
||||
break;
|
||||
case AXIS_MNC:
|
||||
return config.mnc;
|
||||
case AXIS_LANGUAGE:
|
||||
return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
|
||||
| (((uint32_t)config.language[1]) << 8) | (config.language[0]);
|
||||
value.intValue = config.mnc;
|
||||
break;
|
||||
case AXIS_LOCALE:
|
||||
value.localeValue.initFromResTable(config);
|
||||
break;
|
||||
case AXIS_LAYOUTDIR:
|
||||
return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
|
||||
value.intValue = config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
|
||||
break;
|
||||
case AXIS_SCREENLAYOUTSIZE:
|
||||
return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
|
||||
value.intValue = config.screenLayout&ResTable_config::MASK_SCREENSIZE;
|
||||
break;
|
||||
case AXIS_ORIENTATION:
|
||||
return config.orientation;
|
||||
value.intValue = config.orientation;
|
||||
break;
|
||||
case AXIS_UIMODETYPE:
|
||||
return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
|
||||
value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
|
||||
break;
|
||||
case AXIS_UIMODENIGHT:
|
||||
return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
|
||||
value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
|
||||
break;
|
||||
case AXIS_DENSITY:
|
||||
return config.density;
|
||||
value.intValue = config.density;
|
||||
break;
|
||||
case AXIS_TOUCHSCREEN:
|
||||
return config.touchscreen;
|
||||
value.intValue = config.touchscreen;
|
||||
break;
|
||||
case AXIS_KEYSHIDDEN:
|
||||
return config.inputFlags;
|
||||
value.intValue = config.inputFlags;
|
||||
break;
|
||||
case AXIS_KEYBOARD:
|
||||
return config.keyboard;
|
||||
value.intValue = config.keyboard;
|
||||
break;
|
||||
case AXIS_NAVIGATION:
|
||||
return config.navigation;
|
||||
value.intValue = config.navigation;
|
||||
break;
|
||||
case AXIS_SCREENSIZE:
|
||||
return config.screenSize;
|
||||
value.intValue = config.screenSize;
|
||||
break;
|
||||
case AXIS_SMALLESTSCREENWIDTHDP:
|
||||
return config.smallestScreenWidthDp;
|
||||
value.intValue = config.smallestScreenWidthDp;
|
||||
break;
|
||||
case AXIS_SCREENWIDTHDP:
|
||||
return config.screenWidthDp;
|
||||
value.intValue = config.screenWidthDp;
|
||||
break;
|
||||
case AXIS_SCREENHEIGHTDP:
|
||||
return config.screenHeightDp;
|
||||
value.intValue = config.screenHeightDp;
|
||||
break;
|
||||
case AXIS_VERSION:
|
||||
return config.version;
|
||||
value.intValue = config.version;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -371,24 +672,14 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
|
||||
mParamsChanged = true;
|
||||
|
||||
Vector<String8> parts;
|
||||
AaptLocaleValue::splitAndLowerCase(dir, &parts, '-');
|
||||
|
||||
String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
|
||||
String8 mcc, mnc, layoutsize, layoutlong, orient, den;
|
||||
String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
|
||||
String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
|
||||
|
||||
const char *p = dir;
|
||||
const char *q;
|
||||
while (NULL != (q = strchr(p, '-'))) {
|
||||
String8 val(p, q-p);
|
||||
val.toLower();
|
||||
parts.add(val);
|
||||
//printf("part: %s\n", parts[parts.size()-1].string());
|
||||
p = q+1;
|
||||
}
|
||||
String8 val(p);
|
||||
val.toLower();
|
||||
parts.add(val);
|
||||
//printf("part: %s\n", parts[parts.size()-1].string());
|
||||
AaptLocaleValue locale;
|
||||
int numLocaleComponents = 0;
|
||||
|
||||
const int N = parts.size();
|
||||
int index = 0;
|
||||
@ -429,38 +720,18 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
|
||||
}
|
||||
part = parts[index];
|
||||
} else {
|
||||
//printf("not mcc: %s\n", part.string());
|
||||
//printf("not mnc: %s\n", part.string());
|
||||
}
|
||||
|
||||
// locale - language
|
||||
if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
|
||||
loc = part;
|
||||
|
||||
index++;
|
||||
if (index == N) {
|
||||
index = locale.initFromDirName(parts, index);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
if (index >= N){
|
||||
goto success;
|
||||
}
|
||||
|
||||
part = parts[index];
|
||||
} else {
|
||||
//printf("not language: %s\n", part.string());
|
||||
}
|
||||
|
||||
// locale - region
|
||||
if (loc.length() > 0
|
||||
&& part.length() == 3 && part[0] == 'r' && part[0] && part[1]) {
|
||||
loc += "-";
|
||||
part.toUpper();
|
||||
loc += part.string() + 1;
|
||||
|
||||
index++;
|
||||
if (index == N) {
|
||||
goto success;
|
||||
}
|
||||
part = parts[index];
|
||||
} else {
|
||||
//printf("not region: %s\n", part.string());
|
||||
}
|
||||
|
||||
if (getLayoutDirectionName(part.string())) {
|
||||
layoutDir = part;
|
||||
|
||||
@ -679,7 +950,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
|
||||
success:
|
||||
this->mcc = mcc;
|
||||
this->mnc = mnc;
|
||||
this->locale = loc;
|
||||
this->locale = locale;
|
||||
this->screenLayoutSize = layoutsize;
|
||||
this->screenLayoutLong = layoutlong;
|
||||
this->smallestScreenWidthDp = smallestwidthdp;
|
||||
@ -711,7 +982,7 @@ AaptGroupEntry::toString() const
|
||||
s += ",";
|
||||
s += this->mnc;
|
||||
s += ",";
|
||||
s += this->locale;
|
||||
s += locale.toDirName();
|
||||
s += ",";
|
||||
s += layoutDirection;
|
||||
s += ",";
|
||||
@ -765,12 +1036,15 @@ AaptGroupEntry::toDirName(const String8& resType) const
|
||||
}
|
||||
s += mnc;
|
||||
}
|
||||
if (this->locale != "") {
|
||||
|
||||
const String8 localeComponent = locale.toDirName();
|
||||
if (localeComponent != "") {
|
||||
if (s.length() > 0) {
|
||||
s += "-";
|
||||
}
|
||||
s += locale;
|
||||
s += localeComponent;
|
||||
}
|
||||
|
||||
if (this->layoutDirection != "") {
|
||||
if (s.length() > 0) {
|
||||
s += "-";
|
||||
@ -942,55 +1216,6 @@ bool AaptGroupEntry::getMncName(const char* name,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does this directory name fit the pattern of a locale dir ("en-rUS" or
|
||||
* "default")?
|
||||
*
|
||||
* TODO: Should insist that the first two letters are lower case, and the
|
||||
* second two are upper.
|
||||
*/
|
||||
bool AaptGroupEntry::getLocaleName(const char* fileName,
|
||||
ResTable_config* out)
|
||||
{
|
||||
if (strcmp(fileName, kWildcardName) == 0
|
||||
|| strcmp(fileName, kDefaultLocale) == 0) {
|
||||
if (out) {
|
||||
out->language[0] = 0;
|
||||
out->language[1] = 0;
|
||||
out->country[0] = 0;
|
||||
out->country[1] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strlen(fileName) == 2 && isalpha(fileName[0]) && isalpha(fileName[1])) {
|
||||
if (out) {
|
||||
out->language[0] = fileName[0];
|
||||
out->language[1] = fileName[1];
|
||||
out->country[0] = 0;
|
||||
out->country[1] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strlen(fileName) == 5 &&
|
||||
isalpha(fileName[0]) &&
|
||||
isalpha(fileName[1]) &&
|
||||
fileName[2] == '-' &&
|
||||
isalpha(fileName[3]) &&
|
||||
isalpha(fileName[4])) {
|
||||
if (out) {
|
||||
out->language[0] = fileName[0];
|
||||
out->language[1] = fileName[1];
|
||||
out->country[0] = fileName[3];
|
||||
out->country[1] = fileName[4];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
|
||||
{
|
||||
if (strcmp(name, kWildcardName) == 0) {
|
||||
@ -1496,18 +1721,18 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const
|
||||
return v;
|
||||
}
|
||||
|
||||
const ResTable_config& AaptGroupEntry::toParams() const
|
||||
const ResTable_config AaptGroupEntry::toParams() const
|
||||
{
|
||||
if (!mParamsChanged) {
|
||||
return mParams;
|
||||
}
|
||||
|
||||
mParamsChanged = false;
|
||||
ResTable_config& params(mParams);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ResTable_config& params = mParams;
|
||||
memset(¶ms, 0, sizeof(ResTable_config));
|
||||
getMccName(mcc.string(), ¶ms);
|
||||
getMncName(mnc.string(), ¶ms);
|
||||
getLocaleName(locale.string(), ¶ms);
|
||||
locale.writeTo(¶ms);
|
||||
getLayoutDirectionName(layoutDirection.string(), ¶ms);
|
||||
getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), ¶ms);
|
||||
getScreenWidthDpName(screenWidthDp.string(), ¶ms);
|
||||
@ -1982,7 +2207,9 @@ status_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols)
|
||||
|
||||
AaptAssets::AaptAssets()
|
||||
: AaptDir(String8(), String8()),
|
||||
mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
|
||||
mHavePrivateSymbols(false),
|
||||
mChanged(false), mHaveIncludedAssets(false),
|
||||
mRes(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2491,9 +2718,9 @@ status_t AaptAssets::filter(Bundle* bundle)
|
||||
// If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
|
||||
// pick xhdpi.
|
||||
uint32_t preferredDensity = 0;
|
||||
const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
|
||||
const SortedVector<AxisValue>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
|
||||
if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
|
||||
preferredDensity = (*preferredConfigs)[0];
|
||||
preferredDensity = (*preferredConfigs)[0].intValue;
|
||||
}
|
||||
|
||||
// Now deal with preferred configurations.
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/SortedVector.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Vector.h>
|
||||
#include "ZipFile.h"
|
||||
|
||||
@ -34,8 +33,7 @@ enum {
|
||||
AXIS_NONE = 0,
|
||||
AXIS_MCC = 1,
|
||||
AXIS_MNC,
|
||||
AXIS_LANGUAGE,
|
||||
AXIS_REGION,
|
||||
AXIS_LOCALE,
|
||||
AXIS_SCREENLAYOUTSIZE,
|
||||
AXIS_SCREENLAYOUTLONG,
|
||||
AXIS_ORIENTATION,
|
||||
@ -58,6 +56,73 @@ enum {
|
||||
AXIS_END = AXIS_VERSION,
|
||||
};
|
||||
|
||||
struct AaptLocaleValue {
|
||||
char language[4];
|
||||
char region[4];
|
||||
char script[4];
|
||||
char variant[8];
|
||||
|
||||
AaptLocaleValue() {
|
||||
memset(this, 0, sizeof(AaptLocaleValue));
|
||||
}
|
||||
|
||||
// Initialize this AaptLocaleValue from a config string.
|
||||
bool initFromFilterString(const String8& config);
|
||||
|
||||
int initFromDirName(const Vector<String8>& parts, const int startIndex);
|
||||
|
||||
// Initialize this AaptLocaleValue from a ResTable_config.
|
||||
void initFromResTable(const ResTable_config& config);
|
||||
|
||||
void writeTo(ResTable_config* out) const;
|
||||
|
||||
String8 toDirName() const;
|
||||
|
||||
int compare(const AaptLocaleValue& other) const {
|
||||
return memcmp(this, &other, sizeof(AaptLocaleValue));
|
||||
}
|
||||
|
||||
static void splitAndLowerCase(const char* const chars, Vector<String8>* parts,
|
||||
const char separator);
|
||||
|
||||
inline bool operator<(const AaptLocaleValue& o) const { return compare(o) < 0; }
|
||||
inline bool operator<=(const AaptLocaleValue& o) const { return compare(o) <= 0; }
|
||||
inline bool operator==(const AaptLocaleValue& o) const { return compare(o) == 0; }
|
||||
inline bool operator!=(const AaptLocaleValue& o) const { return compare(o) != 0; }
|
||||
inline bool operator>=(const AaptLocaleValue& o) const { return compare(o) >= 0; }
|
||||
inline bool operator>(const AaptLocaleValue& o) const { return compare(o) > 0; }
|
||||
private:
|
||||
void setLanguage(const char* language);
|
||||
void setRegion(const char* language);
|
||||
void setScript(const char* script);
|
||||
void setVariant(const char* variant);
|
||||
};
|
||||
|
||||
struct AxisValue {
|
||||
// Used for all axes except AXIS_LOCALE, which is represented
|
||||
// as a AaptLocaleValue value.
|
||||
int intValue;
|
||||
AaptLocaleValue localeValue;
|
||||
|
||||
AxisValue() : intValue(0) {
|
||||
}
|
||||
|
||||
inline int compare(const AxisValue &other) const {
|
||||
if (intValue != other.intValue) {
|
||||
return intValue - other.intValue;
|
||||
}
|
||||
|
||||
return localeValue.compare(other.localeValue);
|
||||
}
|
||||
|
||||
inline bool operator<(const AxisValue& o) const { return compare(o) < 0; }
|
||||
inline bool operator<=(const AxisValue& o) const { return compare(o) <= 0; }
|
||||
inline bool operator==(const AxisValue& o) const { return compare(o) == 0; }
|
||||
inline bool operator!=(const AxisValue& o) const { return compare(o) != 0; }
|
||||
inline bool operator>=(const AxisValue& o) const { return compare(o) >= 0; }
|
||||
inline bool operator>(const AxisValue& o) const { return compare(o) > 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure contains a specific variation of a single file out
|
||||
* of all the variations it can have that we can have.
|
||||
@ -65,22 +130,38 @@ enum {
|
||||
struct AaptGroupEntry
|
||||
{
|
||||
public:
|
||||
AaptGroupEntry() : mParamsChanged(true) { }
|
||||
AaptGroupEntry(const String8& _locale, const String8& _vendor)
|
||||
: locale(_locale), vendor(_vendor), mParamsChanged(true) { }
|
||||
AaptGroupEntry() : mParamsChanged(true) {
|
||||
memset(&mParams, 0, sizeof(ResTable_config));
|
||||
}
|
||||
|
||||
bool initFromDirName(const char* dir, String8* resType);
|
||||
|
||||
static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
|
||||
static bool parseFilterNamePart(const String8& part, int* axis, AxisValue* value);
|
||||
|
||||
static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
|
||||
static AxisValue getConfigValueForAxis(const ResTable_config& config, int axis);
|
||||
|
||||
static bool configSameExcept(const ResTable_config& config,
|
||||
const ResTable_config& otherConfig, int axis);
|
||||
|
||||
int compare(const AaptGroupEntry& o) const;
|
||||
|
||||
const ResTable_config toParams() const;
|
||||
|
||||
inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
|
||||
inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
|
||||
inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
|
||||
inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
|
||||
inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
|
||||
inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
|
||||
|
||||
String8 toString() const;
|
||||
String8 toDirName(const String8& resType) const;
|
||||
|
||||
const String8& getVersionString() const { return version; }
|
||||
|
||||
private:
|
||||
static bool getMccName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getMncName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getLocaleName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getOrientationName(const char* name, ResTable_config* out = NULL);
|
||||
@ -99,26 +180,9 @@ public:
|
||||
static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
|
||||
static bool getVersionName(const char* name, ResTable_config* out = NULL);
|
||||
|
||||
int compare(const AaptGroupEntry& o) const;
|
||||
|
||||
const ResTable_config& toParams() const;
|
||||
|
||||
inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
|
||||
inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
|
||||
inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
|
||||
inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
|
||||
inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
|
||||
inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
|
||||
|
||||
String8 toString() const;
|
||||
String8 toDirName(const String8& resType) const;
|
||||
|
||||
const String8& getVersionString() const { return version; }
|
||||
|
||||
private:
|
||||
String8 mcc;
|
||||
String8 mnc;
|
||||
String8 locale;
|
||||
AaptLocaleValue locale;
|
||||
String8 vendor;
|
||||
String8 smallestScreenWidthDp;
|
||||
String8 screenWidthDp;
|
||||
|
@ -517,6 +517,7 @@ int doDump(Bundle* bundle)
|
||||
// the API version because key resources like icons will have an implicit
|
||||
// version if they are using newer config types like density.
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(ResTable_config));
|
||||
config.language[0] = 'e';
|
||||
config.language[1] = 'n';
|
||||
config.country[0] = 'U';
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType)
|
||||
: mResType(resType), mSet(set), mSetPos(0), mGroupPos(0)
|
||||
{
|
||||
memset(&mParams, 0, sizeof(ResTable_config));
|
||||
}
|
||||
|
||||
inline const sp<AaptGroup>& getGroup() const { return mGroup; }
|
||||
|
@ -28,8 +28,8 @@ ResourceFilter::parse(const char* arg)
|
||||
mContainsPseudo = true;
|
||||
}
|
||||
int axis;
|
||||
uint32_t value;
|
||||
if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
|
||||
AxisValue value;
|
||||
if (!AaptGroupEntry::parseFilterNamePart(part, &axis, &value)) {
|
||||
fprintf(stderr, "Invalid configuration: %s\n", arg);
|
||||
fprintf(stderr, " ");
|
||||
for (int i=0; i<p-arg; i++) {
|
||||
@ -44,15 +44,20 @@ ResourceFilter::parse(const char* arg)
|
||||
|
||||
ssize_t index = mData.indexOfKey(axis);
|
||||
if (index < 0) {
|
||||
mData.add(axis, SortedVector<uint32_t>());
|
||||
mData.add(axis, SortedVector<AxisValue>());
|
||||
}
|
||||
SortedVector<uint32_t>& sv = mData.editValueFor(axis);
|
||||
SortedVector<AxisValue>& sv = mData.editValueFor(axis);
|
||||
sv.add(value);
|
||||
// if it's a locale with a region, also match an unmodified locale of the
|
||||
// same language
|
||||
if (axis == AXIS_LANGUAGE) {
|
||||
if (value & 0xffff0000) {
|
||||
sv.add(value & 0x0000ffff);
|
||||
|
||||
// If it's a locale with a region, script or variant, we should also match an
|
||||
// unmodified locale of the same language
|
||||
if (axis == AXIS_LOCALE) {
|
||||
if (value.localeValue.region[0] || value.localeValue.script[0] ||
|
||||
value.localeValue.variant[0]) {
|
||||
AxisValue copy;
|
||||
memcpy(copy.localeValue.language, value.localeValue.language,
|
||||
sizeof(value.localeValue.language));
|
||||
sv.add(copy);
|
||||
}
|
||||
}
|
||||
p = q;
|
||||
@ -70,9 +75,9 @@ ResourceFilter::isEmpty() const
|
||||
}
|
||||
|
||||
bool
|
||||
ResourceFilter::match(int axis, uint32_t value) const
|
||||
ResourceFilter::match(int axis, const AxisValue& value) const
|
||||
{
|
||||
if (value == 0) {
|
||||
if (value.intValue == 0 && (value.localeValue.language[0] == 0)) {
|
||||
// they didn't specify anything so take everything
|
||||
return true;
|
||||
}
|
||||
@ -81,7 +86,7 @@ ResourceFilter::match(int axis, uint32_t value) const
|
||||
// we didn't request anything on this axis so take everything
|
||||
return true;
|
||||
}
|
||||
const SortedVector<uint32_t>& sv = mData.valueAt(index);
|
||||
const SortedVector<AxisValue>& sv = mData.valueAt(index);
|
||||
return sv.indexOf(value) >= 0;
|
||||
}
|
||||
|
||||
@ -102,7 +107,7 @@ ResourceFilter::match(const ResTable_config& config) const
|
||||
return true;
|
||||
}
|
||||
|
||||
const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const
|
||||
const SortedVector<AxisValue>* ResourceFilter::configsForAxis(int axis) const
|
||||
{
|
||||
ssize_t index = mData.indexOfKey(axis);
|
||||
if (index < 0) {
|
||||
|
@ -19,14 +19,15 @@ public:
|
||||
ResourceFilter() : mData(), mContainsPseudo(false) {}
|
||||
status_t parse(const char* arg);
|
||||
bool isEmpty() const;
|
||||
bool match(int axis, uint32_t value) const;
|
||||
bool match(int axis, const ResTable_config& config) const;
|
||||
bool match(const ResTable_config& config) const;
|
||||
const SortedVector<uint32_t>* configsForAxis(int axis) const;
|
||||
const SortedVector<AxisValue>* configsForAxis(int axis) const;
|
||||
inline bool containsPseudo() const { return mContainsPseudo; }
|
||||
|
||||
private:
|
||||
KeyedVector<int,SortedVector<uint32_t> > mData;
|
||||
bool match(int axis, const AxisValue& value) const;
|
||||
|
||||
KeyedVector<int,SortedVector<AxisValue> > mData;
|
||||
bool mContainsPseudo;
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define RESOURCE_ID_CACHE_H
|
||||
|
||||
namespace android {
|
||||
class android::String16;
|
||||
|
||||
class ResourceIdCache {
|
||||
public:
|
||||
|
@ -1292,8 +1292,8 @@ status_t compileResourceFile(Bundle* bundle,
|
||||
curIsStyled = true;
|
||||
} else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
|
||||
// Note the existence and locale of every string we process
|
||||
char rawLocale[16];
|
||||
curParams.getLocale(rawLocale);
|
||||
char rawLocale[RESTABLE_MAX_LOCALE_LEN];
|
||||
curParams.getBcp47Locale(rawLocale);
|
||||
String8 locale(rawLocale);
|
||||
String16 name;
|
||||
String16 translatable;
|
||||
|
Reference in New Issue
Block a user