protected void updatePhoneObject() {
   if (mPhoneBase
       .getContext()
       .getResources()
       .getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) {
     // If the phone is not registered on a network, no need to update.
     boolean isRegistered =
         mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
             || mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY;
     if (!isRegistered) {
       Rlog.d(LOG_TAG, "updatePhoneObject: Ignore update");
       return;
     }
     mPhoneBase.updatePhoneObject(mSS.getRilVoiceRadioTechnology());
   }
 }
 private int updateEfForIccType(int efid) {
   // Check if we are trying to read ADN records
   if (efid == IccConstants.EF_ADN) {
     if (phone.getIccCard().isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
       return IccConstants.EF_PBR;
     }
   }
   return efid;
 }
 /**
  * Notify all mDataConnectionRatChangeRegistrants using an AsyncResult in msg.obj where
  * AsyncResult#result contains the new RAT as an Integer Object.
  */
 protected void notifyDataRegStateRilRadioTechnologyChanged() {
   int rat = mSS.getRilDataRadioTechnology();
   int drs = mSS.getDataRegState();
   if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
   mPhoneBase.setSystemProperty(
       TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
       ServiceState.rilRadioTechnologyToString(rat));
   mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));
 }
 public DisconnectCause disconnectCauseFromCode(int causeCode, PhoneBase phone) {
   /** See 22.001 Annex F.4 for mapping of cause codes to local tones */
   switch (causeCode) {
     case CallFailCause.NO_CIRCUIT_AVAIL:
     case CallFailCause.TEMPORARY_FAILURE:
     case CallFailCause.SWITCHING_CONGESTION:
     case CallFailCause.CHANNEL_NOT_AVAIL:
     case CallFailCause.QOS_NOT_AVAIL:
     case CallFailCause.BEARER_NOT_AVAIL:
       return DisconnectCause.CONGESTION;
     case CallFailCause.ACM_LIMIT_EXCEEDED:
       return DisconnectCause.LIMIT_EXCEEDED;
     case CallFailCause.CALL_BARRED:
       return DisconnectCause.CALL_BARRED;
     case CallFailCause.FDN_BLOCKED:
       return DisconnectCause.FDN_BLOCKED;
     case CallFailCause.UNOBTAINABLE_NUMBER:
       return DisconnectCause.UNOBTAINABLE_NUMBER;
     case CallFailCause.DIAL_MODIFIED_TO_USSD:
       return DisconnectCause.DIAL_MODIFIED_TO_USSD;
     case CallFailCause.DIAL_MODIFIED_TO_SS:
       return DisconnectCause.DIAL_MODIFIED_TO_SS;
     case CallFailCause.DIAL_MODIFIED_TO_DIAL:
       return DisconnectCause.DIAL_MODIFIED_TO_DIAL;
     case CallFailCause.USER_BUSY:
       return DisconnectCause.BUSY;
     case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE:
       return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE;
     case CallFailCause.CDMA_DROP:
       return DisconnectCause.CDMA_DROP;
     case CallFailCause.CDMA_INTERCEPT:
       return DisconnectCause.CDMA_INTERCEPT;
     case CallFailCause.CDMA_REORDER:
       return DisconnectCause.CDMA_REORDER;
     case CallFailCause.CDMA_SO_REJECT:
       return DisconnectCause.CDMA_SO_REJECT;
     case CallFailCause.CDMA_RETRY_ORDER:
       return DisconnectCause.CDMA_RETRY_ORDER;
     case CallFailCause.CDMA_ACCESS_FAILURE:
       return DisconnectCause.CDMA_ACCESS_FAILURE;
     case CallFailCause.CDMA_PREEMPTED:
       return DisconnectCause.CDMA_PREEMPTED;
     case CallFailCause.CDMA_NOT_EMERGENCY:
       return DisconnectCause.CDMA_NOT_EMERGENCY;
     case CallFailCause.CDMA_ACCESS_BLOCKED:
       return DisconnectCause.CDMA_ACCESS_BLOCKED;
     case CallFailCause.ERROR_UNSPECIFIED:
     case CallFailCause.NORMAL_CLEARING:
     default:
       {
         return phone.disconnectCauseFromCode(causeCode);
       }
   }
 }
  protected ServiceStateTracker(PhoneBase phoneBase, CommandsInterface ci, CellInfo cellInfo) {
    mPhoneBase = phoneBase;
    mCellInfo = cellInfo;
    mCi = ci;
    mVoiceCapable =
        mPhoneBase
            .getContext()
            .getResources()
            .getBoolean(com.android.internal.R.bool.config_voice_capable);
    mUiccController = UiccController.getInstance();
    mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
    mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
    mCi.registerForCellInfoList(this, EVENT_UNSOL_CELL_INFO_LIST, null);

    mSubscriptionController = SubscriptionController.getInstance();
    mSubscriptionManager = SubscriptionManager.from(phoneBase.getContext());
    mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);

    mPhoneBase.setSystemProperty(
        TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
        ServiceState.rilRadioTechnologyToString(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
    mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
  }
  /**
   * Replace oldAdn with newAdn in ADN-like record in EF
   *
   * <p>getAdnRecordsInEf must be called at least once before this function, otherwise an error will
   * be returned. Currently the email field if set in the ADN record is ignored. throws
   * SecurityException if no WRITE_CONTACTS permission
   *
   * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
   * @param oldTag adn tag to be replaced
   * @param oldPhoneNumber adn number to be replaced Set both oldTag and oldPhoneNubmer to "" means
   *     to replace an empty record, aka, insert new record
   * @param newTag adn tag to be stored
   * @param newPhoneNumber adn number ot be stored Set both newTag and newPhoneNubmer to "" means to
   *     replace the old record with empty one, aka, delete old record
   * @param pin2 required to update EF_FDN, otherwise must be null
   * @return true for success
   */
  public boolean updateAdnRecordsInEfBySearch(
      int efid,
      String oldTag,
      String oldPhoneNumber,
      String newTag,
      String newPhoneNumber,
      String pin2) {

    if (phone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.WRITE_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {
      throw new SecurityException("Requires android.permission.WRITE_CONTACTS permission");
    }

    if (DBG)
      logd(
          "updateAdnRecordsInEfBySearch: efid="
              + efid
              + " ("
              + oldTag
              + ","
              + oldPhoneNumber
              + ")"
              + "==>"
              + " ("
              + newTag
              + ","
              + newPhoneNumber
              + ")"
              + " pin2="
              + pin2);

    efid = updateEfForIccType(efid);

    synchronized (mLock) {
      checkThread();
      success = false;
      Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
      AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
      AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
      adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
      try {
        mLock.wait();
      } catch (InterruptedException e) {
        logd("interrupted while trying to update by search");
      }
    }
    return success;
  }
 protected boolean notifySignalStrength() {
   boolean notified = false;
   synchronized (mCellInfo) {
     if (!mSignalStrength.equals(mLastSignalStrength)) {
       try {
         mPhoneBase.notifySignalStrength();
         notified = true;
       } catch (NullPointerException ex) {
         loge(
             "updateSignalStrength() Phone already destroyed: "
                 + ex
                 + "SignalStrength not notified");
       }
     }
   }
   return notified;
 }
 /**
  * Clean up existing voice and data connection then turn off radio power.
  *
  * <p>Hang up the existing voice calls to decrease call drop rate.
  */
 public void powerOffRadioSafely(DcTrackerBase dcTracker) {
   synchronized (this) {
     if (!mPendingRadioPowerOffAfterDataOff) {
       // In some network, deactivate PDP connection cause releasing of RRC connection,
       // which MM/IMSI detaching request needs. Without this detaching, network can
       // not release the network resources previously attached.
       // So we are avoiding data detaching on these networks.
       String[] networkNotClearData =
           mPhoneBase
               .getContext()
               .getResources()
               .getStringArray(com.android.internal.R.array.networks_not_clear_data);
       String currentNetwork = mSS.getOperatorNumeric();
       if ((networkNotClearData != null) && (currentNetwork != null)) {
         for (int i = 0; i < networkNotClearData.length; i++) {
           if (currentNetwork.equals(networkNotClearData[i])) {
             // Don't clear data connection for this carrier
             if (DBG) log("Not disconnecting data for " + currentNetwork);
             hangupAndPowerOff();
             return;
           }
         }
       }
       // To minimize race conditions we call cleanUpAllConnections on
       // both if else paths instead of before this isDisconnected test.
       if (dcTracker.isDisconnected()) {
         // To minimize race conditions we do this after isDisconnected
         dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
         if (DBG) log("Data disconnected, turn off radio right away.");
         hangupAndPowerOff();
       } else {
         dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
         Message msg = Message.obtain(this);
         msg.what = EVENT_SET_RADIO_POWER_OFF;
         msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
         if (sendMessageDelayed(msg, 30000)) {
           if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
           mPendingRadioPowerOffAfterDataOff = true;
         } else {
           log("Cannot send delayed Msg, turn off radio right away.");
           hangupAndPowerOff();
         }
       }
     }
   }
 }
  /**
   * Loads the AdnRecords in efid and returns them as a List of AdnRecords
   *
   * <p>throws SecurityException if no READ_CONTACTS permission
   *
   * @param efid the EF id of a ADN-like ICC
   * @return List of AdnRecord
   */
  public List<AdnRecord> getAdnRecordsInEf(int efid) {

    if (phone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {
      throw new SecurityException("Requires android.permission.READ_CONTACTS permission");
    }

    efid = updateEfForIccType(efid);
    if (DBG) logd("getAdnRecordsInEF: efid=" + efid);

    synchronized (mLock) {
      checkThread();
      Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
      adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
      try {
        mLock.wait();
      } catch (InterruptedException e) {
        logd("interrupted while trying to load from the SIM");
      }
    }
    return records;
  }
  public static void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    pw.println("PhoneFactory:");
    PhoneProxy[] phones = (PhoneProxy[]) PhoneFactory.getPhones();
    int i = -1;
    for (PhoneProxy phoneProxy : phones) {
      PhoneBase phoneBase;
      i += 1;

      try {
        phoneBase = (PhoneBase) phoneProxy.getActivePhone();
        phoneBase.dump(fd, pw, args);
      } catch (Exception e) {
        pw.println("Telephony DebugService: Could not get Phone[" + i + "] e=" + e);
        continue;
      }

      pw.flush();
      pw.println("++++++++++++++++++++++++++++++++");

      try {
        ((IccCardProxy) phoneProxy.getIccCard()).dump(fd, pw, args);
      } catch (Exception e) {
        e.printStackTrace();
      }
      pw.flush();
      pw.println("++++++++++++++++++++++++++++++++");
    }

    try {
      DctController.getInstance().dump(fd, pw, args);
    } catch (Exception e) {
      e.printStackTrace();
    }

    try {
      mUiccController.dump(fd, pw, args);
    } catch (Exception e) {
      e.printStackTrace();
    }
    pw.flush();
    pw.println("++++++++++++++++++++++++++++++++");

    try {
      SubscriptionController.getInstance().dump(fd, pw, args);
    } catch (Exception e) {
      e.printStackTrace();
    }
    pw.flush();
    pw.println("++++++++++++++++++++++++++++++++");

    try {
      sSubInfoRecordUpdater.dump(fd, pw, args);
    } catch (Exception e) {
      e.printStackTrace();
    }
    pw.flush();

    pw.println("++++++++++++++++++++++++++++++++");
    synchronized (sLocalLogs) {
      final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
      for (String key : sLocalLogs.keySet()) {
        ipw.println(key);
        ipw.increaseIndent();
        sLocalLogs.get(key).dump(fd, ipw, args);
        ipw.decreaseIndent();
      }
      ipw.flush();
    }
  }
 public String getSystemProperty(String property, String defValue) {
   return TelephonyManager.getTelephonyProperty(mPhoneBase.getPhoneId(), property, defValue);
 }
  @Override
  public void handleMessage(Message msg) {
    switch (msg.what) {
      case EVENT_SET_RADIO_POWER_OFF:
        synchronized (this) {
          if (mPendingRadioPowerOffAfterDataOff
              && (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
            if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
            hangupAndPowerOff();
            mPendingRadioPowerOffAfterDataOffTag += 1;
            mPendingRadioPowerOffAfterDataOff = false;
          } else {
            log(
                "EVENT_SET_RADIO_OFF is stale arg1="
                    + msg.arg1
                    + "!= tag="
                    + mPendingRadioPowerOffAfterDataOffTag);
          }
        }
        break;

      case EVENT_ICC_CHANGED:
        onUpdateIccAvailability();
        break;

      case EVENT_GET_CELL_INFO_LIST:
        {
          AsyncResult ar = (AsyncResult) msg.obj;
          CellInfoResult result = (CellInfoResult) ar.userObj;
          synchronized (result.lockObj) {
            if (ar.exception != null) {
              log("EVENT_GET_CELL_INFO_LIST: error ret null, e=" + ar.exception);
              result.list = null;
            } else {
              result.list = (List<CellInfo>) ar.result;

              if (VDBG) {
                log(
                    "EVENT_GET_CELL_INFO_LIST: size="
                        + result.list.size()
                        + " list="
                        + result.list);
              }
            }
            mLastCellInfoListTime = SystemClock.elapsedRealtime();
            mLastCellInfoList = result.list;
            result.lockObj.notify();
          }
          break;
        }

      case EVENT_UNSOL_CELL_INFO_LIST:
        {
          AsyncResult ar = (AsyncResult) msg.obj;
          if (ar.exception != null) {
            log("EVENT_UNSOL_CELL_INFO_LIST: error ignoring, e=" + ar.exception);
          } else {
            List<CellInfo> list = (List<CellInfo>) ar.result;
            if (DBG) {
              log("EVENT_UNSOL_CELL_INFO_LIST: size=" + list.size() + " list=" + list);
            }
            mLastCellInfoListTime = SystemClock.elapsedRealtime();
            mLastCellInfoList = list;
            mPhoneBase.notifyCellInfo(list);
          }
          break;
        }

      case EVENT_IMS_STATE_CHANGED: // received unsol
        mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE));
        break;

      case EVENT_IMS_STATE_DONE:
        AsyncResult ar = (AsyncResult) msg.obj;
        if (ar.exception == null) {
          int[] responseArray = (int[]) ar.result;
          mImsRegistered = (responseArray[0] == 1) ? true : false;
        }
        break;

      default:
        log("Unhandled message with number: " + msg.what);
        break;
    }
  }
 protected int getPhoneId() {
   return mPhoneBase.getPhoneId();
 }
 protected String getHomeOperatorNumeric() {
   return ((TelephonyManager) mPhoneBase.getContext().getSystemService(Context.TELEPHONY_SERVICE))
       .getSimOperatorNumericForPhone(mPhoneBase.getPhoneId());
 }
  // TBD move this to phone & implement in cdma & gsmphone
  DisconnectCause disconnectCauseFromCode(PhoneBase phone, int causeCode) {
    /** See 22.001 Annex F.4 for mapping of cause codes to local tones */
    switch (causeCode) {
      case CallFailCause.USER_BUSY:
        return DisconnectCause.BUSY;
      case CallFailCause.NO_CIRCUIT_AVAIL:
      case CallFailCause.TEMPORARY_FAILURE:
      case CallFailCause.SWITCHING_CONGESTION:
      case CallFailCause.CHANNEL_NOT_AVAIL:
      case CallFailCause.QOS_NOT_AVAIL:
      case CallFailCause.BEARER_NOT_AVAIL:
        return DisconnectCause.CONGESTION;
      case CallFailCause.ACM_LIMIT_EXCEEDED:
        return DisconnectCause.LIMIT_EXCEEDED;
      case CallFailCause.CALL_BARRED:
        return DisconnectCause.CALL_BARRED;
      case CallFailCause.FDN_BLOCKED:
        return DisconnectCause.FDN_BLOCKED;

      case CallFailCause.UNOBTAINABLE_NUMBER:
        return DisconnectCause.UNOBTAINABLE_NUMBER;

      case CallFailCause.DIAL_MODIFIED_TO_USSD:
        return DisconnectCause.DIAL_MODIFIED_TO_USSD;
      case CallFailCause.DIAL_MODIFIED_TO_SS:
        return DisconnectCause.DIAL_MODIFIED_TO_SS;
      case CallFailCause.DIAL_MODIFIED_TO_DIAL:
        return DisconnectCause.DIAL_MODIFIED_TO_DIAL;
      case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE:
        return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE;
      case CallFailCause.CDMA_DROP:
        return DisconnectCause.CDMA_DROP;
      case CallFailCause.CDMA_INTERCEPT:
        return DisconnectCause.CDMA_INTERCEPT;
      case CallFailCause.CDMA_REORDER:
        return DisconnectCause.CDMA_REORDER;
      case CallFailCause.CDMA_SO_REJECT:
        return DisconnectCause.CDMA_SO_REJECT;
      case CallFailCause.CDMA_RETRY_ORDER:
        return DisconnectCause.CDMA_RETRY_ORDER;
      case CallFailCause.CDMA_ACCESS_FAILURE:
        return DisconnectCause.CDMA_ACCESS_FAILURE;
      case CallFailCause.CDMA_PREEMPTED:
        return DisconnectCause.CDMA_PREEMPTED;
      case CallFailCause.CDMA_NOT_EMERGENCY:
        return DisconnectCause.CDMA_NOT_EMERGENCY;
      case CallFailCause.CDMA_ACCESS_BLOCKED:
        return DisconnectCause.CDMA_ACCESS_BLOCKED;
      case CallFailCause.ERROR_UNSPECIFIED:
      case CallFailCause.NORMAL_CLEARING:
      default:
        int serviceState = phone.getServiceState().getState();
        if (serviceState == ServiceState.STATE_POWER_OFF) {
          return DisconnectCause.POWER_OFF;
        } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
            || serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
          return DisconnectCause.OUT_OF_SERVICE;
        } else if (causeCode == CallFailCause.NORMAL_CLEARING) {
          return DisconnectCause.NORMAL;
        } else {
          return DisconnectCause.ERROR_UNSPECIFIED;
        }
    }
  }