/**
   * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
   * connection.
   *
   * @param phoneAccountHandle The phone account handle for the connection.
   * @param connection The connection to add.
   */
  public final void addExistingConnection(
      PhoneAccountHandle phoneAccountHandle, Connection connection) {

    String id = addExistingConnectionInternal(connection);
    if (id != null) {
      List<String> emptyList = new ArrayList<>(0);

      ParcelableConnection parcelableConnection =
          new ParcelableConnection(
              phoneAccountHandle,
              connection.getState(),
              connection.getConnectionCapabilities(),
              connection.getAddress(),
              connection.getAddressPresentation(),
              connection.getCallerDisplayName(),
              connection.getCallerDisplayNamePresentation(),
              connection.getVideoProvider() == null
                  ? null
                  : connection.getVideoProvider().getInterface(),
              connection.getVideoState(),
              connection.isRingbackRequested(),
              connection.getAudioModeIsVoip(),
              connection.getStatusHints(),
              connection.getDisconnectCause(),
              emptyList);
      mAdapter.addExistingConnection(id, parcelableConnection);
    }
  }
  public synchronized void handlePacket(Connection c, Packet p) {
    Address address = c.getAddress();
    System.out.println(p.toString());

    // silently ignore packets from a connection if we haven't received a version packet

    if (!c.hasReceivedVersion() && p.packetType() != PacketType.VERSION) {
      return;
    }

    switch (p.packetType()) {
      case VERSION:
        VersionPacket v = (VersionPacket) p;
        long ourVersion = ProtocolVersion.version(),
            theirVersion = v.getVersion(),
            negotiatedVersion;
        negotiatedVersion = theirVersion < ourVersion ? theirVersion : ourVersion;
        c.setVersion(negotiatedVersion);
        c.hasReceivedVersion(true);
        addressBook.justSeen(address);
        if (negotiatedVersion >= 209) {
          Packet verack = c.createPacket(PacketType.VERACK);
          c.sendPacket(verack);
        }
        break;
      case VERACK:
        c.hasRecievedVerack(true);
        addressBook.justSeen(address);
        break;
      case HEADERS:
        // primitive headers function
        HeadersPacket h = (HeadersPacket) p;
        if (h.headers().size() == 0) {
          break;
        }
        for (Block header : h.headers()) {
          try {
            blockChain.addBlock(header);

          } catch (InvalidBlockException e) {
            // TODO actually handle
            e.printStackTrace();
            continue;
          } catch (OrphanBlockException e) {
            // TODO actually handle
            e.printStackTrace();
            continue;
          } catch (BlockExistsException e) {
            // TODO actually handle
            e.printStackTrace();
            continue;
          }
        }
        GetHeadersPacket gh = (GetHeadersPacket) c.createPacket(PacketType.GETHEADERS);
        gh.startHashes().add(blockChain.topBlock().hash());
        c.sendPacket(gh);
    }
  }
 public synchronized Connection connectTo(Address a) throws IOException {
   addressBook.justTried(a);
   Connection c = new Connection(this, a);
   connections.add(c);
   addressBook.justConnected(a);
   VersionPacket p = (VersionPacket) c.createPacket(PacketType.VERSION);
   p.setRemoteAddress(c.getAddress());
   p.setFromAddress(localAddress);
   c.sendPacket(p);
   c.connect();
   return c;
 }
 public void OnConnectionServiceReady() {
   if (isMaster) {
     mConnection.startServer(
         1,
         connectedListener,
         maxConnectionsListener,
         dataReceivedListener,
         disconnectedListener);
     self.setTitle(
         "MultiScreen Video: " + mConnection.getName() + "-" + mConnection.getAddress());
   } else {
     Intent serverListIntent = new Intent(self, ServerListActivity.class);
     startActivityForResult(serverListIntent, SERVER_LIST_RESULT_CODE);
   }
 }
  /**
   * This can be used by telecom to either create a new outgoing call or attach to an existing
   * incoming call. In either case, telecom will cycle through a set of services and call
   * createConnection util a connection service cancels the process or completes it successfully.
   */
  private void createConnection(
      final PhoneAccountHandle callManagerAccount,
      final String callId,
      final ConnectionRequest request,
      boolean isIncoming,
      boolean isUnknown) {
    Log.d(
        this,
        "createConnection, callManagerAccount: %s, callId: %s, request: %s, "
            + "isIncoming: %b, isUnknown: %b",
        callManagerAccount,
        callId,
        request,
        isIncoming,
        isUnknown);

    Connection connection =
        isUnknown
            ? onCreateUnknownConnection(callManagerAccount, request)
            : isIncoming
                ? onCreateIncomingConnection(callManagerAccount, request)
                : onCreateOutgoingConnection(callManagerAccount, request);
    Log.d(this, "createConnection, connection: %s", connection);
    if (connection == null) {
      connection = Connection.createFailedConnection(new DisconnectCause(DisconnectCause.ERROR));
    }

    if (connection.getState() != Connection.STATE_DISCONNECTED) {
      addConnection(callId, connection);
    }

    Uri address = connection.getAddress();
    String number = address == null ? "null" : address.getSchemeSpecificPart();
    Log.v(
        this,
        "createConnection, number: %s, state: %s, capabilities: %s",
        Connection.toLogSafePhoneNumber(number),
        Connection.stateToString(connection.getState()),
        Connection.capabilitiesToString(connection.getConnectionCapabilities()));

    Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
    mAdapter.handleCreateConnectionComplete(
        callId,
        request,
        new ParcelableConnection(
            request.getAccountHandle(),
            connection.getState(),
            connection.getConnectionCapabilities(),
            connection.getAddress(),
            connection.getAddressPresentation(),
            connection.getCallerDisplayName(),
            connection.getCallerDisplayNamePresentation(),
            connection.getVideoProvider() == null
                ? null
                : connection.getVideoProvider().getInterface(),
            connection.getVideoState(),
            connection.isRingbackRequested(),
            connection.getAudioModeIsVoip(),
            connection.getStatusHints(),
            connection.getDisconnectCause(),
            createIdList(connection.getConferenceables())));
  }
 private void removeConnectionsFromAddressList(
     List<Connection> connections, List<Address> addresses) {
   for (Connection c : connections) {
     addresses.remove(c.getAddress());
   }
 }