Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be57fca4 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "Extended locales in AAPT / AssetManager."

parents 49024bac 788fa414
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -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) {
+27 −14
Original line number Diff line number Diff line
@@ -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
+6 −24
Original line number Diff line number Diff line
@@ -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);
}
+73 −22
Original line number Diff line number Diff line
@@ -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();
+35 −0
Original line number Diff line number Diff line
@@ -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