Merge "Allow fallback translated languages in MccTable"
[android/platform/frameworks/opt/telephony.git] / src / java / com / android / internal / telephony / MccTable.java
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.internal.telephony;
18
19 import android.app.ActivityManager;
20 import android.app.AlarmManager;
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.net.wifi.WifiManager;
24 import android.os.Build;
25 import android.os.RemoteException;
26 import android.os.SystemProperties;
27 import android.telephony.TelephonyManager;
28 import android.text.TextUtils;
29 import android.util.Slog;
30
31 import com.android.internal.app.LocaleStore;
32 import com.android.internal.app.LocaleStore.LocaleInfo;
33
34 import libcore.icu.ICU;
35 import libcore.icu.TimeZoneNames;
36
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Map;
44
45 /**
46  * Mobile Country Code
47  *
48  * {@hide}
49  */
50 public final class MccTable {
51     static final String LOG_TAG = "MccTable";
52
53     static ArrayList<MccEntry> sTable;
54
55     static class MccEntry implements Comparable<MccEntry> {
56         final int mMcc;
57         final String mIso;
58         final int mSmallestDigitsMnc;
59
60         MccEntry(int mnc, String iso, int smallestDigitsMCC) {
61             if (iso == null) {
62                 throw new NullPointerException();
63             }
64             mMcc = mnc;
65             mIso = iso;
66             mSmallestDigitsMnc = smallestDigitsMCC;
67         }
68
69         @Override
70         public int compareTo(MccEntry o) {
71             return mMcc - o.mMcc;
72         }
73     }
74
75     private static MccEntry entryForMcc(int mcc) {
76         MccEntry m = new MccEntry(mcc, "", 0);
77
78         int index = Collections.binarySearch(sTable, m);
79
80         if (index < 0) {
81             return null;
82         } else {
83             return sTable.get(index);
84         }
85     }
86
87     /**
88      * Returns a default time zone ID for the given MCC.
89      * @param mcc Mobile Country Code
90      * @return default TimeZone ID, or null if not specified
91      */
92     public static String defaultTimeZoneForMcc(int mcc) {
93         MccEntry entry = entryForMcc(mcc);
94         if (entry == null) {
95             return null;
96         }
97         Locale locale = new Locale("", entry.mIso);
98         String[] tz = TimeZoneNames.forLocale(locale);
99         if (tz.length == 0) return null;
100         return tz[0];
101     }
102
103     /**
104      * Given a GSM Mobile Country Code, returns
105      * an ISO two-character country code if available.
106      * Returns "" if unavailable.
107      */
108     public static String countryCodeForMcc(int mcc) {
109         MccEntry entry = entryForMcc(mcc);
110
111         if (entry == null) {
112             return "";
113         } else {
114             return entry.mIso;
115         }
116     }
117
118     /**
119      * Given a GSM Mobile Country Code, returns
120      * an ISO 2-3 character language code if available.
121      * Returns null if unavailable.
122      */
123     public static String defaultLanguageForMcc(int mcc) {
124         MccEntry entry = entryForMcc(mcc);
125         if (entry == null) {
126             Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): no country for mcc");
127             return null;
128         }
129
130         final String country = entry.mIso;
131
132         // Choose English as the default language for India.
133         if ("in".equals(country)) {
134             return "en";
135         }
136
137         // Ask CLDR for the language this country uses...
138         Locale likelyLocale = ICU.addLikelySubtags(new Locale("und", country));
139         String likelyLanguage = likelyLocale.getLanguage();
140         Slog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): country " + country + " uses " +
141                likelyLanguage);
142         return likelyLanguage;
143     }
144
145     /**
146      * Given a GSM Mobile Country Code, returns
147      * the smallest number of digits that M if available.
148      * Returns 2 if unavailable.
149      */
150     public static int smallestDigitsMccForMnc(int mcc) {
151         MccEntry entry = entryForMcc(mcc);
152
153         if (entry == null) {
154             return 2;
155         } else {
156             return entry.mSmallestDigitsMnc;
157         }
158     }
159
160     /**
161      * Updates MCC and MNC device configuration information for application retrieving
162      * correct version of resources.  If MCC is 0, MCC and MNC will be ignored (not set).
163      * @param context Context to act on.
164      * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
165      * @param fromServiceState true if coming from the radio service state, false if from SIM
166      */
167     public static void updateMccMncConfiguration(Context context, String mccmnc,
168             boolean fromServiceState) {
169         Slog.d(LOG_TAG, "updateMccMncConfiguration mccmnc='" + mccmnc + "' fromServiceState=" + fromServiceState);
170
171         if (Build.IS_DEBUGGABLE) {
172             String overrideMcc = SystemProperties.get("persist.sys.override_mcc");
173             if (!TextUtils.isEmpty(overrideMcc)) {
174                 mccmnc = overrideMcc;
175                 Slog.d(LOG_TAG, "updateMccMncConfiguration overriding mccmnc='" + mccmnc + "'");
176             }
177         }
178
179         if (!TextUtils.isEmpty(mccmnc)) {
180             int mcc, mnc;
181
182             String defaultMccMnc = TelephonyManager.getDefault().getSimOperatorNumeric();
183             Slog.d(LOG_TAG, "updateMccMncConfiguration defaultMccMnc=" + defaultMccMnc);
184             //Update mccmnc only for default subscription in case of MultiSim.
185 //            if (!defaultMccMnc.equals(mccmnc)) {
186 //                Slog.d(LOG_TAG, "Not a Default subscription, ignoring mccmnc config update.");
187 //                return;
188 //            }
189
190             try {
191                 mcc = Integer.parseInt(mccmnc.substring(0,3));
192                 mnc = Integer.parseInt(mccmnc.substring(3));
193             } catch (NumberFormatException e) {
194                 Slog.e(LOG_TAG, "Error parsing IMSI: " + mccmnc);
195                 return;
196             }
197
198             Slog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
199             if (mcc != 0) {
200                 setTimezoneFromMccIfNeeded(context, mcc);
201             }
202             if (fromServiceState) {
203                 setWifiCountryCodeFromMcc(context, mcc);
204             } else {
205                 // from SIM
206                 try {
207                     Configuration config = new Configuration();
208                     boolean updateConfig = false;
209                     if (mcc != 0) {
210                         config.mcc = mcc;
211                         config.mnc = mnc == 0 ? Configuration.MNC_ZERO : mnc;
212                         updateConfig = true;
213                     }
214
215                     if (updateConfig) {
216                         Slog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config);
217                         ActivityManager.getService().updateConfiguration(config);
218                     } else {
219                         Slog.d(LOG_TAG, "updateMccMncConfiguration nothing to update");
220                     }
221                 } catch (RemoteException e) {
222                     Slog.e(LOG_TAG, "Can't update configuration", e);
223                 }
224             }
225         } else {
226             if (fromServiceState) {
227                 // an empty mccmnc means no signal - tell wifi we don't know
228                 setWifiCountryCodeFromMcc(context, 0);
229             }
230         }
231     }
232
233     /**
234      * Maps a given locale to a fallback locale that approximates it. This is a hack.
235      */
236     private static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>();
237
238     static {
239         // If we have English (without a country) explicitly prioritize en_US. http://b/28998094
240         FALLBACKS.put(Locale.ENGLISH, Locale.US);
241     }
242
243     /**
244      * Finds a suitable locale among {@code candidates} to use as the fallback locale for
245      * {@code target}. This looks through the list of {@link #FALLBACKS}, and follows the chain
246      * until a locale in {@code candidates} is found.
247      * This function assumes that {@code target} is not in {@code candidates}.
248      *
249      * TODO: This should really follow the CLDR chain of parent locales! That might be a bit
250      * of a problem because we don't really have an en-001 locale on android.
251      *
252      * @return The fallback locale or {@code null} if there is no suitable fallback defined in the
253      *         lookup.
254      */
255     private static Locale lookupFallback(Locale target, List<Locale> candidates) {
256         Locale fallback = target;
257         while ((fallback = FALLBACKS.get(fallback)) != null) {
258             if (candidates.contains(fallback)) {
259                 return fallback;
260             }
261         }
262
263         return null;
264     }
265
266     /**
267      * Return Locale for the language and country or null if no good match.
268      *
269      * @param context Context to act on.
270      * @param language Two character language code desired
271      * @param country Two character country code desired
272      *
273      * @return Locale or null if no appropriate value
274      */
275     private static Locale getLocaleForLanguageCountry(Context context, String language,
276             String country) {
277         if (language == null) {
278             Slog.d(LOG_TAG, "getLocaleForLanguageCountry: skipping no language");
279             return null; // no match possible
280         }
281         if (country == null) {
282             country = ""; // The Locale constructor throws if passed null.
283         }
284
285         final Locale target = new Locale(language, country);
286         try {
287             String[] localeArray = context.getAssets().getLocales();
288             List<String> locales = new ArrayList<>(Arrays.asList(localeArray));
289
290             // Even in developer mode, you don't want the pseudolocales.
291             locales.remove("ar-XB");
292             locales.remove("en-XA");
293
294             List<Locale> languageMatches = new ArrayList<>();
295             for (String locale : locales) {
296                 final Locale l = Locale.forLanguageTag(locale.replace('_', '-'));
297
298                 // Only consider locales with both language and country.
299                 if (l == null || "und".equals(l.getLanguage()) ||
300                         l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
301                     continue;
302                 }
303                 if (l.getLanguage().equals(target.getLanguage())) {
304                     // If we got a perfect match, we're done.
305                     if (l.getCountry().equals(target.getCountry())) {
306                         Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got perfect match: " +
307                                l.toLanguageTag());
308                         return l;
309                     }
310
311                     // We've only matched the language, not the country.
312                     languageMatches.add(l);
313                 }
314             }
315
316             if (languageMatches.isEmpty()) {
317                 Slog.d(LOG_TAG, "getLocaleForLanguageCountry: no locales for language " + language);
318                 return null;
319             }
320
321             Locale bestMatch = lookupFallback(target, languageMatches);
322             if (bestMatch != null) {
323                 Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got a fallback match: "
324                         + bestMatch.toLanguageTag());
325                 return bestMatch;
326             } else {
327                 // Ask {@link LocaleStore} whether this locale is considered "translated".
328                 // LocaleStore has a broader definition of translated than just the asset locales
329                 // above: a locale is "translated" if it has translation assets, or another locale
330                 // with the same language and script has translation assets.
331                 // If a locale is "translated", it is selectable in setup wizard, and can therefore
332                 // be considerd a valid result for this method.
333                 if (!TextUtils.isEmpty(target.getCountry())) {
334                     LocaleStore.fillCache(context);
335                     LocaleInfo targetInfo = LocaleStore.getLocaleInfo(target);
336                     if (targetInfo.isTranslated()) {
337                         Slog.d(LOG_TAG, "getLocaleForLanguageCountry: "
338                                 + "target locale is translated: " + target);
339                         return target;
340                     }
341                 }
342
343                 // Somewhat arbitrarily take the first locale for the language,
344                 // unless we get a perfect match later. Note that these come back in no
345                 // particular order, so there's no reason to think the first match is
346                 // a particularly good match.
347                 Slog.d(LOG_TAG, "getLocaleForLanguageCountry: got language-only match: "
348                         + language);
349                 return languageMatches.get(0);
350             }
351         } catch (Exception e) {
352             Slog.d(LOG_TAG, "getLocaleForLanguageCountry: exception", e);
353         }
354
355         return null;
356     }
357
358     /**
359      * If the timezone is not already set, set it based on the MCC of the SIM.
360      * @param context Context to act on.
361      * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
362      */
363     private static void setTimezoneFromMccIfNeeded(Context context, int mcc) {
364         String timezone = SystemProperties.get(ServiceStateTracker.TIMEZONE_PROPERTY);
365         if (timezone == null || timezone.length() == 0) {
366             String zoneId = defaultTimeZoneForMcc(mcc);
367             if (zoneId != null && zoneId.length() > 0) {
368                 // Set time zone based on MCC
369                 AlarmManager alarm =
370                         (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
371                 alarm.setTimeZone(zoneId);
372                 Slog.d(LOG_TAG, "timezone set to " + zoneId);
373             }
374         }
375     }
376
377     /**
378      * Get Locale based on the MCC of the SIM.
379      *
380      * @param context Context to act on.
381      * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
382      * @param simLanguage (nullable) the language from the SIM records (if present).
383      *
384      * @return locale for the mcc or null if none
385      */
386     public static Locale getLocaleFromMcc(Context context, int mcc, String simLanguage) {
387         boolean hasSimLanguage = !TextUtils.isEmpty(simLanguage);
388         String language = hasSimLanguage ? simLanguage : MccTable.defaultLanguageForMcc(mcc);
389         String country = MccTable.countryCodeForMcc(mcc);
390
391         Slog.d(LOG_TAG, "getLocaleFromMcc(" + language + ", " + country + ", " + mcc);
392         final Locale locale = getLocaleForLanguageCountry(context, language, country);
393
394         // If we couldn't find a locale that matches the SIM language, give it a go again
395         // with the "likely" language for the given country.
396         if (locale == null && hasSimLanguage) {
397             language = MccTable.defaultLanguageForMcc(mcc);
398             Slog.d(LOG_TAG, "[retry ] getLocaleFromMcc(" + language + ", " + country + ", " + mcc);
399             return getLocaleForLanguageCountry(context, language, country);
400         }
401
402         return locale;
403     }
404
405     /**
406      * Set the country code for wifi.  This sets allowed wifi channels based on the
407      * country of the carrier we see.  If we can't see any, reset to 0 so we don't
408      * broadcast on forbidden channels.
409      * @param context Context to act on.
410      * @param mcc Mobile Country Code of the operator.  0 if not known
411      */
412     private static void setWifiCountryCodeFromMcc(Context context, int mcc) {
413         String country = MccTable.countryCodeForMcc(mcc);
414         Slog.d(LOG_TAG, "WIFI_COUNTRY_CODE set to " + country);
415         WifiManager wM = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
416         wM.setCountryCode(country, false);
417     }
418
419     static {
420         sTable = new ArrayList<MccEntry>(240);
421
422
423         /*
424          * The table below is built from two resources:
425          *
426          * 1) ITU "Mobile Network Code (MNC) for the international
427          *   identification plan for mobile terminals and mobile users"
428          *   which is available as an annex to the ITU operational bulletin
429          *   available here: http://www.itu.int/itu-t/bulletin/annex.html
430          *
431          * 2) The ISO 3166 country codes list, available here:
432          *    http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html
433          *
434          * This table has not been verified.
435          */
436
437                 sTable.add(new MccEntry(202,"gr",2));   //Greece
438                 sTable.add(new MccEntry(204,"nl",2));   //Netherlands (Kingdom of the)
439                 sTable.add(new MccEntry(206,"be",2));   //Belgium
440                 sTable.add(new MccEntry(208,"fr",2));   //France
441                 sTable.add(new MccEntry(212,"mc",2));   //Monaco (Principality of)
442                 sTable.add(new MccEntry(213,"ad",2));   //Andorra (Principality of)
443                 sTable.add(new MccEntry(214,"es",2));   //Spain
444                 sTable.add(new MccEntry(216,"hu",2));   //Hungary (Republic of)
445                 sTable.add(new MccEntry(218,"ba",2));   //Bosnia and Herzegovina
446                 sTable.add(new MccEntry(219,"hr",2));   //Croatia (Republic of)
447                 sTable.add(new MccEntry(220,"rs",2));   //Serbia and Montenegro
448                 sTable.add(new MccEntry(222,"it",2));   //Italy
449                 sTable.add(new MccEntry(225,"va",2));   //Vatican City State
450                 sTable.add(new MccEntry(226,"ro",2));   //Romania
451                 sTable.add(new MccEntry(228,"ch",2));   //Switzerland (Confederation of)
452                 sTable.add(new MccEntry(230,"cz",2));   //Czechia
453                 sTable.add(new MccEntry(231,"sk",2));   //Slovak Republic
454                 sTable.add(new MccEntry(232,"at",2));   //Austria
455                 sTable.add(new MccEntry(234,"gb",2));   //United Kingdom of Great Britain and Northern Ireland
456                 sTable.add(new MccEntry(235,"gb",2));   //United Kingdom of Great Britain and Northern Ireland
457                 sTable.add(new MccEntry(238,"dk",2));   //Denmark
458                 sTable.add(new MccEntry(240,"se",2));   //Sweden
459                 sTable.add(new MccEntry(242,"no",2));   //Norway
460                 sTable.add(new MccEntry(244,"fi",2));   //Finland
461                 sTable.add(new MccEntry(246,"lt",2));   //Lithuania (Republic of)
462                 sTable.add(new MccEntry(247,"lv",2));   //Latvia (Republic of)
463                 sTable.add(new MccEntry(248,"ee",2));   //Estonia (Republic of)
464                 sTable.add(new MccEntry(250,"ru",2));   //Russian Federation
465                 sTable.add(new MccEntry(255,"ua",2));   //Ukraine
466                 sTable.add(new MccEntry(257,"by",2));   //Belarus (Republic of)
467                 sTable.add(new MccEntry(259,"md",2));   //Moldova (Republic of)
468                 sTable.add(new MccEntry(260,"pl",2));   //Poland (Republic of)
469                 sTable.add(new MccEntry(262,"de",2));   //Germany (Federal Republic of)
470                 sTable.add(new MccEntry(266,"gi",2));   //Gibraltar
471                 sTable.add(new MccEntry(268,"pt",2));   //Portugal
472                 sTable.add(new MccEntry(270,"lu",2));   //Luxembourg
473                 sTable.add(new MccEntry(272,"ie",2));   //Ireland
474                 sTable.add(new MccEntry(274,"is",2));   //Iceland
475                 sTable.add(new MccEntry(276,"al",2));   //Albania (Republic of)
476                 sTable.add(new MccEntry(278,"mt",2));   //Malta
477                 sTable.add(new MccEntry(280,"cy",2));   //Cyprus (Republic of)
478                 sTable.add(new MccEntry(282,"ge",2));   //Georgia
479                 sTable.add(new MccEntry(283,"am",2));   //Armenia (Republic of)
480                 sTable.add(new MccEntry(284,"bg",2));   //Bulgaria (Republic of)
481                 sTable.add(new MccEntry(286,"tr",2));   //Turkey
482                 sTable.add(new MccEntry(288,"fo",2));   //Faroe Islands
483                 sTable.add(new MccEntry(289,"ge",2));    //Abkhazia (Georgia)
484                 sTable.add(new MccEntry(290,"gl",2));   //Greenland (Denmark)
485                 sTable.add(new MccEntry(292,"sm",2));   //San Marino (Republic of)
486                 sTable.add(new MccEntry(293,"si",2));   //Slovenia (Republic of)
487                 sTable.add(new MccEntry(294,"mk",2));   //The Former Yugoslav Republic of Macedonia
488                 sTable.add(new MccEntry(295,"li",2));   //Liechtenstein (Principality of)
489                 sTable.add(new MccEntry(297,"me",2));    //Montenegro (Republic of)
490                 sTable.add(new MccEntry(302,"ca",3));   //Canada
491                 sTable.add(new MccEntry(308,"pm",2));   //Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)
492                 sTable.add(new MccEntry(310,"us",3));   //United States of America
493                 sTable.add(new MccEntry(311,"us",3));   //United States of America
494                 sTable.add(new MccEntry(312,"us",3));   //United States of America
495                 sTable.add(new MccEntry(313,"us",3));   //United States of America
496                 sTable.add(new MccEntry(314,"us",3));   //United States of America
497                 sTable.add(new MccEntry(315,"us",3));   //United States of America
498                 sTable.add(new MccEntry(316,"us",3));   //United States of America
499                 sTable.add(new MccEntry(330,"pr",2));   //Puerto Rico
500                 sTable.add(new MccEntry(332,"vi",2));   //United States Virgin Islands
501                 sTable.add(new MccEntry(334,"mx",3));   //Mexico
502                 sTable.add(new MccEntry(338,"jm",3));   //Jamaica
503                 sTable.add(new MccEntry(340,"gp",2));   //Guadeloupe (French Department of)
504                 sTable.add(new MccEntry(342,"bb",3));   //Barbados
505                 sTable.add(new MccEntry(344,"ag",3));   //Antigua and Barbuda
506                 sTable.add(new MccEntry(346,"ky",3));   //Cayman Islands
507                 sTable.add(new MccEntry(348,"vg",3));   //British Virgin Islands
508                 sTable.add(new MccEntry(350,"bm",2));   //Bermuda
509                 sTable.add(new MccEntry(352,"gd",2));   //Grenada
510                 sTable.add(new MccEntry(354,"ms",2));   //Montserrat
511                 sTable.add(new MccEntry(356,"kn",2));   //Saint Kitts and Nevis
512                 sTable.add(new MccEntry(358,"lc",2));   //Saint Lucia
513                 sTable.add(new MccEntry(360,"vc",2));   //Saint Vincent and the Grenadines
514                 sTable.add(new MccEntry(362,"ai",2));   //Netherlands Antilles
515                 sTable.add(new MccEntry(363,"aw",2));   //Aruba
516                 sTable.add(new MccEntry(364,"bs",2));   //Bahamas (Commonwealth of the)
517                 sTable.add(new MccEntry(365,"ai",3));   //Anguilla
518                 sTable.add(new MccEntry(366,"dm",2));   //Dominica (Commonwealth of)
519                 sTable.add(new MccEntry(368,"cu",2));   //Cuba
520                 sTable.add(new MccEntry(370,"do",2));   //Dominican Republic
521                 sTable.add(new MccEntry(372,"ht",2));   //Haiti (Republic of)
522                 sTable.add(new MccEntry(374,"tt",2));   //Trinidad and Tobago
523                 sTable.add(new MccEntry(376,"tc",2));   //Turks and Caicos Islands
524                 sTable.add(new MccEntry(400,"az",2));   //Azerbaijani Republic
525                 sTable.add(new MccEntry(401,"kz",2));   //Kazakhstan (Republic of)
526                 sTable.add(new MccEntry(402,"bt",2));   //Bhutan (Kingdom of)
527                 sTable.add(new MccEntry(404,"in",2));   //India (Republic of)
528                 sTable.add(new MccEntry(405,"in",2));   //India (Republic of)
529                 sTable.add(new MccEntry(406,"in",2));   //India (Republic of)
530                 sTable.add(new MccEntry(410,"pk",2));   //Pakistan (Islamic Republic of)
531                 sTable.add(new MccEntry(412,"af",2));   //Afghanistan
532                 sTable.add(new MccEntry(413,"lk",2));   //Sri Lanka (Democratic Socialist Republic of)
533                 sTable.add(new MccEntry(414,"mm",2));   //Myanmar (Union of)
534                 sTable.add(new MccEntry(415,"lb",2));   //Lebanon
535                 sTable.add(new MccEntry(416,"jo",2));   //Jordan (Hashemite Kingdom of)
536                 sTable.add(new MccEntry(417,"sy",2));   //Syrian Arab Republic
537                 sTable.add(new MccEntry(418,"iq",2));   //Iraq (Republic of)
538                 sTable.add(new MccEntry(419,"kw",2));   //Kuwait (State of)
539                 sTable.add(new MccEntry(420,"sa",2));   //Saudi Arabia (Kingdom of)
540                 sTable.add(new MccEntry(421,"ye",2));   //Yemen (Republic of)
541                 sTable.add(new MccEntry(422,"om",2));   //Oman (Sultanate of)
542                 sTable.add(new MccEntry(423,"ps",2));    //Palestine
543                 sTable.add(new MccEntry(424,"ae",2));   //United Arab Emirates
544                 sTable.add(new MccEntry(425,"il",2));   //Israel (State of)
545                 sTable.add(new MccEntry(426,"bh",2));   //Bahrain (Kingdom of)
546                 sTable.add(new MccEntry(427,"qa",2));   //Qatar (State of)
547                 sTable.add(new MccEntry(428,"mn",2));   //Mongolia
548                 sTable.add(new MccEntry(429,"np",2));   //Nepal
549                 sTable.add(new MccEntry(430,"ae",2));   //United Arab Emirates
550                 sTable.add(new MccEntry(431,"ae",2));   //United Arab Emirates
551                 sTable.add(new MccEntry(432,"ir",2));   //Iran (Islamic Republic of)
552                 sTable.add(new MccEntry(434,"uz",2));   //Uzbekistan (Republic of)
553                 sTable.add(new MccEntry(436,"tj",2));   //Tajikistan (Republic of)
554                 sTable.add(new MccEntry(437,"kg",2));   //Kyrgyz Republic
555                 sTable.add(new MccEntry(438,"tm",2));   //Turkmenistan
556                 sTable.add(new MccEntry(440,"jp",2));   //Japan
557                 sTable.add(new MccEntry(441,"jp",2));   //Japan
558                 sTable.add(new MccEntry(450,"kr",2));   //Korea (Republic of)
559                 sTable.add(new MccEntry(452,"vn",2));   //Viet Nam (Socialist Republic of)
560                 sTable.add(new MccEntry(454,"hk",2));   //"Hong Kong, China"
561                 sTable.add(new MccEntry(455,"mo",2));   //"Macao, China"
562                 sTable.add(new MccEntry(456,"kh",2));   //Cambodia (Kingdom of)
563                 sTable.add(new MccEntry(457,"la",2));   //Lao People's Democratic Republic
564                 sTable.add(new MccEntry(460,"cn",2));   //China (People's Republic of)
565                 sTable.add(new MccEntry(461,"cn",2));   //China (People's Republic of)
566                 sTable.add(new MccEntry(466,"tw",2));   //Taiwan
567                 sTable.add(new MccEntry(467,"kp",2));   //Democratic People's Republic of Korea
568                 sTable.add(new MccEntry(470,"bd",2));   //Bangladesh (People's Republic of)
569                 sTable.add(new MccEntry(472,"mv",2));   //Maldives (Republic of)
570                 sTable.add(new MccEntry(502,"my",2));   //Malaysia
571                 sTable.add(new MccEntry(505,"au",2));   //Australia
572                 sTable.add(new MccEntry(510,"id",2));   //Indonesia (Republic of)
573                 sTable.add(new MccEntry(514,"tl",2));   //Democratic Republic of Timor-Leste
574                 sTable.add(new MccEntry(515,"ph",2));   //Philippines (Republic of the)
575                 sTable.add(new MccEntry(520,"th",2));   //Thailand
576                 sTable.add(new MccEntry(525,"sg",2));   //Singapore (Republic of)
577                 sTable.add(new MccEntry(528,"bn",2));   //Brunei Darussalam
578                 sTable.add(new MccEntry(530,"nz",2));   //New Zealand
579                 sTable.add(new MccEntry(534,"mp",2));   //Northern Mariana Islands (Commonwealth of the)
580                 sTable.add(new MccEntry(535,"gu",2));   //Guam
581                 sTable.add(new MccEntry(536,"nr",2));   //Nauru (Republic of)
582                 sTable.add(new MccEntry(537,"pg",2));   //Papua New Guinea
583                 sTable.add(new MccEntry(539,"to",2));   //Tonga (Kingdom of)
584                 sTable.add(new MccEntry(540,"sb",2));   //Solomon Islands
585                 sTable.add(new MccEntry(541,"vu",2));   //Vanuatu (Republic of)
586                 sTable.add(new MccEntry(542,"fj",2));   //Fiji (Republic of)
587                 sTable.add(new MccEntry(543,"wf",2));   //Wallis and Futuna (Territoire franais d'outre-mer)
588                 sTable.add(new MccEntry(544,"as",2));   //American Samoa
589                 sTable.add(new MccEntry(545,"ki",2));   //Kiribati (Republic of)
590                 sTable.add(new MccEntry(546,"nc",2));   //New Caledonia (Territoire franais d'outre-mer)
591                 sTable.add(new MccEntry(547,"pf",2));   //French Polynesia (Territoire franais d'outre-mer)
592                 sTable.add(new MccEntry(548,"ck",2));   //Cook Islands
593                 sTable.add(new MccEntry(549,"ws",2));   //Samoa (Independent State of)
594                 sTable.add(new MccEntry(550,"fm",2));   //Micronesia (Federated States of)
595                 sTable.add(new MccEntry(551,"mh",2));   //Marshall Islands (Republic of the)
596                 sTable.add(new MccEntry(552,"pw",2));   //Palau (Republic of)
597                 sTable.add(new MccEntry(553,"tv",2));   //Tuvalu
598                 sTable.add(new MccEntry(555,"nu",2));   //Niue
599                 sTable.add(new MccEntry(602,"eg",2));   //Egypt (Arab Republic of)
600                 sTable.add(new MccEntry(603,"dz",2));   //Algeria (People's Democratic Republic of)
601                 sTable.add(new MccEntry(604,"ma",2));   //Morocco (Kingdom of)
602                 sTable.add(new MccEntry(605,"tn",2));   //Tunisia
603                 sTable.add(new MccEntry(606,"ly",2));   //Libya (Socialist People's Libyan Arab Jamahiriya)
604                 sTable.add(new MccEntry(607,"gm",2));   //Gambia (Republic of the)
605                 sTable.add(new MccEntry(608,"sn",2));   //Senegal (Republic of)
606                 sTable.add(new MccEntry(609,"mr",2));   //Mauritania (Islamic Republic of)
607                 sTable.add(new MccEntry(610,"ml",2));   //Mali (Republic of)
608                 sTable.add(new MccEntry(611,"gn",2));   //Guinea (Republic of)
609                 sTable.add(new MccEntry(612,"ci",2));   //Côte d'Ivoire (Republic of)
610                 sTable.add(new MccEntry(613,"bf",2));   //Burkina Faso
611                 sTable.add(new MccEntry(614,"ne",2));   //Niger (Republic of the)
612                 sTable.add(new MccEntry(615,"tg",2));   //Togolese Republic
613                 sTable.add(new MccEntry(616,"bj",2));   //Benin (Republic of)
614                 sTable.add(new MccEntry(617,"mu",2));   //Mauritius (Republic of)
615                 sTable.add(new MccEntry(618,"lr",2));   //Liberia (Republic of)
616                 sTable.add(new MccEntry(619,"sl",2));   //Sierra Leone
617                 sTable.add(new MccEntry(620,"gh",2));   //Ghana
618                 sTable.add(new MccEntry(621,"ng",2));   //Nigeria (Federal Republic of)
619                 sTable.add(new MccEntry(622,"td",2));   //Chad (Republic of)
620                 sTable.add(new MccEntry(623,"cf",2));   //Central African Republic
621                 sTable.add(new MccEntry(624,"cm",2));   //Cameroon (Republic of)
622                 sTable.add(new MccEntry(625,"cv",2));   //Cape Verde (Republic of)
623                 sTable.add(new MccEntry(626,"st",2));   //Sao Tome and Principe (Democratic Republic of)
624                 sTable.add(new MccEntry(627,"gq",2));   //Equatorial Guinea (Republic of)
625                 sTable.add(new MccEntry(628,"ga",2));   //Gabonese Republic
626                 sTable.add(new MccEntry(629,"cg",2));   //Congo (Republic of the)
627                 sTable.add(new MccEntry(630,"cd",2));   //Democratic Republic of the Congo
628                 sTable.add(new MccEntry(631,"ao",2));   //Angola (Republic of)
629                 sTable.add(new MccEntry(632,"gw",2));   //Guinea-Bissau (Republic of)
630                 sTable.add(new MccEntry(633,"sc",2));   //Seychelles (Republic of)
631                 sTable.add(new MccEntry(634,"sd",2));   //Sudan (Republic of the)
632                 sTable.add(new MccEntry(635,"rw",2));   //Rwanda (Republic of)
633                 sTable.add(new MccEntry(636,"et",2));   //Ethiopia (Federal Democratic Republic of)
634                 sTable.add(new MccEntry(637,"so",2));   //Somali Democratic Republic
635                 sTable.add(new MccEntry(638,"dj",2));   //Djibouti (Republic of)
636                 sTable.add(new MccEntry(639,"ke",2));   //Kenya (Republic of)
637                 sTable.add(new MccEntry(640,"tz",2));   //Tanzania (United Republic of)
638                 sTable.add(new MccEntry(641,"ug",2));   //Uganda (Republic of)
639                 sTable.add(new MccEntry(642,"bi",2));   //Burundi (Republic of)
640                 sTable.add(new MccEntry(643,"mz",2));   //Mozambique (Republic of)
641                 sTable.add(new MccEntry(645,"zm",2));   //Zambia (Republic of)
642                 sTable.add(new MccEntry(646,"mg",2));   //Madagascar (Republic of)
643                 sTable.add(new MccEntry(647,"re",2));   //Reunion (French Department of)
644                 sTable.add(new MccEntry(648,"zw",2));   //Zimbabwe (Republic of)
645                 sTable.add(new MccEntry(649,"na",2));   //Namibia (Republic of)
646                 sTable.add(new MccEntry(650,"mw",2));   //Malawi
647                 sTable.add(new MccEntry(651,"ls",2));   //Lesotho (Kingdom of)
648                 sTable.add(new MccEntry(652,"bw",2));   //Botswana (Republic of)
649                 sTable.add(new MccEntry(653,"sz",2));   //Swaziland (Kingdom of)
650                 sTable.add(new MccEntry(654,"km",2));   //Comoros (Union of the)
651                 sTable.add(new MccEntry(655,"za",2));   //South Africa (Republic of)
652                 sTable.add(new MccEntry(657,"er",2));   //Eritrea
653                 sTable.add(new MccEntry(658,"sh",2));   //Saint Helena, Ascension and Tristan da Cunha
654                 sTable.add(new MccEntry(659,"ss",2));   //South Sudan (Republic of)
655                 sTable.add(new MccEntry(702,"bz",2));   //Belize
656                 sTable.add(new MccEntry(704,"gt",2));   //Guatemala (Republic of)
657                 sTable.add(new MccEntry(706,"sv",2));   //El Salvador (Republic of)
658                 sTable.add(new MccEntry(708,"hn",3));   //Honduras (Republic of)
659                 sTable.add(new MccEntry(710,"ni",2));   //Nicaragua
660                 sTable.add(new MccEntry(712,"cr",2));   //Costa Rica
661                 sTable.add(new MccEntry(714,"pa",2));   //Panama (Republic of)
662                 sTable.add(new MccEntry(716,"pe",2));   //Peru
663                 sTable.add(new MccEntry(722,"ar",3));   //Argentine Republic
664                 sTable.add(new MccEntry(724,"br",2));   //Brazil (Federative Republic of)
665                 sTable.add(new MccEntry(730,"cl",2));   //Chile
666                 sTable.add(new MccEntry(732,"co",3));   //Colombia (Republic of)
667                 sTable.add(new MccEntry(734,"ve",2));   //Venezuela (Bolivarian Republic of)
668                 sTable.add(new MccEntry(736,"bo",2));   //Bolivia (Republic of)
669                 sTable.add(new MccEntry(738,"gy",2));   //Guyana
670                 sTable.add(new MccEntry(740,"ec",2));   //Ecuador
671                 sTable.add(new MccEntry(742,"gf",2));   //French Guiana (French Department of)
672                 sTable.add(new MccEntry(744,"py",2));   //Paraguay (Republic of)
673                 sTable.add(new MccEntry(746,"sr",2));   //Suriname (Republic of)
674                 sTable.add(new MccEntry(748,"uy",2));   //Uruguay (Eastern Republic of)
675                 sTable.add(new MccEntry(750,"fk",2));   //Falkland Islands (Malvinas)
676         //table.add(new MccEntry(901,"",2));    //"International Mobile, shared code"
677
678         Collections.sort(sTable);
679     }
680 }