content: /*
   * Copyright (C) 2014 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.internal.telephony;
  
  import android.content.Context;
  import android.database.Cursor;
  import android.database.SQLException;
  import android.os.Binder;
  import android.os.Build;
  import android.os.PersistableBundle;
  import android.telephony.CarrierConfigManager;
  import android.telephony.PhoneNumberUtils;
  import android.telephony.Rlog;
  import android.telephony.TelephonyManager;
  import android.text.TextUtils;
  
  import com.android.internal.telephony.HbpcdLookup.MccIdd;
  import com.android.internal.telephony.HbpcdLookup.MccLookup;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  
  
   /**
   * This class implements handle the MO SMS target address before sending.
   * This is special for VZW requirement. Follow the specifications of assisted dialing
   * of MO SMS while traveling on VZW CDMA, international CDMA or GSM markets.
   * {@hide}
   */
  public class SmsNumberUtils {
      private static final String TAG = "SmsNumberUtils";
      private static final boolean DBG = Build.IS_DEBUGGABLE;
  
      private static final String PLUS_SIGN = "+";
  
      private static final int NANP_SHORT_LENGTH = 7;
      private static final int NANP_MEDIUM_LENGTH = 10;
      private static final int NANP_LONG_LENGTH = 11;
  
      private static final int NANP_CC = 1;
      private static final String NANP_NDD = "1";
      private static final String NANP_IDD = "011";
  
      private static final int MIN_COUNTRY_AREA_LOCAL_LENGTH = 10;
  
      private static final int GSM_UMTS_NETWORK = 0;
      private static final int CDMA_HOME_NETWORK = 1;
      private static final int CDMA_ROAMING_NETWORK = 2;
  
      private static final int NP_NONE = 0;
      private static final int NP_NANP_BEGIN = 1;
  
      /* <Phone Number>, <NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_LOCAL = NP_NANP_BEGIN;
  
      /* <Area_code>-<Phone Number>, <NXX>-<NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_AREA_LOCAL = NP_NANP_BEGIN + 1;
  
      /* <1>-<Area_code>-<Phone Number>, 1-<NXX>-<NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_NDD_AREA_LOCAL = NP_NANP_BEGIN + 2;
  
      /* <+><U.S.Country_code><Area_code><Phone Number>, +1-<NXX>-<NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_NBPCD_CC_AREA_LOCAL = NP_NANP_BEGIN + 3;
  
      /* <Local_IDD><Country_code><Area_code><Phone Number>, 001-1-<NXX>-<NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_LOCALIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 4;
  
      /* <+><Home_IDD><Country_code><Area_code><Phone Number>, +011-1-<NXX>-<NXX>-<XXXX> N[2-9] */
      private static final int NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_NANP_BEGIN + 5;
  
      private static final int NP_INTERNATIONAL_BEGIN = 100;
      /* <+>-<Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, +011-86-25-86281234 */
      private static final int NP_NBPCD_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN;
  
      /* <Home_IDD>-<Country_code>-<Area_code>-<Phone Number>, 011-86-25-86281234 */
      private static final int NP_HOMEIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 1;
  
      /* <NBPCD>-<Country_code>-<Area_code>-<Phone Number>, +1-86-25-86281234 */
      private static final int NP_NBPCD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 2;
  
      /* <Local_IDD>-<Country_code>-<Area_code>-<Phone Number>, 00-86-25-86281234 */
      private static final int NP_LOCALIDD_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 3;
  
      /* <Country_code>-<Area_code>-<Phone Number>, 86-25-86281234*/
      private static final int NP_CC_AREA_LOCAL = NP_INTERNATIONAL_BEGIN + 4;
  
      private static int[] ALL_COUNTRY_CODES = null;
      private static int MAX_COUNTRY_CODES_LENGTH;
      private static HashMap<String, ArrayList<String>> IDDS_MAPS =
              new HashMap<String, ArrayList<String>>();
  
      private static class NumberEntry {
          public String number;
          public String IDD;
          public int countryCode;
          public NumberEntry(String number) {
              this.number = number;
          }
      }
  
      /* Breaks the given number down and formats it according to the rules
       * for different number plans and different network.
       *
       * @param number destination number which need to be format
       * @param activeMcc current network's mcc
       * @param networkType current network type
       *
       * @return the number after formatting.
       */
      private static String formatNumber(Context context, String number,
                                 String activeMcc,
                                 int networkType) {
          if (number == null ) {
              throw new IllegalArgumentException("number is null");
          }
  
          if (activeMcc == null || activeMcc.trim().length() == 0) {
              throw new IllegalArgumentException("activeMcc is null or empty!");
          }
  
          String networkPortionNumber = PhoneNumberUtils.extractNetworkPortion(number);
          if (networkPortionNumber == null || networkPortionNumber.length() == 0) {
              throw new IllegalArgumentException("Number is invalid!");
          }
  
          NumberEntry numberEntry = new NumberEntry(networkPortionNumber);
          ArrayList<String> allIDDs = getAllIDDs(context, activeMcc);
  
          // First check whether the number is a NANP number.
          int nanpState = checkNANP(numberEntry, allIDDs);
          if (DBG) Rlog.d(TAG, "NANP type: " + getNumberPlanType(nanpState));
  
          if ((nanpState == NP_NANP_LOCAL)
              || (nanpState == NP_NANP_AREA_LOCAL)
              || (nanpState == NP_NANP_NDD_AREA_LOCAL)) {
              return networkPortionNumber;
          } else if (nanpState == NP_NANP_NBPCD_CC_AREA_LOCAL) {
              if (networkType == CDMA_HOME_NETWORK
                      || networkType == CDMA_ROAMING_NETWORK) {
                  // Remove "+"
                  return networkPortionNumber.substring(1);
              } else {
                  return networkPortionNumber;
              }
          } else if (nanpState == NP_NANP_LOCALIDD_CC_AREA_LOCAL) {
              if (networkType == CDMA_HOME_NETWORK) {
                  return networkPortionNumber;
              } else if (networkType == GSM_UMTS_NETWORK) {
                  // Remove the local IDD and replace with "+"
                  int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
                  return PLUS_SIGN + networkPortionNumber.substring(iddLength);
              } else if (networkType == CDMA_ROAMING_NETWORK) {
                  // Remove the local IDD
                  int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
                  return  networkPortionNumber.substring(iddLength);
              }
          }
  
          int internationalState = checkInternationalNumberPlan(context, numberEntry, allIDDs,
                  NANP_IDD);
          if (DBG) Rlog.d(TAG, "International type: " + getNumberPlanType(internationalState));
          String returnNumber = null;
  
          switch (internationalState) {
              case NP_NBPCD_HOMEIDD_CC_AREA_LOCAL:
                  if (networkType == GSM_UMTS_NETWORK) {
                      // Remove "+"
                      returnNumber = networkPortionNumber.substring(1);
                  }
                  break;
  
              case NP_NBPCD_CC_AREA_LOCAL:
                  // Replace "+" with "011"
                  returnNumber = NANP_IDD + networkPortionNumber.substring(1);
                  break;
  
              case NP_LOCALIDD_CC_AREA_LOCAL:
                  if (networkType == GSM_UMTS_NETWORK || networkType == CDMA_ROAMING_NETWORK) {
                      int iddLength  =  numberEntry.IDD != null ? numberEntry.IDD.length() : 0;
                      // Replace <Local IDD> to <Home IDD>("011")
                      returnNumber = NANP_IDD + networkPortionNumber.substring(iddLength);
                  }
                  break;
  
              case NP_CC_AREA_LOCAL:
                  int countryCode = numberEntry.countryCode;
  
                  if (!inExceptionListForNpCcAreaLocal(numberEntry)
                      && networkPortionNumber.length() >= 11 && countryCode != NANP_CC) {
                      // Add "011"
                      returnNumber = NANP_IDD + networkPortionNumber;
                  }
                  break;
  
              case NP_HOMEIDD_CC_AREA_LOCAL:
                  returnNumber = networkPortionNumber;
                  break;
  
              default:
                  // Replace "+" with 011 in CDMA network if the number's country
                  // code is not in the HbpcdLookup database.
                  if (networkPortionNumber.startsWith(PLUS_SIGN)
                      && (networkType == CDMA_HOME_NETWORK || networkType == CDMA_ROAMING_NETWORK)) {
                      if (networkPortionNumber.startsWith(PLUS_SIGN + NANP_IDD)) {
                          // Only remove "+"
                          returnNumber = networkPortionNumber.substring(1);
                      } else {
                          // Replace "+" with "011"
                          returnNumber = NANP_IDD + networkPortionNumber.substring(1);
                      }
                  }
          }
  
          if (returnNumber == null) {
              returnNumber = networkPortionNumber;
          }
          return returnNumber;
      }
  
      /* Query International direct dialing from HbpcdLookup.db
       * for specified country code
       *
       * @param mcc current network's country code
       *
       * @return the IDD array list.
       */
      private static ArrayList<String> getAllIDDs(Context context, String mcc) {
          ArrayList<String> allIDDs = IDDS_MAPS.get(mcc);
          if (allIDDs != null) {
              return allIDDs;
          } else {
              allIDDs = new ArrayList<String>();
          }
  
          String projection[] = {MccIdd.IDD, MccIdd.MCC};
          String where = null;
  
          // if mcc is null         : return all rows
          // if mcc is empty-string : return those rows whose mcc is emptry-string
          String[] selectionArgs = null;
          if (mcc != null) {
              where = MccIdd.MCC + "=?";
              selectionArgs = new String[] {mcc};
          }
  
          Cursor cursor = null;
          try {
              cursor = context.getContentResolver().query(MccIdd.CONTENT_URI, projection,
                      where, selectionArgs, null);
              if (cursor.getCount() > 0) {
                  while (cursor.moveToNext()) {
                      String idd = cursor.getString(0);
                      if (!allIDDs.contains(idd)) {
                          allIDDs.add(idd);
                      }
                  }
              }
          } catch (SQLException e) {
              Rlog.e(TAG, "Can't access HbpcdLookup database", e);
          } finally {
              if (cursor != null) {
                  cursor.close();
              }
          }
  
          IDDS_MAPS.put(mcc, allIDDs);
  
          if (DBG) Rlog.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs);
          return allIDDs;
      }
  
  
      /* Verify if the the destination number is a NANP number
       *
       * @param numberEntry including number and IDD array
       * @param allIDDs the IDD array list of the current network's country code
       *
       * @return the number plan type related NANP
       */
      private static int checkNANP(NumberEntry numberEntry, ArrayList<String> allIDDs) {
          boolean isNANP = false;
          String number = numberEntry.number;
  
          if (number.length() == NANP_SHORT_LENGTH) {
              // 7 digits - Seven digit phone numbers
              char firstChar = number.charAt(0);
              if (firstChar >= '2' && firstChar <= '9') {
                  isNANP = true;
                  for (int i=1; i< NANP_SHORT_LENGTH; i++ ) {
                      char c= number.charAt(i);
                      if (!PhoneNumberUtils.isISODigit(c)) {
                          isNANP = false;
                          break;
                      }
                  }
              }
              if (isNANP) {
                  return NP_NANP_LOCAL;
              }
          } else if (number.length() == NANP_MEDIUM_LENGTH) {
              // 10 digits - Three digit area code followed by seven digit phone numbers/
              if (isNANP(number)) {
                  return NP_NANP_AREA_LOCAL;
              }
          } else if (number.length() == NANP_LONG_LENGTH) {
              // 11 digits - One digit U.S. NDD(National Direct Dial) prefix '1',
              // followed by three digit area code and seven digit phone numbers
              if (isNANP(number)) {
                  return NP_NANP_NDD_AREA_LOCAL;
              }
          } else if (number.startsWith(PLUS_SIGN)) {
              number = number.substring(1);
              if (number.length() == NANP_LONG_LENGTH) {
                  // '+' and 11 digits -'+', followed by NANP CC prefix '1' followed by
                  // three digit area code and seven digit phone numbers
                  if (isNANP(number)) {
                      return NP_NANP_NBPCD_CC_AREA_LOCAL;
                  }
              } else if (number.startsWith(NANP_IDD) && number.length() == NANP_LONG_LENGTH + 3) {
                  // '+' and 14 digits -'+', followed by NANP IDD "011" followed by NANP CC
                  // prefix '1' followed by three digit area code and seven digit phone numbers
                  number = number.substring(3);
                  if (isNANP(number)) {
                      return NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL;
                  }
              }
          } else {
              // Check whether it's NP_NANP_LOCALIDD_CC_AREA_LOCAL
              for (String idd : allIDDs) {
                  if (number.startsWith(idd)) {
                      String number2 = number.substring(idd.length());
                      if(number2 !=null && number2.startsWith(String.valueOf(NANP_CC))){
                          if (isNANP(number2)) {
                              numberEntry.IDD = idd;
                              return NP_NANP_LOCALIDD_CC_AREA_LOCAL;
                          }
                      }
                  }
              }
          }
  
          return NP_NONE;
      }
  
      private static boolean isNANP(String number) {
          if (number.length() == NANP_MEDIUM_LENGTH
              || (number.length() == NANP_LONG_LENGTH  && number.startsWith(NANP_NDD))) {
              if (number.length() == NANP_LONG_LENGTH) {
                  number = number.substring(1);
              }
              return (PhoneNumberUtils.isNanp(number));
          }
          return false;
      }
  
      /* Verify if the the destination number is an internal number
       *
       * @param numberEntry including number and IDD array
       * @param allIDDs the IDD array list of the current network's country code
       *
       * @return the number plan type related international number
       */
      private static int checkInternationalNumberPlan(Context context, NumberEntry numberEntry,
              ArrayList<String> allIDDs,String homeIDD) {
          String number = numberEntry.number;
          int countryCode = -1;
  
          if (number.startsWith(PLUS_SIGN)) {
              // +xxxxxxxxxx
              String numberNoNBPCD = number.substring(1);
              if (numberNoNBPCD.startsWith(homeIDD)) {
                  // +011xxxxxxxx
                  String numberCountryAreaLocal = numberNoNBPCD.substring(homeIDD.length());
                  if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) {
                      numberEntry.countryCode = countryCode;
                      return NP_NBPCD_HOMEIDD_CC_AREA_LOCAL;
                  }
              } else if ((countryCode = getCountryCode(context, numberNoNBPCD)) > 0) {
                  numberEntry.countryCode = countryCode;
                  return NP_NBPCD_CC_AREA_LOCAL;
              }
  
          } else if (number.startsWith(homeIDD)) {
              // 011xxxxxxxxx
              String numberCountryAreaLocal = number.substring(homeIDD.length());
              if ((countryCode = getCountryCode(context, numberCountryAreaLocal)) > 0) {
                  numberEntry.countryCode = countryCode;
                  return NP_HOMEIDD_CC_AREA_LOCAL;
              }
          } else {
              for (String exitCode : allIDDs) {
                  if (number.startsWith(exitCode)) {
                      String numberNoIDD = number.substring(exitCode.length());
                      if ((countryCode = getCountryCode(context, numberNoIDD)) > 0) {
                          numberEntry.countryCode = countryCode;
                          numberEntry.IDD = exitCode;
                          return NP_LOCALIDD_CC_AREA_LOCAL;
                      }
                  }
              }
  
              if (!number.startsWith("0") && (countryCode = getCountryCode(context, number)) > 0) {
                  numberEntry.countryCode = countryCode;
                  return NP_CC_AREA_LOCAL;
              }
          }
          return NP_NONE;
      }
  
      /**
       *  Returns the country code from the given number.
       */
      private static int getCountryCode(Context context, String number) {
          int countryCode = -1;
          if (number.length() >= MIN_COUNTRY_AREA_LOCAL_LENGTH) {
              // Check Country code
              int[] allCCs = getAllCountryCodes(context);
              if (allCCs == null) {
                  return countryCode;
              }
  
              int[] ccArray = new int[MAX_COUNTRY_CODES_LENGTH];
              for (int i = 0; i < MAX_COUNTRY_CODES_LENGTH; i ++) {
                  ccArray[i] = Integer.parseInt(number.substring(0, i+1));
              }
  
              for (int i = 0; i < allCCs.length; i ++) {
                  int tempCC = allCCs[i];
                  for (int j = 0; j < MAX_COUNTRY_CODES_LENGTH; j ++) {
                      if (tempCC == ccArray[j]) {
                          if (DBG) Rlog.d(TAG, "Country code = " + tempCC);
                          return tempCC;
                      }
                  }
              }
          }
  
          return countryCode;
      }
  
      /**
       *  Gets all country Codes information with given MCC.
       */
      private static int[] getAllCountryCodes(Context context) {
          if (ALL_COUNTRY_CODES != null) {
              return ALL_COUNTRY_CODES;
          }
  
          Cursor cursor = null;
          try {
              String projection[] = {MccLookup.COUNTRY_CODE};
              cursor = context.getContentResolver().query(MccLookup.CONTENT_URI,
                      projection, null, null, null);
  
              if (cursor.getCount() > 0) {
                  ALL_COUNTRY_CODES = new int[cursor.getCount()];
                  int i = 0;
                  while (cursor.moveToNext()) {
                      int countryCode = cursor.getInt(0);
                      ALL_COUNTRY_CODES[i++] = countryCode;
                      int length = String.valueOf(countryCode).trim().length();
                      if (length > MAX_COUNTRY_CODES_LENGTH) {
                          MAX_COUNTRY_CODES_LENGTH = length;
                      }
                  }
              }
          } catch (SQLException e) {
              Rlog.e(TAG, "Can't access HbpcdLookup database", e);
          } finally {
              if (cursor != null) {
                  cursor.close();
              }
          }
          return ALL_COUNTRY_CODES;
      }
  
      private static boolean inExceptionListForNpCcAreaLocal(NumberEntry numberEntry) {
          int countryCode = numberEntry.countryCode;
          boolean result = (numberEntry.number.length() == 12
                            && (countryCode == 7 || countryCode == 20
                                || countryCode == 65 || countryCode == 90));
          return result;
      }
  
      private static String getNumberPlanType(int state) {
          String numberPlanType = "Number Plan type (" + state + "): ";
  
          if (state == NP_NANP_LOCAL) {
              numberPlanType = "NP_NANP_LOCAL";
          } else if (state == NP_NANP_AREA_LOCAL) {
              numberPlanType = "NP_NANP_AREA_LOCAL";
          } else if (state  == NP_NANP_NDD_AREA_LOCAL) {
              numberPlanType = "NP_NANP_NDD_AREA_LOCAL";
          } else if (state == NP_NANP_NBPCD_CC_AREA_LOCAL) {
              numberPlanType = "NP_NANP_NBPCD_CC_AREA_LOCAL";
          } else if (state == NP_NANP_LOCALIDD_CC_AREA_LOCAL) {
              numberPlanType = "NP_NANP_LOCALIDD_CC_AREA_LOCAL";
          } else if (state == NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL) {
              numberPlanType = "NP_NANP_NBPCD_HOMEIDD_CC_AREA_LOCAL";
          } else if (state == NP_NBPCD_HOMEIDD_CC_AREA_LOCAL) {
              numberPlanType = "NP_NBPCD_HOMEIDD_CC_AREA_LOCAL";
          } else if (state == NP_HOMEIDD_CC_AREA_LOCAL) {
              numberPlanType = "NP_HOMEIDD_CC_AREA_LOCAL";
          } else if (state == NP_NBPCD_CC_AREA_LOCAL) {
              numberPlanType = "NP_NBPCD_CC_AREA_LOCAL";
          } else if (state == NP_LOCALIDD_CC_AREA_LOCAL) {
              numberPlanType = "NP_LOCALIDD_CC_AREA_LOCAL";
          } else if (state == NP_CC_AREA_LOCAL) {
              numberPlanType = "NP_CC_AREA_LOCAL";
          } else {
              numberPlanType = "Unknown type";
          }
          return numberPlanType;
      }
  
      /**
       *  Filter the destination number if using VZW sim card.
       */
      public static String filterDestAddr(Phone phone, String destAddr) {
          if (DBG) Rlog.d(TAG, "enter filterDestAddr. destAddr=\"" + Rlog.pii(TAG, destAddr) + "\"" );
  
          if (destAddr == null || !PhoneNumberUtils.isGlobalPhoneNumber(destAddr)) {
              Rlog.w(TAG, "destAddr" + Rlog.pii(TAG, destAddr) +
                      " is not a global phone number! Nothing changed.");
              return destAddr;
          }
  
          final String networkOperator = TelephonyManager.from(phone.getContext()).
                  getNetworkOperator(phone.getSubId());
          String result = null;
  
          if (needToConvert(phone)) {
              final int networkType = getNetworkType(phone);
              if (networkType != -1 && !TextUtils.isEmpty(networkOperator)) {
                  String networkMcc = networkOperator.substring(0, 3);
                  if (networkMcc != null && networkMcc.trim().length() > 0) {
                      result = formatNumber(phone.getContext(), destAddr, networkMcc, networkType);
                  }
              }
          }
  
          if (DBG) {
              Rlog.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted."));
              Rlog.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? Rlog.pii(TAG,
                      result) : Rlog.pii(TAG, destAddr)) + "\"");
          }
          return result != null ? result : destAddr;
      }
  
      /**
       * Returns the current network type
       */
      private static int getNetworkType(Phone phone) {
          int networkType = -1;
          int phoneType = phone.getPhoneType();
  
          if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
              networkType = GSM_UMTS_NETWORK;
          } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
              if (isInternationalRoaming(phone)) {
                  networkType = CDMA_ROAMING_NETWORK;
              } else {
                  networkType = CDMA_HOME_NETWORK;
              }
          } else {
              if (DBG) Rlog.w(TAG, "warning! unknown mPhoneType value=" + phoneType);
          }
  
          return networkType;
      }
  
      private static boolean isInternationalRoaming(Phone phone) {
          String operatorIsoCountry = TelephonyManager.from(phone.getContext()).
                  getNetworkCountryIsoForPhone(phone.getPhoneId());
          String simIsoCountry = TelephonyManager.from(phone.getContext()).getSimCountryIsoForPhone(
                  phone.getPhoneId());
          boolean internationalRoaming = !TextUtils.isEmpty(operatorIsoCountry)
                  && !TextUtils.isEmpty(simIsoCountry)
                  && !simIsoCountry.equals(operatorIsoCountry);
          if (internationalRoaming) {
              if ("us".equals(simIsoCountry)) {
                  internationalRoaming = !"vi".equals(operatorIsoCountry);
              } else if ("vi".equals(simIsoCountry)) {
                  internationalRoaming = !"us".equals(operatorIsoCountry);
              }
          }
          return internationalRoaming;
      }
  
      private static boolean needToConvert(Phone phone) {
          // Calling package may not have READ_PHONE_STATE which is required for getConfig().
          // Clear the calling identity so that it is called as self.
          final long identity = Binder.clearCallingIdentity();
          try {
              CarrierConfigManager configManager = (CarrierConfigManager)
                      phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
              if (configManager != null) {
                  PersistableBundle bundle = configManager.getConfigForSubId(phone.getSubId());
                  if (bundle != null) {
                      return bundle.getBoolean(CarrierConfigManager
                              .KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL);
                  }
              }
          } finally {
              Binder.restoreCallingIdentity(identity);
          }
          // by default this value is false
          return false;
      }
  
      private static boolean compareGid1(Phone phone, String serviceGid1) {
          String gid1 = phone.getGroupIdLevel1();
          boolean ret = true;
  
          if (TextUtils.isEmpty(serviceGid1)) {
              if (DBG) Rlog.d(TAG, "compareGid1 serviceGid is empty, return " + ret);
              return ret;
          }
  
          int gid_length = serviceGid1.length();
          // Check if gid1 match service GID1
          if (!((gid1 != null) && (gid1.length() >= gid_length) &&
                  gid1.substring(0, gid_length).equalsIgnoreCase(serviceGid1))) {
              if (DBG) Rlog.d(TAG, " gid1 " + gid1 + " serviceGid1 " + serviceGid1);
              ret = false;
          }
          if (DBG) Rlog.d(TAG, "compareGid1 is " + (ret?"Same":"Different"));
          return ret;
      }
  }
  