diff options
author | 2024-12-12 00:41:45 -0800 | |
---|---|---|
committer | 2024-12-16 11:48:21 -0800 | |
commit | 304911f3d38be34933232756d82fa7ecca83d378 (patch) | |
tree | aeb1f9009234ba2eabd619bf8d12c9416c38891d | |
parent | ec9d51f1d7cda752b333fbce676fa730fb877a14 (diff) |
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
-rw-r--r-- | system/bta/jv/bta_jv_act.cc | 26 | ||||
-rw-r--r-- | system/btif/src/btif_sock_rfc.cc | 42 | ||||
-rw-r--r-- | system/stack/include/port_api.h | 2 | ||||
-rw-r--r-- | system/stack/include/rfcdefs.h | 5 | ||||
-rw-r--r-- | system/stack/rfcomm/port_rfc.cc | 7 |
5 files changed, 74 insertions, 8 deletions
diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 7b6fa38ca8..0a752d710b 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -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; } diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index d15bbf1891..2e42f07c32 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -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; } } diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h index 856166b144..3a9fd7e4b3 100644 --- a/system/stack/include/port_api.h +++ b/system/stack/include/port_api.h @@ -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 { diff --git a/system/stack/include/rfcdefs.h b/system/stack/include/rfcdefs.h index 628fc77c45..35be4076d6 100644 --- a/system/stack/include/rfcdefs.h +++ b/system/stack/include/rfcdefs.h @@ -45,6 +45,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 */ #define RFCOMM_CMD_BUF_SIZE BT_SMALL_BUFFER_SIZE // command packet buffer size diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc index 01c8270869..72da403105 100644 --- a/system/stack/rfcomm/port_rfc.cc +++ b/system/stack/rfcomm/port_rfc.cc @@ -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); |