From 60d6c96b0176e0198e1d0176b0532660da41239e Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski <jpawlowski@google.com> Date: Thu, 18 May 2023 14:02:17 +0200 Subject: [PATCH] LE Audio: Return SDP services if GATT discovery on LE transport fails Right now, if GATT discovery fails, we would prevent any services from being connected in Settings on dual mode device. After this patch, if LE GATT discovery fails, we will fall back to SDP only services, which should keep the audio devices usable. Bug: 278804760 Test: pair with LE Audio capable device that would fail to establish LE connection, or time out during GATT service discovery (cherry picked from https://android-review.googlesource.com/q/commit:4d5d871ab40ab59e25332be14e8d7187a7f95450) Merged-In: I734f792cb841d44e04748fd421fbfe458bb4ff41 Change-Id: I734f792cb841d44e04748fd421fbfe458bb4ff41 --- system/btif/src/btif_dm.cc | 56 ++++++++++++++++++++----- system/gd/rust/common/src/init_flags.rs | 1 + system/gd/rust/shim/src/init_flags.rs | 1 + 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 56eb6031486..7a2cbea6978 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -756,6 +756,28 @@ bool is_device_le_audio_capable(const RawAddress bd_addr) { return false; } +/* use to check if device is LE Audio Capable during bonding */ +bool is_le_audio_capable_during_service_discovery(const RawAddress& bd_addr) { + if (!GetInterfaceToProfiles() + ->profileSpecific_HACK->IsLeAudioClientRunning()) { + /* If LE Audio profile is not enabled, do nothing. */ + return false; + } + + if (bd_addr != pairing_cb.bd_addr && bd_addr != pairing_cb.static_bdaddr) { + return false; + } + + if (check_cod_le_audio(bd_addr) || + metadata_cb.le_audio_cache.contains(bd_addr) || + metadata_cb.le_audio_cache.contains(pairing_cb.bd_addr) || + BTA_DmCheckLeAudioCapable(bd_addr)) { + return true; + } + + return false; +} + /******************************************************************************* * * Function btif_dm_cb_create_bond @@ -1718,17 +1740,10 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, * capable of a2dp, and both sides can do LE Audio, and it haven't * finished GATT over LE yet, then wait for LE service discovery to finish * before before passing services to upper layers. */ - if ((bd_addr == pairing_cb.bd_addr || - bd_addr == pairing_cb.static_bdaddr) && - a2dp_sink_capable && - GetInterfaceToProfiles() - ->profileSpecific_HACK->IsLeAudioClientRunning() && + if (a2dp_sink_capable && 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(pairing_cb.bd_addr) || - BTA_DmCheckLeAudioCapable(bd_addr))) { + is_le_audio_capable_during_service_discovery(bd_addr)) { skip_reporting_wait_for_le = true; } @@ -1871,7 +1886,28 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, if (uuids.empty()) { LOG_INFO("No well known GATT services discovered"); - return; + + /* If services were returned as part of SDP discovery, we will + * immediately send them with rest of SDP results in BTA_DM_DISC_RES_EVT + */ + if (event == BTA_DM_GATT_OVER_SDP_RES_EVT) { + return; + } + + if (is_le_audio_capable_during_service_discovery(bd_addr)) { + if (bluetooth::common::init_flags:: + sdp_return_classic_services_when_le_discovery_fails_is_enabled()) { + LOG_INFO( + "Will return Classic SDP results, if done, to unblock bonding"); + } else { + // LEA device w/o this flag + // TODO: we might want to remove bond or do some action on + // half-discovered device + return; + } + } else { + return; + } } Uuid existing_uuids[BT_MAX_NUM_UUIDS] = {}; diff --git a/system/gd/rust/common/src/init_flags.rs b/system/gd/rust/common/src/init_flags.rs index b3cb59c22ae..598346c16ec 100644 --- a/system/gd/rust/common/src/init_flags.rs +++ b/system/gd/rust/common/src/init_flags.rs @@ -402,6 +402,7 @@ init_flags!( subrating = true, trigger_advertising_callbacks_on_first_resume_after_pause = true, use_unified_connection_manager, + sdp_return_classic_services_when_le_discovery_fails = true, } // dynamic flags can be updated at runtime and should be accessed directly // to check. diff --git a/system/gd/rust/shim/src/init_flags.rs b/system/gd/rust/shim/src/init_flags.rs index 27f1f3c4d2b..3b1d3398b98 100644 --- a/system/gd/rust/shim/src/init_flags.rs +++ b/system/gd/rust/shim/src/init_flags.rs @@ -56,6 +56,7 @@ mod ffi { fn subrating_is_enabled() -> bool; fn trigger_advertising_callbacks_on_first_resume_after_pause_is_enabled() -> bool; fn use_unified_connection_manager_is_enabled() -> bool; + fn sdp_return_classic_services_when_le_discovery_fails_is_enabled() -> bool; } } -- GitLab