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

Commit 1d473609 authored by Jack He's avatar Jack He
Browse files

HFP: Fix ACL collision handling and WBS update

* Correctly set control block handle when passing WBS event data to
  upstream
* Correctly reject local outgoing connection when a colliding incoming
  connection is connected to RFCOMM
* Add more logging to help with future debugging

Bug: 80251999
Test: connect HFP devices rapidly and toggle Bluetooth rapidly
      testplans/details/166812/3975
Change-Id: I90616d70335ca68c40251fb722146924c4801cbe
parent 36e90951
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -294,10 +294,11 @@ void bta_ag_disc_fail(tBTA_AG_SCB* p_scb,
  /* reinitialize stuff */

  /* clear the remote BD address */
  RawAddress peer_addr = p_scb->peer_addr;
  p_scb->peer_addr = RawAddress::kEmpty;

  /* call open cback w. failure */
  bta_ag_cback_open(p_scb, RawAddress::kEmpty, BTA_AG_FAIL_SDP);
  bta_ag_cback_open(p_scb, peer_addr, BTA_AG_FAIL_SDP);
}

/*******************************************************************************
@@ -513,7 +514,7 @@ void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
 *
 ******************************************************************************/
void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  APPL_TRACE_DEBUG("%s: serv_handle0 = %d serv_handle1 = %d", __func__,
  APPL_TRACE_DEBUG("%s: serv_handle0 = %d serv_handle = %d", __func__,
                   p_scb->serv_handle[0], p_scb->serv_handle[1]);
  /* set role */
  p_scb->role = BTA_AG_ACP;
@@ -531,14 +532,17 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  for (tBTA_AG_SCB& ag_scb : bta_ag_cb.scb) {
    // Cancel any pending collision timers
    if (ag_scb.in_use && alarm_is_scheduled(ag_scb.collision_timer)) {
      VLOG(1) << __func__ << ": cancel collision alarm for "
              << ag_scb.peer_addr;
      alarm_cancel(ag_scb.collision_timer);
      if (dev_addr != ag_scb.peer_addr && p_scb != &ag_scb) {
        // Resume outgoing connection if incoming is not on the same device
        bta_ag_resume_open(&ag_scb);
      }
      break;
    }
    if (dev_addr == ag_scb.peer_addr && p_scb != &ag_scb) {
      VLOG(1) << __func__ << ": fail outgoing connection before accepting "
              << ag_scb.peer_addr;
      // Fail the outgoing connection to clean up any upper layer states
      bta_ag_rfc_fail(&ag_scb, tBTA_AG_DATA::kEmpty);
      // If client port is opened, close it
@@ -552,6 +556,10 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
        }
      }
    }
    VLOG(1) << __func__ << ": dev_addr=" << dev_addr
            << ", peer_addr=" << ag_scb.peer_addr
            << ", in_use=" << ag_scb.in_use
            << ", index=" << bta_ag_scb_to_idx(p_scb);
  }

  p_scb->peer_addr = dev_addr;
@@ -604,11 +612,13 @@ void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
    /* read data from rfcomm; if bad status, we're done */
    if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) !=
        PORT_SUCCESS) {
      LOG(ERROR) << __func__ << ": failed to read data " << p_scb->peer_addr;
      break;
    }

    /* if no data, we're done */
    if (len == 0) {
      LOG(WARNING) << __func__ << ": no data for " << p_scb->peer_addr;
      break;
    }

@@ -791,6 +801,7 @@ void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb,
void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  tBTA_AG_PEER_CODEC codec_type = data.api_setcodec.codec;
  tBTA_AG_VAL val = {};
  val.hdr.handle = bta_ag_scb_to_idx(p_scb);

  /* Check if the requested codec type is valid */
  if ((codec_type != BTA_AG_CODEC_NONE) && (codec_type != BTA_AG_CODEC_CVSD) &&
+6 −1
Original line number Diff line number Diff line
@@ -79,11 +79,16 @@ static void bta_ag_port_cback(UNUSED_ATTR uint32_t code, uint16_t port_handle,
  if (p_scb != nullptr) {
    /* ignore port events for port handles other than connected handle */
    if (port_handle != p_scb->conn_handle) {
      APPL_TRACE_DEBUG(
      APPL_TRACE_ERROR(
          "ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
          port_handle, p_scb->conn_handle, handle);
      return;
    }
    if (!bta_ag_scb_open(p_scb)) {
      LOG(ERROR) << __func__ << ": rfcomm data on an unopened control block "
                 << handle << " peer_addr " << p_scb->peer_addr << " state "
                 << std::to_string(p_scb->state);
    }
    do_in_bta_thread(FROM_HERE,
                     base::Bind(&bta_ag_sm_execute_by_handle, handle,
                                BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));