feat(ble/bluedroid): Optimize Bluedroid memory usage

- Delete unused device records (~356B each)


(cherry picked from commit 7d1c0e9a32)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
This commit is contained in:
Zhang Hai Peng
2026-06-26 20:24:34 +08:00
parent 7b2b31bb0d
commit e9fce74445
3 changed files with 87 additions and 11 deletions

View File

@@ -183,7 +183,6 @@ uint32_t btc_get_ble_status(void)
}
#endif // #if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE))
#if (SMP_INCLUDED == TRUE)
// Number of recorded devices
extern uint8_t btm_ble_sec_dev_record_count(void);
uint8_t sec_dev_cnt = btm_ble_sec_dev_record_count();
@@ -191,14 +190,14 @@ uint32_t btc_get_ble_status(void)
BTC_TRACE_WARNING("%s security device record count %d", __func__, sec_dev_cnt);
status |= BIT(BTC_BLE_STATUS_DEVICE_REC);
}
#if SMP_INCLUDED == TRUE
// Number of saved bonded devices
int bond_cnt = btc_storage_get_num_ble_bond_devices();
if (bond_cnt) {
BTC_TRACE_WARNING("%s bonded devices count %d", __func__, bond_cnt);
status |= BIT(BTC_BLE_STATUS_BOND);
}
#endif // SMP_INCLUDED
#endif // SMP_INCLUDED == TRUE
#if (BLE_PRIVACY_SPT == TRUE)
// Privacy enabled

View File

@@ -2903,26 +2903,47 @@ uint8_t btm_ble_scan_active_count(void)
return count;
}
#if (BLE_INCLUDED == TRUE)
#if (SMP_INCLUDED == TRUE)
extern bool btc_config_has_section(const char *section);
#endif
uint8_t btm_ble_sec_dev_record_count(void)
{
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
list_node_t *p_node = NULL;
uint8_t count = 0;
/* First look for the non-paired devices for the oldest entry */
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
#if (SMP_INCLUDED == TRUE)
if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE) && (p_dev_rec->ble.key_type != BTM_LE_KEY_NONE)) {
BTM_TRACE_DEBUG("%s BLE security device #%d: bd_addr=%02X:%02X:%02X:%02X:%02X:%02X",
#else
if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE)) {
#endif
#if (SMP_INCLUDED == TRUE)
/* Check if device exists in NVS */
char bdstr[18] = {0};
bdaddr_to_string((bt_bdaddr_t *)p_dev_rec->bd_addr, bdstr, sizeof(bdstr));
BTM_TRACE_WARNING("%s device #%d: "MACSTR", key_type=0x%02x (PENC:%d PID:%d PCSRK:%d LENC:%d LID:%d LCSRK:%d), in_nvs=%d",
__func__,
count,
p_dev_rec->bd_addr[0],
p_dev_rec->bd_addr[1],
p_dev_rec->bd_addr[2],
p_dev_rec->bd_addr[3],
p_dev_rec->bd_addr[4],
p_dev_rec->bd_addr[5]);
MAC2STR(p_dev_rec->bd_addr),
p_dev_rec->ble.key_type,
(p_dev_rec->ble.key_type & BTM_LE_KEY_PENC) ? 1 : 0,
(p_dev_rec->ble.key_type & BTM_LE_KEY_PID) ? 1 : 0,
(p_dev_rec->ble.key_type & BTM_LE_KEY_PCSRK) ? 1 : 0,
(p_dev_rec->ble.key_type & BTM_LE_KEY_LENC) ? 1 : 0,
(p_dev_rec->ble.key_type & BTM_LE_KEY_LID) ? 1 : 0,
(p_dev_rec->ble.key_type & BTM_LE_KEY_LCSRK) ? 1 : 0,
btc_config_has_section(bdstr));
#else
BTM_TRACE_WARNING("%s device #%d: "MACSTR,
__func__,
count,
MAC2STR(p_dev_rec->bd_addr));
#endif
count++;
}
}

View File

@@ -951,6 +951,20 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
handle = HCID_GET_HANDLE (handle);
#if BLE_INCLUDED == TRUE
/* Capture the disconnecting device's address before btm_acl_disconnected()
* clears the matched connection handle. The record itself is re-looked-up
* afterwards (by address) because callbacks fired during disconnection may
* have already freed it. */
BD_ADDR disc_bda;
BOOLEAN have_disc_bda = FALSE;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle(handle);
if (p_dev_rec) {
memcpy(disc_bda, p_dev_rec->bd_addr, BD_ADDR_LEN);
have_disc_bda = TRUE;
}
#endif
dev_find = btm_acl_disconnected(handle, reason);
#if (BLE_FEAT_ISO_CIG_EN == TRUE)
@@ -963,6 +977,48 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x dev_find %d", handle, reason, dev_find);
UNUSED(dev_find);
#if BLE_INCLUDED == TRUE
/* Delete unpaired device records to free memory (~356B per device).
*
* Re-find the record by address: callbacks invoked during
* btm_acl_disconnected() may already have freed it, so the pointer captured
* before the call cannot be trusted.
*
* Only delete when the device is fully idle and unpaired:
* 1. No active BR/EDR connection (hci_handle invalid)
* 2. No active LE connection (ble_hci_handle invalid) - protects the still
* connected transport of a dual-mode device when the other one drops
* 3. No BLE security keys (unpaired) - when SMP is enabled
*
* BT_TRANSPORT_LE is used so that any retained BR/EDR link key keeps a
* BR/EDR-bonded record alive; an LE-unpaired record that has no BR/EDR key
* collapses to BTM_SEC_IN_USE only and is removed from the list.
*
* Skip deletion on HCI_ERR_CONN_FAILED_ESTABLISHMENT when connect
* retry is enabled.
*/
if (have_disc_bda
#if (GATTC_CONNECT_RETRY_EN == TRUE)
&& reason != HCI_ERR_CONN_FAILED_ESTABLISHMENT
#endif
) {
p_dev_rec = btm_find_dev(disc_bda);
if (p_dev_rec
&& p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE /* No active BR/EDR connection */
&& p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE /* No active LE connection */
#if SMP_INCLUDED == TRUE
&& !p_dev_rec->ble.key_type /* No BLE security keys */
#endif
) {
BTM_TRACE_WARNING(
"Deleting unpaired device %02X:%02X:%02X:%02X:%02X:%02X",
p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
btm_sec_free_dev(p_dev_rec, BT_TRANSPORT_LE);
}
}
#endif // BLE_INCLUDED == TRUE
}
/*******************************************************************************