/**
   * Sets the new call state onto the call and performs some additional logic associated with
   * setting the state.
   */
  private void setNewState(Call call, int newState, Connection connection) {
    Preconditions.checkState(call.getState() != newState);

    // When starting an outgoing call, we need to grab gateway information
    // for the call, if available, and set it.
    final RawGatewayInfo info = mCallGatewayManager.getGatewayInfo(connection);

    if (Call.State.isDialing(newState)) {
      if (!info.isEmpty()) {
        call.setGatewayNumber(info.getFormattedGatewayNumber());
        call.setGatewayPackage(info.packageName);
      }
    } else if (!Call.State.isConnected(newState)) {
      mCallGatewayManager.clearGatewayData(connection);
    }

    call.setState(newState);
  }
  /**
   * Updates the Call properties to match the state of the connection object that it represents.
   *
   * @param call The call object to update.
   * @param connection The connection object from which to update call.
   * @param isForConference There are slight differences in how we populate data for conference
   *     calls. This boolean tells us which method to use.
   */
  private boolean updateCallFromConnection(
      Call call, Connection connection, boolean isForConference) {
    boolean changed = false;

    final int newState = translateStateFromTelephony(connection, isForConference);

    if (call.getState() != newState) {
      setNewState(call, newState, connection);
      changed = true;
    }

    mapCallDetails(call, connection);

    final Call.DisconnectCause newDisconnectCause =
        translateDisconnectCauseFromTelephony(connection.getDisconnectCause());
    if (call.getDisconnectCause() != newDisconnectCause) {
      call.setDisconnectCause(newDisconnectCause);
      changed = true;
    }

    final long oldConnectTime = call.getConnectTime();
    if (oldConnectTime != connection.getConnectTime()) {
      call.setConnectTime(connection.getConnectTime());
      changed = true;
    }

    // creation time should be fixed
    call.setCreateTime(connection.getCreateTime());

    if (!isForConference) {
      // Number
      final String oldNumber = call.getNumber();
      String newNumber = connection.getAddress();
      RawGatewayInfo info = mCallGatewayManager.getGatewayInfo(connection);
      if (!info.isEmpty()) {
        newNumber = info.trueNumber;
      }
      if (TextUtils.isEmpty(oldNumber) || !oldNumber.equals(newNumber)) {
        call.setNumber(newNumber);
        changed = true;
      }

      // Number presentation
      final int newNumberPresentation = connection.getNumberPresentation();
      if (call.getNumberPresentation() != newNumberPresentation) {
        call.setNumberPresentation(newNumberPresentation);
        changed = true;
      }

      // Name
      final String oldCnapName = call.getCnapName();
      if (TextUtils.isEmpty(oldCnapName) || !oldCnapName.equals(connection.getCnapName())) {
        call.setCnapName(connection.getCnapName());
        changed = true;
      }

      // Name Presentation
      final int newCnapNamePresentation = connection.getCnapNamePresentation();
      if (call.getCnapNamePresentation() != newCnapNamePresentation) {
        call.setCnapNamePresentation(newCnapNamePresentation);
        changed = true;
      }
    } else {

      // update the list of children by:
      // 1) Saving the old set
      // 2) Removing all children
      // 3) Adding the correct children into the Call
      // 4) Comparing the new children set with the old children set
      ImmutableSortedSet<Integer> oldSet = call.getChildCallIds();
      call.removeAllChildren();

      if (connection.getCall() != null) {
        for (Connection childConn : connection.getCall().getConnections()) {
          final Call childCall = getCallFromMap(mCallMap, childConn, false);
          if (childCall != null && childConn.isAlive()) {
            call.addChildId(childCall.getCallId());
          }
        }
      }
      changed |= !oldSet.equals(call.getChildCallIds());
    }

    // Subscription id, this shall be done when Call object created.
    if (call.getSubscription() == MSimConstants.INVALID_SUBSCRIPTION) {
      call.setSubscription(connection.getCall().getPhone().getSubscription());
    }

    /** !!! Uses values from connection and call collected above so this part must be last !!! */
    final int newCapabilities = getCapabilitiesFor(connection, call, isForConference);
    if (call.getCapabilities() != newCapabilities) {
      call.setCapabilities(newCapabilities);
      changed = true;
    }

    return changed;
  }