summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Liang Li <lianglli@google.com> 2024-12-12 00:41:45 -0800
committer Liang Li <lianglli@google.com> 2024-12-16 11:48:21 -0800
commit304911f3d38be34933232756d82fa7ecca83d378 (patch)
treeaeb1f9009234ba2eabd619bf8d12c9416c38891d
parentec9d51f1d7cda752b333fbce676fa730fb877a14 (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.cc26
-rw-r--r--system/btif/src/btif_sock_rfc.cc42
-rw-r--r--system/stack/include/port_api.h2
-rw-r--r--system/stack/include/rfcdefs.h5
-rw-r--r--system/stack/rfcomm/port_rfc.cc7
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);