From 3b266e017aa913582dacfbfdba539eceefe79c99 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 | 3 ++- 16 files changed, 24 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 2fcf2bdcb8e..c1350d043bc 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); } } @@ -1843,6 +1844,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 ec8129e6847..a5221ec9043 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 18bc0493801..e2bf88aebf9 100644 --- a/components/bt/host/bluedroid/bta/hd/bta_hd_act.c +++ b/components/bt/host/bluedroid/bta/hd/bta_hd_act.c @@ -129,6 +129,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 8550a0e06e1..9eec1914f47 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_api.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_api.c @@ -94,7 +94,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 6650e404c65..b7a51ccdfbf 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c @@ -478,6 +478,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) { (*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status); /* all connections are down, no waiting for disconnect */ 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 78fc08b04d1..436d19b6d47 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -765,6 +765,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 af220475342..050d3bd5fad 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 @@ -181,8 +181,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) { @@ -194,6 +192,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 1dc09dabcf5..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); @@ -555,6 +555,7 @@ void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg) void bta_sys_deregister(UINT8 id) { bta_sys_cb.is_reg[id] = FALSE; + bta_sys_cb.reg[id] = NULL; } /*******************************************************************************