Bug 1434805 - Use LocaleList on Android N+. r=jchen draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Fri, 08 Jun 2018 17:35:43 +0900
changeset 807556 b07608b7c51ae530ccb80f79e24aee6eface4712
parent 807395 91db0c695f0272f00bf92c81c471a85101056d96
push id113152
push userbmo:m_kato@ga2.so-net.ne.jp
push dateThu, 14 Jun 2018 22:21:36 +0000
reviewersjchen
bugs1434805
milestone62.0a1
Bug 1434805 - Use LocaleList on Android N+. r=jchen Android N+ has new Locale mode that selects multiple locale for font selection. We should support it to be better locale system selection. MozReview-Commit-ID: HndldWO5yOd
intl/locale/android/OSPreferences_android.cpp
mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
--- a/intl/locale/android/OSPreferences_android.cpp
+++ b/intl/locale/android/OSPreferences_android.cpp
@@ -25,20 +25,24 @@ OSPreferences::ReadSystemLocales(nsTArra
 {
   if (!mozilla::jni::IsAvailable()) {
     return false;
   }
 
   //XXX: Notice, this value may be empty on an early read. In that case
   //     we won't add anything to the return list so that it doesn't get
   //     cached in mSystemLocales.
-  auto locale = mozilla::jni::IsFennec() ? java::BrowserLocaleManager::GetLocale() :
-                java::GeckoAppShell::GetDefaultLocale();
-  if (locale) {
-    aLocaleList.AppendElement(locale->ToCString());
+  auto locales = mozilla::jni::IsFennec() ?
+                   java::BrowserLocaleManager::GetLocales() :
+                   java::GeckoAppShell::GetDefaultLocales();
+  if (locales) {
+    for (size_t i = 0; i < locales->Length(); i++) {
+      jni::String::LocalRef locale = locales->GetElement(i);
+      aLocaleList.AppendElement(locale->ToCString());
+    }
     return true;
   }
   return false;
 }
 
 bool
 OSPreferences::ReadRegionalPrefsLocales(nsTArray<nsCString>& aLocaleList)
 {
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -22,16 +23,17 @@ import org.mozilla.gecko.util.GeckoJarRe
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
+import android.os.LocaleList;
 import android.util.Log;
 
 /**
  * This class manages persistence, application, and otherwise handling of
  * user-specified locales.
  *
  * Of note:
  *
@@ -441,25 +443,35 @@ public class BrowserLocaleManager implem
         return FALLBACK_LOCALE_TAG;
     }
 
     @WrapForJNI(dispatchTo = "Gecko")
     private static native void refreshLocales();
 
 
     @WrapForJNI
-    private static String getLocale() {
+    private static String[] getLocales() {
         try {
+            ArrayList<String> locales = new ArrayList<String>();
             LocaleManager localeManager = Locales.getLocaleManager();
             Context context = GeckoAppShell.getApplicationContext();
             if (!localeManager.isMirroringSystemLocale(context)) {
                 // User uses specific browser locale instead of system locale
-                return Locales.getLanguageTag(localeManager.getCurrentLocale(context));
+                locales.add(Locales.getLanguageTag(localeManager.getCurrentLocale(context)));
+                return locales.toArray(new String[locales.size()]);
             }
-            // Since user selects system default for browser locale, we should return system locale
-            Locale locale = localeManager.getDefaultSystemLocale();
-            return Locales.getLanguageTag(locale);
+            // Since user selects system default for browser locale, we should return system locales too.
+            if (Build.VERSION.SDK_INT >= 24) {
+                LocaleList localeList = LocaleList.getDefault();
+                for (int i = 0; i < localeList.size(); i++) {
+                    // Some locales such as "he" need conversion.
+                    locales.add(Locales.getLanguageTag(localeList.get(i)));
+                }
+            } else {
+                locales.add(Locales.getLanguageTag(localeManager.getDefaultSystemLocale()));
+            }
+            return locales.toArray(new String[locales.size()]);
         } catch (NullPointerException e) {
             Log.i(LOG_TAG, "Couldn't get current locale.");
             return null;
         }
     }
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -74,16 +74,17 @@ import android.location.LocationListener
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.LocaleList;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.support.annotation.NonNull;
@@ -1915,28 +1916,44 @@ public class GeckoAppShell
         }
         final String prop = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
         if (prop == null) {
             return DEFAULT;
         }
         return Integer.parseInt(prop);
     }
 
-    @WrapForJNI
-    public static String getDefaultLocale() {
-        final Locale locale = Locale.getDefault();
-        if (Build.VERSION.SDK_INT >= 21) {
-            return locale.toLanguageTag();
-        }
-
+    private static String getLanguageTag(final Locale locale) {
         final StringBuilder out = new StringBuilder(locale.getLanguage());
         final String country = locale.getCountry();
         final String variant = locale.getVariant();
         if (!TextUtils.isEmpty(country)) {
             out.append('-').append(country);
         }
         if (!TextUtils.isEmpty(variant)) {
             out.append('-').append(variant);
         }
         // e.g. "en", "en-US", or "en-US-POSIX".
         return out.toString();
     }
+
+    @WrapForJNI
+    public static String[] getDefaultLocales() {
+        // XXX We may have to convert some language codes such as "id" vs "in".
+        if (Build.VERSION.SDK_INT >= 24) {
+            final LocaleList localeList = LocaleList.getDefault();
+            String[] locales = new String[localeList.size()];
+            for (int i = 0; i < localeList.size(); i++) {
+                locales[i] = localeList.get(i).toLanguageTag();
+            }
+            return locales;
+        }
+        String[] locales = new String[1];
+        final Locale locale = Locale.getDefault();
+        if (Build.VERSION.SDK_INT >= 21) {
+            locales[0] = locale.toLanguageTag();
+            return locales;
+        }
+
+        locales[0] = getLanguageTag(locale);
+        return locales;
+    }
 }