FileDocCategorySizeDatePackage
MccTable.javaAPI DocAndroid 5.1 API30971Thu Mar 12 22:22:54 GMT 2015com.android.internal.telephony

MccTable

public final class MccTable extends Object
Mobile Country Code {@hide}

Fields Summary
static final String
LOG_TAG
static ArrayList
sTable
Constructors Summary
Methods Summary
public static java.lang.StringcountryCodeForMcc(int mcc)
Given a GSM Mobile Country Code, returns an ISO two-character country code if available. Returns "" if unavailable.

        MccEntry entry = entryForMcc(mcc);

        if (entry == null) {
            return "";
        } else {
            return entry.mIso;
        }
    
public static java.lang.StringdefaultLanguageForMcc(int mcc)
Given a GSM Mobile Country Code, returns an ISO 2-3 character language code if available. Returns null if unavailable.

        MccEntry entry = entryForMcc(mcc);
        if (entry == null) {
            Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): no country for mcc");
            return null;
        }

        // Ask CLDR for the language this country uses...
        Locale likelyLocale = ICU.addLikelySubtags(new Locale("und", entry.mIso));
        String likelyLanguage = likelyLocale.getLanguage();
        Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): country " + entry.mIso + " uses " +
               likelyLanguage);
        return likelyLanguage;
    
public static java.lang.StringdefaultTimeZoneForMcc(int mcc)
Returns a default time zone ID for the given MCC.

param
mcc Mobile Country Code
return
default TimeZone ID, or null if not specified

        MccEntry entry = entryForMcc(mcc);
        if (entry == null) {
            return null;
        }
        Locale locale = new Locale("", entry.mIso);
        String[] tz = TimeZoneNames.forLocale(locale);
        if (tz.length == 0) return null;
        return tz[0];
    
private static com.android.internal.telephony.MccTable$MccEntryentryForMcc(int mcc)

        MccEntry m = new MccEntry(mcc, "", 0);

        int index = Collections.binarySearch(sTable, m);

        if (index < 0) {
            return null;
        } else {
            return sTable.get(index);
        }
    
private static java.util.LocalegetLocaleForLanguageCountry(android.content.Context context, java.lang.String language, java.lang.String country)
Return Locale for the language and country or null if no good match.

param
context Context to act on.
param
language Two character language code desired
param
country Two character country code desired
return
Locale or null if no appropriate value

        if (language == null) {
            Slog.d(LOG_TAG, "getLocaleForLanguageCountry: skipping no language");
            return null; // no match possible
        }
        if (country == null) {
            country = ""; // The Locale constructor throws if passed null.
        }

        // Check whether a developer is trying to test an arbitrary MCC.
        boolean debuggingMccOverride = false;
        if (Build.IS_DEBUGGABLE) {
            String overrideMcc = SystemProperties.get("persist.sys.override_mcc", "");
            if (!overrideMcc.isEmpty()) {
                debuggingMccOverride = true;
            }
        }

        // If this is a regular user and they already have a persisted locale, we're done.
        if (!debuggingMccOverride) {
            String persistSysLanguage = SystemProperties.get("persist.sys.language", "");
            String persistSysCountry = SystemProperties.get("persist.sys.country", "");
            if (!(persistSysLanguage.isEmpty() && persistSysCountry.isEmpty())) {
                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: skipping already persisted");
                return 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();
            List<String> locales = new ArrayList<>(Arrays.asList(localeArray));

            // Even in developer mode, you don't want the pseudolocales.
            locales.remove("ar-XB");
            locales.remove("en-XA");

            Locale firstMatch = null;
            for (String locale : locales) {
                final Locale l = Locale.forLanguageTag(locale.replace('_", '-"));

                // Only consider locales with both language and country.
                if (l == null || "und".equals(l.getLanguage()) ||
                        l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
                    continue;
                }
                if (l.getLanguage().equals(target.getLanguage())) {
                    // If we got a perfect match, we're done.
                    if (l.getCountry().equals(target.getCountry())) {
                        Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got perfect match: " +
                               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 didn't find the exact locale, so return whichever locale we saw first where
            // the language matched (if any).
            if (firstMatch != null) {
                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got a language-only match: " +
                       firstMatch.toLanguageTag());
                return firstMatch;
            } else {
                Slog.d(LOG_TAG, "getLocaleForLanguageCountry: no locales for language " +
                       language);
            }
        } catch (Exception e) {
            Slog.d(LOG_TAG, "getLocaleForLanguageCountry: exception", e);
        }

        return null;
    
private static java.util.LocalegetLocaleFromMcc(android.content.Context context, int mcc)
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)
return
locale for the mcc or null if none

        String language = MccTable.defaultLanguageForMcc(mcc);
        String country = MccTable.countryCodeForMcc(mcc);

        Slog.d(LOG_TAG, "getLocaleFromMcc to " + language + "_" + country + " mcc=" + mcc);
        return getLocaleForLanguageCountry(context, language, country);
    
public static voidsetSystemLocale(android.content.Context context, java.lang.String language, java.lang.String country)
Utility code to set the system locale if it's not set already

param
context Context to act on.
param
language Two character language code desired
param
country Two character country code desired {@hide}

        Locale locale = getLocaleForLanguageCountry(context, language, country);
        if (locale != null) {
            Configuration config = new Configuration();
            config.setLocale(locale);
            config.userSetLocale = false;
            Slog.d(LOG_TAG, "setSystemLocale: updateLocale config=" + config);
            try {
                ActivityManagerNative.getDefault().updateConfiguration(config);
            } catch (RemoteException e) {
                Slog.d(LOG_TAG, "setSystemLocale exception", e);
            }
        } else {
            Slog.d(LOG_TAG, "setSystemLocale: no locale");
        }
    
private static voidsetTimezoneFromMccIfNeeded(android.content.Context context, int mcc)
If the timezone is not already set, set it 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)

        String timezone = SystemProperties.get(ServiceStateTracker.TIMEZONE_PROPERTY);
        if (timezone == null || timezone.length() == 0) {
            String zoneId = defaultTimeZoneForMcc(mcc);
            if (zoneId != null && zoneId.length() > 0) {
                // Set time zone based on MCC
                AlarmManager alarm =
                        (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
                alarm.setTimeZone(zoneId);
                Slog.d(LOG_TAG, "timezone set to "+zoneId);
            }
        }
    
private static voidsetWifiCountryCodeFromMcc(android.content.Context context, int mcc)
Set the country code for wifi. This sets allowed wifi channels based on the country of the carrier we see. If we can't see any, reset to 0 so we don't broadcast on forbidden channels.

param
context Context to act on.
param
mcc Mobile Country Code of the operator. 0 if not known

        String country = MccTable.countryCodeForMcc(mcc);
        Slog.d(LOG_TAG, "WIFI_COUNTRY_CODE set to " + country);
        WifiManager wM = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        //persist
        wM.setCountryCode(country, true);
    
public static intsmallestDigitsMccForMnc(int mcc)
Given a GSM Mobile Country Code, returns the smallest number of digits that M if available. Returns 2 if unavailable.

        MccEntry entry = entryForMcc(mcc);

        if (entry == null) {
            return 2;
        } else {
            return entry.mSmallestDigitsMnc;
        }
    
public static voidupdateMccMncConfiguration(android.content.Context context, java.lang.String mccmnc, boolean fromServiceState)
Updates MCC and MNC device configuration information for application retrieving correct version of resources. If MCC is 0, MCC and MNC will be ignored (not set).

param
context Context to act on.
param
mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
param
fromServiceState true if coming from the radio service state, false if from SIM

        Slog.d(LOG_TAG, "updateMccMncConfiguration mccmnc='" + mccmnc + "' fromServiceState=" + fromServiceState);

        if (Build.IS_DEBUGGABLE) {
            String overrideMcc = SystemProperties.get("persist.sys.override_mcc");
            if (!TextUtils.isEmpty(overrideMcc)) {
                mccmnc = overrideMcc;
                Slog.d(LOG_TAG, "updateMccMncConfiguration overriding mccmnc='" + mccmnc + "'");
            }
        }

        if (!TextUtils.isEmpty(mccmnc)) {
            int mcc, mnc;

            String defaultMccMnc = TelephonyManager.getDefault().getSimOperatorNumeric();
            Slog.d(LOG_TAG, "updateMccMncConfiguration defaultMccMnc=" + defaultMccMnc);
            //Update mccmnc only for default subscription in case of MultiSim.
//            if (!defaultMccMnc.equals(mccmnc)) {
//                Slog.d(LOG_TAG, "Not a Default subscription, ignoring mccmnc config update.");
//                return;
//            }

            try {
                mcc = Integer.parseInt(mccmnc.substring(0,3));
                mnc = Integer.parseInt(mccmnc.substring(3));
            } catch (NumberFormatException e) {
                Slog.e(LOG_TAG, "Error parsing IMSI: " + mccmnc);
                return;
            }

            Slog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);

            Locale locale = null;
            if (mcc != 0) {
                setTimezoneFromMccIfNeeded(context, mcc);
                locale = getLocaleFromMcc(context, mcc);
            }
            if (fromServiceState) {
                setWifiCountryCodeFromMcc(context, mcc);
            } else {
                // from SIM
                try {
                    Configuration config = new Configuration();
                    boolean updateConfig = false;
                    if (mcc != 0) {
                        config.mcc = mcc;
                        config.mnc = mnc == 0 ? Configuration.MNC_ZERO : mnc;
                        updateConfig = true;
                    }
                    if (locale != null) {
                        config.setLocale(locale);
                        updateConfig = true;
                    }
                    if (updateConfig) {
                        Slog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config);
                        ActivityManagerNative.getDefault().updateConfiguration(config);
                    } else {
                        Slog.d(LOG_TAG, "updateMccMncConfiguration nothing to update");
                    }
                } catch (RemoteException e) {
                    Slog.e(LOG_TAG, "Can't update configuration", e);
                }
            }
        } else {
            if (fromServiceState) {
                // an empty mccmnc means no signal - tell wifi we don't know
                setWifiCountryCodeFromMcc(context, 0);
            }
        }