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)
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 */
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:
******************************************************************************/
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);
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;
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);
}
}
+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
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";
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);