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

Commit 6b4b6f56 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov
Browse files

Implement HCI_Read_Failed_Contact_Counter mechanism

Also, read the Failed Contact Counter when flushing the A2DP Tx queue

Test: Streaming A2DP headset and trigger audio stutter
Bug: 64038257
Change-Id: I8ff72560e3840c5c22cfac9613c4be670b8a4cf1
parent 0dbbfc4c
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ static void log_tstamps_us(const char* comment, uint64_t timestamp_us);
static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us,
                                    uint64_t expected_delta);
static void btm_read_rssi_cb(void* data);
static void btm_read_failed_contact_counter_cb(void* data);

UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
  switch (event) {
@@ -743,9 +744,19 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n) {
      osi_free(fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue));
    }

    // Request RSSI for log purposes if we had to flush buffers
    // Request RSSI and Failed Contact Counter for log purposes if we had to
    // flush buffers.
    RawAddress peer_bda = btif_av_get_addr();
    BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
    tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
    if (status != BTM_CMD_STARTED) {
      LOG_WARN(LOG_TAG, "%s: Cannot read RSSI: status %d", __func__, status);
    }
    status = BTM_ReadFailedContactCounter(peer_bda,
                                          btm_read_failed_contact_counter_cb);
    if (status != BTM_CMD_STARTED) {
      LOG_WARN(LOG_TAG, "%s: Cannot read Failed Contact Counter: status %d",
               __func__, status);
    }
  }

  /* Update the statistics */
@@ -1095,3 +1106,22 @@ static void btm_read_rssi_cb(void* data) {
  LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__,
           result->rem_bda.ToString().c_str(), result->rssi);
}

static void btm_read_failed_contact_counter_cb(void* data) {
  if (data == nullptr) {
    LOG_ERROR(LOG_TAG, "%s Failed Contact Counter request timed out", __func__);
    return;
  }

  tBTM_FAILED_CONTACT_COUNTER_RESULT* result =
      (tBTM_FAILED_CONTACT_COUNTER_RESULT*)data;
  if (result->status != BTM_SUCCESS) {
    LOG_ERROR(LOG_TAG,
              "%s unable to read remote Failed Result Counter (status %d)",
              __func__, result->status);
    return;
  }

  LOG_WARN(LOG_TAG, "%s device: %s, Failed Contact Counter: %u", __func__,
           result->rem_bda.ToString().c_str(), result->failed_contact_counter);
}
+107 −0
Original line number Diff line number Diff line
@@ -1923,6 +1923,46 @@ tBTM_STATUS BTM_ReadRSSI(const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb) {
  return (BTM_UNKNOWN_ADDR);
}

/*******************************************************************************
 *
 * Function         BTM_ReadFailedContactCounter
 *
 * Description      This function is called to read the failed contact counter.
 *                  The result is returned in the callback.
 *                  (tBTM_FAILED_CONTACT_COUNTER_RESULT)
 *
 * Returns          BTM_CMD_STARTED if successfully initiated or error code
 *
 ******************************************************************************/
tBTM_STATUS BTM_ReadFailedContactCounter(const RawAddress& remote_bda,
                                         tBTM_CMPL_CB* p_cb) {
  tACL_CONN* p;
  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
  tBT_DEVICE_TYPE dev_type;
  tBLE_ADDR_TYPE addr_type;

  /* If someone already waiting on the result, do not allow another */
  if (btm_cb.devcb.p_failed_contact_counter_cmpl_cb) return (BTM_BUSY);

  BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type);
  if (dev_type == BT_DEVICE_TYPE_BLE) transport = BT_TRANSPORT_LE;

  p = btm_bda_to_acl(remote_bda, transport);
  if (p != (tACL_CONN*)NULL) {
    btm_cb.devcb.p_failed_contact_counter_cmpl_cb = p_cb;
    alarm_set_on_queue(btm_cb.devcb.read_failed_contact_counter_timer,
                       BTM_DEV_REPLY_TIMEOUT_MS,
                       btm_read_failed_contact_counter_timeout, NULL,
                       btu_general_alarm_queue);

    btsnd_hcic_read_failed_contact_counter(p->hci_handle);
    return (BTM_CMD_STARTED);
  }

  /* If here, no BD Addr found */
  return (BTM_UNKNOWN_ADDR);
}

/*******************************************************************************
 *
 * Function         BTM_ReadLinkQuality
@@ -2133,6 +2173,73 @@ void btm_read_rssi_complete(uint8_t* p) {
  }
}

/*******************************************************************************
 *
 * Function         btm_read_failed_contact_counter_timeout
 *
 * Description      Callback when reading the failed contact counter times out.
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_read_failed_contact_counter_timeout(UNUSED_ATTR void* data) {
  tBTM_FAILED_CONTACT_COUNTER_RESULT result;
  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_failed_contact_counter_cmpl_cb;
  btm_cb.devcb.p_failed_contact_counter_cmpl_cb = NULL;
  result.status = BTM_DEVICE_TIMEOUT;
  if (p_cb) (*p_cb)(&result);
}

/*******************************************************************************
 *
 * Function         btm_read_failed_contact_counter_complete
 *
 * Description      This function is called when the command complete message
 *                  is received from the HCI for the read failed contact
 *                  counter request.
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_read_failed_contact_counter_complete(uint8_t* p) {
  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_failed_contact_counter_cmpl_cb;
  tBTM_FAILED_CONTACT_COUNTER_RESULT result;
  tACL_CONN* p_acl_cb = &btm_cb.acl_db[0];

  BTM_TRACE_DEBUG("%s", __func__);
  alarm_cancel(btm_cb.devcb.read_failed_contact_counter_timer);
  btm_cb.devcb.p_failed_contact_counter_cmpl_cb = NULL;

  /* If there was a registered callback, call it */
  if (p_cb) {
    uint16_t handle;
    STREAM_TO_UINT8(result.hci_status, p);

    if (result.hci_status == HCI_SUCCESS) {
      result.status = BTM_SUCCESS;

      STREAM_TO_UINT16(handle, p);

      STREAM_TO_UINT16(result.failed_contact_counter, p);
      BTM_TRACE_DEBUG(
          "BTM Failed Contact Counter Complete: counter %u, hci status 0x%02x",
          result.failed_contact_counter, result.hci_status);

      /* Search through the list of active channels for the correct BD Addr */
      for (uint16_t index = 0; index < MAX_L2CAP_LINKS; index++, p_acl_cb++) {
        if ((p_acl_cb->in_use) && (handle == p_acl_cb->hci_handle)) {
          result.rem_bda = p_acl_cb->remote_addr;
          break;
        }
      }
    } else {
      result.status = BTM_ERR_PROCESSING;
    }

    (*p_cb)(&result);
  }
}

/*******************************************************************************
 *
 * Function         btm_read_link_quality_timeout
+9 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ void btm_dev_init(void) {

  btm_cb.devcb.read_local_name_timer = alarm_new("btm.read_local_name_timer");
  btm_cb.devcb.read_rssi_timer = alarm_new("btm.read_rssi_timer");
  btm_cb.devcb.read_failed_contact_counter_timer =
      alarm_new("btm.read_failed_contact_counter_timer");
  btm_cb.devcb.read_link_quality_timer =
      alarm_new("btm.read_link_quality_timer");
  btm_cb.devcb.read_inq_tx_power_timer =
@@ -131,6 +133,13 @@ static void btm_db_reset(void) {

    if (p_cb) (*p_cb)((tBTM_RSSI_RESULTS*)&status);
  }

  if (btm_cb.devcb.p_failed_contact_counter_cmpl_cb) {
    p_cb = btm_cb.devcb.p_failed_contact_counter_cmpl_cb;
    btm_cb.devcb.p_failed_contact_counter_cmpl_cb = NULL;

    if (p_cb) (*p_cb)((tBTM_FAILED_CONTACT_COUNTER_RESULT*)&status);
  }
}

bool set_sec_state_idle(void* data, void* context) {
+3 −0
Original line number Diff line number Diff line
@@ -92,6 +92,9 @@ extern void btm_read_link_policy_complete(uint8_t* p);
extern void btm_read_rssi_timeout(void* data);
extern void btm_read_rssi_complete(uint8_t* p);

extern void btm_read_failed_contact_counter_timeout(void* data);
extern void btm_read_failed_contact_counter_complete(uint8_t* p);

extern void btm_read_tx_power_timeout(void* data);
extern void btm_read_tx_power_complete(uint8_t* p, bool is_ble);

+4 −0
Original line number Diff line number Diff line
@@ -125,6 +125,10 @@ typedef struct {
  alarm_t* read_rssi_timer;       /* Read RSSI timer */
  tBTM_CMPL_CB* p_rssi_cmpl_cb;   /* Callback function to be called when  */
                                  /* read RSSI function completes */
  alarm_t* read_failed_contact_counter_timer; /* Read Failed Contact Counter */
                                              /* timer */
  tBTM_CMPL_CB* p_failed_contact_counter_cmpl_cb; /* Callback function to be */
  /* called when read Failed Contact Counter function completes */
  alarm_t* read_link_quality_timer;
  tBTM_CMPL_CB* p_link_qual_cmpl_cb; /* Callback function to be called when  */
                                     /* read link quality function completes */
Loading