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

Commit 2cba2968 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov
Browse files

Implement HCI_Read_Automatic_Flush_Timeout mechanism

Also, read the Automatic Flush Timeout when flushing the A2DP Tx queue

Test: Streaming A2DP headset and trigger audio stutter
Bug: 64038257
Change-Id: Ic49b5236328ddacde1d7f2aee131e35e317a14ef
parent 014c832a
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ 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);
static void btm_read_automatic_flush_timeout_cb(void* data);

UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
  switch (event) {
@@ -744,8 +745,7 @@ 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 and Failed Contact Counter for log purposes if we had to
    // flush buffers.
    // Request additional debug info if we had to flush buffers
    RawAddress peer_bda = btif_av_get_addr();
    tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
    if (status != BTM_CMD_STARTED) {
@@ -757,6 +757,12 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n) {
      LOG_WARN(LOG_TAG, "%s: Cannot read Failed Contact Counter: status %d",
               __func__, status);
    }
    status = BTM_ReadAutomaticFlushTimeout(peer_bda,
                                           btm_read_automatic_flush_timeout_cb);
    if (status != BTM_CMD_STARTED) {
      LOG_WARN(LOG_TAG, "%s: Cannot read Automatic Flush Timeout: status %d",
               __func__, status);
    }
  }

  /* Update the statistics */
@@ -1092,7 +1098,7 @@ void btif_a2dp_source_update_metrics(void) {

static void btm_read_rssi_cb(void* data) {
  if (data == nullptr) {
    LOG_ERROR(LOG_TAG, "%s RSSI request timed out", __func__);
    LOG_ERROR(LOG_TAG, "%s Read RSSI request timed out", __func__);
    return;
  }

@@ -1109,15 +1115,15 @@ static void btm_read_rssi_cb(void* data) {

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__);
    LOG_ERROR(LOG_TAG, "%s Read 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)",
    LOG_ERROR(LOG_TAG, "%s unable to read Failed Contact Counter (status %d)",
              __func__, result->status);
    return;
  }
@@ -1125,3 +1131,22 @@ static void btm_read_failed_contact_counter_cb(void* data) {
  LOG_WARN(LOG_TAG, "%s device: %s, Failed Contact Counter: %u", __func__,
           result->rem_bda.ToString().c_str(), result->failed_contact_counter);
}

static void btm_read_automatic_flush_timeout_cb(void* data) {
  if (data == nullptr) {
    LOG_ERROR(LOG_TAG, "%s Read Automatic Flush Timeout request timed out",
              __func__);
    return;
  }

  tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT* result =
      (tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT*)data;
  if (result->status != BTM_SUCCESS) {
    LOG_ERROR(LOG_TAG, "%s unable to read Automatic Flush Timeout (status %d)",
              __func__, result->status);
    return;
  }

  LOG_WARN(LOG_TAG, "%s device: %s, Automatic Flush Timeout: %u", __func__,
           result->rem_bda.ToString().c_str(), result->automatic_flush_timeout);
}
+104 −0
Original line number Diff line number Diff line
@@ -1963,6 +1963,43 @@ tBTM_STATUS BTM_ReadFailedContactCounter(const RawAddress& remote_bda,
  return (BTM_UNKNOWN_ADDR);
}

/*******************************************************************************
 *
 * Function         BTM_ReadAutomaticFlushTimeout
 *
 * Description      This function is called to read the automatic flush timeout.
 *                  The result is returned in the callback.
 *                  (tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT)
 *
 * Returns          BTM_CMD_STARTED if successfully initiated or error code
 *
 ******************************************************************************/
tBTM_STATUS BTM_ReadAutomaticFlushTimeout(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_automatic_flush_timeout_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) return BTM_UNKNOWN_ADDR;

  btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb = p_cb;
  alarm_set_on_queue(btm_cb.devcb.read_automatic_flush_timeout_timer,
                     BTM_DEV_REPLY_TIMEOUT_MS,
                     btm_read_automatic_flush_timeout_timeout, nullptr,
                     btu_general_alarm_queue);

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

/*******************************************************************************
 *
 * Function         BTM_ReadLinkQuality
@@ -2240,6 +2277,73 @@ void btm_read_failed_contact_counter_complete(uint8_t* p) {
  }
}

/*******************************************************************************
 *
 * Function         btm_read_automatic_flush_timeout_timeout
 *
 * Description      Callback when reading the automatic flush timeout times out.
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_read_automatic_flush_timeout_timeout(UNUSED_ATTR void* data) {
  tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT result;
  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb;
  btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb = nullptr;
  result.status = BTM_DEVICE_TIMEOUT;
  if (p_cb) (*p_cb)(&result);
}

/*******************************************************************************
 *
 * Function         btm_read_automatic_flush_timeout_complete
 *
 * Description      This function is called when the command complete message
 *                  is received from the HCI for the read automatic flush
 *                  timeout request.
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_read_automatic_flush_timeout_complete(uint8_t* p) {
  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb;
  tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT result;
  tACL_CONN* p_acl_cb = &btm_cb.acl_db[0];

  BTM_TRACE_DEBUG("%s", __func__);
  alarm_cancel(btm_cb.devcb.read_automatic_flush_timeout_timer);
  btm_cb.devcb.p_automatic_flush_timeout_cmpl_cb = nullptr;

  /* 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.automatic_flush_timeout, p);
      BTM_TRACE_DEBUG(
          "BTM Automatic Flush Timeout Complete: timeout %u, hci status 0x%02x",
          result.automatic_flush_timeout, 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
@@ -85,6 +85,8 @@ void btm_dev_init(void) {
  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_automatic_flush_timeout_timer =
      alarm_new("btm.read_automatic_flush_timeout_timer");
  btm_cb.devcb.read_link_quality_timer =
      alarm_new("btm.read_link_quality_timer");
  btm_cb.devcb.read_inq_tx_power_timer =
@@ -140,6 +142,13 @@ static void btm_db_reset(void) {

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

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

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

bool set_sec_state_idle(void* data, void* context) {
+3 −0
Original line number Diff line number Diff line
@@ -95,6 +95,9 @@ 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_automatic_flush_timeout_timeout(void* data);
extern void btm_read_automatic_flush_timeout_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);

+9 −0
Original line number Diff line number Diff line
@@ -122,13 +122,22 @@ typedef struct {
  alarm_t* read_local_name_timer; /* Read local name timer */
  tBTM_CMPL_CB* p_rln_cmpl_cb;    /* Callback function to be called when  */
                                  /* read local name function complete    */

  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_automatic_flush_timeout_timer; /* Read Automatic Flush Timeout */
                                          /* timer */
  tBTM_CMPL_CB* p_automatic_flush_timeout_cmpl_cb; /* Callback function to be */
  /* called when read Automatic Flush Timeout 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