summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/res/Resources.java4
-rw-r--r--core/java/android/util/LocaleList.java43
-rw-r--r--core/tests/coretests/Android.mk2
-rw-r--r--core/tests/coretests/res/values-fa/strings.xml4
-rw-r--r--core/tests/coretests/res/values/strings.xml3
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java53
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());
+ }
+}
+