From 4824c598ae0da93744662f5c199625e7ad0003a1 Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Tue, 18 Aug 2026 17:19:46 +0800 Subject: [PATCH] fix(bt/bluedroid): fixed BTA event dispatch race during module disable - Gate bta_sys_event() on both 'is_reg' and 'reg[id]' to prevent stale event delivery. - Defer bta_sys_deregister() to the end of profile disable handlers to ensure pending DISABLE events are processed. - Add disabling flag to HFP AG for tracking asynchronous teardown. --- components/bt/host/bluedroid/bta/av/bta_av_act.c | 1 + components/bt/host/bluedroid/bta/av/bta_av_api.c | 1 - components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c | 2 ++ components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c | 1 - components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c | 2 ++ components/bt/host/bluedroid/bta/gatt/bta_gatts_api.c | 1 - components/bt/host/bluedroid/bta/hd/bta_hd_act.c | 2 ++ components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c | 9 ++++++--- .../bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h | 1 + .../bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c | 4 +--- components/bt/host/bluedroid/bta/hh/bta_hh_api.c | 1 - components/bt/host/bluedroid/bta/hh/bta_hh_utils.c | 2 ++ components/bt/host/bluedroid/bta/jv/bta_jv_act.c | 2 ++ .../bt/host/bluedroid/bta/pba/bta_pba_client_act.c | 3 +-- components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c | 2 ++ components/bt/host/bluedroid/bta/sys/bta_sys_main.c | 2 +- 16 files changed, 23 insertions(+), 13 deletions(-) diff --git a/components/bt/host/bluedroid/bta/av/bta_av_act.c b/components/bt/host/bluedroid/bta/av/bta_av_act.c index 2d8df0599ee..7db65283e6f 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_act.c @@ -2015,6 +2015,7 @@ void bta_av_dereg_comp(tBTA_AV_DATA *p_data) #endif if (p_cb->disabling) { + bta_sys_deregister(BTA_ID_AV); p_cb->disabling = FALSE; bta_av_cb.features = 0; } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_api.c b/components/bt/host/bluedroid/bta/av/bta_av_api.c index f65966e5479..4867eae4806 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_api.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_api.c @@ -87,7 +87,6 @@ void BTA_AvDisable(void) { BT_HDR *p_buf; - bta_sys_deregister(BTA_ID_AV); if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_AV_API_DISABLE_EVT; bta_sys_sendmsg(p_buf); diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index e2aa4c05308..fb5fe51cc28 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -175,6 +175,7 @@ void bta_gattc_disable(tBTA_GATTC_CB *p_cb) if (p_cb->state != BTA_GATTC_STATE_DISABLING) { p_cb->state = BTA_GATTC_STATE_DISABLED; memset(p_cb, 0, sizeof(tBTA_GATTC_CB)); + bta_sys_deregister(BTA_ID_GATTC); } } @@ -1844,6 +1845,7 @@ void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg) if (bta_gattc_num_reg_app() == 0 && p_cb->state == BTA_GATTC_STATE_DISABLING) { p_cb->state = BTA_GATTC_STATE_DISABLED; + bta_sys_deregister(BTA_ID_GATTC); } } diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c index c0de44c2b44..89a294a23ea 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c @@ -65,7 +65,6 @@ void BTA_GATTC_Disable(void) p_buf->event = BTA_GATTC_API_DISABLE_EVT; bta_sys_sendmsg(p_buf); } - bta_sys_deregister(BTA_ID_GATTC); } diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c index b0c539eefdf..05a71b0f644 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gatts_act.c @@ -159,6 +159,8 @@ void bta_gatts_api_disable(tBTA_GATTS_CB *p_cb) } else { APPL_TRACE_ERROR("GATTS not enabled"); } + + bta_sys_deregister(BTA_ID_GATTS); } /******************************************************************************* diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gatts_api.c b/components/bt/host/bluedroid/bta/gatt/bta_gatts_api.c index f8774de77c5..04c8276349a 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gatts_api.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gatts_api.c @@ -66,7 +66,6 @@ void BTA_GATTS_Disable(void) p_buf->event = BTA_GATTS_API_DISABLE_EVT; bta_sys_sendmsg(p_buf); } - bta_sys_deregister(BTA_ID_GATTS); } diff --git a/components/bt/host/bluedroid/bta/hd/bta_hd_act.c b/components/bt/host/bluedroid/bta/hd/bta_hd_act.c index 16937bbd2c3..f8846c7edf4 100644 --- a/components/bt/host/bluedroid/bta/hd/bta_hd_act.c +++ b/components/bt/host/bluedroid/bta/hd/bta_hd_act.c @@ -148,6 +148,8 @@ void bta_hd_api_disable(void) APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret); } + bta_sys_deregister(BTA_ID_HD); + (*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status); memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB)); diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c index b52ab14ea6a..aff9410f8d7 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c @@ -492,7 +492,7 @@ void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb) memset(p_scb, 0, sizeof(tBTA_AG_SCB)); p_scb->sco_idx = BTM_INVALID_SCO_INDEX; /* If all scbs are deallocated, callback with disable event */ - if (!bta_sys_is_register (BTA_ID_AG)) { + if (bta_ag_cb.disabling) { for (idx = 0; idx < BTA_AG_NUM_SCB; idx++) { if (bta_ag_cb.scb[idx].in_use) { allocated = TRUE; @@ -500,6 +500,8 @@ void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb) } } if (!allocated) { + bta_ag_cb.disabling = FALSE; + bta_sys_deregister(BTA_ID_AG); (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL); } } @@ -822,8 +824,7 @@ static void bta_ag_api_disable(tBTA_AG_DATA *p_data) APPL_TRACE_ERROR("BTA AG is already disabled, ignoring ..."); return; } - /* De-register with BTA system manager */ - bta_sys_deregister(BTA_ID_AG); + bta_ag_cb.disabling = TRUE; for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++) { if (p_scb->in_use) { @@ -834,6 +835,8 @@ static void bta_ag_api_disable(tBTA_AG_DATA *p_data) if (!do_dereg) { /* Done, send callback evt to app */ + bta_ag_cb.disabling = FALSE; + bta_sys_deregister(BTA_ID_AG); (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL); } bta_sys_collision_register (BTA_ID_AG, NULL); diff --git a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h index c8b7be36ea7..505809fabb1 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h +++ b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h @@ -367,6 +367,7 @@ typedef struct tBTA_AG_CBACK *p_cback; /* application callback */ tBTA_AG_PARSE_MODE parse_mode; /* parse/pass-through mode */ BOOLEAN msbc_enabled; + BOOLEAN disabling; } tBTA_AG_CB; /***************************************************************************** diff --git a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c index d811fa51dfd..99efa103e33 100644 --- a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -323,6 +323,7 @@ void bta_hf_client_scb_disable(void) bta_hf_client_at_reset(); bta_hf_client_scb_init(); + bta_sys_deregister(BTA_ID_HS); if (bta_hf_client_cb.p_cback) { (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_DISABLE_EVT, NULL); @@ -487,9 +488,6 @@ static void bta_hf_client_api_disable(tBTA_HF_CLIENT_DATA *p_data) return; } - /* De-register with BTA system manager */ - bta_sys_deregister(BTA_ID_HS); - bta_hf_client_sm_execute(BTA_HF_CLIENT_API_DEREGISTER_EVT, p_data); bta_sys_collision_register (BTA_ID_HS, NULL); diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_api.c b/components/bt/host/bluedroid/bta/hh/bta_hh_api.c index 4dc676c0a80..784f756ddc3 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_api.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_api.c @@ -93,7 +93,6 @@ void BTA_HhDisable(void) { BT_HDR *p_buf; - bta_sys_deregister(BTA_ID_HH); if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HH_API_DISABLE_EVT; bta_sys_sendmsg(p_buf); diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c index 9768cbb0260..360b3fd85ea 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c @@ -481,6 +481,8 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status) } utl_freebuf((void **)&bta_hh_cb.p_disc_db); + bta_sys_deregister(BTA_ID_HH); + if (bta_hh_cb.p_cback) { tBTA_HH data = {0}; data.status = status; diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c index b803de9896e..e5ac11a10ad 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -767,6 +767,8 @@ void bta_jv_disable (tBTA_JV_MSG *p_data) bta_jv_cb.pm_cb[i].handle = BTA_JV_PM_HANDLE_CLEAR; } + bta_sys_deregister(BTA_ID_JV); + if (p_data->disable.p_cback) { p_data->disable.p_cback(BTA_JV_DISABLE_EVT, (tBTA_JV *)&evt_data, NULL); } diff --git a/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c b/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c index 7eeb2159b3b..82b000b99de 100644 --- a/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c +++ b/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c @@ -284,8 +284,6 @@ void bta_pba_client_api_disable(tBTA_PBA_CLIENT_DATA *p_data) if (!bta_sys_is_register(BTA_ID_PBC)) { return; } - /* deregister with BTA system manager */ - bta_sys_deregister(BTA_ID_PBC); /* close all connections */ for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { @@ -297,6 +295,7 @@ void bta_pba_client_api_disable(tBTA_PBA_CLIENT_DATA *p_data) /* store and clear callback function */ tBTA_PBA_CLIENT_CBACK *p_cback = bta_pba_client_cb.p_cback; bta_pba_client_cb.p_cback = NULL; + bta_sys_deregister(BTA_ID_PBC); if(p_cback) { p_cback(BTA_PBA_CLIENT_DISABLE_EVT, NULL); diff --git a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c index ccfb5b0c7cf..12e4cadc1da 100644 --- a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c +++ b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c @@ -653,6 +653,8 @@ void bta_sdp_disable(tBTA_SDP_MSG *p_data) } } + bta_sys_deregister(BTA_ID_SDP); + if (dm_cbk) { dm_cbk(BTA_SDP_DISABLE_EVT, &bta_sdp, NULL); } diff --git a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c index f55aeb0f65f..eee98773006 100644 --- a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c @@ -513,7 +513,7 @@ void bta_sys_event(void * param) id = (UINT8) (p_msg->event >> 8); /* verify id and call subsystem event handler */ - if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) { + if ((id < BTA_ID_MAX) && bta_sys_cb.is_reg[id] && (bta_sys_cb.reg[id] != NULL)) { freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg); } else { APPL_TRACE_WARNING("BTA got unregistered event id %d\n", id);