OSDN Git Service

A2DP: Wait for previous AVDTP instance to be clean up before re-enabling
authorCheney Ni <cheneyni@google.com>
Wed, 19 Feb 2020 09:41:59 +0000 (17:41 +0800)
committerCheney Ni <cheneyni@google.com>
Tue, 14 Apr 2020 09:44:11 +0000 (17:44 +0800)
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
Merged-In: I8e700ce195aa634819ea1ad8cf5892cc35669e10
(cherry picked from commit 21fe257db23887b3000a6c8d38ee339fcccbdc2b)

bta/av/bta_av_int.h
bta/av/bta_av_main.cc
bta/sys/bta_sys.h
bta/sys/bta_sys_main.cc
stack/btu/btu_task.cc
stack/include/btu.h

index 9c8f3dd..3925e55 100644 (file)
@@ -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:
index 44da99e..61e4b4e 100644 (file)
@@ -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;
index 29e9a3f..3ceefc1 100644 (file)
@@ -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);
index 1036e74..e81320d 100644 (file)
@@ -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
index 8838206..06d06d1 100644 (file)
@@ -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";
 
index 77d5051..03fe2a1 100644 (file)
@@ -62,6 +62,9 @@ bluetooth::common::MessageLoopThread* get_main_thread();
 base::MessageLoop* get_main_message_loop();
 bt_status_t do_in_main_thread(const base::Location& from_here,
                               base::OnceClosure task);
+bt_status_t do_in_main_thread_delayed(const base::Location& from_here,
+                                      base::OnceClosure task,
+                                      const base::TimeDelta& delay);
 
 void BTU_StartUp(void);
 void BTU_ShutDown(void);