private boolean handleCallHoldIncallSupplementaryService(String dialString)
      throws CallStateException {
    int len = dialString.length();

    if (len > 2) {
      return false;
    }

    GsmCall call = (GsmCall) getForegroundCall();

    if (len > 1) {
      try {
        char ch = dialString.charAt(1);
        int callIndex = ch - '0';
        GsmConnection conn = mCT.getConnectionByIndex(call, callIndex);

        // gsm index starts at 1, up to 5 connections in a call,
        if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: separate call " + callIndex);
          mCT.separate(conn);
        } else {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "separate: invalid call index " + callIndex);
          notifySuppServiceFailed(Phone.SuppService.SEPARATE);
        }
      } catch (CallStateException e) {
        if (LOCAL_DEBUG) Log.d(LOG_TAG, "separate failed", e);
        notifySuppServiceFailed(Phone.SuppService.SEPARATE);
      }
    } else {
      try {
        if (getRingingCall().getState() != GsmCall.State.IDLE) {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: accept ringing call");
          mCT.acceptCall();
        } else {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: switchWaitingOrHoldingAndActive");
          mCT.switchWaitingOrHoldingAndActive();
        }
      } catch (CallStateException e) {
        if (LOCAL_DEBUG) Log.d(LOG_TAG, "switch failed", e);
        notifySuppServiceFailed(Phone.SuppService.SWITCH);
      }
    }

    return true;
  }
  private boolean handleCcbsIncallSupplementaryService(String dialString)
      throws CallStateException {
    if (dialString.length() > 1) {
      return false;
    }

    Log.i(LOG_TAG, "MmiCode 5: CCBS not supported!");
    // Treat it as an "unknown" service.
    notifySuppServiceFailed(Phone.SuppService.UNKNOWN);
    return true;
  }
  private boolean handleMultipartyIncallSupplementaryService(String dialString)
      throws CallStateException {
    if (dialString.length() > 1) {
      return false;
    }

    if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 3: merge calls");
    try {
      conference();
    } catch (CallStateException e) {
      if (LOCAL_DEBUG) Log.d(LOG_TAG, "conference failed", e);
      notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
    }
    return true;
  }
  private boolean handleEctIncallSupplementaryService(String dialString) throws CallStateException {

    int len = dialString.length();

    if (len != 1) {
      return false;
    }

    if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 4: explicit call transfer");
    try {
      explicitCallTransfer();
    } catch (CallStateException e) {
      if (LOCAL_DEBUG) Log.d(LOG_TAG, "transfer failed", e);
      notifySuppServiceFailed(Phone.SuppService.TRANSFER);
    }
    return true;
  }
  private boolean handleCallDeflectionIncallSupplementaryService(String dialString)
      throws CallStateException {
    if (dialString.length() > 1) {
      return false;
    }

    if (getRingingCall().getState() != GsmCall.State.IDLE) {
      if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: rejectCall");
      try {
        mCT.rejectCall();
      } catch (CallStateException e) {
        if (LOCAL_DEBUG) Log.d(LOG_TAG, "reject failed", e);
        notifySuppServiceFailed(Phone.SuppService.REJECT);
      }
    } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) {
      if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: hangupWaitingOrBackground");
      mCT.hangupWaitingOrBackground();
    }

    return true;
  }
  private boolean handleCallWaitingIncallSupplementaryService(String dialString)
      throws CallStateException {
    int len = dialString.length();

    if (len > 2) {
      return false;
    }

    GsmCall call = (GsmCall) getForegroundCall();

    try {
      if (len > 1) {
        char ch = dialString.charAt(1);
        int callIndex = ch - '0';

        if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 1: hangupConnectionByIndex " + callIndex);
          mCT.hangupConnectionByIndex(call, callIndex);
        }
      } else {
        if (call.getState() != GsmCall.State.IDLE) {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 1: hangup foreground");
          // mCT.hangupForegroundResumeBackground();
          mCT.hangup(call);
        } else {
          if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 1: switchWaitingOrHoldingAndActive");
          mCT.switchWaitingOrHoldingAndActive();
        }
      }
    } catch (CallStateException e) {
      if (LOCAL_DEBUG) Log.d(LOG_TAG, "hangup failed", e);
      notifySuppServiceFailed(Phone.SuppService.HANGUP);
    }

    return true;
  }
  public void handleMessage(Message msg) {
    AsyncResult ar;

    switch (msg.what) {
      case EVENT_POLL_CALLS_RESULT:
        ar = (AsyncResult) msg.obj;

        if (msg == lastRelevantPoll) {
          if (DBG_POLL) log("handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
          needsPoll = false;
          lastRelevantPoll = null;
          handlePollCalls((AsyncResult) msg.obj);
        }
        break;

      case EVENT_OPERATION_COMPLETE:
        ar = (AsyncResult) msg.obj;
        operationComplete();
        break;

      case EVENT_SWITCH_RESULT:
      case EVENT_CONFERENCE_RESULT:
      case EVENT_SEPARATE_RESULT:
      case EVENT_ECT_RESULT:
        ar = (AsyncResult) msg.obj;
        if (ar.exception != null) {
          phone.notifySuppServiceFailed(getFailedService(msg.what));
        }
        operationComplete();
        break;

      case EVENT_GET_LAST_CALL_FAIL_CAUSE:
        int causeCode;
        ar = (AsyncResult) msg.obj;

        operationComplete();

        if (ar.exception != null) {
          // An exception occurred...just treat the disconnect
          // cause as "normal"
          causeCode = CallFailCause.NORMAL_CLEARING;
          Rlog.i(LOG_TAG, "Exception during getLastCallFailCause, assuming normal disconnect");
        } else {
          causeCode = ((int[]) ar.result)[0];
        }
        // Log the causeCode if its not normal
        if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL
            || causeCode == CallFailCause.TEMPORARY_FAILURE
            || causeCode == CallFailCause.SWITCHING_CONGESTION
            || causeCode == CallFailCause.CHANNEL_NOT_AVAIL
            || causeCode == CallFailCause.QOS_NOT_AVAIL
            || causeCode == CallFailCause.BEARER_NOT_AVAIL
            || causeCode == CallFailCause.ERROR_UNSPECIFIED) {
          GsmCellLocation loc = ((GsmCellLocation) phone.getCellLocation());
          EventLog.writeEvent(
              EventLogTags.CALL_DROP,
              causeCode,
              loc != null ? loc.getCid() : -1,
              TelephonyManager.getDefault().getNetworkType());
        }

        for (int i = 0, s = droppedDuringPoll.size(); i < s; i++) {
          GsmConnection conn = droppedDuringPoll.get(i);

          conn.onRemoteDisconnect(causeCode);
        }

        updatePhoneState();

        phone.notifyPreciseCallStateChanged();
        droppedDuringPoll.clear();
        break;

      case EVENT_REPOLL_AFTER_DELAY:
      case EVENT_CALL_STATE_CHANGE:
        pollCallsWhenSafe();
        break;

      case EVENT_RADIO_AVAILABLE:
        handleRadioAvailable();
        break;

      case EVENT_RADIO_NOT_AVAILABLE:
        handleRadioNotAvailable();
        break;
    }
  }