/**
   * Called when there is a change to the call list. Sets the In-Call state for the entire in-call
   * app based on the information it gets from CallList. Dispatches the in-call state to all
   * listeners. Can trigger the creation or destruction of the UI based on the states that is
   * calculates.
   */
  @Override
  public void onCallListChange(CallList callList) {
    if (callList == null) {
      return;
    }
    InCallState newState = getPotentialStateFromCallList(callList);
    newState = startOrFinishUi(newState);

    // Renable notification shade and soft navigation buttons, if we are no longer in the
    // incoming call screen
    if (!newState.isIncoming()) {
      if (mAccelerometerListener != null) {
        mAccelerometerListener.enableSensor(false);
      }
      CallCommandClient.getInstance().setSystemBarNavigationEnabled(true);
    }

    // Set the new state before announcing it to the world
    Log.i(this, "Phone switching state: " + mInCallState + " -> " + newState);
    mInCallState = newState;

    // notify listeners of new state
    for (InCallStateListener listener : mListeners) {
      Log.d(this, "Notify " + listener + " of state " + mInCallState.toString());
      listener.onStateChange(mInCallState, callList);
    }

    if (isActivityStarted()) {
      final boolean hasCall =
          callList.getActiveOrBackgroundCall() != null || callList.getOutgoingCall() != null;
      mInCallActivity.dismissKeyguard(hasCall);
    }
  }
  /** Given the call list, return the state in which the in-call screen should be. */
  public static InCallState getPotentialStateFromCallList(CallList callList) {

    InCallState newState = InCallState.NO_CALLS;

    if (callList == null) {
      return newState;
    }
    if (callList.getIncomingCall() != null) {
      newState = InCallState.INCOMING;
    } else if (callList.getOutgoingCall() != null) {
      newState = InCallState.OUTGOING;
    } else if (callList.getActiveCall() != null
        || callList.getBackgroundCall() != null
        || callList.getDisconnectedCall() != null
        || callList.getDisconnectingCall() != null) {
      newState = InCallState.INCALL;
    }

    return newState;
  }
  /** Hangs up any active or outgoing calls. */
  public void hangUpOngoingCall(Context context) {
    // By the time we receive this intent, we could be shut down and call list
    // could be null.  Bail in those cases.
    if (mCallList == null) {
      if (mStatusBarNotifier == null) {
        // The In Call UI has crashed but the notification still stayed up. We should not
        // come to this stage.
        StatusBarNotifier.clearInCallNotification(context);
      }
      return;
    }

    Call call = mCallList.getOutgoingCall();
    if (call == null) {
      call = mCallList.getActiveOrBackgroundCall();
    }

    if (call != null) {
      CallCommandClient.getInstance().disconnectCall(call.getCallId());
    }
  }