• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ActivityManagerNative;
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.RemoteException;
25 import android.os.SystemProperties;
26 import android.provider.Settings;
27 import android.util.Log;
28 
29 import java.util.Arrays;
30 
31 /**
32  * The table below is built from two resources:
33  *
34  * 1) ITU "Mobile Network Code (MNC) for the international
35  *   identification plan for mobile terminals and mobile users"
36  *   which is available as an annex to the ITU operational bulletin
37  *   available here: http://www.itu.int/itu-t/bulletin/annex.html
38  *
39  * 2) The ISO 3166 country codes list, available here:
40  *    http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html
41  *
42  * This table was verified (28 Aug 2009) against
43  * http://en.wikipedia.org/wiki/List_of_mobile_country_codes with the
44  * only unresolved discrepancy being that this list has an extra entry
45  * (461) for China.
46  *
47  * TODO: Complete the mappings for timezones and language/locale codes.
48  *
49  * The actual table data used in the Java code is generated from the
50  * below Python code for efficiency.  The information is expected to
51  * be static, but if changes are required, the table in the python
52  * code can be modified and the trailing code run to re-generate the
53  * tables that are to be used by Java.
54 
55 mcc_table = [
56   (202, 'gr', 2, 'Greece'),
57   (204, 'nl', 2, 'Europe/Amsterdam', 'nl', 13, 'Netherlands (Kingdom of the)'),
58   (206, 'be', 2, 'Belgium'),
59   (208, 'fr', 2, 'Europe/Paris', 'fr', 'France'),
60   (212, 'mc', 2, 'Monaco (Principality of)'),
61   (213, 'ad', 2, 'Andorra (Principality of)'),
62   (214, 'es', 2, 'Europe/Madrid', 'es', 'Spain'),
63   (216, 'hu', 2, 'Hungary (Republic of)'),
64   (218, 'ba', 2, 'Bosnia and Herzegovina'),
65   (219, 'hr', 2, 'Croatia (Republic of)'),
66   (220, 'rs', 2, 'Serbia and Montenegro'),
67   (222, 'it', 2, 'Europe/Rome', 'it', 'Italy'),
68   (225, 'va', 2, 'Europe/Rome', 'it', 'Vatican City State'),
69   (226, 'ro', 2, 'Romania'),
70   (228, 'ch', 2, 'Europe/Zurich', 'de', 'Switzerland (Confederation of)'),
71   (230, 'cz', 2, 'Europe/Prague', 'cs', 13, 'Czech Republic'),
72   (231, 'sk', 2, 'Slovak Republic'),
73   (232, 'at', 2, 'Europe/Vienna', 'de', 13, 'Austria'),
74   (234, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'),
75   (235, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'),
76   (238, 'dk', 2, 'Denmark'),
77   (240, 'se', 2, 'Sweden'),
78   (242, 'no', 2, 'Norway'),
79   (244, 'fi', 2, 'Finland'),
80   (246, 'lt', 2, 'Lithuania (Republic of)'),
81   (247, 'lv', 2, 'Latvia (Republic of)'),
82   (248, 'ee', 2, 'Estonia (Republic of)'),
83   (250, 'ru', 2, 'Russian Federation'),
84   (255, 'ua', 2, 'Ukraine'),
85   (257, 'by', 2, 'Belarus (Republic of)'),
86   (259, 'md', 2, 'Moldova (Republic of)'),
87   (260, 'pl', 2, 'Europe/Warsaw', 'Poland (Republic of)'),
88   (262, 'de', 2, 'Europe/Berlin', 'de', 13, 'Germany (Federal Republic of)'),
89   (266, 'gi', 2, 'Gibraltar'),
90   (268, 'pt', 2, 'Portugal'),
91   (270, 'lu', 2, 'Luxembourg'),
92   (272, 'ie', 2, 'Europe/Dublin', 'en', 'Ireland'),
93   (274, 'is', 2, 'Iceland'),
94   (276, 'al', 2, 'Albania (Republic of)'),
95   (278, 'mt', 2, 'Malta'),
96   (280, 'cy', 2, 'Cyprus (Republic of)'),
97   (282, 'ge', 2, 'Georgia'),
98   (283, 'am', 2, 'Armenia (Republic of)'),
99   (284, 'bg', 2, 'Bulgaria (Republic of)'),
100   (286, 'tr', 2, 'Turkey'),
101   (288, 'fo', 2, 'Faroe Islands'),
102   (289, 'ge', 2, 'Abkhazia (Georgia)'),
103   (290, 'gl', 2, 'Greenland (Denmark)'),
104   (292, 'sm', 2, 'San Marino (Republic of)'),
105   (293, 'sl', 2, 'Slovenia (Republic of)'),
106   (294, 'mk', 2, 'The Former Yugoslav Republic of Macedonia'),
107   (295, 'li', 2, 'Liechtenstein (Principality of)'),
108   (297, 'me', 2, 'Montenegro (Republic of)'),
109   (302, 'ca', 2, '', '', 11, 'Canada'),
110   (308, 'pm', 2, 'Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)'),
111   (310, 'us', 3, '', 'en', 11, 'United States of America'),
112   (311, 'us', 3, '', 'en', 11, 'United States of America'),
113   (312, 'us', 3, '', 'en', 11, 'United States of America'),
114   (313, 'us', 3, '', 'en', 11, 'United States of America'),
115   (314, 'us', 3, '', 'en', 11, 'United States of America'),
116   (315, 'us', 3, '', 'en', 11, 'United States of America'),
117   (316, 'us', 3, '', 'en', 11, 'United States of America'),
118   (330, 'pr', 2, 'Puerto Rico'),
119   (332, 'vi', 2, 'United States Virgin Islands'),
120   (334, 'mx', 3, 'Mexico'),
121   (338, 'jm', 3, 'Jamaica'),
122   (340, 'gp', 2, 'Guadeloupe (French Department of)'),
123   (342, 'bb', 3, 'Barbados'),
124   (344, 'ag', 3, 'Antigua and Barbuda'),
125   (346, 'ky', 3, 'Cayman Islands'),
126   (348, 'vg', 3, 'British Virgin Islands'),
127   (350, 'bm', 2, 'Bermuda'),
128   (352, 'gd', 2, 'Grenada'),
129   (354, 'ms', 2, 'Montserrat'),
130   (356, 'kn', 2, 'Saint Kitts and Nevis'),
131   (358, 'lc', 2, 'Saint Lucia'),
132   (360, 'vc', 2, 'Saint Vincent and the Grenadines'),
133   (362, 'nl', 2, 'Netherlands Antilles'),
134   (363, 'aw', 2, 'Aruba'),
135   (364, 'bs', 2, 'Bahamas (Commonwealth of the)'),
136   (365, 'ai', 3, 'Anguilla'),
137   (366, 'dm', 2, 'Dominica (Commonwealth of)'),
138   (368, 'cu', 2, 'Cuba'),
139   (370, 'do', 2, 'Dominican Republic'),
140   (372, 'ht', 2, 'Haiti (Republic of)'),
141   (374, 'tt', 2, 'Trinidad and Tobago'),
142   (376, 'tc', 2, 'Turks and Caicos Islands'),
143   (400, 'az', 2, 'Azerbaijani Republic'),
144   (401, 'kz', 2, 'Kazakhstan (Republic of)'),
145   (402, 'bt', 2, 'Bhutan (Kingdom of)'),
146   (404, 'in', 2, 'India (Republic of)'),
147   (405, 'in', 2, 'India (Republic of)'),
148   (410, 'pk', 2, 'Pakistan (Islamic Republic of)'),
149   (412, 'af', 2, 'Afghanistan'),
150   (413, 'lk', 2, 'Sri Lanka (Democratic Socialist Republic of)'),
151   (414, 'mm', 2, 'Myanmar (Union of)'),
152   (415, 'lb', 2, 'Lebanon'),
153   (416, 'jo', 2, 'Jordan (Hashemite Kingdom of)'),
154   (417, 'sy', 2, 'Syrian Arab Republic'),
155   (418, 'iq', 2, 'Iraq (Republic of)'),
156   (419, 'kw', 2, 'Kuwait (State of)'),
157   (420, 'sa', 2, 'Saudi Arabia (Kingdom of)'),
158   (421, 'ye', 2, 'Yemen (Republic of)'),
159   (422, 'om', 2, 'Oman (Sultanate of)'),
160   (423, 'ps', 2, 'Palestine'),
161   (424, 'ae', 2, 'United Arab Emirates'),
162   (425, 'il', 2, 'Israel (State of)'),
163   (426, 'bh', 2, 'Bahrain (Kingdom of)'),
164   (427, 'qa', 2, 'Qatar (State of)'),
165   (428, 'mn', 2, 'Mongolia'),
166   (429, 'np', 2, 'Nepal'),
167   (430, 'ae', 2, 'United Arab Emirates'),
168   (431, 'ae', 2, 'United Arab Emirates'),
169   (432, 'ir', 2, 'Iran (Islamic Republic of)'),
170   (434, 'uz', 2, 'Uzbekistan (Republic of)'),
171   (436, 'tj', 2, 'Tajikistan (Republic of)'),
172   (437, 'kg', 2, 'Kyrgyz Republic'),
173   (438, 'tm', 2, 'Turkmenistan'),
174   (440, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'),
175   (441, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'),
176   (450, 'kr', 2, 'Korea (Republic of)'),
177   (452, 'vn', 2, 'Viet Nam (Socialist Republic of)'),
178   (454, 'hk', 2, '"Hong Kong, China"'),
179   (455, 'mo', 2, '"Macao, China"'),
180   (456, 'kh', 2, 'Cambodia (Kingdom of)'),
181   (457, 'la', 2, "Lao People's Democratic Republic"),
182   (460, 'cn', 2, "China (People's Republic of)"),
183   (461, 'cn', 2, "China (People's Republic of)"),
184   (466, 'tw', 2, "Taiwan (Republic of China)"),
185   (467, 'kp', 2, "Democratic People's Republic of Korea"),
186   (470, 'bd', 2, "Bangladesh (People's Republic of)"),
187   (472, 'mv', 2, 'Maldives (Republic of)'),
188   (502, 'my', 2, 'Malaysia'),
189   (505, 'au', 2, 'Australia/Sydney', 'en', 11, 'Australia'),
190   (510, 'id', 2, 'Indonesia (Republic of)'),
191   (514, 'tl', 2, 'Democratic Republic of Timor-Leste'),
192   (515, 'ph', 2, 'Philippines (Republic of the)'),
193   (520, 'th', 2, 'Thailand'),
194   (525, 'sg', 2, 'Singapore', 'en', 11, 'Singapore (Republic of)'),
195   (528, 'bn', 2, 'Brunei Darussalam'),
196   (530, 'nz', 2, 'Pacific/Auckland', 'en', 'New Zealand'),
197   (534, 'mp', 2, 'Northern Mariana Islands (Commonwealth of the)'),
198   (535, 'gu', 2, 'Guam'),
199   (536, 'nr', 2, 'Nauru (Republic of)'),
200   (537, 'pg', 2, 'Papua New Guinea'),
201   (539, 'to', 2, 'Tonga (Kingdom of)'),
202   (540, 'sb', 2, 'Solomon Islands'),
203   (541, 'vu', 2, 'Vanuatu (Republic of)'),
204   (542, 'fj', 2, 'Fiji (Republic of)'),
205   (543, 'wf', 2, "Wallis and Futuna (Territoire franais d'outre-mer)"),
206   (544, 'as', 2, 'American Samoa'),
207   (545, 'ki', 2, 'Kiribati (Republic of)'),
208   (546, 'nc', 2, "New Caledonia (Territoire franais d'outre-mer)"),
209   (547, 'pf', 2, "French Polynesia (Territoire franais d'outre-mer)"),
210   (548, 'ck', 2, 'Cook Islands'),
211   (549, 'ws', 2, 'Samoa (Independent State of)'),
212   (550, 'fm', 2, 'Micronesia (Federated States of)'),
213   (551, 'mh', 2, 'Marshall Islands (Republic of the)'),
214   (552, 'pw', 2, 'Palau (Republic of)'),
215   (602, 'eg', 2, 'Egypt (Arab Republic of)'),
216   (603, 'dz', 2, "Algeria (People's Democratic Republic of)"),
217   (604, 'ma', 2, 'Morocco (Kingdom of)'),
218   (605, 'tn', 2, 'Tunisia'),
219   (606, 'ly', 2, "Libya (Socialist People's Libyan Arab Jamahiriya)"),
220   (607, 'gm', 2, 'Gambia (Republic of the)'),
221   (608, 'sn', 2, 'Senegal (Republic of)'),
222   (609, 'mr', 2, 'Mauritania (Islamic Republic of)'),
223   (610, 'ml', 2, 'Mali (Republic of)'),
224   (611, 'gn', 2, 'Guinea (Republic of)'),
225   (612, 'ci', 2, "Cte d'Ivoire (Republic of)"),
226   (613, 'bf', 2, 'Burkina Faso'),
227   (614, 'ne', 2, 'Niger (Republic of the)'),
228   (615, 'tg', 2, 'Togolese Republic'),
229   (616, 'bj', 2, 'Benin (Republic of)'),
230   (617, 'mu', 2, 'Mauritius (Republic of)'),
231   (618, 'lr', 2, 'Liberia (Republic of)'),
232   (619, 'sl', 2, 'Sierra Leone'),
233   (620, 'gh', 2, 'Ghana'),
234   (621, 'ng', 2, 'Nigeria (Federal Republic of)'),
235   (622, 'td', 2, 'Chad (Republic of)'),
236   (623, 'cf', 2, 'Central African Republic'),
237   (624, 'cm', 2, 'Cameroon (Republic of)'),
238   (625, 'cv', 2, 'Cape Verde (Republic of)'),
239   (626, 'st', 2, 'Sao Tome and Principe (Democratic Republic of)'),
240   (627, 'gq', 2, 'Equatorial Guinea (Republic of)'),
241   (628, 'ga', 2, 'Gabonese Republic'),
242   (629, 'cg', 2, 'Congo (Republic of the)'),
243   (630, 'cg', 2, 'Democratic Republic of the Congo'),
244   (631, 'ao', 2, 'Angola (Republic of)'),
245   (632, 'gw', 2, 'Guinea-Bissau (Republic of)'),
246   (633, 'sc', 2, 'Seychelles (Republic of)'),
247   (634, 'sd', 2, 'Sudan (Republic of the)'),
248   (635, 'rw', 2, 'Rwanda (Republic of)'),
249   (636, 'et', 2, 'Ethiopia (Federal Democratic Republic of)'),
250   (637, 'so', 2, 'Somali Democratic Republic'),
251   (638, 'dj', 2, 'Djibouti (Republic of)'),
252   (639, 'ke', 2, 'Kenya (Republic of)'),
253   (640, 'tz', 2, 'Tanzania (United Republic of)'),
254   (641, 'ug', 2, 'Uganda (Republic of)'),
255   (642, 'bi', 2, 'Burundi (Republic of)'),
256   (643, 'mz', 2, 'Mozambique (Republic of)'),
257   (645, 'zm', 2, 'Zambia (Republic of)'),
258   (646, 'mg', 2, 'Madagascar (Republic of)'),
259   (647, 're', 2, 'Reunion (French Department of)'),
260   (648, 'zw', 2, 'Zimbabwe (Republic of)'),
261   (649, 'na', 2, 'Namibia (Republic of)'),
262   (650, 'mw', 2, 'Malawi'),
263   (651, 'ls', 2, 'Lesotho (Kingdom of)'),
264   (652, 'bw', 2, 'Botswana (Republic of)'),
265   (653, 'sz', 2, 'Swaziland (Kingdom of)'),
266   (654, 'km', 2, 'Comoros (Union of the)'),
267   (655, 'za', 2, 'Africa/Johannesburg', 'en', 'South Africa (Republic of)'),
268   (657, 'er', 2, 'Eritrea'),
269   (702, 'bz', 2, 'Belize'),
270   (704, 'gt', 2, 'Guatemala (Republic of)'),
271   (706, 'sv', 2, 'El Salvador (Republic of)'),
272   (708, 'hn', 3, 'Honduras (Republic of)'),
273   (710, 'ni', 2, 'Nicaragua'),
274   (712, 'cr', 2, 'Costa Rica'),
275   (714, 'pa', 2, 'Panama (Republic of)'),
276   (716, 'pe', 2, 'Peru'),
277   (722, 'ar', 3, 'Argentine Republic'),
278   (724, 'br', 2, 'Brazil (Federative Republic of)'),
279   (730, 'cl', 2, 'Chile'),
280   (732, 'co', 3, 'Colombia (Republic of)'),
281   (734, 've', 2, 'Venezuela (Bolivarian Republic of)'),
282   (736, 'bo', 2, 'Bolivia (Republic of)'),
283   (738, 'gy', 2, 'Guyana'),
284   (740, 'ec', 2, 'Ecuador'),
285   (742, 'gf', 2, 'French Guiana (French Department of)'),
286   (744, 'py', 2, 'Paraguay (Republic of)'),
287   (746, 'sr', 2, 'Suriname (Republic of)'),
288   (748, 'uy', 2, 'Uruguay (Eastern Republic of)'),
289   (750, 'fk', 2, 'Falkland Islands (Malvinas)')]
290 
291 get_mcc = lambda elt: elt[0]
292 get_iso = lambda elt: elt[1]
293 get_sd = lambda elt: elt[2]
294 get_tz = lambda elt: len(elt) > 4 and elt[3] or ''
295 get_lang = lambda elt: len(elt) > 5 and elt[4] or ''
296 get_wifi = lambda elt: len(elt) > 6 and elt[5] or 0
297 
298 mcc_codes = ['0x%04x' % get_mcc(elt) for elt in mcc_table]
299 tz_set = sorted(x for x in set(get_tz(elt) for elt in mcc_table))
300 lang_set = sorted(x for x in set(get_lang(elt) for elt in mcc_table))
301 
302 def mk_ind_code(elt):
303   iso = get_iso(elt)
304   iso_code = ((ord(iso[0]) << 8) | ord(iso[1])) & 0xFFFF # 16 bits
305   wifi = get_wifi(elt) & 0x000F                          #  4 bits
306   sd = get_sd(elt) & 0x0003                              #  2 bits
307   tz_ind = tz_set.index(get_tz(elt)) & 0x001F            #  5 bits
308   lang_ind = lang_set.index(get_lang(elt)) & 0x000F      #  4 bits
309   return (iso_code << 16) | (wifi << 11) | (sd << 9) | (tz_ind << 4) | lang_ind
310 
311 ind_codes = ['0x%08x' % mk_ind_code(elt) for elt in mcc_table]
312 
313 def fmt_list(title, l, batch_sz):
314   sl = []
315   for i in range(len(l) / batch_sz + (len(l) % batch_sz and 1 or 0)):
316     j = i * batch_sz
317     sl.append((' ' * 8) + ', '.join(l[j:j + batch_sz]))
318   return '    private static final %s = {\n' % title + ',\n'.join(sl) + '\n    };\n'
319 
320 def do_autogen_comment(extra_desc=[]):
321   print '    /' + '**\n    * AUTO GENERATED (by the Python code above)'
322   for line in extra_desc:
323     print '    * %s' % line
324   print '    *' + '/'
325 
326 do_autogen_comment()
327 print fmt_list('String[] TZ_STRINGS', ['"%s"' % x for x in tz_set], 1)
328 do_autogen_comment()
329 print fmt_list('String[] LANG_STRINGS', ['"%s"' % x for x in lang_set], 10)
330 do_autogen_comment(['This table is a list of MCC codes.  The index in this table',
331                     'of a given MCC code is the index of extra information about',
332                     'that MCC in the IND_CODES table.'])
333 print fmt_list('short[] MCC_CODES', mcc_codes, 10)
334 do_autogen_comment(['The values in this table are broken down as follows (msb to lsb):',
335                     '    iso country code 16 bits',
336                     '    (unused)          1 bit',
337                     '    wifi channel      4 bits',
338                     '    smalled digit     2 bits',
339                     '    default timezone  5 bits',
340                     '    default language  4 bits'])
341 print fmt_list('int[] IND_CODES', ind_codes, 6)
342 
343 def parse_ind_code(ind):
344   mcc = eval(mcc_codes[ind])
345   code = eval(ind_codes[ind])
346   iso_lsb = int((code >> 16) & 0x00FF)
347   iso_msb = int((code >> 24) & 0x00FF)
348   iso = '%s%s' % (chr(iso_msb), chr(iso_lsb))
349   wifi = int((code >> 11) & 0x000F)
350   sd = int((code >> 9) & 0x0003)
351   tz_ind = (code >> 4) & 0x001F
352   lang_ind = (code >> 0) & 0x000F
353   return (mcc, iso, sd, tz_set[tz_ind], lang_set[lang_ind], wifi)
354 
355 fmt_str = 'mcc = %s, iso = %s, sd = %s, tz = %s, lang = %s, wifi = %s'
356 orig_table = [fmt_str % (get_mcc(elt), get_iso(elt), get_sd(elt),
357                          get_tz(elt), get_lang(elt), get_wifi(elt))
358               for elt in mcc_table]
359 derived_table = [fmt_str % parse_ind_code(i) for i in range(len(ind_codes))]
360 for i in range(len(orig_table)):
361   if orig_table[i] == derived_table[i]: continue
362   print 'MISMATCH ERROR : ', orig_table[i], " != ", derived_table[i]
363 
364 */
365 
366 /**
367  * Mobile Country Code
368  *
369  * {@hide}
370  */
371 public final class MccTable
372 {
373     /**
374     * AUTO GENERATED (by the Python code above)
375     */
376     private static final String[] TZ_STRINGS = {
377         "",
378         "Africa/Johannesburg",
379         "Asia/Tokyo",
380         "Australia/Sydney",
381         "Europe/Amsterdam",
382         "Europe/Berlin",
383         "Europe/Dublin",
384         "Europe/London",
385         "Europe/Madrid",
386         "Europe/Paris",
387         "Europe/Prague",
388         "Europe/Rome",
389         "Europe/Vienna",
390         "Europe/Warsaw",
391         "Europe/Zurich",
392         "Pacific/Auckland",
393         "Singapore"
394     };
395 
396     /**
397     * AUTO GENERATED (by the Python code above)
398     */
399     private static final String[] LANG_STRINGS = {
400         "", "cs", "de", "en", "es", "fr", "it", "ja", "nl"
401     };
402 
403     /**
404     * AUTO GENERATED (by the Python code above)
405     * This table is a list of MCC codes.  The index in this table
406     * of a given MCC code is the index of extra information about
407     * that MCC in the IND_CODES table.
408     */
409     private static final short[] MCC_CODES = {
410         0x00ca, 0x00cc, 0x00ce, 0x00d0, 0x00d4, 0x00d5, 0x00d6, 0x00d8, 0x00da, 0x00db,
411         0x00dc, 0x00de, 0x00e1, 0x00e2, 0x00e4, 0x00e6, 0x00e7, 0x00e8, 0x00ea, 0x00eb,
412         0x00ee, 0x00f0, 0x00f2, 0x00f4, 0x00f6, 0x00f7, 0x00f8, 0x00fa, 0x00ff, 0x0101,
413         0x0103, 0x0104, 0x0106, 0x010a, 0x010c, 0x010e, 0x0110, 0x0112, 0x0114, 0x0116,
414         0x0118, 0x011a, 0x011b, 0x011c, 0x011e, 0x0120, 0x0121, 0x0122, 0x0124, 0x0125,
415         0x0126, 0x0127, 0x0129, 0x012e, 0x0134, 0x0136, 0x0137, 0x0138, 0x0139, 0x013a,
416         0x013b, 0x013c, 0x014a, 0x014c, 0x014e, 0x0152, 0x0154, 0x0156, 0x0158, 0x015a,
417         0x015c, 0x015e, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016a, 0x016b, 0x016c,
418         0x016d, 0x016e, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0190, 0x0191, 0x0192,
419         0x0194, 0x0195, 0x019a, 0x019c, 0x019d, 0x019e, 0x019f, 0x01a0, 0x01a1, 0x01a2,
420         0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac,
421         0x01ad, 0x01ae, 0x01af, 0x01b0, 0x01b2, 0x01b4, 0x01b5, 0x01b6, 0x01b8, 0x01b9,
422         0x01c2, 0x01c4, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01cc, 0x01cd, 0x01d2, 0x01d3,
423         0x01d6, 0x01d8, 0x01f6, 0x01f9, 0x01fe, 0x0202, 0x0203, 0x0208, 0x020d, 0x0210,
424         0x0212, 0x0216, 0x0217, 0x0218, 0x0219, 0x021b, 0x021c, 0x021d, 0x021e, 0x021f,
425         0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x025a,
426         0x025b, 0x025c, 0x025d, 0x025e, 0x025f, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264,
427         0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e,
428         0x026f, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278,
429         0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, 0x0280, 0x0281, 0x0282,
430         0x0283, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d,
431         0x028e, 0x028f, 0x0291, 0x02be, 0x02c0, 0x02c2, 0x02c4, 0x02c6, 0x02c8, 0x02ca,
432         0x02cc, 0x02d2, 0x02d4, 0x02da, 0x02dc, 0x02de, 0x02e0, 0x02e2, 0x02e4, 0x02e6,
433         0x02e8, 0x02ea, 0x02ec, 0x02ee
434     };
435 
436     /**
437     * AUTO GENERATED (by the Python code above)
438     * The values in this table are broken down as follows (msb to lsb):
439     *     iso country code 16 bits
440     *     (unused)          1 bit
441     *     wifi channel      4 bits
442     *     smalled digit     2 bits
443     *     default timezone  5 bits
444     *     default language  4 bits
445     */
446     private static final int[] IND_CODES = {
447         0x67720400, 0x6e6c6c48, 0x62650400, 0x66720495, 0x6d630400, 0x61640400,
448         0x65730484, 0x68750400, 0x62610400, 0x68720400, 0x72730400, 0x697404b6,
449         0x766104b6, 0x726f0400, 0x636804e2, 0x637a6ca1, 0x736b0400, 0x61746cc2,
450         0x67626c73, 0x67626c73, 0x646b0400, 0x73650400, 0x6e6f0400, 0x66690400,
451         0x6c740400, 0x6c760400, 0x65650400, 0x72750400, 0x75610400, 0x62790400,
452         0x6d640400, 0x706c04d0, 0x64656c52, 0x67690400, 0x70740400, 0x6c750400,
453         0x69650463, 0x69730400, 0x616c0400, 0x6d740400, 0x63790400, 0x67650400,
454         0x616d0400, 0x62670400, 0x74720400, 0x666f0400, 0x67650400, 0x676c0400,
455         0x736d0400, 0x736c0400, 0x6d6b0400, 0x6c690400, 0x6d650400, 0x63615c00,
456         0x706d0400, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03,
457         0x75735e03, 0x75735e03, 0x70720400, 0x76690400, 0x6d780600, 0x6a6d0600,
458         0x67700400, 0x62620600, 0x61670600, 0x6b790600, 0x76670600, 0x626d0400,
459         0x67640400, 0x6d730400, 0x6b6e0400, 0x6c630400, 0x76630400, 0x6e6c0400,
460         0x61770400, 0x62730400, 0x61690600, 0x646d0400, 0x63750400, 0x646f0400,
461         0x68740400, 0x74740400, 0x74630400, 0x617a0400, 0x6b7a0400, 0x62740400,
462         0x696e0400, 0x696e0400, 0x706b0400, 0x61660400, 0x6c6b0400, 0x6d6d0400,
463         0x6c620400, 0x6a6f0400, 0x73790400, 0x69710400, 0x6b770400, 0x73610400,
464         0x79650400, 0x6f6d0400, 0x70730400, 0x61650400, 0x696c0400, 0x62680400,
465         0x71610400, 0x6d6e0400, 0x6e700400, 0x61650400, 0x61650400, 0x69720400,
466         0x757a0400, 0x746a0400, 0x6b670400, 0x746d0400, 0x6a707427, 0x6a707427,
467         0x6b720400, 0x766e0400, 0x686b0400, 0x6d6f0400, 0x6b680400, 0x6c610400,
468         0x636e0400, 0x636e0400, 0x74770400, 0x6b700400, 0x62640400, 0x6d760400,
469         0x6d790400, 0x61755c33, 0x69640400, 0x746c0400, 0x70680400, 0x74680400,
470         0x73675d03, 0x626e0400, 0x6e7a04f3, 0x6d700400, 0x67750400, 0x6e720400,
471         0x70670400, 0x746f0400, 0x73620400, 0x76750400, 0x666a0400, 0x77660400,
472         0x61730400, 0x6b690400, 0x6e630400, 0x70660400, 0x636b0400, 0x77730400,
473         0x666d0400, 0x6d680400, 0x70770400, 0x65670400, 0x647a0400, 0x6d610400,
474         0x746e0400, 0x6c790400, 0x676d0400, 0x736e0400, 0x6d720400, 0x6d6c0400,
475         0x676e0400, 0x63690400, 0x62660400, 0x6e650400, 0x74670400, 0x626a0400,
476         0x6d750400, 0x6c720400, 0x736c0400, 0x67680400, 0x6e670400, 0x74640400,
477         0x63660400, 0x636d0400, 0x63760400, 0x73740400, 0x67710400, 0x67610400,
478         0x63670400, 0x63670400, 0x616f0400, 0x67770400, 0x73630400, 0x73640400,
479         0x72770400, 0x65740400, 0x736f0400, 0x646a0400, 0x6b650400, 0x747a0400,
480         0x75670400, 0x62690400, 0x6d7a0400, 0x7a6d0400, 0x6d670400, 0x72650400,
481         0x7a770400, 0x6e610400, 0x6d770400, 0x6c730400, 0x62770400, 0x737a0400,
482         0x6b6d0400, 0x7a610413, 0x65720400, 0x627a0400, 0x67740400, 0x73760400,
483         0x686e0600, 0x6e690400, 0x63720400, 0x70610400, 0x70650400, 0x61720600,
484         0x62720400, 0x636c0400, 0x636f0600, 0x76650400, 0x626f0400, 0x67790400,
485         0x65630400, 0x67660400, 0x70790400, 0x73720400, 0x75790400, 0x666b0400
486     };
487 
488     static final String LOG_TAG = "MccTable";
489 
490     /**
491      * Given a Mobile Country Code, returns a default time zone ID
492      * if available.  Returns null if unavailable.
493      */
defaultTimeZoneForMcc(int mcc)494     public static String defaultTimeZoneForMcc(int mcc) {
495         int index = Arrays.binarySearch(MCC_CODES, (short)mcc);
496         if (index < 0) {
497             return null;
498         }
499         int indCode = IND_CODES[index];
500         int tzInd = (indCode >>> 4) & 0x001F;
501         String tz = TZ_STRINGS[tzInd];
502         if (tz == "") {
503             return null;
504         }
505         return tz;
506     }
507 
508     /**
509      * Given a Mobile Country Code, returns an ISO two-character
510      * country code if available.  Returns "" if unavailable.
511      */
countryCodeForMcc(int mcc)512     public static String countryCodeForMcc(int mcc) {
513         int index = Arrays.binarySearch(MCC_CODES, (short)mcc);
514         if (index < 0) {
515             return "";
516         }
517         int indCode = IND_CODES[index];
518         byte[] iso = {(byte)((indCode >>> 24) & 0x00FF), (byte)((indCode >>> 16) & 0x00FF)};
519         return new String(iso);
520     }
521 
522     /**
523      * Given a GSM Mobile Country Code, returns an ISO 2-3 character
524      * language code if available.  Returns null if unavailable.
525      */
defaultLanguageForMcc(int mcc)526     public static String defaultLanguageForMcc(int mcc) {
527         int index = Arrays.binarySearch(MCC_CODES, (short)mcc);
528         if (index < 0) {
529             return null;
530         }
531         int indCode = IND_CODES[index];
532         int langInd = indCode & 0x000F;
533         String lang = LANG_STRINGS[langInd];
534         if (lang == "") {
535             return null;
536         }
537         return lang;
538     }
539 
540     /**
541      * Given a GSM Mobile Country Code, returns the corresponding
542      * smallest number of digits field.  Returns 2 if unavailable.
543      */
smallestDigitsMccForMnc(int mcc)544     public static int smallestDigitsMccForMnc(int mcc) {
545         int index = Arrays.binarySearch(MCC_CODES, (short)mcc);
546         if (index < 0) {
547             return 2;
548         }
549         int indCode = IND_CODES[index];
550         int smDig = (indCode >>> 9) & 0x0003;
551         return smDig;
552     }
553 
554     /**
555      * Given a GSM Mobile Country Code, returns the number of wifi
556      * channels allowed in that country.  Returns 0 if unavailable.
557      */
wifiChannelsForMcc(int mcc)558     public static int wifiChannelsForMcc(int mcc) {
559         int index = Arrays.binarySearch(MCC_CODES, (short)mcc);
560         if (index < 0) {
561             return 0;
562         }
563         int indCode = IND_CODES[index];
564         int wifi = (indCode >>> 11) & 0x000F;
565         return wifi;
566     }
567 
568     /**
569      * Updates MCC and MNC device configuration information for application retrieving
570      * correct version of resources.  If either MCC or MNC is 0, they will be ignored (not set).
571      * @param phone PhoneBae to act on.
572      * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
573      */
updateMccMncConfiguration(PhoneBase phone, String mccmnc)574     public static void updateMccMncConfiguration(PhoneBase phone, String mccmnc) {
575         int mcc, mnc;
576 
577         try {
578             mcc = Integer.parseInt(mccmnc.substring(0,3));
579             mnc = Integer.parseInt(mccmnc.substring(3));
580         } catch (NumberFormatException e) {
581             Log.e(LOG_TAG, "Error parsing IMSI");
582             return;
583         }
584 
585         Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
586 
587         if (mcc != 0) {
588             setTimezoneFromMccIfNeeded(phone, mcc);
589             setLocaleFromMccIfNeeded(phone, mcc);
590             setWifiChannelsFromMccIfNeeded(phone, mcc);
591         }
592         try {
593             Configuration config = ActivityManagerNative.getDefault().getConfiguration();
594             if (mcc != 0) {
595                 config.mcc = mcc;
596             }
597             if (mnc != 0) {
598                 config.mnc = mnc;
599             }
600             ActivityManagerNative.getDefault().updateConfiguration(config);
601         } catch (RemoteException e) {
602             Log.e(LOG_TAG, "Can't update configuration", e);
603         }
604     }
605 
606     /**
607      * If the timezone is not already set, set it based on the MCC of the SIM.
608      * @param phone PhoneBase to act on (get context from).
609      * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
610      */
setTimezoneFromMccIfNeeded(PhoneBase phone, int mcc)611     private static void setTimezoneFromMccIfNeeded(PhoneBase phone, int mcc) {
612         String timezone = SystemProperties.get(ServiceStateTracker.TIMEZONE_PROPERTY);
613         if (timezone == null || timezone.length() == 0) {
614             String zoneId = defaultTimeZoneForMcc(mcc);
615             if (zoneId != null && zoneId.length() > 0) {
616                 Context context = phone.getContext();
617                 // Set time zone based on MCC
618                 AlarmManager alarm =
619                         (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
620                 alarm.setTimeZone(zoneId);
621                 Log.d(LOG_TAG, "timezone set to "+zoneId);
622             }
623         }
624     }
625 
626     /**
627      * If the locale is not already set, set it based on the MCC of the SIM.
628      * @param phone PhoneBase to act on.
629      * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
630      */
setLocaleFromMccIfNeeded(PhoneBase phone, int mcc)631     private static void setLocaleFromMccIfNeeded(PhoneBase phone, int mcc) {
632         String language = MccTable.defaultLanguageForMcc(mcc);
633         String country = MccTable.countryCodeForMcc(mcc);
634 
635         Log.d(LOG_TAG, "locale set to "+language+"_"+country);
636         phone.setSystemLocale(language, country);
637     }
638 
639     /**
640      * If the number of allowed wifi channels has not been set, set it based on
641      * the MCC of the SIM.
642      * @param phone PhoneBase to act on (get context from).
643      * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
644      */
setWifiChannelsFromMccIfNeeded(PhoneBase phone, int mcc)645     private static void setWifiChannelsFromMccIfNeeded(PhoneBase phone, int mcc) {
646         int wifiChannels = MccTable.wifiChannelsForMcc(mcc);
647         if (wifiChannels != 0) {
648             Context context = phone.getContext();
649             // only set to this default if the user hasn't manually set it
650             try {
651                 Settings.Secure.getInt(context.getContentResolver(),
652                         Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
653             } catch (Settings.SettingNotFoundException e) {
654                 Log.d(LOG_TAG, "WIFI_NUM_ALLOWED_CHANNESL set to " + wifiChannels);
655                 WifiManager wM = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
656                 // don't persist
657                 wM.setNumAllowedChannels(wifiChannels, false);
658             }
659         }
660     }
661 }
662