Loading src/java/com/android/internal/telephony/MccTable.java +62 −20 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.os.RemoteException; import android.os.SystemProperties; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; Loading @@ -32,8 +31,11 @@ import android.util.Slog; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import libcore.icu.ICU; import libcore.icu.TimeZoneNames; Loading Loading @@ -218,6 +220,41 @@ public final class MccTable { } } /** * Maps a given locale to a fallback locale that approximates it. This is a hack. */ private static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>(); static { FALLBACKS.put(Locale.CANADA, Locale.US); } /** * Find the best match we actually have a localization for. This function assumes we * couldn't find an exact match. * * TODO: This should really follow the CLDR chain of parent locales! That might be a bit * of a problem because we don't really have an en-001 locale on android. */ private static Locale chooseBestFallback(Locale target, List<Locale> candidates) { if (candidates.isEmpty()) { return null; } Locale fallback = target; while ((fallback = FALLBACKS.get(fallback)) != null) { if (candidates.contains(fallback)) { return fallback; } } // Somewhat arbitrarily take the first locale for the language, // unless we get a perfect match later. Note that these come back in no // particular order, so there's no reason to think the first match is // a particularly good match. return candidates.get(0); } /** * Return Locale for the language and country or null if no good match. * Loading @@ -237,8 +274,6 @@ public final class MccTable { country = ""; // The Locale constructor throws if passed null. } // Find the best match we actually have a localization for. // TODO: this should really follow the CLDR chain of parent locales! final Locale target = new Locale(language, country); try { String[] localeArray = context.getAssets().getLocales(); Loading @@ -248,7 +283,7 @@ public final class MccTable { locales.remove("ar-XB"); locales.remove("en-XA"); Locale firstMatch = null; List<Locale> languageMatches = new ArrayList<>(); for (String locale : locales) { final Locale l = Locale.forLanguageTag(locale.replace('_', '-')); Loading @@ -264,22 +299,17 @@ public final class MccTable { l.toLanguageTag()); return l; } // Otherwise somewhat arbitrarily take the first locale for the language, // unless we get a perfect match later. Note that these come back in no // particular order, so there's no reason to think the first match is // a particularly good match. if (firstMatch == null) { firstMatch = l; } // We've only matched the language, not the country. languageMatches.add(l); } } // We didn't find the exact locale, so return whichever locale we saw first where // the language matched (if any). if (firstMatch != null) { Locale bestMatch = chooseBestFallback(target, languageMatches); if (bestMatch != null) { Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got a language-only match: " + firstMatch.toLanguageTag()); return firstMatch; bestMatch.toLanguageTag()); return bestMatch; } else { Slog.d(LOG_TAG, "getLocaleForLanguageCountry: no locales for language " + language); Loading Loading @@ -312,17 +342,29 @@ public final class MccTable { /** * Get Locale based on the MCC of the SIM. * * @param context Context to act on. * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) * @param simLanguage (nullable) the language from the SIM records (if present). * * @return locale for the mcc or null if none */ public static Locale getLocaleFromMcc(Context context, int mcc) { String language = MccTable.defaultLanguageForMcc(mcc); public static Locale getLocaleFromMcc(Context context, int mcc, String simLanguage) { String language = (simLanguage == null) ? MccTable.defaultLanguageForMcc(mcc) : simLanguage; String country = MccTable.countryCodeForMcc(mcc); Slog.d(LOG_TAG, "getLocaleFromMcc to " + language + "_" + country + " mcc=" + mcc); return getLocaleForLanguageCountry(context, language, country); Slog.d(LOG_TAG, "getLocaleFromMcc(" + language + ", " + country + ", " + mcc); final Locale locale = getLocaleForLanguageCountry(context, language, country); // If we couldn't find a locale that matches the SIM language, give it a go again // with the "likely" language for the given country. if (locale == null && simLanguage != null) { language = MccTable.defaultLanguageForMcc(mcc); Slog.d(LOG_TAG, "[retry ] getLocaleFromMcc(" + language + ", " + country + ", " + mcc); return getLocaleForLanguageCountry(context, null, country); } return locale; } /** Loading Loading
src/java/com/android/internal/telephony/MccTable.java +62 −20 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.os.RemoteException; import android.os.SystemProperties; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; Loading @@ -32,8 +31,11 @@ import android.util.Slog; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import libcore.icu.ICU; import libcore.icu.TimeZoneNames; Loading Loading @@ -218,6 +220,41 @@ public final class MccTable { } } /** * Maps a given locale to a fallback locale that approximates it. This is a hack. */ private static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>(); static { FALLBACKS.put(Locale.CANADA, Locale.US); } /** * Find the best match we actually have a localization for. This function assumes we * couldn't find an exact match. * * TODO: This should really follow the CLDR chain of parent locales! That might be a bit * of a problem because we don't really have an en-001 locale on android. */ private static Locale chooseBestFallback(Locale target, List<Locale> candidates) { if (candidates.isEmpty()) { return null; } Locale fallback = target; while ((fallback = FALLBACKS.get(fallback)) != null) { if (candidates.contains(fallback)) { return fallback; } } // Somewhat arbitrarily take the first locale for the language, // unless we get a perfect match later. Note that these come back in no // particular order, so there's no reason to think the first match is // a particularly good match. return candidates.get(0); } /** * Return Locale for the language and country or null if no good match. * Loading @@ -237,8 +274,6 @@ public final class MccTable { country = ""; // The Locale constructor throws if passed null. } // Find the best match we actually have a localization for. // TODO: this should really follow the CLDR chain of parent locales! final Locale target = new Locale(language, country); try { String[] localeArray = context.getAssets().getLocales(); Loading @@ -248,7 +283,7 @@ public final class MccTable { locales.remove("ar-XB"); locales.remove("en-XA"); Locale firstMatch = null; List<Locale> languageMatches = new ArrayList<>(); for (String locale : locales) { final Locale l = Locale.forLanguageTag(locale.replace('_', '-')); Loading @@ -264,22 +299,17 @@ public final class MccTable { l.toLanguageTag()); return l; } // Otherwise somewhat arbitrarily take the first locale for the language, // unless we get a perfect match later. Note that these come back in no // particular order, so there's no reason to think the first match is // a particularly good match. if (firstMatch == null) { firstMatch = l; } // We've only matched the language, not the country. languageMatches.add(l); } } // We didn't find the exact locale, so return whichever locale we saw first where // the language matched (if any). if (firstMatch != null) { Locale bestMatch = chooseBestFallback(target, languageMatches); if (bestMatch != null) { Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got a language-only match: " + firstMatch.toLanguageTag()); return firstMatch; bestMatch.toLanguageTag()); return bestMatch; } else { Slog.d(LOG_TAG, "getLocaleForLanguageCountry: no locales for language " + language); Loading Loading @@ -312,17 +342,29 @@ public final class MccTable { /** * Get Locale based on the MCC of the SIM. * * @param context Context to act on. * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA) * @param simLanguage (nullable) the language from the SIM records (if present). * * @return locale for the mcc or null if none */ public static Locale getLocaleFromMcc(Context context, int mcc) { String language = MccTable.defaultLanguageForMcc(mcc); public static Locale getLocaleFromMcc(Context context, int mcc, String simLanguage) { String language = (simLanguage == null) ? MccTable.defaultLanguageForMcc(mcc) : simLanguage; String country = MccTable.countryCodeForMcc(mcc); Slog.d(LOG_TAG, "getLocaleFromMcc to " + language + "_" + country + " mcc=" + mcc); return getLocaleForLanguageCountry(context, language, country); Slog.d(LOG_TAG, "getLocaleFromMcc(" + language + ", " + country + ", " + mcc); final Locale locale = getLocaleForLanguageCountry(context, language, country); // If we couldn't find a locale that matches the SIM language, give it a go again // with the "likely" language for the given country. if (locale == null && simLanguage != null) { language = MccTable.defaultLanguageForMcc(mcc); Slog.d(LOG_TAG, "[retry ] getLocaleFromMcc(" + language + ", " + country + ", " + mcc); return getLocaleForLanguageCountry(context, null, country); } return locale; } /** Loading