diff options
author | Victor Chang <vichang@google.com> | 2018-05-21 17:51:11 +0100 |
---|---|---|
committer | Victor Chang <vichang@google.com> | 2018-05-25 10:35:03 +0100 |
commit | 5a0b0d722c203bcffc922b580bf64780de0eed66 (patch) | |
tree | 98a902c37e002b0054fd8b03e7ac19056f3a92af /icu4j/main/classes | |
parent | 38f23dcbf8eecc5312de4cdaf0da2dac34b08969 (diff) | |
download | icu-5a0b0d722c203bcffc922b580bf64780de0eed66.tar.gz |
Android Patch: Fix BCP 47 locale extension in ULocale for first usage
Upstream ticket: http://bugs.icu-project.org/trac/ticket/13776
- For the first usage of locale extension, there is interdependency between ULocale and KeyTypeData.
The example call stack would be:
ULocale.forLocale -> KeyTypeData.toLegacyKey -> KeyTypeData.<clinit>
-> ULocale.getDefault -> ULocale.forLocale -> KeyTypeData.toLegacyKey.
- Break the inter-dependency by not using ULocale.getDefault for fallback
icu4c/source/data/misc/keyTypeData.txt indicates "no fallback" in the resource bundle.
==========================
keyTypeData:table(nofallback)
ICUResourceBundle#instantiateBundle doesn't seem to use the value of
ULocale.getDefault foe loading the resource if the resource bundle has no fallback.
======= ICUResourceBundle#instantiateBundle =======
if (openType == OpenType.DIRECT || (b != null && b.getNoFallback())) {
return b;
}
----
<use default locale>
----
==================================================
Before going into instantiateBundle(), if the caller didn't request
disableFallback or OpenType.DIRECT, the code calls ULocale.getDefault().
If the caller did, then a null String is used for the defaultID.
=================================================
public static ICUResourceBundle getBundleInstance(String baseName, String localeID,
ClassLoader root, OpenType openType) {
if (baseName == null) {
baseName = ICUData.ICU_BASE_NAME;
}
localeID = ULocale.getBaseName(localeID);
ICUResourceBundle b;
if (openType == OpenType.LOCALE_DEFAULT_ROOT) {
b = instantiateBundle(baseName, localeID, ULocale.getDefault().getBaseName(),
root, openType);
} else {
b = instantiateBundle(baseName, localeID, null, root, openType);
}
if(b==null){
throw new MissingResourceException(
"Could not find the bundle "+ baseName+"/"+ localeID+".res","","");
}
return b;
}
================================================
I verified that the bundle object's noFallback field is true for this data file.
- Add a test that will fail individually when the bug occurs.
I don't know how to de-initalize class KeyTypeData during the test,
but we could potentially put the test into a separate test suite.
Other codes in many places, e.g. JUnit, Zygote, framework,
could still hide the bug by initializing KeyTypeMap and being the first victim of the bug.
Bug: 70943715
Test: cts-tradefed run cts-dev -m CtsIcuTestCases -t android.icu.dev.test.util.ULocaleTest#TestForLanguageTagBug13776
pass after the CL. previously, it will fail if running individually.
Test: cts-tradefed run cts-dev -m CtsIcuTestCases
Test: cts-tradefed run cts-dev -m CtsLibcoreTestCases
Test: ant check
Change-Id: I50654a262777426c984023354797c91efaef9baf
Diffstat (limited to 'icu4j/main/classes')
-rw-r--r-- | icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java index a8dda07af..776d0f0c0 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java @@ -210,10 +210,18 @@ public class KeyTypeData { } private static void initFromResourceBundle() { + // Android patch: Avoid inter-dependency issue on ULocale.getDefault(). Ticket#13776 + /* UResourceBundle keyTypeDataRes = UResourceBundle.getBundleInstance( ICUData.ICU_BASE_NAME, "keyTypeData", ICUResourceBundle.ICU_DATA_CLASS_LOADER); + */ + UResourceBundle keyTypeDataRes = ICUResourceBundle.getBundleInstance( + ICUData.ICU_BASE_NAME, + "keyTypeData", + ICUResourceBundle.ICU_DATA_CLASS_LOADER, + ICUResourceBundle.OpenType.DIRECT); getKeyInfo(keyTypeDataRes.get("keyInfo")); getTypeInfo(keyTypeDataRes.get("typeInfo")); |