From e4345dbd2a892f38e62269d94e5ee7002d121bed Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Thu, 26 Jun 2014 16:01:28 +0100 Subject: Fall back to "tl" if "fil" is absent. For JB-MR1, there was a hack that used "tl" where we really meant "fil" because ICU didn't have localizations for "fil". This has now been fixed, and we now support 3 letter language codes for AAPT so we can use "fil" where required. For the benefit of apps that need to target older platforms, we fall back to "tl" if the app has assets for "tl" and the resource locale is "fil". See bugs 7291355, 7207176 and 8049507 for more context. Change-Id: I1ac8502525f99b40f9091d5efd2df33518d47a41 --- libs/androidfw/AssetManager.cpp | 57 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'libs/androidfw') diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 87164ca..482dfc8 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -347,6 +347,15 @@ void AssetManager::setLocale(const char* locale) setLocaleLocked(locale); } + +static const char kFilPrefix[] = "fil"; +static const char kTlPrefix[] = "tl"; + +// The sizes of the prefixes, excluding the 0 suffix. +// char. +static const int kFilPrefixLen = sizeof(kFilPrefix) - 1; +static const int kTlPrefixLen = sizeof(kTlPrefix) - 1; + void AssetManager::setLocaleLocked(const char* locale) { if (mLocale != NULL) { @@ -355,8 +364,44 @@ void AssetManager::setLocaleLocked(const char* locale) //mZipSet.purgeLocale(); delete[] mLocale; } - mLocale = strdupNew(locale); + + // If we're attempting to set a locale that starts with "fil", + // we should convert it to "tl" for backwards compatibility since + // we've been using "tl" instead of "fil" prior to L. + // + // If the resource table already has entries for "fil", we use that + // instead of attempting a fallback. + if (strncmp(locale, kFilPrefix, kFilPrefixLen) == 0) { + Vector locales; + getLocales(&locales); + const size_t localesSize = locales.size(); + bool hasFil = false; + for (size_t i = 0; i < localesSize; ++i) { + if (locales[i].find(kFilPrefix) == 0) { + hasFil = true; + break; + } + } + + + if (!hasFil) { + const size_t newLocaleLen = strlen(locale); + // This isn't a bug. We really do want mLocale to be 1 byte + // shorter than locale, because we're replacing "fil-" with + // "tl-". + mLocale = new char[newLocaleLen]; + // Copy over "tl". + memcpy(mLocale, kTlPrefix, kTlPrefixLen); + // Copy the rest of |locale|, including the terminating '\0'. + memcpy(mLocale + kTlPrefixLen, locale + kFilPrefixLen, + newLocaleLen - kFilPrefixLen + 1); + updateResourceParamsLocked(); + return; + } + } + + mLocale = strdupNew(locale); updateResourceParamsLocked(); } @@ -741,6 +786,16 @@ void AssetManager::getLocales(Vector* locales) const if (res != NULL) { res->getLocales(locales); } + + const size_t numLocales = locales->size(); + for (size_t i = 0; i < numLocales; ++i) { + const String8& localeStr = locales->itemAt(i); + if (localeStr.find(kTlPrefix) == 0) { + String8 replaced("fil"); + replaced += (localeStr.string() + kTlPrefixLen); + locales->editItemAt(i) = replaced; + } + } } /* -- cgit v1.1