diff options
| -rw-r--r-- | core/java/android/content/res/Resources.java | 4 | ||||
| -rw-r--r-- | core/java/android/util/LocaleList.java | 43 | ||||
| -rw-r--r-- | core/tests/coretests/Android.mk | 2 | ||||
| -rw-r--r-- | core/tests/coretests/res/values-fa/strings.xml | 4 | ||||
| -rw-r--r-- | core/tests/coretests/res/values/strings.xml | 3 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java | 53 |
6 files changed, 96 insertions, 13 deletions
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index c460746ba514..b01633e641f3 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1978,7 +1978,7 @@ public class Resources { || (configChanges & Configuration.NATIVE_CONFIG_LOCALE) != 0) { if (locales.size() == 1) { // This is an optimization to avoid the JNI call(s) when the result of - // getFirstMatch() does not depend on the supported locales. + // getFirstMatchWithEnglishSupported() does not depend on the supported locales. mResolvedLocale = locales.getPrimary(); } else { String[] supportedLocales = mAssets.getNonSystemLocales(); @@ -1989,7 +1989,7 @@ public class Resources { // their own. supportedLocales = mAssets.getLocales(); } - mResolvedLocale = locales.getFirstMatch(supportedLocales); + mResolvedLocale = locales.getFirstMatchWithEnglishSupported(supportedLocales); } } mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java index 3d8e330334cd..f22cde0c1ca7 100644 --- a/core/java/android/util/LocaleList.java +++ b/core/java/android/util/LocaleList.java @@ -246,14 +246,9 @@ public final class LocaleList implements Parcelable { return supportedScr.equals(desiredScr) ? 1 : 0; } - /** - * Returns the first match in the locale list given an unordered array of supported locales - * in BCP47 format. - * - * If the locale list is empty, null would be returned. - */ - @Nullable - public Locale getFirstMatch(String[] supportedLocales) { + private static final Locale EN_LATN = Locale.forLanguageTag("en-Latn"); + + private Locale computeFirstMatch(String[] supportedLocales, boolean assumeEnglishIsSupported) { if (mList.length == 1) { // just one locale, perhaps the most common scenario return mList[0]; } @@ -261,8 +256,16 @@ public final class LocaleList implements Parcelable { return null; } int bestIndex = Integer.MAX_VALUE; - for (String tag : supportedLocales) { - final Locale supportedLocale = Locale.forLanguageTag(tag); + final int numSupportedLocales = + supportedLocales.length + (assumeEnglishIsSupported ? 1 : 0); + for (int i = 0; i < numSupportedLocales; i++) { + final Locale supportedLocale; + if (assumeEnglishIsSupported) { + // Try English first, so we can return early if it's in the LocaleList + supportedLocale = (i == 0) ? EN_LATN : Locale.forLanguageTag(supportedLocales[i-1]); + } else { + supportedLocale = Locale.forLanguageTag(supportedLocales[i]); + } // We expect the average length of locale lists used for locale resolution to be // smaller than three, so it's OK to do this as an O(mn) algorithm. for (int idx = 0; idx < mList.length; idx++) { @@ -284,6 +287,26 @@ public final class LocaleList implements Parcelable { } /** + * Returns the first match in the locale list given an unordered array of supported locales + * in BCP47 format. + * + * If the locale list is empty, null would be returned. + */ + @Nullable + public Locale getFirstMatch(String[] supportedLocales) { + return computeFirstMatch(supportedLocales, false /* assume English is not supported */); + } + + /** + * Same as getFirstMatch(), but with English assumed to be supported, even if it's not. + * {@hide} + */ + @Nullable + public Locale getFirstMatchWithEnglishSupported(String[] supportedLocales) { + return computeFirstMatch(supportedLocales, true /* assume English is supported */); + } + + /** * Returns true if the array of locale tags only contains empty locales and pseudolocales. * Assumes that there is no repetition in the input. * {@hide} diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index 7cd25afe5bcd..ee8921ef8228 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -22,7 +22,7 @@ LOCAL_SRC_FILES := \ $(call all-java-files-under, EnabledTestApp/src) LOCAL_DX_FLAGS := --core-library -LOCAL_AAPT_FLAGS = -0 dat -0 gld +LOCAL_AAPT_FLAGS = -0 dat -0 gld -c fa LOCAL_STATIC_JAVA_LIBRARIES := \ core-tests-support \ android-common \ diff --git a/core/tests/coretests/res/values-fa/strings.xml b/core/tests/coretests/res/values-fa/strings.xml new file mode 100644 index 000000000000..c83f5f1bebf4 --- /dev/null +++ b/core/tests/coretests/res/values-fa/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="dummy_string">رشتهٔ الکی</string> +</resources> diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml index 04b0478c96d1..ef915bba1013 100644 --- a/core/tests/coretests/res/values/strings.xml +++ b/core/tests/coretests/res/values/strings.xml @@ -139,4 +139,7 @@ <!-- RestrictionsManagerTest --> <string name="restrictionManager_title">Title</string> <string name="restrictionManager_desc">Description</string> + + <!-- ResourcesLocaleResolutionTest --> + <string name="dummy_string">dummy string</string> </resources> diff --git a/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java b/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java new file mode 100644 index 000000000000..55c00314ee63 --- /dev/null +++ b/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2015 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package android.content.res; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.DisplayMetrics; +import android.util.LocaleList; + +import java.util.Arrays; +import java.util.Locale; + +public class ResourcesLocaleResolutionTest extends AndroidTestCase { + @SmallTest + public void testGetResolvedLocale_englishIsAlwaysConsideredSupported() { + // First make sure English has no explicit assets other than the default assets + final AssetManager assets = getContext().getAssets(); + final String supportedLocales[] = assets.getNonSystemLocales(); + for (String languageTag : supportedLocales) { + if ("en-XA".equals(languageTag)) { + continue; + } + assertFalse( + "supported locales: " + Arrays.toString(supportedLocales), + "en".equals(Locale.forLanguageTag(languageTag).getLanguage())); + } + + final DisplayMetrics dm = new DisplayMetrics(); + dm.setToDefaults(); + final Configuration cfg = new Configuration(); + cfg.setToDefaults(); + // Avestan and English have no assets, but Persian does. + cfg.setLocales(LocaleList.forLanguageTags("ae,en,fa")); + Resources res = new Resources(assets, dm, cfg); + // We should get English, because it is always considered supported. + assertEquals("en", res.getResolvedLocale().toLanguageTag()); + } +} + |