Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 304911f3 authored by Liang Li's avatar Liang Li
Browse files

Determine local mtu for offload RFCOMM socket

The local MTU is selected as the minimum of:
  - The socket hal's offload capabilities
  - The application's requested maximum RX packet size

However, the MTU must be at least the minimum required by the RFCOMM specification.

Flag: com.android.bluetooth.flags.socket_settings_api
Bug: 342012881
Bug: 374358112
Test: m com.android.btservices
Change-Id: Ia4a789aec3068d05fe80833246acc08774c86502
parent ec9d51f1
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -1536,9 +1536,16 @@ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddre
            0);
  }

  if (RFCOMM_CreateConnectionWithSecurity(
              UUID_SERVCLASS_SERIAL_PORT, remote_scn, false, BTA_JV_DEF_RFC_MTU, peer_bd_addr,
              &handle, bta_jv_port_mgmt_cl_cback, sec_mask, cfg) != PORT_SUCCESS) {
  uint16_t mtu = BTA_JV_DEF_RFC_MTU;
  if (com::android::bluetooth::flags::socket_settings_api()) {
    if (cfg.rx_mtu_present) {
      mtu = cfg.rx_mtu;
    }
  }

  if (RFCOMM_CreateConnectionWithSecurity(UUID_SERVCLASS_SERIAL_PORT, remote_scn, false, mtu,
                                          peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback,
                                          sec_mask, cfg) != PORT_SUCCESS) {
    log::error("RFCOMM_CreateConnection failed");
    bta_jv.rfc_cl_init.status = tBTA_JV_STATUS::FAILURE;
  } else {
@@ -1856,10 +1863,17 @@ void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t ma
  memset(&evt_data, 0, sizeof(evt_data));
  evt_data.status = tBTA_JV_STATUS::FAILURE;

  uint16_t mtu = BTA_JV_DEF_RFC_MTU;
  if (com::android::bluetooth::flags::socket_settings_api()) {
    if (cfg.rx_mtu_present) {
      mtu = cfg.rx_mtu;
    }
  }

  do {
    if (RFCOMM_CreateConnectionWithSecurity(0, local_scn, true, BTA_JV_DEF_RFC_MTU,
                                            RawAddress::kAny, &handle, bta_jv_port_mgmt_sr_cback,
                                            sec_mask, cfg) != PORT_SUCCESS) {
    if (RFCOMM_CreateConnectionWithSecurity(0, local_scn, true, mtu, RawAddress::kAny, &handle,
                                            bta_jv_port_mgmt_sr_cback, sec_mask,
                                            cfg) != PORT_SUCCESS) {
      log::error("RFCOMM_CreateConnection failed");
      break;
    }
+40 −2
Original line number Diff line number Diff line
@@ -329,10 +329,32 @@ bt_status_t btsock_rfc_control_req(uint8_t dlci, const RawAddress& bd_addr, uint
  return BT_STATUS_SUCCESS;
}

/// Determine the local MTU for the offloaded RFCOMM connection.
///
/// The local MTU is selected as the minimum of:
///   - The socket hal's offload capabilities (socket_cap.rfcommCapabilities.max_frame_size)
///   - The application's requested maximum RX packet size (app_max_rx_packet_size)
///
/// However, the MTU must be at least the minimum required by the RFCOMM
/// specification (RFCOMM_MIN_MTU).
static bool btsock_rfc_get_offload_mtu(int app_max_rx_packet_size, int* rx_mtu) {
  hal::SocketCapabilities socket_cap =
          bluetooth::shim::GetLppOffloadManager()->GetSocketCapabilities();
  if (!socket_cap.rfcomm_capabilities.number_of_supported_sockets) {
    return false;
  }
  // Socket HAL client has already verified that the MTU is in a valid range.
  int mtu = static_cast<int>(socket_cap.rfcomm_capabilities.max_frame_size);
  mtu = std::min(mtu, app_max_rx_packet_size);
  mtu = std::max(mtu, RFCOMM_MIN_MTU);
  *rx_mtu = mtu;
  return true;
}

bt_status_t btsock_rfc_listen(const char* service_name, const Uuid* service_uuid, int channel,
                              int* sock_fd, int flags, int app_uid, btsock_data_path_t data_path,
                              const char* socket_name, uint64_t hub_id, uint64_t endpoint_id,
                              int /* max_rx_packet_size */) {
                              int max_rx_packet_size) {
  log::assert_that(sock_fd != NULL, "assert failed: sock_fd != NULL");
  log::assert_that((service_uuid != NULL) || (channel >= 1 && channel <= MAX_RFC_CHANNEL) ||
                           ((flags & BTSOCK_FLAG_NO_SDP) != 0),
@@ -391,6 +413,11 @@ bt_status_t btsock_rfc_listen(const char* service_name, const Uuid* service_uuid
    }
    slot->hub_id = hub_id;
    slot->endpoint_id = endpoint_id;
    if (data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
      if (!btsock_rfc_get_offload_mtu(max_rx_packet_size, &slot->mtu)) {
        return BT_STATUS_UNSUPPORTED;
      }
    }
  }
  btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, slot->id);
  // start monitoring the socketpair to get call back when app is accepting on server socket
@@ -404,7 +431,7 @@ bt_status_t btsock_rfc_listen(const char* service_name, const Uuid* service_uuid
bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, const Uuid* service_uuid, int channel,
                               int* sock_fd, int flags, int app_uid, btsock_data_path_t data_path,
                               const char* socket_name, uint64_t hub_id, uint64_t endpoint_id,
                               int /* max_rx_packet_size */) {
                               int max_rx_packet_size) {
  log::assert_that(sock_fd != NULL, "assert failed: sock_fd != NULL");
  log::assert_that((service_uuid != NULL) || (channel >= 1 && channel <= MAX_RFC_CHANNEL),
                   "assert failed: (service_uuid != NULL) || (channel >= 1 && channel <= "
@@ -468,6 +495,11 @@ bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, const Uuid* service_uu
    }
    slot->hub_id = hub_id;
    slot->endpoint_id = endpoint_id;
    if (data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
      if (!btsock_rfc_get_offload_mtu(max_rx_packet_size, &slot->mtu)) {
        return BT_STATUS_UNSUPPORTED;
      }
    }
  }
  btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, slot->id);

@@ -1005,6 +1037,8 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
          if (rs->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
            cfg.init_credit_present = true;
            cfg.init_credit = 0;
            cfg.rx_mtu_present = rs->mtu > 0;
            cfg.rx_mtu = rs->mtu;
          }
        }
        // now start the rfcomm server after sdp & channel # assigned
@@ -1043,6 +1077,8 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
        if (slot->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
          cfg.init_credit_present = true;
          cfg.init_credit = 0;
          cfg.rx_mtu_present = slot->mtu > 0;
          cfg.rx_mtu = slot->mtu;
        }
      }
      // Start the rfcomm server after sdp & channel # assigned.
@@ -1100,6 +1136,8 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) {
    if (slot->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
      cfg.init_credit_present = true;
      cfg.init_credit = 0;
      cfg.rx_mtu_present = slot->mtu > 0;
      cfg.rx_mtu = slot->mtu;
    }
  }

+2 −0
Original line number Diff line number Diff line
@@ -186,6 +186,8 @@ inline std::string port_result_text(const tPORT_RESULT& result) {
struct RfcommCfgInfo {
  bool init_credit_present;
  uint16_t init_credit;
  bool rx_mtu_present;
  uint16_t rx_mtu;
};

namespace std {
+5 −0
Original line number Diff line number Diff line
@@ -44,6 +44,11 @@
 */
#define RFCOMM_DEFAULT_MTU 127

/*
 *  The minimum allowed MTU should be 23 according to the RFCOMM specs
 */
#define RFCOMM_MIN_MTU 23

/*
 * RFCOMM buffer sizes
 */
+7 −0
Original line number Diff line number Diff line
@@ -305,6 +305,13 @@ void PORT_ParNegInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl, uin

  p_port->bd_addr = p_mcb->bd_addr;

  /* Update the local mtu with the optional configuration if set by the app */
  if (com::android::bluetooth::flags::socket_settings_api()) {
    if (p_port->rfc_cfg_info.rx_mtu_present) {
      p_port->mtu = p_port->rfc_cfg_info.rx_mtu;
    }
  }

  /* Connection is up and we know local and remote features, select MTU */
  port_select_mtu(p_port);