diff --git a/components/bt/host/bluedroid/bta/av/bta_av_aact.c b/components/bt/host/bluedroid/bta/av/bta_av_aact.c index 1120c9fb0b5..1cf3d65714e 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_aact.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_aact.c @@ -35,6 +35,7 @@ #include "bta_av_int.h" #include "stack/avdt_api.h" +#include "stack/sdp_api.h" #include "bta/utl.h" #include "stack/l2c_api.h" #include "stack/l2cdefs.h" @@ -1035,7 +1036,7 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) /* free any buffers */ utl_freebuf((void **) &p_scb->p_cap); - utl_freebuf((void **) &p_scb->p_disc_db); + bta_av_free_sdb(p_scb, NULL); p_scb->avdt_version = 0; /* initialize some control block variables */ @@ -1082,7 +1083,10 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) void bta_av_free_sdb(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) { UNUSED(p_data); - utl_freebuf((void **) &p_scb->p_disc_db); + if (p_scb->p_disc_db) { + SDP_CancelServiceSearch(p_scb->p_disc_db); + utl_freebuf((void **) &p_scb->p_disc_db); + } } /******************************************************************************* @@ -1586,7 +1590,7 @@ void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) { UNUSED(p_data); - utl_freebuf((void **) &p_scb->p_disc_db); + bta_av_free_sdb(p_scb, NULL); if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) { /* SNK initiated L2C connection while SRC was doing SDP. */ @@ -1613,7 +1617,7 @@ void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_scb->open_status = BTA_AV_FAIL_SDP; } - utl_freebuf((void **) &p_scb->p_disc_db); + bta_av_free_sdb(p_scb, NULL); bta_av_str_closed(p_scb, p_data); } 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 00f6b5f341c..42185814e6e 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_act.c @@ -31,6 +31,7 @@ #include "bta_av_int.h" #include "stack/avdt_api.h" #include "bta/utl.h" +#include "stack/sdp_api.h" #include "stack/l2c_api.h" #include "osi/allocator.h" #include "osi/list.h" @@ -1302,7 +1303,14 @@ void bta_av_disable(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) bta_av_close_all_rc(p_cb); - utl_freebuf((void **) &p_cb->p_disc_db); + /* Clear disc first so a late BTA_AV_SDP_AVRC_DISC_EVT hits + * bta_av_rc_disc_done()'s if (!p_cb->disc) and does not scan p_disc_db. */ + p_cb->disc = 0; + if (p_cb->p_disc_db) { + /* SDP may still be writing into this buffer (AVRCP discovery). */ + SDP_CancelServiceSearch(p_cb->p_disc_db); + utl_freebuf((void **) &p_cb->p_disc_db); + } /* disable audio/video - de-register all channels, * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */ @@ -1757,7 +1765,10 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) } #endif p_cb->disc = 0; - utl_freebuf((void **) &p_cb->p_disc_db); + if (p_cb->p_disc_db) { + SDP_CancelServiceSearch(p_cb->p_disc_db); + utl_freebuf((void **) &p_cb->p_disc_db); + } APPL_TRACE_DEBUG("peer_features 0x%x, local features 0x%x", peer_features, p_cb->features); diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c index efe6a99ebd9..42bc2a04f7a 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c @@ -35,6 +35,7 @@ #include "bta/bta_hh_co.h" #include "bta/utl.h" #include "osi/allocator.h" +#include "stack/sdp_api.h" /***************************************************************************** ** Constants @@ -129,6 +130,9 @@ void bta_hh_api_disable(void) return; } + /* Drop in-flight SDP before tearing down connections / HID host. */ + bta_hh_free_disc_db(); + /* no live connection, signal DISC_CMPL_EVT directly */ if (!bta_hh_cb.cnt_num) { bta_hh_disc_cmpl(); @@ -243,7 +247,7 @@ static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask, } /* free disc_db when SDP is completed */ - utl_freebuf((void **)&bta_hh_cb.p_disc_db); + bta_hh_free_disc_db(); /* send SDP_CMPL_EVT into state machine */ data.status = status; @@ -301,7 +305,7 @@ static void bta_hh_di_sdp_cback(UINT16 result) if (status != BTA_HH_OK) { - utl_freebuf((void **)&bta_hh_cb.p_disc_db); + bta_hh_free_disc_db(); /* send SDP_CMPL_EVT into state machine */ data.status = status; bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &data); @@ -384,7 +388,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) Status 0x%2X", status); #endif status = BTA_HH_ERR_SDP; - utl_freebuf((void **)&bta_hh_cb.p_disc_db); + bta_hh_free_disc_db(); } else { status = BTA_HH_OK; } 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 360b3fd85ea..48a7239c586 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c @@ -22,6 +22,7 @@ #include "osi/allocator.h" #include "bta_hh_int.h" +#include "stack/sdp_api.h" /* if SSR max latency is not defined by remote device, set the default value as half of the link supervision timeout */ @@ -462,6 +463,25 @@ tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UIN return status; } +/******************************************************************************* +** +** Function bta_hh_free_disc_db +** +** Description Cancel any in-flight SDP search using the HID discovery +** database, then free it. +** +** Returns void +** +*******************************************************************************/ +void bta_hh_free_disc_db(void) +{ + if (bta_hh_cb.p_disc_db) { + /* SDP (DI discover / HID_HostGetSDPRecord) may still write this buffer. */ + SDP_CancelServiceSearch(bta_hh_cb.p_disc_db); + utl_freebuf((void **)&bta_hh_cb.p_disc_db); + } +} + /******************************************************************************* ** ** Function bta_hh_cleanup_disable @@ -479,7 +499,7 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status) for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) { utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list); } - utl_freebuf((void **)&bta_hh_cb.p_disc_db); + bta_hh_free_disc_db(); bta_sys_deregister(BTA_ID_HH); diff --git a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h index 56f99e8420d..fc6b06de1d9 100644 --- a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h +++ b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h @@ -356,6 +356,7 @@ extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle, extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id, UINT16 version, UINT8 flag); extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status); +extern void bta_hh_free_disc_db(void); extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle); 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 e5ac11a10ad..1c24cd5844f 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -754,6 +754,15 @@ void bta_jv_disable (tBTA_JV_MSG *p_data) tBTA_JV_STATUS evt_data; evt_data = BTA_JV_SUCCESS; + /* An SDP search still in progress keeps writing into p_bta_jv_cfg->p_sdp_db, + * which BTA_JvFree() releases once BTA_JV_DISABLE_EVT is handled. Cancel it + * first: the connection control block then rejects any late response instead + * of parsing it into freed memory. */ + if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) { + APPL_TRACE_WARNING("%s: SDP discovery active, cancelling it", __func__); + SDP_CancelServiceSearch(p_bta_jv_cfg->p_sdp_db); + } + // clear all the pm_cb slots for (int i = 0; i < BTA_JV_PM_MAX_NUM; i++) { if (bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) {