From b86baddb62ef5b785eb5dc5d578153d35528dd27 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski <jpawlowski@google.com> Date: Wed, 4 Jan 2023 13:03:57 +0100 Subject: [PATCH] LE Audio: improve LE Audio device detection for Bonding As per BAP 1.0.1 and CAP 1.0 specs, LE Audio capable device shall/should put Service data for some services into the Advertisement. If these are detected, such devices should be treated as LE Audio capable for bonding. This is addition to existing mechanisms that was using just CoD field. Bug: 246560805 Test: pair with dual mode capable devices Change-Id: Icd6287fecbeadbc853e1ae4146937c85adea9104 --- system/bta/dm/bta_dm_api.cc | 11 +++++++++++ system/bta/include/bta_api.h | 10 ++++++++++ system/btif/src/btif_dm.cc | 11 ++++++++--- system/stack/btm/btm_ble_gap.cc | 24 ++++++++++++++++++++---- system/stack/btm/neighbor_inquiry.h | 1 + 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc index e2ba3a3c941..c9076dedd86 100644 --- a/system/bta/dm/bta_dm_api.cc +++ b/system/bta/dm/bta_dm_api.cc @@ -802,3 +802,14 @@ void BTA_DmBleSubrateRequest(const RawAddress& bd_addr, uint16_t subrate_min, base::Bind(bta_dm_ble_subrate_request, bd_addr, subrate_min, subrate_max, max_latency, cont_num, timeout)); } + +bool BTA_DmCheckLeAudioCapable(const RawAddress& address) { + for (tBTM_INQ_INFO* inq_ent = BTM_InqDbFirst(); inq_ent != nullptr; + inq_ent = BTM_InqDbNext(inq_ent)) { + if (inq_ent->results.remote_bd_addr != address) continue; + + LOG_INFO("Device is LE Audio capable based on AD content"); + return inq_ent->results.ble_ad_is_le_audio_capable; + } + return false; +} diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 0925b98bc43..ff85ece8a9e 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -1393,4 +1393,14 @@ extern void BTA_DmBleSubrateRequest(const RawAddress& bd_addr, uint16_t max_latency, uint16_t cont_num, uint16_t timeout); +/******************************************************************************* + * + * Function BTA_DmCheckLeAudioCapable + * + * Description Checks if device should be considered as LE Audio capable + * + * Returns True if Le Audio capable device, false otherwise + * + ******************************************************************************/ +extern bool BTA_DmCheckLeAudioCapable(const RawAddress& address); #endif /* BTA_API_H */ diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 921ecaea6f5..a192b7b5c23 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -657,12 +657,16 @@ static void btif_update_remote_properties(const RawAddress& bdaddr, * ordering issues (first Classic, GATT over SDP, etc) */ static bool is_device_le_audio_capable(const RawAddress bd_addr) { if (!GetInterfaceToProfiles() - ->profileSpecific_HACK->IsLeAudioClientRunning() || - !check_cod_le_audio(bd_addr)) { + ->profileSpecific_HACK->IsLeAudioClientRunning()) { /* If LE Audio profile is not enabled, do nothing. */ return false; } + if (!check_cod_le_audio(bd_addr) && !BTA_DmCheckLeAudioCapable(bd_addr)) { + /* LE Audio not present in CoD or in LE Advertisement, do nothing.*/ + return false; + } + tBT_DEVICE_TYPE tmp_dev_type; tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC; BTM_ReadDevInfo(bd_addr, &tmp_dev_type, &addr_type); @@ -1548,7 +1552,8 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, pairing_cb.gatt_over_le != btif_dm_pairing_cb_t::ServiceDiscoveryState::FINISHED && (check_cod_le_audio(bd_addr) || - metadata_cb.le_audio_cache.contains(bd_addr))) { + metadata_cb.le_audio_cache.contains(bd_addr) || + BTA_DmCheckLeAudioCapable(bd_addr))) { skip_reporting_wait_for_le = true; } diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc index 2a91e3be8f6..fc9d6abfc2a 100644 --- a/system/stack/btm/btm_ble_gap.cc +++ b/system/stack/btm/btm_ble_gap.cc @@ -2403,9 +2403,7 @@ void btm_ble_update_inq_result(tINQ_DB_ENT* p_i, uint8_t addr_type, has_advertising_flags = true; p_cur->flag = *p_flag; } - } - if (!data.empty()) { /* Check to see the BLE device has the Appearance UUID in the advertising * data. If it does * then try to convert the appearance value to a class of device value @@ -2435,14 +2433,32 @@ void btm_ble_update_inq_result(tINQ_DB_ENT* p_i, uint8_t addr_type, } } } - } - if (!data.empty()) { const uint8_t* p_rsi = AdvertiseDataParser::GetFieldByType(data, BTM_BLE_AD_TYPE_RSI, &len); if (p_rsi != nullptr && len == 6) { STREAM_TO_BDADDR(p_cur->ble_ad_rsi, p_rsi); } + + const uint8_t* p_service_data = data.data(); + uint16_t remaining_data_len = data.size(); + uint8_t service_data_len = 0; + + while ((p_service_data = AdvertiseDataParser::GetFieldByType( + p_service_data + service_data_len, + (remaining_data_len -= service_data_len), + BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE, &service_data_len))) { + uint16_t uuid; + STREAM_TO_UINT16(uuid, p_service_data); + + if (uuid == 0x184E /* Audio Stream Control service */ || + uuid == 0x184F /* Broadcast Audio Scan service */ || + uuid == 0x1850 /* Published Audio Capabilities service */ || + uuid == 0x1853 /* Common Audio service */) { + p_cur->ble_ad_is_le_audio_capable = true; + break; + } + } } // Non-connectable packets may omit flags entirely, in which case nothing diff --git a/system/stack/btm/neighbor_inquiry.h b/system/stack/btm/neighbor_inquiry.h index 20f76d4aeb9..d03ea08ddcc 100644 --- a/system/stack/btm/neighbor_inquiry.h +++ b/system/stack/btm/neighbor_inquiry.h @@ -117,6 +117,7 @@ typedef struct { int8_t ble_tx_power; uint16_t ble_periodic_adv_int; RawAddress ble_ad_rsi; /* Resolvable Set Identifier from advertising */ + bool ble_ad_is_le_audio_capable; uint8_t flag; bool include_rsi; RawAddress original_bda; -- GitLab