Merge "Move locale negotiation to ResourcesManager"
diff --git a/api/current.txt b/api/current.txt
index fc69955..e35458a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10108,7 +10108,6 @@
     method public java.lang.String getQuantityString(int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getQuantityString(int, int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.CharSequence getQuantityText(int, int) throws android.content.res.Resources.NotFoundException;
-    method public java.util.Locale getResolvedLocale();
     method public java.lang.String getResourceEntryName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourceName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourcePackageName(int) throws android.content.res.Resources.NotFoundException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 0fe4934..0f7d9aa 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10504,7 +10504,6 @@
     method public java.lang.String getQuantityString(int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getQuantityString(int, int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.CharSequence getQuantityText(int, int) throws android.content.res.Resources.NotFoundException;
-    method public java.util.Locale getResolvedLocale();
     method public java.lang.String getResourceEntryName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourceName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourcePackageName(int) throws android.content.res.Resources.NotFoundException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 3348468..c6269fc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10116,7 +10116,6 @@
     method public java.lang.String getQuantityString(int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getQuantityString(int, int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.CharSequence getQuantityText(int, int) throws android.content.res.Resources.NotFoundException;
-    method public java.util.Locale getResolvedLocale();
     method public java.lang.String getResourceEntryName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourceName(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getResourcePackageName(int) throws android.content.res.Resources.NotFoundException;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index dedc8e5..1e7457c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4916,8 +4916,10 @@
 
         /*
          * Initialize the default locales in this process for the reasons we set the time zone.
+         *
+         * We do this through ResourcesManager, since we need to do locale negotiation.
          */
-        LocaleList.setDefault(data.config.getLocales());
+        mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
 
         /*
          * Update the system configuration since its preloaded and might not
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 260216c..94e584e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -35,6 +35,9 @@
 import android.view.DisplayAdjustments;
 
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
 
 /** @hide */
 public class ResourcesManager {
@@ -42,11 +45,15 @@
     private static final boolean DEBUG = false;
 
     private static ResourcesManager sResourcesManager;
-    private final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources =
+    private final ArrayMap<ResourcesKey, WeakReference<Resources>> mActiveResources =
             new ArrayMap<>();
     private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
             new ArrayMap<>();
 
+    private String[] mSystemLocales = {};
+    private final HashSet<String> mNonSystemLocales = new HashSet<String>();
+    private boolean mHasNonSystemLocales = false;
+
     CompatibilityInfo mResCompatibilityInfo;
 
     Configuration mResConfiguration;
@@ -165,6 +172,8 @@
                 ? new Configuration(overrideConfiguration) : null;
         ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
         Resources r;
+        final boolean findSystemLocales;
+        final boolean hasNonSystemLocales;
         synchronized (this) {
             // Resources is app scale dependent.
             if (DEBUG) Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
@@ -178,6 +187,8 @@
                         + " key=" + key + " overrideConfig=" + overrideConfiguration);
                 return r;
             }
+            findSystemLocales = (mSystemLocales.length == 0);
+            hasNonSystemLocales = mHasNonSystemLocales;
         }
 
         //if (r != null) {
@@ -243,6 +254,18 @@
         if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
                 + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
 
+        final String[] systemLocales = (
+                findSystemLocales ?
+                AssetManager.getSystem().getLocales() :
+                null);
+        final String[] nonSystemLocales = assets.getNonSystemLocales();
+        // Avoid checking for non-pseudo-locales if we already know there were some from a previous
+        // Resources. The default value (for when hasNonSystemLocales is true) doesn't matter,
+        // since mHasNonSystemLocales will also be true, and thus isPseudoLocalesOnly would not be
+        // able to affect mHasNonSystemLocales.
+        final boolean isPseudoLocalesOnly = hasNonSystemLocales ||
+                LocaleList.isPseudoLocalesOnly(nonSystemLocales);
+
         synchronized (this) {
             WeakReference<Resources> wr = mActiveResources.get(key);
             Resources existing = wr != null ? wr.get() : null;
@@ -255,11 +278,30 @@
 
             // XXX need to remove entries when weak references go away
             mActiveResources.put(key, new WeakReference<>(r));
+            if (mSystemLocales.length == 0) {
+                mSystemLocales = systemLocales;
+            }
+            mNonSystemLocales.addAll(Arrays.asList(nonSystemLocales));
+            mHasNonSystemLocales = mHasNonSystemLocales || !isPseudoLocalesOnly;
             if (DEBUG) Slog.v(TAG, "mActiveResources.size()=" + mActiveResources.size());
             return r;
         }
     }
 
+    /* package */ void setDefaultLocalesLocked(LocaleList locales) {
+        final int bestLocale;
+        if (mHasNonSystemLocales) {
+            bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mNonSystemLocales);
+        } else {
+            // We fallback to system locales if there was no locale specifically supported by the
+            // assets. This is to properly support apps that only rely on the shared system assets
+            // and don't need assets of their own.
+            bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mSystemLocales);
+        }
+        // set it for Java, this also affects newly created Resources
+        LocaleList.setDefault(locales, bestLocale);
+    }
+
     final boolean applyConfigurationToResourcesLocked(Configuration config,
             CompatibilityInfo compat) {
         if (mResConfiguration == null) {
@@ -283,13 +325,28 @@
                     | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
         }
 
-        // set it for java, this also affects newly created Resources
-        final LocaleList localeList = config.getLocales();
-        if (!localeList.isEmpty()) {
-            LocaleList.setDefault(localeList);
+        Configuration localeAdjustedConfig = config;
+        final LocaleList configLocales = config.getLocales();
+        if (!configLocales.isEmpty()) {
+            setDefaultLocalesLocked(configLocales);
+            final LocaleList adjustedLocales = LocaleList.getAdjustedDefault();
+            if (adjustedLocales != configLocales) { // has the same result as .equals() in this case
+                // The first locale in the list was not chosen. So we create a modified
+                // configuration with the adjusted locales (which moves the chosen locale to the
+                // front).
+                localeAdjustedConfig = new Configuration();
+                localeAdjustedConfig.setTo(config);
+                localeAdjustedConfig.setLocales(adjustedLocales);
+                // Also adjust the locale list in mResConfiguration, so that the Resources created
+                // later would have the same locale list.
+                if (!mResConfiguration.getLocales().equals(adjustedLocales)) {
+                    mResConfiguration.setLocales(adjustedLocales);
+                    changes |= ActivityInfo.CONFIG_LOCALE;
+                }
+            }
         }
 
-        Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
+        Resources.updateSystemConfiguration(localeAdjustedConfig, defaultDisplayMetrics, compat);
 
         ApplicationPackageManager.configurationChanged();
         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
@@ -301,7 +358,7 @@
             Resources r = mActiveResources.valueAt(i).get();
             if (r != null) {
                 if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
-                        + r + " config to: " + config);
+                        + r + " config to: " + localeAdjustedConfig);
                 int displayId = key.mDisplayId;
                 boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
                 DisplayMetrics dm = defaultDisplayMetrics;
@@ -310,7 +367,7 @@
                     if (tmpConfig == null) {
                         tmpConfig = new Configuration();
                     }
-                    tmpConfig.setTo(config);
+                    tmpConfig.setTo(localeAdjustedConfig);
                     if (!isDefaultDisplay) {
                         dm = getDisplayMetricsLocked(displayId);
                         applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
@@ -320,7 +377,7 @@
                     }
                     r.updateConfiguration(tmpConfig, dm, compat);
                 } else {
-                    r.updateConfiguration(config, dm, compat);
+                    r.updateConfiguration(localeAdjustedConfig, dm, compat);
                 }
                 //Slog.i(TAG, "Updated app resources " + v.getKey()
                 //        + " " + r + ": " + r.getConfiguration());
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ed64ead..e404429 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -162,10 +162,6 @@
 
     private final Configuration mConfiguration = new Configuration();
 
-    // Invariant: mResolvedLocale is the resolved locale of mLocalesForResolved
-    private LocaleList mLocalesForResolved = null;
-    private Locale mResolvedLocale = null;
-
     private PluralRules mPluralRule;
 
     private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
@@ -321,16 +317,6 @@
     }
 
     /**
-     * Return the Locale resulting from locale negotiation between the Resources and the
-     * Configuration objects used to construct the Resources. The locale is used for retrieving
-     * resources as well as for determining plural rules.
-     */
-    @NonNull
-    public Locale getResolvedLocale() {
-        return mResolvedLocale;
-    }
-
-    /**
      * Return the string value associated with a particular resource ID.  The
      * returned object will be a String if this is a plain string; it will be
      * some other type of CharSequence if it is styled.
@@ -394,7 +380,7 @@
     private PluralRules getPluralRule() {
         synchronized (sSync) {
             if (mPluralRule == null) {
-                mPluralRule = PluralRules.forLocale(mResolvedLocale);
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().getPrimary());
             }
             return mPluralRule;
         }
@@ -457,7 +443,7 @@
     @NonNull
     public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
         final String raw = getString(id);
-        return String.format(mResolvedLocale, raw, formatArgs);
+        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
     }
 
     /**
@@ -488,7 +474,7 @@
     public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
             throws NotFoundException {
         String raw = getQuantityText(id, quantity).toString();
-        return String.format(mResolvedLocale, raw, formatArgs);
+        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
     }
 
     /**
@@ -1955,7 +1941,7 @@
 
             LocaleList locales = mConfiguration.getLocales();
             if (locales.isEmpty()) {
-                locales = LocaleList.getDefault();
+                locales = LocaleList.getAdjustedDefault();
                 mConfiguration.setLocales(locales);
             }
             if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
@@ -1983,26 +1969,8 @@
                 keyboardHidden = mConfiguration.keyboardHidden;
             }
 
-            if (locales != mLocalesForResolved) {
-                if (locales.size() == 1) {
-                    // This is an optimization to avoid the JNI call(s) when the result of
-                    // getFirstMatchWithEnglishSupported() does not depend on the supported locales.
-                    mResolvedLocale = locales.getPrimary();
-                } else {
-                    String[] supportedLocales = mAssets.getNonSystemLocales();
-                    if (LocaleList.isPseudoLocalesOnly(supportedLocales)) {
-                        // We fallback to all locales (including system locales) if there was no
-                        // locale specifically supported by the assets. This is to properly support
-                        // apps that only rely on the shared system assets and don't need assets of
-                        // their own.
-                        supportedLocales = mAssets.getLocales();
-                    }
-                    mResolvedLocale = locales.getFirstMatchWithEnglishSupported(supportedLocales);
-                }
-                mLocalesForResolved = locales;
-            }
             mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
-                    adjustLanguageTag(mResolvedLocale.toLanguageTag()),
+                    adjustLanguageTag(locales.getPrimary().toLanguageTag()),
                     mConfiguration.orientation,
                     mConfiguration.touchscreen,
                     mConfiguration.densityDpi, mConfiguration.keyboard,
@@ -2027,7 +1995,7 @@
         }
         synchronized (sSync) {
             if (mPluralRule != null) {
-                mPluralRule = PluralRules.forLocale(mResolvedLocale);
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().getPrimary());
             }
         }
     }
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index 8a2d015..90a20bc 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -26,6 +26,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Locale;
 
@@ -317,55 +319,72 @@
         return supportedScr.equals(desiredScr) ? 1 : 0;
     }
 
+    private int findFirstMatchIndex(Locale supportedLocale) {
+        for (int idx = 0; idx < mList.length; idx++) {
+            final int score = matchScore(supportedLocale, mList[idx]);
+            if (score > 0) {
+                return idx;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
     private static final Locale EN_LATN = Locale.forLanguageTag("en-Latn");
 
-    private Locale computeFirstMatch(String[] supportedLocales, boolean assumeEnglishIsSupported) {
+    private int computeFirstMatchIndex(Collection<String> supportedLocales,
+            boolean assumeEnglishIsSupported) {
         if (mList.length == 1) {  // just one locale, perhaps the most common scenario
-            return mList[0];
+            return 0;
         }
         if (mList.length == 0) {  // empty locale list
-            return null;
+            return -1;
         }
+
         int bestIndex = Integer.MAX_VALUE;
-        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]);
+        // Try English first, so we can return early if it's in the LocaleList
+        if (assumeEnglishIsSupported) {
+            final int idx = findFirstMatchIndex(EN_LATN);
+            if (idx == 0) { // We have a match on the first locale, which is good enough
+                return 0;
+            } else if (idx < bestIndex) {
+                bestIndex = idx;
             }
+        }
+        for (String languageTag : supportedLocales) {
+            final Locale supportedLocale = Locale.forLanguageTag(languageTag);
             // 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++) {
-                final int score = matchScore(supportedLocale, mList[idx]);
-                if (score > 0) {
-                    if (idx == 0) {  // We have a match on the first locale, which is good enough
-                        return mList[0];
-                    } else if (idx < bestIndex) {
-                        bestIndex = idx;
-                    }
-                }
+            final int idx = findFirstMatchIndex(supportedLocale);
+            if (idx == 0) { // We have a match on the first locale, which is good enough
+                return 0;
+            } else if (idx < bestIndex) {
+                bestIndex = idx;
             }
         }
-        if (bestIndex == Integer.MAX_VALUE) {  // no match was found
-            return mList[0];
+        if (bestIndex == Integer.MAX_VALUE) {
+            // no match was found, so we fall back to the first locale in the locale list
+            return 0;
         } else {
-            return mList[bestIndex];
+            return bestIndex;
         }
     }
 
+    private Locale computeFirstMatch(Collection<String> supportedLocales,
+            boolean assumeEnglishIsSupported) {
+        int bestIndex = computeFirstMatchIndex(supportedLocales, assumeEnglishIsSupported);
+        return bestIndex == -1 ? null : mList[bestIndex];
+    }
+
     /**
      * Returns the first match in the locale list given an unordered array of supported locales
-     * in BCP47 format.
+     * in BCP 47 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 */);
+        return computeFirstMatch(Arrays.asList(supportedLocales),
+                false /* assume English is not supported */);
     }
 
     /**
@@ -374,11 +393,26 @@
      */
     @Nullable
     public Locale getFirstMatchWithEnglishSupported(String[] supportedLocales) {
-        return computeFirstMatch(supportedLocales, true /* assume English is supported */);
+        return computeFirstMatch(Arrays.asList(supportedLocales),
+                true /* assume English is supported */);
     }
 
     /**
-     * Returns true if the array of locale tags only contains empty locales and pseudolocales.
+     * {@hide}
+     */
+    public int getFirstMatchIndexWithEnglishSupported(Collection<String> supportedLocales) {
+        return computeFirstMatchIndex(supportedLocales, true /* assume English is supported */);
+    }
+
+    /**
+     * {@hide}
+     */
+    public int getFirstMatchIndexWithEnglishSupported(String[] supportedLocales) {
+        return getFirstMatchIndexWithEnglishSupported(Arrays.asList(supportedLocales));
+    }
+
+    /**
+     * Returns true if the collection of locale tags only contains empty locales and pseudolocales.
      * Assumes that there is no repetition in the input.
      * {@hide}
      */
@@ -386,7 +420,7 @@
         if (supportedLocales.length > NUM_PSEUDO_LOCALES + 1) {
             // This is for optimization. Since there's no repetition in the input, if we have more
             // than the number of pseudo-locales plus one for the empty string, it's guaranteed
-            // that we have some meaninful locale in the list, so the list is not "practically
+            // that we have some meaninful locale in the collection, so the list is not "practically
             // empty".
             return false;
         }
@@ -405,6 +439,8 @@
     @GuardedBy("sLock")
     private static LocaleList sDefaultLocaleList = null;
     @GuardedBy("sLock")
+    private static LocaleList sDefaultAdjustedLocaleList = null;
+    @GuardedBy("sLock")
     private static Locale sLastDefaultLocale = null;
 
     /**
@@ -415,8 +451,8 @@
      * secondary preference is.
      *
      * Note that the default LocaleList would change if Locale.setDefault() is called. This method
-     * takes that into account by always checking the output of Locale.getDefault() and adjusting
-     * the default LocaleList if needed.
+     * takes that into account by always checking the output of Locale.getDefault() and
+     * recalculating the default LocaleList if needed.
      */
     @NonNull @Size(min=1)
     public static LocaleList getDefault() {
@@ -426,7 +462,7 @@
                 sLastDefaultLocale = defaultLocale;
                 // It's either the first time someone has asked for the default locale list, or
                 // someone has called Locale.setDefault() since we last set or adjusted the default
-                // locale list. So let's adjust the locale list.
+                // locale list. So let's recalculate the locale list.
                 if (sDefaultLocaleList != null
                         && defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
                     // The default Locale has changed, but it happens to be the first locale in the
@@ -434,6 +470,7 @@
                     return sDefaultLocaleList;
                 }
                 sDefaultLocaleList = new LocaleList(defaultLocale, sLastExplicitlySetLocaleList);
+                sDefaultAdjustedLocaleList = sDefaultLocaleList;
             }
             // sDefaultLocaleList can't be null, since it can't be set to null by
             // LocaleList.setDefault(), and if getDefault() is called before a call to
@@ -444,6 +481,20 @@
     }
 
     /**
+     * Returns the default locale list, adjusted by moving the default locale to its first
+     * position.
+     *
+     * {@hide}
+     */
+    @NonNull @Size(min=1)
+    public static LocaleList getAdjustedDefault() {
+        getDefault(); // to recalculate the default locale list, if necessary
+        synchronized (sLock) {
+            return sDefaultAdjustedLocaleList;
+        }
+    }
+
+    /**
      * Also sets the default locale by calling Locale.setDefault() with the first locale in the
      * list.
      *
@@ -474,6 +525,12 @@
             Locale.setDefault(sLastDefaultLocale);
             sLastExplicitlySetLocaleList = locales;
             sDefaultLocaleList = locales;
+            if (localeIndex == 0) {
+                sDefaultAdjustedLocaleList = sDefaultLocaleList;
+            } else {
+                sDefaultAdjustedLocaleList = new LocaleList(
+                        sLastDefaultLocale, sDefaultLocaleList);
+            }
         }
     }
 }
diff --git a/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java b/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java
deleted file mode 100644
index 55c0031..0000000
--- a/core/tests/coretests/src/android/content/res/ResourcesLocaleResolutionTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-* 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());
-    }
-}
-