/* package */ void hangup(GsmCall call) throws CallStateException {
    if (call.getConnections().size() == 0) {
      throw new CallStateException("no connections in call");
    }

    if (call == ringingCall) {
      if (Phone.DEBUG_PHONE) log("(ringing) hangup waiting or background");
      cm.hangupWaitingOrBackground(obtainCompleteMessage());
    } else if (call == foregroundCall) {
      if (call.isDialingOrAlerting()) {
        if (Phone.DEBUG_PHONE) {
          log("(foregnd) hangup dialing or alerting...");
        }
        hangup((GsmConnection) (call.getConnections().get(0)));
      } else {
        hangupForegroundResumeBackground();
      }
    } else if (call == backgroundCall) {
      if (ringingCall.isRinging()) {
        if (Phone.DEBUG_PHONE) {
          log("hangup all conns in background call");
        }
        hangupAllConnections(call);
      } else {
        hangupWaitingOrBackground();
      }
    } else {
      throw new RuntimeException("GsmCall " + call + "does not belong to GsmCallTracker " + this);
    }

    call.onHangupLocal();
    phone.notifyPreciseCallStateChanged();
  }
  boolean canDial() {
    boolean ret;
    int serviceState = phone.getServiceState().getState();
    String disableCall = SystemProperties.get(TelephonyProperties.PROPERTY_DISABLE_CALL, "false");

    ret =
        (serviceState != ServiceState.STATE_POWER_OFF)
            && pendingMO == null
            && !ringingCall.isRinging()
            && !disableCall.equals("true")
            && (!foregroundCall.getState().isAlive() || !backgroundCall.getState().isAlive());

    return ret;
  }
  private void updatePhoneState() {
    PhoneConstants.State oldState = state;

    if (ringingCall.isRinging()) {
      state = PhoneConstants.State.RINGING;
    } else if (pendingMO != null || !(foregroundCall.isIdle() && backgroundCall.isIdle())) {
      state = PhoneConstants.State.OFFHOOK;
    } else {
      state = PhoneConstants.State.IDLE;
    }

    if (state == PhoneConstants.State.IDLE && oldState != state) {
      voiceCallEndedRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
    } else if (oldState == PhoneConstants.State.IDLE && oldState != state) {
      voiceCallStartedRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
    }

    if (state != oldState) {
      phone.notifyPhoneStateChanged();
    }
  }