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

Commit c1ad6fd0 authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

btif_sock_rfc: Cancel ongoing SDP on socket closed

When a socket is closed while the SDP is still ongoing, btif socket slot
would be cleaned up but BTA Jv would not, which makes all later RFCOMM
connection fail. The issue usually persists until the SDP completes, but
we also observed that the SDP complete event could never happen. This
patch shall mitigate the issue.

Bug: 331018524
Bug: 370916753
Test: atest BumbleBluetoothTests:android.bluetooth.RfcommTest#clientConnectToOpenServerSocketBondedInsecurePrematureClosure; Passed with flag enabled and failed with flag disabled
Flag: rfcomm_cancel_ongoing_sdp_on_close
Change-Id: If2bdc0f0d3b5f9cfc48073f1788241fc296582de
parent 95067a56
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -512,6 +512,19 @@ tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, tBTA_JV_CONN_TYPE conn_type);
tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr, uint16_t num_uuid,
                                    const bluetooth::Uuid* p_uuid_list, uint32_t rfcomm_slot_id);

/*******************************************************************************
 *
 * Function         BTA_JvCancelDiscovery
 *
 * Description      This function cancels the ongoing service discovery and make
 *                  sure the tBTA_JV_DM_CBACK callback function will be called
 *                  with a BTA_JV_DISCOVERY_COMP_EVT.
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_JvCancelDiscovery(uint32_t rfcomm_slot_id);

/*******************************************************************************
 *
 * Function         BTA_JvCreateRecordByUser
+22 −0
Original line number Diff line number Diff line
@@ -916,6 +916,28 @@ void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid,
  }
}

void bta_jv_cancel_discovery(uint32_t rfcomm_slot_id) {
  if (!bta_jv_cb.sdp_cb.sdp_active) {
    log::error("Canceling discovery but discovery is not active");
    return;
  }
  if (!get_legacy_stack_sdp_api()->service.SDP_CancelServiceSearch(p_bta_jv_cfg->p_sdp_db)) {
    log::error("Failed to cancel discovery, clean up the control block anyway");
    bta_jv_cb.sdp_cb = {};
    /* Send complete event right away as we might not receive callback from stack */
    if (bta_jv_cb.p_dm_cback) {
      tBTA_JV bta_jv = {
              .status = tBTA_JV_STATUS::FAILURE,
      };
      bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
    } else {
      log::warn("No callback set for discovery complete event");
    }
  } else {
    log::info("Canceled discovery");
  }
}

/* Create an SDP record with the given attributes */
void bta_jv_create_record(uint32_t rfcomm_slot_id) {
  tBTA_JV_CREATE_RECORD evt_data;
+16 −0
Original line number Diff line number Diff line
@@ -166,6 +166,22 @@ tBTA_JV_STATUS BTA_JvStartDiscovery(const RawAddress& bd_addr, uint16_t num_uuid
  return tBTA_JV_STATUS::SUCCESS;
}

/*******************************************************************************
 *
 * Function         BTA_JvCancelDiscovery
 *
 * Description      This function cancels the ongoing service discovery and make
 *                  sure the tBTA_JV_DM_CBACK callback function will be called
 *                  with a BTA_JV_DISCOVERY_COMP_EVT.
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_JvCancelDiscovery(uint32_t rfcomm_slot_id) {
  log::verbose("rfcomm_slot_id:{}", rfcomm_slot_id);
  do_in_main_thread(Bind(&bta_jv_cancel_discovery, rfcomm_slot_id));
}

/*******************************************************************************
 *
 * Function         BTA_JvCreateRecord
+1 −0
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ void bta_jv_get_channel_id(tBTA_JV_CONN_TYPE type, int32_t channel, uint32_t l2c
void bta_jv_free_scn(tBTA_JV_CONN_TYPE type, uint16_t scn);
void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid,
                            bluetooth::Uuid* uuid_list, uint32_t rfcomm_slot_id);
void bta_jv_cancel_discovery(uint32_t rfcomm_slot_id);
void bta_jv_create_record(uint32_t rfcomm_slot_id);
void bta_jv_delete_record(uint32_t handle);
void bta_jv_l2cap_connect(tBTA_JV_CONN_TYPE type, tBTA_SEC sec_mask, uint16_t remote_psm,
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define LOG_TAG "bt_btif_sock_rfcomm"

#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -963,6 +964,10 @@ void btsock_rfc_signaled(int /* fd */, int flags, uint32_t id) {
    // Clean up if there's no data pending.
    int size = 0;
    if (need_close || ioctl(slot->fd, FIONREAD, &size) != 0 || !size) {
      if (com::android::bluetooth::flags::rfcomm_cancel_ongoing_sdp_on_close() &&
          slot->f.doing_sdp_request) {
        BTA_JvCancelDiscovery(slot->id);
      }
      cleanup_rfc_slot(slot);
    }
  }
Loading