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