/**
   * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
   *
   * <p>A remote device connecting to this socket will be authenticated and communication on this
   * socket will be encrypted.
   *
   * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
   * {@link BluetoothServerSocket}.
   *
   * <p>The system will assign an unused RFCOMM channel to listen on.
   *
   * <p>The system will also register a Service Discovery Protocol (SDP) record with the local SDP
   * server containing the specified UUID, service name, and auto-assigned channel. Remote Bluetooth
   * devices can use the same UUID to query our SDP server and discover which channel to connect to.
   * This SDP record will be removed when this socket is closed, or if this application closes
   * unexpectedly.
   *
   * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to connect to this socket from
   * another device using the same {@link UUID}.
   *
   * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
   *
   * @param name service name for SDP record
   * @param uuid uuid for SDP record
   * @return a listening RFCOMM BluetoothServerSocket
   * @throws IOException on error, for example Bluetooth not available, or insufficient permissions,
   *     or channel in use.
   */
  public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
      throws IOException {
    RfcommChannelPicker picker = new RfcommChannelPicker(uuid);

    BluetoothServerSocket socket;
    int channel;
    int errno;
    while (true) {
      channel = picker.nextChannel();

      if (channel == -1) {
        throw new IOException("No available channels");
      }

      socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel);
      errno = socket.mSocket.bindListen();
      if (errno == 0) {
        if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel);
        break; // success
      } else if (errno == BluetoothSocket.EADDRINUSE) {
        if (DBG) Log.d(TAG, "RFCOMM channel " + channel + " in use");
        try {
          socket.close();
        } catch (IOException e) {
        }
        continue; // try another channel
      } else {
        try {
          socket.close();
        } catch (IOException e) {
        }
        socket.mSocket.throwErrnoNative(errno); // Exception as a result of bindListen()
      }
    }

    int handle = -1;
    try {
      handle = mService.addRfcommServiceRecord(name, new ParcelUuid(uuid), channel, new Binder());
    } catch (RemoteException e) {
      Log.e(TAG, "", e);
    }
    if (handle == -1) {
      try {
        socket.close();
      } catch (IOException e) {
      }
      throw new IOException("Not able to register SDP record for " + name);
    }
    socket.setCloseHandler(mHandler, handle);
    return socket;
  }