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

Commit 1c4a3f80 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

One less copy when sending LE CoC data.

After this patch, data is read from socket directly into BT_HDR that is
passed down the stack, rather than copying the data later.

Test: manual
Bug: 68359837
Change-Id: I3f304e6c7e60ce64b44350678d0ba10324fc97bc
parent 2eaa4c42
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -678,8 +678,7 @@ tBTA_JV_STATUS BTA_JvL2capReady(uint32_t handle, uint32_t* p_data_size);
 *                  BTA_JV_FAILURE, otherwise.
 *
 ******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
                                uint8_t* p_data, uint16_t len,
tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg,
                                uint32_t user_id);

/*******************************************************************************
@@ -691,15 +690,10 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
 *                  called with BTA_JV_L2CAP_WRITE_FIXED_EVT. Works for
 *                  fixed-channel connections
 *
 * Returns          BTA_JV_SUCCESS, if the request is being processed.
 *                  BTA_JV_FAILURE, otherwise.
 *
 ******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
                                     uint32_t req_id,
                                     tBTA_JV_L2CAP_CBACK* p_cback,
                                     uint8_t* p_data, uint16_t len,
                                     uint32_t user_id);
void BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
                           uint32_t req_id, tBTA_JV_L2CAP_CBACK* p_cback,
                           BT_HDR* msg, uint32_t user_id);

/*******************************************************************************
 *
+12 −23
Original line number Diff line number Diff line
@@ -1138,8 +1138,8 @@ void bta_jv_l2cap_stop_server(uint16_t local_psm, uint32_t l2cap_socket_id) {
}

/* Write data to an L2CAP connection */
void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, uint8_t* p_data,
                        uint16_t len, uint32_t user_id, tBTA_JV_L2C_CB* p_cb) {
void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, BT_HDR* msg,
                        uint32_t user_id, tBTA_JV_L2C_CB* p_cb) {
  /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be
   * send through the API this check should not be needed. But the API is not
   * designed to be used (safely at least) in a multi-threaded scheduler, hence
@@ -1160,7 +1160,7 @@ void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, uint8_t* p_data,
     * channel is disconnected after the API function is called, but before the
     * message is handled. */
    LOG(ERROR) << __func__ << ": p_cb->p_cback == NULL";
    osi_free(p_data);
    osi_free(msg);
    return;
  }

@@ -1169,24 +1169,20 @@ void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, uint8_t* p_data,
  evt_data.handle = handle;
  evt_data.req_id = req_id;
  evt_data.cong = p_cb->cong;
  evt_data.len = len;
  evt_data.len = msg->len;

  bta_jv_pm_conn_busy(p_cb->p_pm_cb);

  if (!evt_data.cong) {
    BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET + len +
                                      L2CAP_FCS_LENGTH);
    msg->offset = L2CAP_MIN_OFFSET;
    msg->len = len;
    memcpy((uint8_t*)(msg) + BT_HDR_SIZE + msg->offset, p_data, msg->len);
    // TODO: this was set only for non-fixed channel packets. Get rid of it.
  // TODO: this was set only for non-fixed channel packets. Is that needed ?
  msg->event = BT_EVT_TO_BTU_SP_DATA;

  if (evt_data.cong) {
    osi_free(msg);
  } else {
    if (GAP_ConnWriteData(handle, msg) == BT_PASS)
      evt_data.status = BTA_JV_SUCCESS;
  }

  osi_free(p_data);

  tBTA_JV bta_jv;
  bta_jv.l2c_write = evt_data;
  p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, &bta_jv, user_id);
@@ -1194,8 +1190,8 @@ void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, uint8_t* p_data,

/* Write data to an L2CAP connection using Fixed channels */
void bta_jv_l2cap_write_fixed(uint16_t channel, const RawAddress& addr,
                              uint32_t req_id, uint8_t* p_data, uint16_t len,
                              uint32_t user_id, tBTA_JV_L2CAP_CBACK* p_cback) {
                              uint32_t req_id, BT_HDR* msg, uint32_t user_id,
                              tBTA_JV_L2CAP_CBACK* p_cback) {
  tBTA_JV_L2CAP_WRITE_FIXED evt_data;
  evt_data.status = BTA_JV_FAILURE;
  evt_data.channel = channel;
@@ -1203,13 +1199,6 @@ void bta_jv_l2cap_write_fixed(uint16_t channel, const RawAddress& addr,
  evt_data.req_id = req_id;
  evt_data.len = 0;

  BT_HDR* msg = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + len + L2CAP_MIN_OFFSET);
  msg->offset = L2CAP_MIN_OFFSET;
  msg->len = len;
  memcpy((uint8_t*)(msg) + BT_HDR_SIZE + msg->offset, p_data, msg->len);

  osi_free(p_data);

  L2CA_SendFixedChnlData(channel, addr, msg);

  tBTA_JV bta_jv;
+8 −15
Original line number Diff line number Diff line
@@ -514,18 +514,17 @@ tBTA_JV_STATUS BTA_JvL2capReady(uint32_t handle, uint32_t* p_data_size) {
 *                  BTA_JV_FAILURE, otherwise.
 *
 ******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
                                uint8_t* p_data, uint16_t len,
tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg,
                                uint32_t user_id) {
  VLOG(2) << __func__;

  if (handle >= BTA_JV_MAX_L2C_CONN || !bta_jv_cb.l2c_cb[handle].p_cback) {
    osi_free(p_data);
    osi_free(msg);
    return BTA_JV_FAILURE;
  }

  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write, handle, req_id, p_data,
                                   len, user_id, &bta_jv_cb.l2c_cb[handle]));
  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write, handle, req_id, msg,
                                   user_id, &bta_jv_cb.l2c_cb[handle]));
  return BTA_JV_SUCCESS;
}

@@ -539,20 +538,14 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id,
 *                  fixed-channel connections. This function takes ownership of
 *                  p_data, and will osi_free it.
 *
 * Returns          BTA_JV_SUCCESS, if the request is being processed.
 *                  BTA_JV_FAILURE, otherwise.
 *
 ******************************************************************************/
tBTA_JV_STATUS BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
                                     uint32_t req_id,
                                     tBTA_JV_L2CAP_CBACK* p_cback,
                                     uint8_t* p_data, uint16_t len,
                                     uint32_t user_id) {
void BTA_JvL2capWriteFixed(uint16_t channel, const RawAddress& addr,
                           uint32_t req_id, tBTA_JV_L2CAP_CBACK* p_cback,
                           BT_HDR* msg, uint32_t user_id) {
  VLOG(2) << __func__;

  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write_fixed, channel, addr,
                                   req_id, p_data, len, user_id, p_cback));
  return BTA_JV_SUCCESS;
                                   req_id, msg, user_id, p_cback));
}

/*******************************************************************************
+4 −5
Original line number Diff line number Diff line
@@ -166,9 +166,8 @@ extern void bta_jv_l2cap_start_server(
    uint32_t l2cap_socket_id);
extern void bta_jv_l2cap_stop_server(uint16_t local_psm,
                                     uint32_t l2cap_socket_id);
extern void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id,
                               uint8_t* p_data, uint16_t len, uint32_t user_id,
                               tBTA_JV_L2C_CB* p_cb);
extern void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, BT_HDR* msg,
                               uint32_t user_id, tBTA_JV_L2C_CB* p_cb);
extern void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
                                  uint8_t remote_scn,
                                  const RawAddress& peer_bd_addr,
@@ -193,8 +192,8 @@ extern void bta_jv_l2cap_start_server_le(uint16_t local_chan,
                                         uint32_t l2cap_socket_id);
extern void bta_jv_l2cap_stop_server_le(uint16_t local_chan);
extern void bta_jv_l2cap_write_fixed(uint16_t channel, const RawAddress& addr,
                                     uint32_t req_id, uint8_t* p_data,
                                     uint16_t len, uint32_t user_id,
                                     uint32_t req_id, BT_HDR* msg,
                                     uint32_t user_id,
                                     tBTA_JV_L2CAP_CBACK* p_cback);
extern void bta_jv_l2cap_close_fixed(uint32_t handle);

+17 −5
Original line number Diff line number Diff line
@@ -961,6 +961,19 @@ static bool flush_incoming_que_on_wr_signal_l(l2cap_socket* sock) {
  return false;
}

inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
  // We need FCS only for L2CAP_FCR_ERTM_MODE, but it's just 2 bytes so it's ok
  BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET + len +
                                    L2CAP_FCS_LENGTH);
  msg->offset = L2CAP_MIN_OFFSET;
  msg->len = len;
  return msg;
}

inline uint8_t* get_l2cap_sdu_start_ptr(BT_HDR* msg) {
  return (uint8_t*)(msg) + BT_HDR_SIZE + msg->offset;
}

void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) {
  char drop_it = false;

@@ -984,11 +997,11 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) {
           by BT spec). */
        size = std::min(size, (int)sock->mps);

        uint8_t* buffer = (uint8_t*)osi_malloc(size);
        BT_HDR* buffer = malloc_l2cap_buf(size);
        /* The socket is created with SOCK_SEQPACKET, hence we read one message
         * at the time. */
        ssize_t count;
        OSI_NO_INTR(count = recv(fd, buffer, size,
        OSI_NO_INTR(count = recv(fd, get_l2cap_sdu_start_ptr(buffer), size,
                                 MSG_NOSIGNAL | MSG_DONTWAIT | MSG_TRUNC));
        if (count > L2CAP_LE_MAX_MPS) {
          /* This can't happen thanks to check in BluetoothSocket.java but leave
@@ -1002,11 +1015,10 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) {
        if (sock->fixed_chan) {
          // will take care of freeing buffer
          BTA_JvL2capWriteFixed(sock->channel, sock->addr, PTR_TO_UINT(buffer),
                                btsock_l2cap_cbk, buffer, count, user_id);
                                btsock_l2cap_cbk, buffer, user_id);
        } else {
          // will take care of freeing buffer
          BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, count,
                           user_id);
          BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, user_id);
        }
      }
    } else