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

Commit 51bb3e27 authored by Cheney Ni's avatar Cheney Ni
Browse files

A2DP: Wait for previous AVDTP instance to be clean up before re-enabling

Because more connections spend more time to disconnect, the stack may
still be busy at disabling AVDTP, if we re-enable the A2dpService
quickly. This change will defer BTA_AV_API_ENABLE and BTA_AV_API_REG
events if the stack is still disabling the previous instance, so gives
the stack half more seconds to handle its previous task.

Bug: 135655859
Test: manually
Change-Id: I8e700ce195aa634819ea1ad8cf5892cc35669e10
parent caf92609
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -603,6 +603,7 @@ typedef struct {
  tBTA_SEC sec_mask;            /* security mask */
  tBTA_AV_HNDL handle;          /* the handle for SDP activity */
  bool disabling;               /* true if api disabled called */
  uint8_t enabling_attempts;    // counter to wait for previous disabling
  uint8_t
      disc; /* (hdi+1) or (rc_handle|BTA_AV_CHNL_MSK) if p_disc_db is in use */
  uint8_t state;          /* state machine state */
@@ -617,6 +618,10 @@ typedef struct {
  uint8_t audio_streams; /* handle mask of streaming audio channels */
} tBTA_AV_CB;

// total attempts are half seconds
constexpr uint32_t kEnablingAttemptsIntervalMs = 100;
constexpr uint8_t kEnablingAttemptsCountMaximum = 5;

// A2DP offload VSC parameters
class tBT_A2DP_OFFLOAD {
 public:
+26 −2
Original line number Diff line number Diff line
@@ -219,8 +219,17 @@ static const char* bta_av_st_code(uint8_t state);
 ******************************************************************************/
static void bta_av_api_enable(tBTA_AV_DATA* p_data) {
  if (bta_av_cb.disabling) {
    APPL_TRACE_WARNING("%s: previous (reg_audio=%#x) is still disabling",
                       __func__, bta_av_cb.reg_audio);
    APPL_TRACE_WARNING(
        "%s: previous (reg_audio=%#x) is still disabling (attempts=%d)",
        __func__, bta_av_cb.reg_audio, bta_av_cb.enabling_attempts);
    if (++bta_av_cb.enabling_attempts <= kEnablingAttemptsCountMaximum) {
      tBTA_AV_API_ENABLE* p_buf =
          (tBTA_AV_API_ENABLE*)osi_malloc(sizeof(tBTA_AV_API_ENABLE));
      memcpy(p_buf, &p_data->api_enable, sizeof(tBTA_AV_API_ENABLE));
      bta_sys_sendmsg_delayed(p_buf, base::TimeDelta::FromMilliseconds(
                                         kEnablingAttemptsIntervalMs));
      return;
    }
    if (bta_av_cb.sdp_a2dp_handle) {
      SDP_DeleteRecord(bta_av_cb.sdp_a2dp_handle);
      bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
@@ -495,6 +504,21 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) {
  char* p_service_name;
  tBTA_UTL_COD cod;

  if (bta_av_cb.disabling ||
      (bta_av_cb.features == 0 && bta_av_cb.sec_mask == 0)) {
    APPL_TRACE_WARNING(
        "%s: AV instance (features=%#x, sec_mask=%#x, reg_audio=%#x) is not "
        "ready for app_id %d",
        __func__, bta_av_cb.features, bta_av_cb.sec_mask, bta_av_cb.reg_audio,
        p_data->api_reg.app_id);
    tBTA_AV_API_REG* p_buf =
        (tBTA_AV_API_REG*)osi_malloc(sizeof(tBTA_AV_API_REG));
    memcpy(p_buf, &p_data->api_reg, sizeof(tBTA_AV_API_REG));
    bta_sys_sendmsg_delayed(
        p_buf, base::TimeDelta::FromMilliseconds(kEnablingAttemptsIntervalMs));
    return;
  }

  avdtp_stream_config.Reset();

  registr.status = BTA_AV_FAIL_RESOURCES;
+1 −0
Original line number Diff line number Diff line
@@ -222,6 +222,7 @@ extern void bta_sys_deregister(uint8_t id);
extern bool bta_sys_is_register(uint8_t id);
extern uint16_t bta_sys_get_sys_features(void);
extern void bta_sys_sendmsg(void* p_msg);
extern void bta_sys_sendmsg_delayed(void* p_msg, const base::TimeDelta& delay);
extern void bta_sys_start_timer(alarm_t* alarm, uint64_t interval_ms,
                                uint16_t event, uint16_t layer_specific);
extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
+8 −0
Original line number Diff line number Diff line
@@ -532,6 +532,14 @@ void bta_sys_sendmsg(void* p_msg) {
  }
}

void bta_sys_sendmsg_delayed(void* p_msg, const base::TimeDelta& delay) {
  if (do_in_main_thread_delayed(
          FROM_HERE, base::Bind(&bta_sys_event, static_cast<BT_HDR*>(p_msg)),
          delay) != BT_STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": do_in_main_thread_delayed failed";
  }
}

/*******************************************************************************
 *
 * Function         bta_sys_start_timer
+11 −0
Original line number Diff line number Diff line
@@ -97,6 +97,17 @@ bt_status_t do_in_main_thread(const base::Location& from_here,
  return BT_STATUS_SUCCESS;
}

bt_status_t do_in_main_thread_delayed(const base::Location& from_here,
                                      base::OnceClosure task,
                                      const base::TimeDelta& delay) {
  if (!get_main_message_loop()->task_runner()->PostDelayedTask(
          from_here, std::move(task), delay)) {
    LOG(ERROR) << __func__ << ": failed from " << from_here.ToString();
    return BT_STATUS_FAIL;
  }
  return BT_STATUS_SUCCESS;
}

void btu_task_start_up(UNUSED_ATTR void* context) {
  LOG(INFO) << "Bluetooth chip preload is complete";

Loading