1 /* 2 * Copyright (C) 2014 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 java.util.ArrayList; 20 import java.util.HashMap; 21 22 import android.content.Context; 23 import android.os.Build; 24 import android.os.PersistableBundle; 25 import android.text.TextUtils; 26 import android.database.Cursor; 27 import android.database.SQLException; 28 import android.telephony.CarrierConfigManager; 29 import android.telephony.PhoneNumberUtils; 30 import android.telephony.TelephonyManager; 31 import android.telephony.Rlog; 32 33 import com.android.internal.telephony.HbpcdLookup.MccIdd; 34 import com.android.internal.telephony.HbpcdLookup.MccLookup; 35 36 37 /** 38 * This class implements handle the MO SMS target address before sending. 39 * This is special for VZW requirement. Follow the specifications of assisted dialing 40 * of MO SMS while traveling on VZW CDMA, international CDMA or GSM markets. 41 * {@hide} 42 */ 43 public class SmsNumberUtils { 44 private static final String TAG = "SmsNumberUtils"; 45 private static final boolean DBG = Build.IS_DEBUGGABLE; 46 47 private static final String PLUS_SIGN = "+"; 48 49 private static final int NANP_SHORT_LENGTH = 7; 50 private static final int NANP_MEDIUM_LENGTH = 10; 51 private static final int NANP_LONG_LENGTH = 11; 52 53 private static final int NANP_CC = 1; 54 private static final String NANP_NDD = "1"; 55 private static final String NANP_IDD = "011"; 56 57 private static final int MIN_COUNTRY_AREA_LOCAL_LENGTH = 10; 58 59 private static final int GSM_UMTS_NETWORK = 0; 60 private static final int CDMA_HOME_NETWORK = 1; 61 private static final int CDMA_ROAMING_NETWORK = 2; 62 63 private static final int NP_NONE = 0; 64 private static final int NP_NANP_BEGIN = 1; 65 66 /* <Phone Number>, <NXX>-<XXXX> N[2-9] */ 67 private static final int NP_NANP_LOCAL = NP_NANP_BEGIN; 68 69 /* <Area_code>-<Phone Number>, <NXX>-<NXX>-<XXXX> N[2-9] */ 70 private static final int NP_NANP_AREA_LOCAL = NP_NANP_BEGIN + 1; 71 72 /* <1>-<Area_code>-<Phone Number>, 1-<NXX>-<NXX>-<XXXX> N[2-9] */ 73 private static final int NP_NANP_NDD_AREA_LOCAL = NP_NANP_BEGIN + 2; 74 75 /* <+><U.S.Country_code><Area_code><Phone Number>, +1-<NXX>-<NXX>-<XXXX> N[2-9] */ 76 private static final int NP_NANP_NBPCD_CC_AREA_LOCAL = NP_NANP_BEGIN + 3; 77 78 /* <Local_IDD><Country_code><Area_code><Phone Number>, 001-1-<NXX>-<NXX>-<XXXX> N[2-9] */ 79 private static final int NP_NANP_LOCALIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 4; 80 81 /* <+><Home_IDD><Country_code><Area_code><Phone Number>, +011-1-<NXX>-<NXX>-<XXXX> N[2-9] */ 82 private static final int NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 5; 83 84 private static final int NP_INTERNATIONAL_BEGIN = 100; 85 /* <+>-<Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, +011-86-25-86281234 */ 86 private static final int NP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN; 87 88 /* <Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, 011-86-25-86281234 */ 89 private static final int NP_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 1; 90 91 /* <NBPCD>-<Country_code>-<Area_code>-<Phone Number>, +1-86-25-86281234 */ 92 private static final int NP_NBPCD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 2; 93 94 /* <Local_IDD>-<Country_code>-<Area_code>-<Phone Number>, 00-86-25-86281234 */ 95 private static final int NP_LOCALIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 3; 96 97 /* <Country_code>-<Area_code>-<Phone Number>, 86-25-86281234*/ 98 private static final int NP_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 4; 99 100 private static int[] ALL_COUNTRY_CODES = null; 101 private static int MAX_COUNTRY_CODES_LENGTH; 102 private static HashMap<String, ArrayList<String>> IDDS_MAPS = 103 new HashMap<String, ArrayList<String>>(); 104 105 private static class NumberEntry { 106 public String number; 107 public String IDD; 108 public int countryCode; NumberEntry(String number)109 public NumberEntry(String number) { 110 this.number = number; 111 } 112 } 113 114 /* Breaks the given number down and formats it according to the rules 115 * for different number plans and different network. 116 * 117 * @param number destination number which need to be format 118 * @param activeMcc current network's mcc 119 * @param networkType current network type 120 * 121 * @return the number after formatting. 122 */ formatNumber(Context context, String number, String activeMcc, int networkType)123 private static String formatNumber(Context context, String number, 124 String activeMcc, 125 int networkType) { 126 if (number == null ) { 127 throw new IllegalArgumentException("number is null"); 128 } 129 130 if (activeMcc == null || activeMcc.trim().length() == 0) { 131 throw new IllegalArgumentException("activeMcc is null or empty!"); 132 } 133 134 String networkPortionNumber = PhoneNumberUtils.extractNetworkPortion(number); 135 if (networkPortionNumber == null || networkPortionNumber.length() == 0) { 136 throw new IllegalArgumentException("Number is invalid!"); 137 } 138 139 NumberEntry numberEntry = new NumberEntry(networkPortionNumber); 140 ArrayList<String> allIDDs = getAllIDDs(context, activeMcc); 141 142 // First check whether the number is a NANP number. 143 int nanpState = checkNANP(numberEntry, allIDDs); 144 if (DBG) Rlog.d(TAG, "NANP type: " + getNumberPlanType(nanpState)); 145 146 if ((nanpState == NP_NANP_LOCAL) 147 || (nanpState == NP_NANP_AREA_LOCAL) 148 || (nanpState == NP_NANP_NDD_AREA_LOCAL)) { 149 return networkPortionNumber; 150 } else if (nanpState == NP_NANP_NBPCD_CC_AREA_LOCAL) { 151 if (networkType == CDMA_HOME_NETWORK 152 || networkType == CDMA_ROAMING_NETWORK) { 153 // Remove "+" 154 return networkPortionNumber.substring(1); 155 } else { 156 return networkPortionNumber; 157 } 158 } else if (nanpState == NP_NANP_LOCALIDD_CC_AREA_LOCAL) { 159 if (networkType == CDMA_HOME_NETWORK) { 160 return networkPortionNumber; 161 } else if (networkType == GSM_UMTS_NETWORK) { 162 // Remove the local IDD and replace with "+" 163 int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; 164 return PLUS_SIGN + networkPortionNumber.substring(iddLength); 165 } else if (networkType == CDMA_ROAMING_NETWORK) { 166 // Remove the local IDD 167 int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; 168 return networkPortionNumber.substring(iddLength); 169 } 170 } 171 172 int internationalState = checkInternationalNumberPlan(context, numberEntry, allIDDs, 173 NANP_IDD); 174 if (DBG) Rlog.d(TAG, "International type: " + getNumberPlanType(internationalState)); 175 String returnNumber = null; 176 177 switch (internationalState) { 178 case NP_NBPCD_HOMEIDD_CC_AREA_LOCAL: 179 if (networkType == GSM_UMTS_NETWORK) { 180 // Remove "+" 181 returnNumber = networkPortionNumber.substring(1); 182 } 183 break; 184 185 case NP_NBPCD_CC_AREA_LOCAL: 186 // Replace "+" with "011" 187 returnNumber = NANP_IDD + networkPortionNumber.substring(1); 188 break; 189 190 case NP_LOCALIDD_CC_AREA_LOCAL: 191 if (networkType == GSM_UMTS_NETWORK || networkType == CDMA_ROAMING_NETWORK) { 192 int iddLength = numberEntry.IDD != null ? numberEntry.IDD.length() : 0; 193 // Replace <Local IDD> to <Home IDD>("011") 194 returnNumber = NANP_IDD + networkPortionNumber.substring(iddLength); 195 } 196 break; 197 198 case NP_CC_AREA_LOCAL: 199 int countryCode = numberEntry.countryCode; 200 201 if (!inExceptionListForNpCcAreaLocal(numberEntry) 202 && networkPortionNumber.length() >= 11 && countryCode != NANP_CC) { 203 // Add "011" 204 returnNumber = NANP_IDD + networkPortionNumber; 205 } 206 break; 207 208 case NP_HOMEIDD_CC_AREA_LOCAL: 209 returnNumber = networkPortionNumber; 210 break; 211 212 default: 213 // Replace "+" with 011 in CDMA network if the number's country 214 // code is not in the HbpcdLookup database. 215 if (networkPortionNumber.startsWith(PLUS_SIGN) 216 && (networkType == CDMA_HOME_NETWORK || networkType == CDMA_ROAMING_NETWORK)) { 217 if (networkPortionNumber.startsWith(PLUS_SIGN + NANP_IDD)) { 218 // Only remove "+" 219 returnNumber = networkPortionNumber.substring(1); 220 } else { 221 // Replace "+" with "011" 222 returnNumber = NANP_IDD + networkPortionNumber.substring(1); 223 } 224 } 225 } 226 227 if (returnNumber == null) { 228 returnNumber = networkPortionNumber; 229 } 230 return returnNumber; 231 } 232 233 /* Query International direct dialing from HbpcdLookup.db 234 * for specified country code 235 * 236 * @param mcc current network's country code 237 * 238 * @return the IDD array list. 239 */ getAllIDDs(Context context, String mcc)240 private static ArrayList<String> getAllIDDs(Context context, String mcc) { 241 ArrayList<String> allIDDs = IDDS_MAPS.get(mcc); 242 if (allIDDs != null) { 243 return allIDDs; 244 } else { 245 allIDDs = new ArrayList<String>(); 246 } 247 248 String projection[] = {MccIdd.IDD, MccIdd.MCC}; 249 String where = null; 250 251 // if mcc is null : return all rows 252 // if mcc is empty-string : return those rows whose mcc is emptry-string 253 String[] selectionArgs = null; 254 if (mcc != null) { 255 where = MccIdd.MCC + "=?"; 256 selectionArgs = new String[] {mcc}; 257 } 258 259 Cursor cursor = null; 260 try { 261 cursor = context.getContentResolver().query(MccIdd.CONTENT_URI, projection, 262 where, selectionArgs, null); 263 if (cursor.getCount() > 0) { 264 while (cursor.moveToNext()) { 265 String idd = cursor.getString(0); 266 if (!allIDDs.contains(idd)) { 267 allIDDs.add(idd); 268 } 269 } 270 } 271 } catch (SQLException e) { 272 Rlog.e(TAG, "Can't access HbpcdLookup database", e); 273 } finally { 274 if (cursor != null) { 275 cursor.close(); 276 } 277 } 278 279 IDDS_MAPS.put(mcc, allIDDs); 280 281 if (DBG) Rlog.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs); 282 return allIDDs; 283 } 284 285 286 /* Verify if the the destination number is a NANP number 287 * 288 * @param numberEntry including number and IDD array 289 * @param allIDDs the IDD array list of the current network's country code 290 * 291 * @return the number plan type related NANP 292 */ checkNANP(NumberEntry numberEntry, ArrayList<String> allIDDs)293 private static int checkNANP(NumberEntry numberEntry, ArrayList<String> allIDDs) { 294 boolean isNANP = false; 295 String number = numberEntry.number; 296 297 if (number.length() == NANP_SHORT_LENGTH) { 298 // 7 digits - Seven digit phone numbers 299 char firstChar = number.charAt(0); 300 if (firstChar >= '2' && firstChar <= '9') { 301 isNANP = true; 302 for (int i=1; i< NANP_SHORT_LENGTH; i++ ) { 303 char c= number.charAt(i); 304 if (!PhoneNumberUtils.isISODigit(c)) { 305 isNANP = false; 306 break; 307 } 308 } 309 } 310 if (isNANP) { 311 return NP_NANP_LOCAL; 312 } 313 } else if (number.length() == NANP_MEDIUM_LENGTH) { 314 // 10 digits - Three digit area code followed by seven digit phone numbers/ 315 if (isNANP(number)) { 316 return NP_NANP_AREA_LOCAL; 317 } 318 } else if (number.length() == NANP_LONG_LENGTH) { 319 // 11 digits - One digit U.S. NDD(National Direct Dial) prefix '1', 320 // followed by three digit area code and seven digit phone numbers 321 if (isNANP(number)) { 322 return NP_NANP_NDD_AREA_LOCAL; 323 } 324 } else if (number.startsWith(PLUS_SIGN)) { 325 number = number.substring(1); 326 if (number.length() == NANP_LONG_LENGTH) { 327 // '+' and 11 digits -'+', followed by NANP CC prefix '1' followed by 328 // three digit area code and seven digit phone numbers 329 if (isNANP(number)) { 330 return NP_NANP_NBPCD_CC_AREA_LOCAL; 331 } 332 } else if (number.startsWith(NANP_IDD) && number.length() == NANP_LONG_LENGTH + 3) { 333 // '+' and 14 digits -'+', followed by NANP IDD "011" followed by NANP CC 334 // prefix '1' followed by three digit area code and seven digit phone numbers 335 number = number.substring(3); 336 if (isNANP(number)) { 337 return NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL; 338 } 339 } 340 } else { 341 // Check whether it's NP_NANP_LOCALIDD_CC_AREA_LOCAL 342 for (String idd : allIDDs) { 343 if (number.startsWith(idd)) { 344 String number2 = number.substring(idd.length()); 345 if(number2 !=null && number2.startsWith(String.valueOf(NANP_CC))){ 346 if (isNANP(number2)) { 347 numberEntry.IDD = idd; 348 return NP_NANP_LOCALIDD_CC_AREA_LOCAL; 349 } 350 } 351 } 352 } 353 } 354 355 return NP_NONE; 356 } 357 isNANP(String number)358 private static boolean isNANP(String number) { 359 if (number.length() == NANP_MEDIUM_LENGTH 360 || (number.length() == NANP_LONG_LENGTH && number.startsWith(NANP_NDD))) { 361 if (number.length() == NANP_LONG_LENGTH) { 362 number = number.substring(1); 363 } 364 return (PhoneNumberUtils.isNanp(number)); 365 } 366 return false; 367 } 368 369 /* Verify if the the destination number is an internal number 370 * 371 * @param numberEntry including number and IDD array 372 * @param allIDDs the IDD array list of the current network's country code 373 * 374 * @return the number plan type related international number 375 */ checkInternationalNumberPlan(Context context, NumberEntry numberEntry, ArrayList<String> allIDDs,String homeIDD)376 private static int checkInternationalNumberPlan(Context context, NumberEntry numberEntry, 377 ArrayList<String> allIDDs,String homeIDD) { 378 String number = numberEntry.number; 379 int countryCode = -1; 380 381 if (number.startsWith(PLUS_SIGN)) { 382 // +xxxxxxxxxx 383 String numberNoNBPCD = number.substring(1); 384 if (numberNoNBPCD.startsWith(homeIDD)) { 385 // +011xxxxxxxx 386 String numberCountryAreaLocal = numberNoNBPCD.substring(homeIDD.length()); 387 if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) { 388 numberEntry.countryCode = countryCode; 389 return NP_NBPCD_HOMEIDD_CC_AREA_LOCAL; 390 } 391 } else if ((countryCode = getCountryCode(context, numberNoNBPCD)) > 0) { 392 numberEntry.countryCode = countryCode; 393 return NP_NBPCD_CC_AREA_LOCAL; 394 } 395 396 } else if (number.startsWith(homeIDD)) { 397 // 011xxxxxxxxx 398 String numberCountryAreaLocal = number.substring(homeIDD.length()); 399 if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) { 400 numberEntry.countryCode = countryCode; 401 return NP_HOMEIDD_CC_AREA_LOCAL; 402 } 403 } else { 404 for (String exitCode : allIDDs) { 405 if (number.startsWith(exitCode)) { 406 String numberNoIDD = number.substring(exitCode.length()); 407 if ((countryCode = getCountryCode(context, numberNoIDD)) > 0) { 408 numberEntry.countryCode = countryCode; 409 numberEntry.IDD = exitCode; 410 return NP_LOCALIDD_CC_AREA_LOCAL; 411 } 412 } 413 } 414 415 if (!number.startsWith("0") && (countryCode = getCountryCode(context, number)) > 0) { 416 numberEntry.countryCode = countryCode; 417 return NP_CC_AREA_LOCAL; 418 } 419 } 420 return NP_NONE; 421 } 422 423 /** 424 * Returns the country code from the given number. 425 */ getCountryCode(Context context, String number)426 private static int getCountryCode(Context context, String number) { 427 int countryCode = -1; 428 if (number.length() >= MIN_COUNTRY_AREA_LOCAL_LENGTH) { 429 // Check Country code 430 int[] allCCs = getAllCountryCodes(context); 431 if (allCCs == null) { 432 return countryCode; 433 } 434 435 int[] ccArray = new int[MAX_COUNTRY_CODES_LENGTH]; 436 for (int i = 0; i < MAX_COUNTRY_CODES_LENGTH; i ++) { 437 ccArray[i] = Integer.parseInt(number.substring(0, i+1)); 438 } 439 440 for (int i = 0; i < allCCs.length; i ++) { 441 int tempCC = allCCs[i]; 442 for (int j = 0; j < MAX_COUNTRY_CODES_LENGTH; j ++) { 443 if (tempCC == ccArray[j]) { 444 if (DBG) Rlog.d(TAG, "Country code = " + tempCC); 445 return tempCC; 446 } 447 } 448 } 449 } 450 451 return countryCode; 452 } 453 454 /** 455 * Gets all country Codes information with given MCC. 456 */ getAllCountryCodes(Context context)457 private static int[] getAllCountryCodes(Context context) { 458 if (ALL_COUNTRY_CODES != null) { 459 return ALL_COUNTRY_CODES; 460 } 461 462 Cursor cursor = null; 463 try { 464 String projection[] = {MccLookup.COUNTRY_CODE}; 465 cursor = context.getContentResolver().query(MccLookup.CONTENT_URI, 466 projection, null, null, null); 467 468 if (cursor.getCount() > 0) { 469 ALL_COUNTRY_CODES = new int[cursor.getCount()]; 470 int i = 0; 471 while (cursor.moveToNext()) { 472 int countryCode = cursor.getInt(0); 473 ALL_COUNTRY_CODES[i++] = countryCode; 474 int length = String.valueOf(countryCode).trim().length(); 475 if (length > MAX_COUNTRY_CODES_LENGTH) { 476 MAX_COUNTRY_CODES_LENGTH = length; 477 } 478 } 479 } 480 } catch (SQLException e) { 481 Rlog.e(TAG, "Can't access HbpcdLookup database", e); 482 } finally { 483 if (cursor != null) { 484 cursor.close(); 485 } 486 } 487 return ALL_COUNTRY_CODES; 488 } 489 inExceptionListForNpCcAreaLocal(NumberEntry numberEntry)490 private static boolean inExceptionListForNpCcAreaLocal(NumberEntry numberEntry) { 491 int countryCode = numberEntry.countryCode; 492 boolean result = (numberEntry.number.length() == 12 493 && (countryCode == 7 || countryCode == 20 494 || countryCode == 65 || countryCode == 90)); 495 return result; 496 } 497 getNumberPlanType(int state)498 private static String getNumberPlanType(int state) { 499 String numberPlanType = "Number Plan type (" + state + "): "; 500 501 if (state == NP_NANP_LOCAL) { 502 numberPlanType = "NP_NANP_LOCAL"; 503 } else if (state == NP_NANP_AREA_LOCAL) { 504 numberPlanType = "NP_NANP_AREA_LOCAL"; 505 } else if (state == NP_NANP_NDD_AREA_LOCAL) { 506 numberPlanType = "NP_NANP_NDD_AREA_LOCAL"; 507 } else if (state == NP_NANP_NBPCD_CC_AREA_LOCAL) { 508 numberPlanType = "NP_NANP_NBPCD_CC_AREA_LOCAL"; 509 } else if (state == NP_NANP_LOCALIDD_CC_AREA_LOCAL) { 510 numberPlanType = "NP_NANP_LOCALIDD_CC_AREA_LOCAL"; 511 } else if (state == NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL) { 512 numberPlanType = "NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL"; 513 } else if (state == NP_NBPCD_HOMEIDD_CC_AREA_LOCAL) { 514 numberPlanType = "NP_NBPCD_HOMEIDD_CC_AREA_LOCAL"; 515 } else if (state == NP_HOMEIDD_CC_AREA_LOCAL) { 516 numberPlanType = "NP_HOMEIDD_CC_AREA_LOCAL"; 517 } else if (state == NP_NBPCD_CC_AREA_LOCAL) { 518 numberPlanType = "NP_NBPCD_CC_AREA_LOCAL"; 519 } else if (state == NP_LOCALIDD_CC_AREA_LOCAL) { 520 numberPlanType = "NP_LOCALIDD_CC_AREA_LOCAL"; 521 } else if (state == NP_CC_AREA_LOCAL) { 522 numberPlanType = "NP_CC_AREA_LOCAL"; 523 } else { 524 numberPlanType = "Unknown type"; 525 } 526 return numberPlanType; 527 } 528 529 /** 530 * Filter the destination number if using VZW sim card. 531 */ filterDestAddr(Phone phone, String destAddr)532 public static String filterDestAddr(Phone phone, String destAddr) { 533 if (DBG) Rlog.d(TAG, "enter filterDestAddr. destAddr=\"" + Rlog.pii(TAG, destAddr) + "\"" ); 534 535 if (destAddr == null || !PhoneNumberUtils.isGlobalPhoneNumber(destAddr)) { 536 Rlog.w(TAG, "destAddr" + Rlog.pii(TAG, destAddr) + 537 " is not a global phone number! Nothing changed."); 538 return destAddr; 539 } 540 541 final String networkOperator = TelephonyManager.from(phone.getContext()). 542 getNetworkOperator(phone.getSubId()); 543 String result = null; 544 545 if (needToConvert(phone)) { 546 final int networkType = getNetworkType(phone); 547 if (networkType != -1 && !TextUtils.isEmpty(networkOperator)) { 548 String networkMcc = networkOperator.substring(0, 3); 549 if (networkMcc != null && networkMcc.trim().length() > 0) { 550 result = formatNumber(phone.getContext(), destAddr, networkMcc, networkType); 551 } 552 } 553 } 554 555 if (DBG) { 556 Rlog.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted.")); 557 Rlog.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? Rlog.pii(TAG, 558 result) : Rlog.pii(TAG, destAddr)) + "\""); 559 } 560 return result != null ? result : destAddr; 561 } 562 563 /** 564 * Returns the current network type 565 */ getNetworkType(Phone phone)566 private static int getNetworkType(Phone phone) { 567 int networkType = -1; 568 int phoneType = phone.getPhoneType(); 569 570 if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { 571 networkType = GSM_UMTS_NETWORK; 572 } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { 573 if (isInternationalRoaming(phone)) { 574 networkType = CDMA_ROAMING_NETWORK; 575 } else { 576 networkType = CDMA_HOME_NETWORK; 577 } 578 } else { 579 if (DBG) Rlog.w(TAG, "warning! unknown mPhoneType value=" + phoneType); 580 } 581 582 return networkType; 583 } 584 isInternationalRoaming(Phone phone)585 private static boolean isInternationalRoaming(Phone phone) { 586 String operatorIsoCountry = TelephonyManager.from(phone.getContext()). 587 getNetworkCountryIsoForPhone(phone.getPhoneId()); 588 String simIsoCountry = TelephonyManager.from(phone.getContext()).getSimCountryIsoForPhone( 589 phone.getPhoneId()); 590 boolean internationalRoaming = !TextUtils.isEmpty(operatorIsoCountry) 591 && !TextUtils.isEmpty(simIsoCountry) 592 && !simIsoCountry.equals(operatorIsoCountry); 593 if (internationalRoaming) { 594 if ("us".equals(simIsoCountry)) { 595 internationalRoaming = !"vi".equals(operatorIsoCountry); 596 } else if ("vi".equals(simIsoCountry)) { 597 internationalRoaming = !"us".equals(operatorIsoCountry); 598 } 599 } 600 return internationalRoaming; 601 } 602 needToConvert(Phone phone)603 private static boolean needToConvert(Phone phone) { 604 CarrierConfigManager configManager = (CarrierConfigManager) 605 phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 606 if (configManager != null) { 607 PersistableBundle bundle = configManager.getConfig(); 608 if (bundle != null) { 609 return bundle.getBoolean( 610 CarrierConfigManager.KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL); 611 } 612 } 613 // by default this value is false 614 return false; 615 } 616 compareGid1(Phone phone, String serviceGid1)617 private static boolean compareGid1(Phone phone, String serviceGid1) { 618 String gid1 = phone.getGroupIdLevel1(); 619 boolean ret = true; 620 621 if (TextUtils.isEmpty(serviceGid1)) { 622 if (DBG) Rlog.d(TAG, "compareGid1 serviceGid is empty, return " + ret); 623 return ret; 624 } 625 626 int gid_length = serviceGid1.length(); 627 // Check if gid1 match service GID1 628 if (!((gid1 != null) && (gid1.length() >= gid_length) && 629 gid1.substring(0, gid_length).equalsIgnoreCase(serviceGid1))) { 630 if (DBG) Rlog.d(TAG, " gid1 " + gid1 + " serviceGid1 " + serviceGid1); 631 ret = false; 632 } 633 if (DBG) Rlog.d(TAG, "compareGid1 is " + (ret?"Same":"Different")); 634 return ret; 635 } 636 } 637