1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3 * www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <base/functional/bind.h>
19 #include <base/strings/string_number_conversions.h>
20 #include <bluetooth/log.h>
21 #include <com_android_bluetooth_flags.h>
22 #include <lc3.h>
23
24 #include <deque>
25 #include <map>
26 #include <mutex>
27 #include <optional>
28
29 #include "audio_hal_client/audio_hal_client.h"
30 #include "audio_hal_interface/le_audio_software.h"
31 #include "bta/csis/csis_types.h"
32 #include "bta_gatt_api.h"
33 #include "bta_gatt_queue.h"
34 #include "bta_groups.h"
35 #include "bta_le_audio_api.h"
36 #include "bta_le_audio_broadcaster_api.h"
37 #include "btif/include/btif_profile_storage.h"
38 #include "btm_iso_api.h"
39 #include "client_parser.h"
40 #include "codec_interface.h"
41 #include "codec_manager.h"
42 #include "common/strings.h"
43 #include "common/time_util.h"
44 #include "content_control_id_keeper.h"
45 #include "devices.h"
46 #include "hci/controller_interface.h"
47 #include "internal_include/bt_trace.h"
48 #include "internal_include/stack_config.h"
49 #include "le_audio_health_status.h"
50 #include "le_audio_set_configuration_provider.h"
51 #include "le_audio_types.h"
52 #include "le_audio_utils.h"
53 #include "main/shim/entry.h"
54 #include "metrics_collector.h"
55 #include "os/log.h"
56 #include "osi/include/osi.h"
57 #include "osi/include/properties.h"
58 #include "stack/btm/btm_sec.h"
59 #include "stack/include/acl_api.h"
60 #include "stack/include/bt_types.h"
61 #include "stack/include/main_thread.h"
62 #include "state_machine.h"
63 #include "storage_helper.h"
64
65 using base::Closure;
66 using bluetooth::Uuid;
67 using bluetooth::common::ToString;
68 using bluetooth::groups::DeviceGroups;
69 using bluetooth::groups::DeviceGroupsCallbacks;
70 using bluetooth::hci::IsoManager;
71 using bluetooth::hci::iso_manager::cig_create_cmpl_evt;
72 using bluetooth::hci::iso_manager::cig_remove_cmpl_evt;
73 using bluetooth::hci::iso_manager::CigCallbacks;
74 using bluetooth::le_audio::CodecManager;
75 using bluetooth::le_audio::ConnectionState;
76 using bluetooth::le_audio::ContentControlIdKeeper;
77 using bluetooth::le_audio::DeviceConnectState;
78 using bluetooth::le_audio::DsaMode;
79 using bluetooth::le_audio::DsaModes;
80 using bluetooth::le_audio::GroupNodeStatus;
81 using bluetooth::le_audio::GroupStatus;
82 using bluetooth::le_audio::GroupStreamStatus;
83 using bluetooth::le_audio::LeAudioCodecConfiguration;
84 using bluetooth::le_audio::LeAudioDevice;
85 using bluetooth::le_audio::LeAudioDeviceGroup;
86 using bluetooth::le_audio::LeAudioDeviceGroups;
87 using bluetooth::le_audio::LeAudioDevices;
88 using bluetooth::le_audio::LeAudioGroupStateMachine;
89 using bluetooth::le_audio::LeAudioHealthBasedAction;
90 using bluetooth::le_audio::LeAudioHealthDeviceStatType;
91 using bluetooth::le_audio::LeAudioHealthGroupStatType;
92 using bluetooth::le_audio::LeAudioHealthStatus;
93 using bluetooth::le_audio::LeAudioRecommendationActionCb;
94 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
95 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
96 using bluetooth::le_audio::UnicastMonitorModeStatus;
97 using bluetooth::le_audio::types::ase;
98 using bluetooth::le_audio::types::AseState;
99 using bluetooth::le_audio::types::AudioContexts;
100 using bluetooth::le_audio::types::AudioLocations;
101 using bluetooth::le_audio::types::BidirectionalPair;
102 using bluetooth::le_audio::types::DataPathState;
103 using bluetooth::le_audio::types::hdl_pair;
104 using bluetooth::le_audio::types::kDefaultScanDurationS;
105 using bluetooth::le_audio::types::kLeAudioContextAllBidir;
106 using bluetooth::le_audio::types::kLeAudioContextAllRemoteSinkOnly;
107 using bluetooth::le_audio::types::kLeAudioContextAllRemoteSource;
108 using bluetooth::le_audio::types::kLeAudioContextAllTypesArray;
109 using bluetooth::le_audio::types::LeAudioContextType;
110 using bluetooth::le_audio::types::PublishedAudioCapabilities;
111 using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata;
112 using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata;
113
114 using namespace bluetooth;
115
116 /* Enums */
117 enum class AudioReconfigurationResult {
118 RECONFIGURATION_NEEDED = 0x00,
119 RECONFIGURATION_NOT_NEEDED,
120 RECONFIGURATION_NOT_POSSIBLE
121 };
122
123 enum class AudioState {
124 IDLE = 0x00,
125 READY_TO_START,
126 STARTED,
127 READY_TO_RELEASE,
128 RELEASING,
129 };
130
operator <<(std::ostream & os,const AudioReconfigurationResult & state)131 std::ostream& operator<<(std::ostream& os,
132 const AudioReconfigurationResult& state) {
133 switch (state) {
134 case AudioReconfigurationResult::RECONFIGURATION_NEEDED:
135 os << "RECONFIGURATION_NEEDED";
136 break;
137 case AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED:
138 os << "RECONFIGURATION_NOT_NEEDED";
139 break;
140 case AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE:
141 os << "RECONFIGRATION_NOT_POSSIBLE";
142 break;
143 default:
144 os << "UNKNOWN";
145 break;
146 }
147 return os;
148 }
149
operator <<(std::ostream & os,const AudioState & audio_state)150 std::ostream& operator<<(std::ostream& os, const AudioState& audio_state) {
151 switch (audio_state) {
152 case AudioState::IDLE:
153 os << "IDLE";
154 break;
155 case AudioState::READY_TO_START:
156 os << "READY_TO_START";
157 break;
158 case AudioState::STARTED:
159 os << "STARTED";
160 break;
161 case AudioState::READY_TO_RELEASE:
162 os << "READY_TO_RELEASE";
163 break;
164 case AudioState::RELEASING:
165 os << "RELEASING";
166 break;
167 default:
168 os << "UNKNOWN";
169 break;
170 }
171 return os;
172 }
173
174 namespace fmt {
175 template <>
176 struct formatter<AudioState> : ostream_formatter {};
177 } // namespace fmt
178
179 namespace {
180 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
181
182 static void le_audio_health_status_callback(const RawAddress& addr,
183 int group_id,
184 LeAudioHealthBasedAction action);
185
186 class LeAudioClientImpl;
187 LeAudioClientImpl* instance;
188 std::mutex instance_mutex;
189 LeAudioSourceAudioHalClient::Callbacks* audioSinkReceiver;
190 LeAudioSinkAudioHalClient::Callbacks* audioSourceReceiver;
191 CigCallbacks* stateMachineHciCallbacks;
192 LeAudioGroupStateMachine::Callbacks* stateMachineCallbacks;
193 DeviceGroupsCallbacks* device_group_callbacks;
194 LeAudioIsoDataCallback* iso_data_callback;
195
196 /*
197 * Coordinatet Set Identification Profile (CSIP) based on CSIP 1.0
198 * and Coordinatet Set Identification Service (CSIS) 1.0
199 *
200 * CSIP allows to organize audio servers into sets e.g. Stereo Set, 5.1 Set
201 * and speed up connecting it.
202 *
203 * Since leaudio has already grouping API it was decided to integrate here CSIS
204 * and allow it to group devices semi-automatically.
205 *
206 * Flow:
207 * If connected device contains CSIS services, and it is included into CAP
208 * service, implementation marks device as a set member and waits for the
209 * bta/csis to learn about groups and notify implementation about assigned
210 * group id.
211 *
212 */
213 /* LeAudioClientImpl class represents main implementation class for le audio
214 * feature in stack. This class implements GATT, le audio and ISO related parts.
215 *
216 * This class is represented in single instance and manages a group of devices,
217 * and devices. All devices calls back static method from it and are dispatched
218 * to target receivers (e.g. ASEs, devices).
219 *
220 * This instance also implements a LeAudioClient which is a upper layer API.
221 * Also LeAudioClientCallbacks are callbacks for upper layer.
222 *
223 * This class may be bonded with Test socket which allows to drive an instance
224 * for test purposes.
225 */
226 class LeAudioClientImpl : public LeAudioClient {
227 public:
~LeAudioClientImpl()228 ~LeAudioClientImpl() {
229 alarm_free(close_vbc_timeout_);
230 alarm_free(disable_timer_);
231 alarm_free(suspend_timeout_);
232 };
233
LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks * callbacks_,LeAudioGroupStateMachine::Callbacks * state_machine_callbacks_,base::Closure initCb)234 LeAudioClientImpl(
235 bluetooth::le_audio::LeAudioClientCallbacks* callbacks_,
236 LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_,
237 base::Closure initCb)
238 : gatt_if_(0),
239 callbacks_(callbacks_),
240 active_group_id_(bluetooth::groups::kGroupUnknown),
241 configuration_context_type_(LeAudioContextType::UNINITIALIZED),
242 local_metadata_context_types_(
243 {.sink = AudioContexts(), .source = AudioContexts()}),
244 stream_setup_start_timestamp_(0),
245 stream_setup_end_timestamp_(0),
246 audio_receiver_state_(AudioState::IDLE),
247 audio_sender_state_(AudioState::IDLE),
248 in_call_(false),
249 in_voip_call_(false),
250 sink_monitor_mode_(false),
251 sink_monitor_notified_status_(std::nullopt),
252 source_monitor_mode_(false),
253 le_audio_source_hal_client_(nullptr),
254 le_audio_sink_hal_client_(nullptr),
255 close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")),
256 suspend_timeout_(alarm_new("LeAudioSuspendTimeout")),
257 disable_timer_(alarm_new("LeAudioDisableTimer")) {
258 LeAudioGroupStateMachine::Initialize(state_machine_callbacks_);
259 groupStateMachine_ = LeAudioGroupStateMachine::Get();
260
261 if (bluetooth::common::InitFlags::
262 IsTargetedAnnouncementReconnectionMode()) {
263 log::info("Reconnection mode: TARGETED_ANNOUNCEMENTS");
264 reconnection_mode_ = BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS;
265 } else {
266 log::info("Reconnection mode: ALLOW_LIST");
267 reconnection_mode_ = BTM_BLE_BKG_CONNECT_ALLOW_LIST;
268 }
269
270 if (com::android::bluetooth::flags::leaudio_enable_health_based_actions()) {
271 log::info("Loading health status module");
272 leAudioHealthStatus_ = LeAudioHealthStatus::Get();
273 leAudioHealthStatus_->RegisterCallback(
274 base::BindRepeating(le_audio_health_status_callback));
275 }
276
277 BTA_GATTC_AppRegister(
278 le_audio_gattc_callback,
279 base::Bind(
__anonf21162180202(base::Closure initCb, uint8_t client_id, uint8_t status) 280 [](base::Closure initCb, uint8_t client_id, uint8_t status) {
281 if (status != GATT_SUCCESS) {
282 log::error(
283 "Can't start LeAudio profile - no gatt clients left!");
284 return;
285 }
286 instance->gatt_if_ = client_id;
287 initCb.Run();
288 },
289 initCb),
290 true);
291
292 DeviceGroups::Get()->Initialize(device_group_callbacks);
293 }
294
ReconfigureAfterVbcClose()295 void ReconfigureAfterVbcClose() {
296 log::debug("VBC close timeout");
297
298 if (IsInVoipCall()) {
299 SetInVoipCall(false);
300 }
301
302 auto group = aseGroups_.FindById(active_group_id_);
303 if (!group) {
304 log::error("Invalid group: {}", active_group_id_);
305 return;
306 }
307
308 /* Reconfiguration to non requiring source scenario */
309 if (sink_monitor_mode_) {
310 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
311 }
312
313 /* For sonification events we don't really need to reconfigure to HQ
314 * configuration, but if the previous configuration was for HQ Media,
315 * we might want to go back to that scenario.
316 */
317
318 if ((configuration_context_type_ != LeAudioContextType::MEDIA) &&
319 (configuration_context_type_ != LeAudioContextType::GAME)) {
320 log::info(
321 "Keeping the old configuration as no HQ Media playback is needed "
322 "right now.");
323 return;
324 }
325
326 /* Test the existing metadata against the recent availability */
327 local_metadata_context_types_.source &= group->GetAvailableContexts(
328 bluetooth::le_audio::types::kLeAudioDirectionSink);
329 if (local_metadata_context_types_.source.none()) {
330 log::warn("invalid/unknown context metadata, using 'MEDIA' instead");
331 local_metadata_context_types_.source =
332 AudioContexts(LeAudioContextType::MEDIA);
333 }
334
335 /* Choose the right configuration context */
336 auto new_configuration_context = AdjustForVoiceAssistant(
337 group,
338 ChooseConfigurationContextType(local_metadata_context_types_.source));
339
340 log::debug("new_configuration_context= {}",
341 ToString(new_configuration_context));
342 ReconfigureOrUpdateMetadata(group, new_configuration_context,
343 {.sink = local_metadata_context_types_.source,
344 .source = local_metadata_context_types_.sink});
345 }
346
StartVbcCloseTimeout()347 void StartVbcCloseTimeout() {
348 if (alarm_is_scheduled(close_vbc_timeout_)) {
349 StopVbcCloseTimeout();
350 }
351
352 static const uint64_t timeoutMs = 2000;
353 log::debug("Start VBC close timeout with {} ms",
354 static_cast<unsigned long>(timeoutMs));
355
356 alarm_set_on_mloop(
357 close_vbc_timeout_, timeoutMs,
358 [](void*) {
359 if (instance) instance->ReconfigureAfterVbcClose();
360 },
361 nullptr);
362 }
363
StopVbcCloseTimeout()364 void StopVbcCloseTimeout() {
365 if (alarm_is_scheduled(close_vbc_timeout_)) {
366 log::debug("Cancel VBC close timeout");
367 alarm_cancel(close_vbc_timeout_);
368 }
369 }
370
AseInitialStateReadRequest(LeAudioDevice * leAudioDevice)371 void AseInitialStateReadRequest(LeAudioDevice* leAudioDevice) {
372 int ases_num = leAudioDevice->ases_.size();
373 void* notify_flag_ptr = NULL;
374
375 for (int i = 0; i < ases_num; i++) {
376 /* Last read ase characteristic should issue connected state callback
377 * to upper layer
378 */
379
380 if (leAudioDevice->notify_connected_after_read_ &&
381 (i == (ases_num - 1))) {
382 notify_flag_ptr =
383 INT_TO_PTR(leAudioDevice->notify_connected_after_read_);
384 }
385
386 BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
387 leAudioDevice->ases_[i].hdls.val_hdl,
388 OnGattReadRspStatic, notify_flag_ptr);
389 }
390 }
391
OnGroupAddedCb(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)392 void OnGroupAddedCb(const RawAddress& address, const bluetooth::Uuid& uuid,
393 int group_id) {
394 log::info("address: {} group uuid {} group_id: {}", address, uuid,
395 group_id);
396
397 /* We are interested in the groups which are in the context of CAP */
398 if (uuid != bluetooth::le_audio::uuid::kCapServiceUuid) return;
399
400 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
401 if (!leAudioDevice) return;
402 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
403 log::info("group already set: {}", leAudioDevice->group_id_);
404 return;
405 }
406
407 group_add_node(group_id, address);
408 }
409
410 /* If device participates in streaming the group, it has to be stopped and
411 * group needs to be reconfigured if needed to new configuration without
412 * considering this removing device.
413 */
SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice * leAudioDevice)414 void SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice* leAudioDevice) {
415 log::info("device {}", leAudioDevice->address_);
416 leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
417 leAudioDevice->closing_stream_for_disconnection_ = true;
418 GroupStop(leAudioDevice->group_id_);
419 }
420
OnGroupMemberAddedCb(const RawAddress & address,int group_id)421 void OnGroupMemberAddedCb(const RawAddress& address, int group_id) {
422 log::info("address: {} group_id: {}", address, group_id);
423
424 auto group = aseGroups_.FindById(group_id);
425 if (!group) {
426 log::error("Not interested in group id: {}", group_id);
427 return;
428 }
429
430 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
431 if (!leAudioDevice) return;
432 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
433 log::info("group already set: {}", leAudioDevice->group_id_);
434 return;
435 }
436
437 if (leAudioHealthStatus_) {
438 leAudioHealthStatus_->AddStatisticForDevice(
439 leAudioDevice, LeAudioHealthDeviceStatType::VALID_CSIS);
440 }
441
442 group_add_node(group_id, address);
443 }
444
OnGroupMemberRemovedCb(const RawAddress & address,int group_id)445 void OnGroupMemberRemovedCb(const RawAddress& address, int group_id) {
446 log::info("address: {} group_id: {}", address, group_id);
447
448 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
449 if (!leAudioDevice) return;
450 if (leAudioDevice->group_id_ != group_id) {
451 log::warn("Device: {} not assigned to the group.",
452 leAudioDevice->address_);
453 return;
454 }
455
456 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
457 if (group == NULL) {
458 log::info("device not in the group: {}, {}", leAudioDevice->address_,
459 group_id);
460 return;
461 }
462
463 if (leAudioHealthStatus_) {
464 leAudioHealthStatus_->RemoveStatistics(address, group->group_id_);
465 }
466
467 if (leAudioDevice->HaveActiveAse()) {
468 SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
469 return;
470 }
471
472 group_remove_node(group, address);
473 }
474
475 /* This callback happens if kLeAudioDeviceSetStateTimeoutMs timeout happens
476 * during transition from origin to target state
477 */
OnLeAudioDeviceSetStateTimeout(int group_id)478 void OnLeAudioDeviceSetStateTimeout(int group_id) {
479 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
480
481 if (!group) {
482 /* Group removed */
483 return;
484 }
485
486 bool check_if_recovery_needed =
487 group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
488
489 if (leAudioHealthStatus_) {
490 leAudioHealthStatus_->AddStatisticForGroup(
491 group, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
492 }
493
494 log::error(
495 "State not achieved on time for group: group id {}, current state {}, "
496 "target state: {}, check_if_recovery_needed: {}",
497 group_id, ToString(group->GetState()),
498 ToString(group->GetTargetState()), check_if_recovery_needed);
499 group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
500 group->ClearAllCises();
501 group->PrintDebugState();
502
503 /* There is an issue with a setting up stream or any other operation which
504 * are gatt operations. It means peer is not responsable. Lets close ACL
505 */
506 CancelStreamingRequest();
507 LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
508 if (leAudioDevice == nullptr) {
509 log::error("Shouldn't be called without an active device.");
510 leAudioDevice = group->GetFirstDevice();
511 if (leAudioDevice == nullptr) {
512 log::error("Front device is null. Number of devices: {}",
513 group->Size());
514 return;
515 }
516 }
517
518 /* If Timeout happens on stream close and stream is closing just for the
519 * purpose of device disconnection, do not bother with recovery mode
520 */
521 bool recovery = true;
522 if (check_if_recovery_needed) {
523 for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
524 tmpDevice = group->GetNextActiveDevice(tmpDevice)) {
525 if (tmpDevice->closing_stream_for_disconnection_) {
526 recovery = false;
527 break;
528 }
529 }
530 }
531
532 do {
533 DisconnectDevice(leAudioDevice, true, recovery);
534 leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
535 } while (leAudioDevice);
536
537 if (recovery) {
538 /* Both devices will be disconnected soon. Notify upper layer that group
539 * is inactive */
540 groupSetAndNotifyInactive();
541 }
542 }
543
OnDeviceAutonomousStateTransitionTimeout(LeAudioDevice * leAudioDevice)544 void OnDeviceAutonomousStateTransitionTimeout(LeAudioDevice* leAudioDevice) {
545 log::error("Device {}, failed to complete autonomous transition",
546 leAudioDevice->address_);
547 DisconnectDevice(leAudioDevice, true);
548 }
549
UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup * group,bool force=false)550 void UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup* group,
551 bool force = false) {
552 bool group_conf_changed = group->ReloadAudioLocations();
553 group_conf_changed |= group->ReloadAudioDirections();
554 group_conf_changed |= group->UpdateAudioContextAvailability();
555 if (group_conf_changed || force) {
556 /* All the configurations should be recalculated for the new conditions */
557 group->InvalidateCachedConfigurations();
558 group->InvalidateGroupStrategy();
559 callbacks_->OnAudioConf(group->audio_directions_, group->group_id_,
560 group->snk_audio_locations_.to_ulong(),
561 group->src_audio_locations_.to_ulong(),
562 group->GetAvailableContexts().value());
563 }
564 }
565
SuspendedForReconfiguration()566 void SuspendedForReconfiguration() {
567 if (audio_sender_state_ > AudioState::IDLE) {
568 LeAudioLogHistory::Get()->AddLogHistory(
569 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
570 kLogAfSuspendForReconfig + "LocalSource",
571 "r_state: " + ToString(audio_receiver_state_) +
572 "s_state: " + ToString(audio_sender_state_));
573 le_audio_source_hal_client_->SuspendedForReconfiguration();
574 }
575 if (audio_receiver_state_ > AudioState::IDLE) {
576 LeAudioLogHistory::Get()->AddLogHistory(
577 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
578 kLogAfSuspendForReconfig + "LocalSink",
579 "r_state: " + ToString(audio_receiver_state_) +
580 "s_state: " + ToString(audio_sender_state_));
581 le_audio_sink_hal_client_->SuspendedForReconfiguration();
582 }
583 }
584
ReconfigurationComplete(uint8_t directions)585 void ReconfigurationComplete(uint8_t directions) {
586 if (directions & bluetooth::le_audio::types::kLeAudioDirectionSink) {
587 LeAudioLogHistory::Get()->AddLogHistory(
588 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
589 kLogAfReconfigComplete + "LocalSource",
590 "r_state: " + ToString(audio_receiver_state_) +
591 "s_state: " + ToString(audio_sender_state_));
592
593 le_audio_source_hal_client_->ReconfigurationComplete();
594 }
595 if (directions & bluetooth::le_audio::types::kLeAudioDirectionSource) {
596 LeAudioLogHistory::Get()->AddLogHistory(
597 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
598 kLogAfReconfigComplete + "LocalSink",
599 "r_state: " + ToString(audio_receiver_state_) +
600 "s_state: " + ToString(audio_sender_state_));
601
602 le_audio_sink_hal_client_->ReconfigurationComplete();
603 }
604 }
605
CancelLocalAudioSourceStreamingRequest()606 void CancelLocalAudioSourceStreamingRequest() {
607 le_audio_source_hal_client_->CancelStreamingRequest();
608
609 LeAudioLogHistory::Get()->AddLogHistory(
610 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
611 kLogAfCancel + "LocalSource",
612 "s_state: " + ToString(audio_sender_state_));
613
614 audio_sender_state_ = AudioState::IDLE;
615 }
616
CancelLocalAudioSinkStreamingRequest()617 void CancelLocalAudioSinkStreamingRequest() {
618 le_audio_sink_hal_client_->CancelStreamingRequest();
619
620 LeAudioLogHistory::Get()->AddLogHistory(
621 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
622 kLogAfCancel + "LocalSink",
623 "s_state: " + ToString(audio_receiver_state_));
624
625 audio_receiver_state_ = AudioState::IDLE;
626 }
627
CancelStreamingRequest()628 void CancelStreamingRequest() {
629 if (audio_sender_state_ >= AudioState::READY_TO_START) {
630 CancelLocalAudioSourceStreamingRequest();
631 }
632
633 if (audio_receiver_state_ >= AudioState::READY_TO_START) {
634 CancelLocalAudioSinkStreamingRequest();
635 }
636 }
637
group_add_node(const int group_id,const RawAddress & address,bool update_group_module=false)638 void group_add_node(const int group_id, const RawAddress& address,
639 bool update_group_module = false) {
640 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
641 LeAudioDeviceGroup* new_group;
642 LeAudioDeviceGroup* old_group = nullptr;
643
644 if (!leAudioDevice) {
645 /* TODO This part possible to remove as this is to handle adding device to
646 * the group which is unknown and not connected.
647 */
648 log::info("leAudioDevice unknown , address: {} group: 0x{:x}", address,
649 group_id);
650
651 if (group_id == bluetooth::groups::kGroupUnknown) return;
652
653 log::info("Set member adding ...");
654 leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
655 leAudioDevice = leAudioDevices_.FindByAddress(address);
656 } else {
657 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
658 old_group = aseGroups_.FindById(leAudioDevice->group_id_);
659 }
660 }
661
662 auto id = DeviceGroups::Get()->GetGroupId(
663 address, bluetooth::le_audio::uuid::kCapServiceUuid);
664 if (group_id == bluetooth::groups::kGroupUnknown) {
665 if (id == bluetooth::groups::kGroupUnknown) {
666 DeviceGroups::Get()->AddDevice(
667 address, bluetooth::le_audio::uuid::kCapServiceUuid);
668 /* We will get back here when group will be created */
669 return;
670 }
671
672 new_group = aseGroups_.Add(id);
673 if (!new_group) {
674 log::error("can't create group - group is already there?");
675 return;
676 }
677 } else {
678 log::assert_that(id == group_id,
679 "group id missmatch? leaudio id: {}, groups module {}",
680 group_id, id);
681 new_group = aseGroups_.FindById(group_id);
682 if (!new_group) {
683 new_group = aseGroups_.Add(group_id);
684 } else {
685 if (new_group->IsDeviceInTheGroup(leAudioDevice)) return;
686 }
687 }
688
689 log::debug("New group {}, id: {}", fmt::ptr(new_group),
690 new_group->group_id_);
691
692 /* If device was in the group and it was not removed by the application,
693 * lets do it now
694 */
695 if (old_group) group_remove_node(old_group, address, update_group_module);
696
697 new_group->AddNode(leAudioDevices_.GetByAddress(address));
698
699 callbacks_->OnGroupNodeStatus(address, new_group->group_id_,
700 GroupNodeStatus::ADDED);
701
702 /* If device is connected and added to the group, lets read ASE states */
703 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID)
704 AseInitialStateReadRequest(leAudioDevice);
705
706 if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
707 UpdateLocationsAndContextsAvailability(new_group);
708 }
709 }
710
GroupAddNode(const int group_id,const RawAddress & address)711 void GroupAddNode(const int group_id, const RawAddress& address) override {
712 auto id = DeviceGroups::Get()->GetGroupId(
713 address, bluetooth::le_audio::uuid::kCapServiceUuid);
714 if (id == group_id) return;
715
716 if (id != bluetooth::groups::kGroupUnknown) {
717 DeviceGroups::Get()->RemoveDevice(address, id);
718 }
719
720 DeviceGroups::Get()->AddDevice(
721 address, bluetooth::le_audio::uuid::kCapServiceUuid, group_id);
722 }
723
remove_group_if_possible(LeAudioDeviceGroup * group)724 void remove_group_if_possible(LeAudioDeviceGroup* group) {
725 if (!group) {
726 log::debug("group is null");
727 return;
728 }
729 log::debug("Group {}, id: {}, size: {}, is cig_state {}", fmt::ptr(group),
730 group->group_id_, group->Size(),
731 ToString(group->cig.GetState()));
732 if (group->IsEmpty() &&
733 (group->cig.GetState() == bluetooth::le_audio::types::CigState::NONE)) {
734 lastNotifiedGroupStreamStatusMap_.erase(group->group_id_);
735 aseGroups_.Remove(group->group_id_);
736 }
737 }
738
group_remove_node(LeAudioDeviceGroup * group,const RawAddress & address,bool update_group_module=false)739 void group_remove_node(LeAudioDeviceGroup* group, const RawAddress& address,
740 bool update_group_module = false) {
741 int group_id = group->group_id_;
742 group->RemoveNode(leAudioDevices_.GetByAddress(address));
743
744 if (update_group_module) {
745 int groups_group_id = DeviceGroups::Get()->GetGroupId(
746 address, bluetooth::le_audio::uuid::kCapServiceUuid);
747 if (groups_group_id == group_id) {
748 DeviceGroups::Get()->RemoveDevice(address, group_id);
749 }
750 }
751
752 callbacks_->OnGroupNodeStatus(address, group_id, GroupNodeStatus::REMOVED);
753
754 /* Remove group if this was the last leAudioDevice in this group */
755 if (group->IsEmpty()) {
756 remove_group_if_possible(group);
757 return;
758 }
759
760 /* Removing node from group requires updating group context availability */
761 UpdateLocationsAndContextsAvailability(group);
762 }
763
GroupRemoveNode(const int group_id,const RawAddress & address)764 void GroupRemoveNode(const int group_id, const RawAddress& address) override {
765 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
766 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
767
768 log::info("group_id: {} address: {}", group_id, address);
769
770 if (!leAudioDevice) {
771 log::error("Skipping unknown leAudioDevice, address: {}", address);
772 return;
773 }
774
775 if (leAudioDevice->group_id_ != group_id) {
776 log::error("Device is not in group_id: {}, but in group_id: {}", group_id,
777 leAudioDevice->group_id_);
778 return;
779 }
780
781 if (group == NULL) {
782 log::error("device not in the group ?!");
783 return;
784 }
785
786 if (leAudioDevice->HaveActiveAse()) {
787 SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
788 return;
789 }
790
791 group_remove_node(group, address, true);
792 }
793
ChooseMetadataContextType(AudioContexts metadata_context_type)794 AudioContexts ChooseMetadataContextType(AudioContexts metadata_context_type) {
795 /* This function takes already filtered contexts which we are plannig to use
796 * in the Enable or UpdateMetadata command.
797 * Note we are not changing stream configuration here, but just the list of
798 * the contexts in the Metadata which will be provide to remote side.
799 * Ideally, we should send all the bits we have, but not all headsets like
800 * it.
801 */
802 if (osi_property_get_bool(kAllowMultipleContextsInMetadata, true)) {
803 return metadata_context_type;
804 }
805
806 log::debug("Converting to single context type: {}",
807 metadata_context_type.to_string());
808
809 /* Mini policy */
810 if (metadata_context_type.any()) {
811 LeAudioContextType context_priority_list[] = {
812 /* Highest priority first */
813 LeAudioContextType::CONVERSATIONAL,
814 LeAudioContextType::RINGTONE,
815 LeAudioContextType::LIVE,
816 LeAudioContextType::VOICEASSISTANTS,
817 LeAudioContextType::GAME,
818 LeAudioContextType::MEDIA,
819 LeAudioContextType::EMERGENCYALARM,
820 LeAudioContextType::ALERTS,
821 LeAudioContextType::INSTRUCTIONAL,
822 LeAudioContextType::NOTIFICATIONS,
823 LeAudioContextType::SOUNDEFFECTS,
824 };
825 for (auto ct : context_priority_list) {
826 if (metadata_context_type.test(ct)) {
827 log::debug("Converted to single context type: {}", ToString(ct));
828 return AudioContexts(ct);
829 }
830 }
831 }
832
833 /* Fallback to BAP mandated context type */
834 log::warn("Invalid/unknown context, using 'UNSPECIFIED'");
835 return AudioContexts(LeAudioContextType::UNSPECIFIED);
836 }
837
838 /* Return true if stream is started */
GroupStream(int group_id,LeAudioContextType configuration_context_type,BidirectionalPair<AudioContexts> remote_contexts)839 bool GroupStream(int group_id, LeAudioContextType configuration_context_type,
840 BidirectionalPair<AudioContexts> remote_contexts) {
841 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
842
843 log::debug("configuration_context_type= {}",
844 ToString(configuration_context_type));
845
846 log::debug("");
847 if (configuration_context_type >= LeAudioContextType::RFU) {
848 log::error("stream context type is not supported: {}",
849 ToHexString(configuration_context_type));
850 return false;
851 }
852
853 if (!group) {
854 log::error("unknown group id: {}", group_id);
855 return false;
856 }
857
858 log::debug("group state={}, target_state={}", ToString(group->GetState()),
859 ToString(group->GetTargetState()));
860
861 if (!group->IsAnyDeviceConnected()) {
862 log::error("group {} is not connected", group_id);
863 return false;
864 }
865
866 /* Check if any group is in the transition state. If so, we don't allow to
867 * start new group to stream
868 */
869 if (group->IsInTransition()) {
870 /* WARNING: Due to group state machine limitations, we should not
871 * interrupt any ongoing transition. We will check if another
872 * reconfiguration is needed once the group reaches streaming state.
873 */
874 log::warn(
875 "Group is already in the transition state. Waiting for the target "
876 "state to be reached.");
877 return false;
878 }
879
880 /* Make sure we do not take the local sink metadata when only the local
881 * source scenario is about to be started (e.g. MEDIA).
882 */
883 if (!kLeAudioContextAllBidir.test(configuration_context_type)) {
884 remote_contexts.source.clear();
885 }
886
887 /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
888 auto ccid_contexts = remote_contexts;
889 if (IsInVoipCall() && !IsInCall()) {
890 ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
891 ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
892 }
893
894 BidirectionalPair<std::vector<uint8_t>> ccids = {
895 .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
896 ccid_contexts.sink),
897 .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
898 ccid_contexts.source)};
899 if (group->IsPendingConfiguration()) {
900 return groupStateMachine_->ConfigureStream(
901 group, configuration_context_type_, remote_contexts, ccids);
902 } else if (group->GetState() !=
903 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
904 stream_setup_start_timestamp_ =
905 bluetooth::common::time_get_os_boottime_us();
906 }
907
908 /* If assistant have some connected delegators that needs to be informed
909 * when there would be request to stream unicast.
910 */
911 if (com::android::bluetooth::flags::
912 leaudio_broadcast_audio_handover_policies() &&
913 !sink_monitor_mode_ && source_monitor_mode_ && !group->IsStreaming()) {
914 callbacks_->OnUnicastMonitorModeStatus(
915 bluetooth::le_audio::types::kLeAudioDirectionSource,
916 UnicastMonitorModeStatus::STREAMING_REQUESTED);
917 }
918
919 bool result = groupStateMachine_->StartStream(
920 group, configuration_context_type, remote_contexts, ccids);
921
922 return result;
923 }
924
GroupStream(const int group_id,uint16_t context_type)925 void GroupStream(const int group_id, uint16_t context_type) override {
926 BidirectionalPair<AudioContexts> initial_contexts = {
927 AudioContexts(context_type), AudioContexts(context_type)};
928 GroupStream(group_id, LeAudioContextType(context_type), initial_contexts);
929 }
930
GroupSuspend(const int group_id)931 void GroupSuspend(const int group_id) override {
932 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
933
934 if (!group) {
935 log::error("unknown group id: {}", group_id);
936 return;
937 }
938
939 if (!group->IsAnyDeviceConnected()) {
940 log::error("group is not connected");
941 return;
942 }
943
944 if (group->IsInTransition()) {
945 log::info(", group is in transition from: {} to: {}",
946 ToString(group->GetState()), ToString(group->GetTargetState()));
947 return;
948 }
949
950 if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
951 log::error(", invalid current state of group: {}",
952 ToString(group->GetState()));
953 return;
954 }
955
956 groupStateMachine_->SuspendStream(group);
957 }
958
GroupStop(const int group_id)959 void GroupStop(const int group_id) override {
960 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
961
962 if (!group) {
963 log::error("unknown group id: {}", group_id);
964 return;
965 }
966
967 if (group->IsEmpty()) {
968 log::error("group is empty");
969 return;
970 }
971
972 if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
973 if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
974 log::warn("group {} was about to stream, but got canceled: {}",
975 group_id, ToString(group->GetTargetState()));
976 group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
977 } else {
978 log::warn(", group {} already stopped: {}", group_id,
979 ToString(group->GetState()));
980 }
981 return;
982 }
983
984 groupStateMachine_->StopStream(group);
985 }
986
GroupDestroy(const int group_id)987 void GroupDestroy(const int group_id) override {
988 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
989
990 if (!group) {
991 log::error("unknown group id: {}", group_id);
992 return;
993 }
994
995 // Disconnect and remove each device within the group
996 auto* dev = group->GetFirstDevice();
997 while (dev) {
998 auto* next_dev = group->GetNextDevice(dev);
999 RemoveDevice(dev->address_);
1000 dev = next_dev;
1001 }
1002 }
1003
SetCodecConfigPreference(int group_id,bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,bluetooth::le_audio::btle_audio_codec_config_t output_codec_config)1004 void SetCodecConfigPreference(
1005 int group_id,
1006 bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,
1007 bluetooth::le_audio::btle_audio_codec_config_t output_codec_config)
1008 override {
1009 // TODO Implement
1010 }
1011
SetCcidInformation(int ccid,int context_type)1012 void SetCcidInformation(int ccid, int context_type) override {
1013 log::debug("Ccid: {}, context type {}", ccid, context_type);
1014
1015 ContentControlIdKeeper::GetInstance()->SetCcid(AudioContexts(context_type),
1016 ccid);
1017 }
1018
SetInCall(bool in_call)1019 void SetInCall(bool in_call) override {
1020 log::debug("in_call: {}", in_call);
1021 in_call_ = in_call;
1022 }
1023
IsInCall()1024 bool IsInCall() override { return in_call_; }
1025
SetInVoipCall(bool in_call)1026 void SetInVoipCall(bool in_call) override {
1027 log::debug("in_voip_call: {}", in_call);
1028 in_voip_call_ = in_call;
1029 }
1030
IsInVoipCall()1031 bool IsInVoipCall() override { return in_voip_call_; }
1032
IsInStreaming()1033 bool IsInStreaming() override {
1034 return audio_sender_state_ == AudioState::STARTED ||
1035 audio_receiver_state_ == AudioState::STARTED;
1036 }
1037
SetUnicastMonitorMode(uint8_t direction,bool enable)1038 void SetUnicastMonitorMode(uint8_t direction, bool enable) override {
1039 if (!com::android::bluetooth::flags::
1040 leaudio_broadcast_audio_handover_policies()) {
1041 log::warn(
1042 "Monitor mode is disabled, Set Unicast Monitor mode is ignored");
1043 return;
1044 }
1045
1046 if (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
1047 /* Cleanup Sink HAL client interface if listening mode is toggled off
1048 * before group activation (active group context would take care of
1049 * Sink HAL client cleanup).
1050 */
1051 if (sink_monitor_mode_ && !enable && le_audio_sink_hal_client_ &&
1052 active_group_id_ == bluetooth::groups::kGroupUnknown) {
1053 local_metadata_context_types_.sink.clear();
1054 le_audio_sink_hal_client_->Stop();
1055 le_audio_sink_hal_client_.reset();
1056 }
1057
1058 log::debug("enable: {}", enable);
1059 sink_monitor_mode_ = enable;
1060 } else if (direction ==
1061 bluetooth::le_audio::types::kLeAudioDirectionSource) {
1062 log::debug("enable: {}", enable);
1063 source_monitor_mode_ = enable;
1064
1065 if (!enable) {
1066 return;
1067 }
1068
1069 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1070 if (!group) {
1071 callbacks_->OnUnicastMonitorModeStatus(
1072 bluetooth::le_audio::types::kLeAudioDirectionSource,
1073 UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1074
1075 return;
1076 }
1077
1078 if (group->IsStreaming()) {
1079 callbacks_->OnUnicastMonitorModeStatus(
1080 bluetooth::le_audio::types::kLeAudioDirectionSource,
1081 UnicastMonitorModeStatus::STREAMING);
1082 } else {
1083 callbacks_->OnUnicastMonitorModeStatus(
1084 bluetooth::le_audio::types::kLeAudioDirectionSource,
1085 UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1086 }
1087 } else {
1088 log::error("invalid direction: 0x{:02x} monitor mode set", direction);
1089 }
1090 }
1091
SendAudioProfilePreferences(const int group_id,bool is_output_preference_le_audio,bool is_duplex_preference_le_audio)1092 void SendAudioProfilePreferences(
1093 const int group_id, bool is_output_preference_le_audio,
1094 bool is_duplex_preference_le_audio) override {
1095 log::info(
1096 "group_id: {}, is_output_preference_le_audio: {}, "
1097 "is_duplex_preference_le_audio: {}",
1098 group_id, is_output_preference_le_audio, is_duplex_preference_le_audio);
1099 if (group_id == bluetooth::groups::kGroupUnknown) {
1100 log::warn("Unknown group_id");
1101 return;
1102 }
1103 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1104 if (!group) {
1105 log::warn("group_id {} does not exist", group_id);
1106 return;
1107 }
1108
1109 group->is_output_preference_le_audio = is_output_preference_le_audio;
1110 group->is_duplex_preference_le_audio = is_duplex_preference_le_audio;
1111 }
1112
SetGroupAllowedContextMask(int group_id,int sink_context_types,int source_context_types)1113 void SetGroupAllowedContextMask(int group_id, int sink_context_types,
1114 int source_context_types) override {
1115 log::info("group_id: {}, sink context types: {}, source context types: {}",
1116 group_id, sink_context_types, source_context_types);
1117
1118 if (group_id == bluetooth::groups::kGroupUnknown) {
1119 log::warn("Unknown group_id");
1120 return;
1121 }
1122 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1123 if (!group) {
1124 log::warn("group_id {} does not exist", group_id);
1125 return;
1126 }
1127
1128 BidirectionalPair<AudioContexts> allowed_contexts = {
1129 .sink = AudioContexts(sink_context_types),
1130 .source = AudioContexts(source_context_types),
1131 };
1132
1133 group->SetAllowedContextMask(allowed_contexts);
1134 }
1135
StartAudioSession(LeAudioDeviceGroup * group)1136 void StartAudioSession(LeAudioDeviceGroup* group) {
1137 /* This function is called when group is not yet set to active.
1138 * This is why we don't have to check if session is started already.
1139 * Just check if it is acquired.
1140 */
1141 log::assert_that(active_group_id_ == bluetooth::groups::kGroupUnknown,
1142 "Active group is not set.");
1143 log::assert_that(le_audio_source_hal_client_ != nullptr,
1144 "Source session not acquired");
1145 log::assert_that(le_audio_sink_hal_client_ != nullptr,
1146 "Sink session not acquired");
1147
1148 DsaModes dsa_modes = {DsaMode::DISABLED};
1149 if (com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
1150 dsa_modes = group->GetAllowedDsaModes();
1151 }
1152
1153 /* We assume that peer device always use same frame duration */
1154 uint32_t frame_duration_us = 0;
1155 if (!current_encoder_config_.IsInvalid()) {
1156 frame_duration_us = current_encoder_config_.data_interval_us;
1157 } else if (!current_decoder_config_.IsInvalid()) {
1158 frame_duration_us = current_decoder_config_.data_interval_us;
1159 } else {
1160 log::assert_that(true, "Both configs are invalid");
1161 }
1162
1163 L2CA_SetEcosystemBaseInterval(frame_duration_us / 1250);
1164
1165 audio_framework_source_config.data_interval_us = frame_duration_us;
1166 le_audio_source_hal_client_->Start(audio_framework_source_config,
1167 audioSinkReceiver, dsa_modes);
1168
1169 /* We use same frame duration for sink/source */
1170 audio_framework_sink_config.data_interval_us = frame_duration_us;
1171
1172 /* If group supports more than 16kHz for the microphone in converstional
1173 * case let's use that also for Audio Framework.
1174 */
1175 auto sink_configuration = group->GetAudioSessionCodecConfigForDirection(
1176 LeAudioContextType::CONVERSATIONAL,
1177 bluetooth::le_audio::types::kLeAudioDirectionSource);
1178 if (!sink_configuration.IsInvalid() &&
1179 sink_configuration.sample_rate >
1180 bluetooth::audio::le_audio::kSampleRate16000) {
1181 audio_framework_sink_config.sample_rate = sink_configuration.sample_rate;
1182 }
1183
1184 le_audio_sink_hal_client_->Start(audio_framework_sink_config,
1185 audioSourceReceiver, dsa_modes);
1186 }
1187
isOutputPreferenceLeAudio(const RawAddress & address)1188 bool isOutputPreferenceLeAudio(const RawAddress& address) {
1189 log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(),
1190 active_group_id_);
1191 std::vector<RawAddress> active_leaudio_devices =
1192 GetGroupDevices(active_group_id_);
1193 if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(),
1194 address) == active_leaudio_devices.end()) {
1195 log::info("Device {} is not active for LE Audio",
1196 address.ToStringForLogging());
1197 return false;
1198 }
1199
1200 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1201 log::info("active_group_id: {}, is_output_preference_le_audio_: {}",
1202 group->group_id_, group->is_output_preference_le_audio);
1203 return group->is_output_preference_le_audio;
1204 }
1205
isDuplexPreferenceLeAudio(const RawAddress & address)1206 bool isDuplexPreferenceLeAudio(const RawAddress& address) {
1207 log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(),
1208 active_group_id_);
1209 std::vector<RawAddress> active_leaudio_devices =
1210 GetGroupDevices(active_group_id_);
1211 if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(),
1212 address) == active_leaudio_devices.end()) {
1213 log::info("Device {} is not active for LE Audio",
1214 address.ToStringForLogging());
1215 return false;
1216 }
1217
1218 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1219 log::info("active_group_id: {}, is_duplex_preference_le_audio: {}",
1220 group->group_id_, group->is_duplex_preference_le_audio);
1221 return group->is_duplex_preference_le_audio;
1222 }
1223
groupSetAndNotifyInactive(void)1224 void groupSetAndNotifyInactive(void) {
1225 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1226 return;
1227 }
1228 sink_monitor_notified_status_ = std::nullopt;
1229 log::info("Group id: {}", active_group_id_);
1230
1231 if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
1232
1233 StopAudio();
1234 ClientAudioInterfaceRelease();
1235
1236 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::INACTIVE);
1237 active_group_id_ = bluetooth::groups::kGroupUnknown;
1238 }
1239
GroupSetActive(const int group_id)1240 void GroupSetActive(const int group_id) override {
1241 log::info("group_id: {}", group_id);
1242
1243 if (group_id == bluetooth::groups::kGroupUnknown) {
1244 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1245 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1246 /* Nothing to do */
1247 return;
1248 }
1249
1250 log::info("Active group_id changed {} -> {}", active_group_id_, group_id);
1251 auto group_id_to_close = active_group_id_;
1252 groupSetAndNotifyInactive();
1253 GroupStop(group_id_to_close);
1254
1255 return;
1256 }
1257
1258 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1259 if (!group) {
1260 log::error("Invalid group: {}", static_cast<int>(group_id));
1261 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1262 return;
1263 }
1264
1265 if (group->NumOfConnected() == 0) {
1266 log::error("Group: {} is not connected anymore",
1267 static_cast<int>(group_id));
1268 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1269 return;
1270 }
1271
1272 if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
1273 if (active_group_id_ == group_id) {
1274 log::info("Group is already active: {}",
1275 static_cast<int>(active_group_id_));
1276 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1277 return;
1278 }
1279 log::info("switching active group to: {}", group_id);
1280
1281 auto result =
1282 CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1283 le_audio_source_hal_client_.get(),
1284 le_audio_sink_hal_client_.get(), false);
1285 log::assert_that(result, "Could not update session to codec manager");
1286 }
1287
1288 if (!le_audio_source_hal_client_) {
1289 le_audio_source_hal_client_ =
1290 LeAudioSourceAudioHalClient::AcquireUnicast();
1291 if (!le_audio_source_hal_client_) {
1292 log::error("could not acquire audio source interface");
1293 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1294 return;
1295 }
1296 }
1297
1298 if (!le_audio_sink_hal_client_) {
1299 le_audio_sink_hal_client_ = LeAudioSinkAudioHalClient::AcquireUnicast();
1300 if (!le_audio_sink_hal_client_) {
1301 log::error("could not acquire audio sink interface");
1302 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1303 return;
1304 }
1305 }
1306
1307 auto result =
1308 CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1309 le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(),
1310 true);
1311 log::assert_that(result, "Could not update session to codec manager");
1312
1313 /* Mini policy: Try configure audio HAL sessions with most recent context.
1314 * If reconfiguration is not needed it means, context type is not supported.
1315 * If most recent scenario is not supported, try to find first supported.
1316 */
1317 LeAudioContextType default_context_type = configuration_context_type_;
1318 if (!group->IsAudioSetConfigurationAvailable(default_context_type)) {
1319 if (group->IsAudioSetConfigurationAvailable(
1320 LeAudioContextType::UNSPECIFIED)) {
1321 default_context_type = LeAudioContextType::UNSPECIFIED;
1322 default_context_type = LeAudioContextType::UNSPECIFIED;
1323 } else {
1324 for (LeAudioContextType context_type : kLeAudioContextAllTypesArray) {
1325 if (group->IsAudioSetConfigurationAvailable(context_type)) {
1326 default_context_type = context_type;
1327 break;
1328 }
1329 }
1330 }
1331 }
1332
1333 /* Only update the configuration audio context and audio coding session
1334 * parameters if needed.
1335 */
1336 UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type);
1337
1338 auto previous_active_group = active_group_id_;
1339 log::info("Active group_id changed {} -> {}", previous_active_group,
1340 group_id);
1341
1342 if (previous_active_group == bluetooth::groups::kGroupUnknown) {
1343 /* Expose audio sessions if there was no previous active group */
1344 StartAudioSession(group);
1345 active_group_id_ = group_id;
1346 } else {
1347 /* In case there was an active group. Stop the stream, but before that, set
1348 * the new group so the group change is correctly handled in OnStateMachineStatusReportCb
1349 */
1350 active_group_id_ = group_id;
1351 GroupStop(previous_active_group);
1352 callbacks_->OnGroupStatus(previous_active_group, GroupStatus::INACTIVE);
1353 }
1354
1355 /* Reset sink listener notified status */
1356 sink_monitor_notified_status_ = std::nullopt;
1357 if (com::android::bluetooth::flags::
1358 leaudio_codec_config_callback_order_fix()) {
1359 SendAudioGroupSelectableCodecConfigChanged(group);
1360 SendAudioGroupCurrentCodecConfigChanged(group);
1361 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1362 } else {
1363 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1364 SendAudioGroupSelectableCodecConfigChanged(group);
1365 }
1366 }
1367
SetEnableState(const RawAddress & address,bool enabled)1368 void SetEnableState(const RawAddress& address, bool enabled) override {
1369 log::info("{}: {}", address, enabled ? "enabled" : "disabled");
1370 auto leAudioDevice = leAudioDevices_.FindByAddress(address);
1371 if (leAudioDevice == nullptr) {
1372 log::warn("{} is null", address);
1373 return;
1374 }
1375
1376 auto group_id = leAudioDevice->group_id_;
1377 auto group = aseGroups_.FindById(group_id);
1378 if (group == nullptr) {
1379 log::warn("Group {} is not available", group_id);
1380 return;
1381 }
1382
1383 if (enabled) {
1384 group->Enable(gatt_if_, reconnection_mode_);
1385 } else {
1386 group->Disable(gatt_if_);
1387 }
1388 }
1389
RemoveDevice(const RawAddress & address)1390 void RemoveDevice(const RawAddress& address) override {
1391 log::info(": {}", address);
1392 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1393 if (!leAudioDevice) {
1394 return;
1395 }
1396
1397 /* Remove device from the background connect if it is there */
1398 BTA_GATTC_CancelOpen(gatt_if_, address, false);
1399 btif_storage_set_leaudio_autoconnect(address, false);
1400
1401 log::info("{}, state: {}", address,
1402 bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
1403 auto connection_state = leAudioDevice->GetConnectionState();
1404 switch (connection_state) {
1405 case DeviceConnectState::REMOVING:
1406 /* Just return, and let device disconnect */
1407 return;
1408 case DeviceConnectState::CONNECTED:
1409 case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
1410 case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
1411 /* ACL exist in this case, disconnect and mark as removing */
1412 Disconnect(address);
1413 [[fallthrough]];
1414 case DeviceConnectState::DISCONNECTING:
1415 case DeviceConnectState::DISCONNECTING_AND_RECOVER:
1416 /* Device is disconnecting, just mark it shall be removed after all. */
1417 leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
1418 return;
1419 case DeviceConnectState::CONNECTING_BY_USER:
1420 BTA_GATTC_CancelOpen(gatt_if_, address, true);
1421 [[fallthrough]];
1422 case DeviceConnectState::CONNECTING_AUTOCONNECT:
1423 case DeviceConnectState::DISCONNECTED:
1424 /* Do nothing, just remove device */
1425 break;
1426 }
1427
1428 /* Remove the group assignment if not yet removed. It might happen that the
1429 * group module has already called the appropriate callback and we have
1430 * already removed the group assignment.
1431 */
1432 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1433 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
1434 group_remove_node(group, address, true);
1435 }
1436
1437 leAudioDevices_.Remove(address);
1438 }
1439
Connect(const RawAddress & address)1440 void Connect(const RawAddress& address) override {
1441 log::info(": {}", address);
1442
1443 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1444 if (!leAudioDevice) {
1445 if (!BTM_IsLinkKeyKnown(address, BT_TRANSPORT_LE)) {
1446 log::error("Connecting {} when not bonded", address);
1447 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1448 return;
1449 }
1450 leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
1451 } else {
1452 auto current_connect_state = leAudioDevice->GetConnectionState();
1453 if ((current_connect_state == DeviceConnectState::CONNECTED) ||
1454 (current_connect_state == DeviceConnectState::CONNECTING_BY_USER)) {
1455 log::error("Device {} is in invalid state: {}", leAudioDevice->address_,
1456 bluetooth::common::ToString(current_connect_state));
1457
1458 return;
1459 }
1460
1461 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1462 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
1463 if (!group) {
1464 log::warn("{}, trying to connect to disabled group id {}", address,
1465 leAudioDevice->group_id_);
1466 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1467 return;
1468 }
1469 }
1470
1471 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_BY_USER);
1472
1473 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
1474 leAudioDevice->group_id_, address, ConnectionState::CONNECTING,
1475 bluetooth::le_audio::ConnectionStatus::SUCCESS);
1476 }
1477
1478 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
1479 }
1480
GetGroupDevices(const int group_id)1481 std::vector<RawAddress> GetGroupDevices(const int group_id) override {
1482 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1483 std::vector<RawAddress> all_group_device_addrs;
1484
1485 if (group != nullptr) {
1486 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1487 while (leAudioDevice) {
1488 all_group_device_addrs.push_back(leAudioDevice->address_);
1489 leAudioDevice = group->GetNextDevice(leAudioDevice);
1490 };
1491 }
1492
1493 return all_group_device_addrs;
1494 }
1495
1496 /* Restore paired device from storage to recreate groups */
AddFromStorage(const RawAddress & address,bool autoconnect,int sink_audio_location,int source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases)1497 void AddFromStorage(const RawAddress& address, bool autoconnect,
1498 int sink_audio_location, int source_audio_location,
1499 int sink_supported_context_types,
1500 int source_supported_context_types,
1501 const std::vector<uint8_t>& handles,
1502 const std::vector<uint8_t>& sink_pacs,
1503 const std::vector<uint8_t>& source_pacs,
1504 const std::vector<uint8_t>& ases) {
1505 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1506
1507 if (leAudioDevice) {
1508 log::error("Device is already loaded. Nothing to do.");
1509 return;
1510 }
1511
1512 log::info(
1513 "restoring: {}, autoconnect {}, sink_audio_location: {}, "
1514 "source_audio_location: {}, sink_supported_context_types : 0x{:04x}, "
1515 "source_supported_context_types 0x{:04x}",
1516 address, autoconnect, sink_audio_location, source_audio_location,
1517 sink_supported_context_types, source_supported_context_types);
1518
1519 leAudioDevices_.Add(address, DeviceConnectState::DISCONNECTED);
1520 leAudioDevice = leAudioDevices_.FindByAddress(address);
1521
1522 int group_id = DeviceGroups::Get()->GetGroupId(
1523 address, bluetooth::le_audio::uuid::kCapServiceUuid);
1524 if (group_id != bluetooth::groups::kGroupUnknown) {
1525 group_add_node(group_id, address);
1526 }
1527
1528 leAudioDevice->snk_audio_locations_ = sink_audio_location;
1529 if (sink_audio_location != 0) {
1530 leAudioDevice->audio_directions_ |=
1531 bluetooth::le_audio::types::kLeAudioDirectionSink;
1532 }
1533
1534 callbacks_->OnSinkAudioLocationAvailable(
1535 leAudioDevice->address_,
1536 leAudioDevice->snk_audio_locations_.to_ulong());
1537
1538 leAudioDevice->src_audio_locations_ = source_audio_location;
1539 if (source_audio_location != 0) {
1540 leAudioDevice->audio_directions_ |=
1541 bluetooth::le_audio::types::kLeAudioDirectionSource;
1542 }
1543
1544 BidirectionalPair<AudioContexts> supported_contexts = {
1545 .sink = AudioContexts(sink_supported_context_types),
1546 .source = AudioContexts(source_supported_context_types),
1547 };
1548
1549 leAudioDevice->SetSupportedContexts(supported_contexts);
1550
1551 /* Use same as supported ones for now. */
1552 leAudioDevice->SetAvailableContexts(supported_contexts);
1553
1554 if (!DeserializeHandles(leAudioDevice, handles)) {
1555 log::warn("Could not load Handles");
1556 }
1557
1558 if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) {
1559 /* If PACs are invalid, just say whole cache is invalid */
1560 leAudioDevice->known_service_handles_ = false;
1561 log::warn("Could not load sink pacs");
1562 }
1563
1564 if (!DeserializeSourcePacs(leAudioDevice, source_pacs)) {
1565 /* If PACs are invalid, just say whole cache is invalid */
1566 leAudioDevice->known_service_handles_ = false;
1567 log::warn("Could not load source pacs");
1568 }
1569
1570 if (!DeserializeAses(leAudioDevice, ases)) {
1571 /* If ASEs are invalid, just say whole cache is invalid */
1572 leAudioDevice->known_service_handles_ = false;
1573 log::warn("Could not load ases");
1574 }
1575
1576 leAudioDevice->autoconnect_flag_ = autoconnect;
1577 /* When adding from storage, make sure that autoconnect is used
1578 * by all the devices in the group.
1579 */
1580 leAudioDevices_.SetInitialGroupAutoconnectState(
1581 group_id, gatt_if_, reconnection_mode_, autoconnect);
1582 }
1583
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1584 bool GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1585 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1586 return SerializeHandles(leAudioDevice, out);
1587 }
1588
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1589 bool GetSinkPacsForStorage(const RawAddress& addr,
1590 std::vector<uint8_t>& out) {
1591 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1592 return SerializeSinkPacs(leAudioDevice, out);
1593 }
1594
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1595 bool GetSourcePacsForStorage(const RawAddress& addr,
1596 std::vector<uint8_t>& out) {
1597 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1598 return SerializeSourcePacs(leAudioDevice, out);
1599 }
1600
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1601 bool GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1602 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1603
1604 return SerializeAses(leAudioDevice, out);
1605 }
1606
BackgroundConnectIfNeeded(LeAudioDevice * leAudioDevice)1607 void BackgroundConnectIfNeeded(LeAudioDevice* leAudioDevice) {
1608 if (!leAudioDevice->autoconnect_flag_) {
1609 log::debug("Device {} not in the background connect",
1610 leAudioDevice->address_);
1611 return;
1612 }
1613 AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
1614 }
1615
Disconnect(const RawAddress & address)1616 void Disconnect(const RawAddress& address) override {
1617 log::info(": {}", address);
1618 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1619
1620 if (!leAudioDevice) {
1621 log::warn("leAudioDevice not connected ( {} )", address);
1622 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1623 return;
1624 }
1625
1626 auto connection_state = leAudioDevice->GetConnectionState();
1627 log::info("{}, state: {}", address,
1628 bluetooth::common::ToString(connection_state));
1629
1630 switch (connection_state) {
1631 case DeviceConnectState::CONNECTING_BY_USER:
1632 /* Timeout happen on the Java layer. Device probably not in the range.
1633 * Cancel just direct connection and keep background if it is there.
1634 */
1635 BTA_GATTC_CancelOpen(gatt_if_, address, true);
1636 /* If this is a device which is a part of the group which is connected,
1637 * lets start backgroup connect
1638 */
1639 BackgroundConnectIfNeeded(leAudioDevice);
1640 return;
1641 case DeviceConnectState::CONNECTED: {
1642 /* User is disconnecting the device, we shall remove the autoconnect
1643 * flag for this device and all others if not TA is used
1644 */
1645 /* If target announcement is used, do not remove autoconnect
1646 */
1647 bool remove_from_autoconnect =
1648 (reconnection_mode_ != BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS);
1649
1650 if (leAudioDevice->autoconnect_flag_ && remove_from_autoconnect) {
1651 log::info("Removing autoconnect flag for group_id {}",
1652 leAudioDevice->group_id_);
1653
1654 /* Removes device from background connect */
1655 BTA_GATTC_CancelOpen(gatt_if_, address, false);
1656 btif_storage_set_leaudio_autoconnect(address, false);
1657 leAudioDevice->autoconnect_flag_ = false;
1658 }
1659
1660 /* Make sure ACL is disconnected to avoid reconnecting immediately
1661 * when autoconnect with TA reconnection mechanism is used.
1662 */
1663 bool force_acl_disconnect = leAudioDevice->autoconnect_flag_;
1664
1665 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
1666 if (group) {
1667 /* Remove devices from auto connect mode */
1668 for (auto dev = group->GetFirstDevice(); dev;
1669 dev = group->GetNextDevice(dev)) {
1670 if (remove_from_autoconnect &&
1671 (dev->GetConnectionState() ==
1672 DeviceConnectState::CONNECTING_AUTOCONNECT)) {
1673 btif_storage_set_leaudio_autoconnect(dev->address_, false);
1674 dev->autoconnect_flag_ = false;
1675 BTA_GATTC_CancelOpen(gatt_if_, dev->address_, false);
1676 dev->SetConnectionState(DeviceConnectState::DISCONNECTED);
1677 }
1678 }
1679 if (group->IsStreaming() || !group->IsReleasingOrIdle()) {
1680 leAudioDevice->closing_stream_for_disconnection_ = true;
1681 groupStateMachine_->StopStream(group);
1682 return;
1683 }
1684 force_acl_disconnect &= group->IsEnabled();
1685 }
1686
1687 DisconnectDevice(leAudioDevice, force_acl_disconnect);
1688 }
1689 return;
1690 case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
1691 /* Timeout happen on the Java layer before native got ready with the
1692 * device */
1693 DisconnectDevice(leAudioDevice);
1694 return;
1695 case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
1696 /* Java is not aware about autoconnect actions,
1697 * therefore this should not happen.
1698 */
1699 log::warn("Should not happen - disconnect device");
1700 DisconnectDevice(leAudioDevice);
1701 return;
1702 case DeviceConnectState::DISCONNECTED:
1703 case DeviceConnectState::DISCONNECTING:
1704 case DeviceConnectState::DISCONNECTING_AND_RECOVER:
1705 case DeviceConnectState::CONNECTING_AUTOCONNECT:
1706 case DeviceConnectState::REMOVING:
1707 log::warn("{}, invalid state {}", address,
1708 bluetooth::common::ToString(connection_state));
1709 return;
1710 }
1711 }
1712
DisconnectDevice(LeAudioDevice * leAudioDevice,bool acl_force_disconnect=false,bool recover=false)1713 void DisconnectDevice(LeAudioDevice* leAudioDevice,
1714 bool acl_force_disconnect = false,
1715 bool recover = false) {
1716 if (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
1717 return;
1718 }
1719
1720 if (leAudioDevice->GetConnectionState() != DeviceConnectState::REMOVING) {
1721 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
1722 }
1723
1724 BtaGattQueue::Clean(leAudioDevice->conn_id_);
1725
1726 /* Remote in bad state, force ACL Disconnection. */
1727 if (acl_force_disconnect) {
1728 leAudioDevice->DisconnectAcl();
1729 if (recover) {
1730 leAudioDevice->SetConnectionState(
1731 DeviceConnectState::DISCONNECTING_AND_RECOVER);
1732 }
1733 } else {
1734 BTA_GATTC_Close(leAudioDevice->conn_id_);
1735 }
1736 }
1737
DeregisterNotifications(LeAudioDevice * leAudioDevice)1738 void DeregisterNotifications(LeAudioDevice* leAudioDevice) {
1739 /* GATTC will ommit not registered previously handles */
1740 for (auto pac_tuple : leAudioDevice->snk_pacs_) {
1741 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
1742 std::get<0>(pac_tuple).val_hdl);
1743 }
1744 for (auto pac_tuple : leAudioDevice->src_pacs_) {
1745 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
1746 std::get<0>(pac_tuple).val_hdl);
1747 }
1748
1749 if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0)
1750 BTA_GATTC_DeregisterForNotifications(
1751 gatt_if_, leAudioDevice->address_,
1752 leAudioDevice->snk_audio_locations_hdls_.val_hdl);
1753 if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0)
1754 BTA_GATTC_DeregisterForNotifications(
1755 gatt_if_, leAudioDevice->address_,
1756 leAudioDevice->src_audio_locations_hdls_.val_hdl);
1757 if (leAudioDevice->audio_avail_hdls_.val_hdl != 0)
1758 BTA_GATTC_DeregisterForNotifications(
1759 gatt_if_, leAudioDevice->address_,
1760 leAudioDevice->audio_avail_hdls_.val_hdl);
1761 if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0)
1762 BTA_GATTC_DeregisterForNotifications(
1763 gatt_if_, leAudioDevice->address_,
1764 leAudioDevice->audio_supp_cont_hdls_.val_hdl);
1765 if (leAudioDevice->ctp_hdls_.val_hdl != 0)
1766 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
1767 leAudioDevice->ctp_hdls_.val_hdl);
1768
1769 for (struct ase& ase : leAudioDevice->ases_)
1770 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
1771 ase.hdls.val_hdl);
1772 }
1773
1774 /* This is a generic read/notify/indicate handler for gatt. Here messages
1775 * are dispatched to correct elements e.g. ASEs, PACs, audio locations etc.
1776 */
LeAudioCharValueHandle(uint16_t conn_id,uint16_t hdl,uint16_t len,uint8_t * value,bool notify=false)1777 void LeAudioCharValueHandle(uint16_t conn_id, uint16_t hdl, uint16_t len,
1778 uint8_t* value, bool notify = false) {
1779 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
1780 struct ase* ase;
1781
1782 if (!leAudioDevice) {
1783 log::error("no leAudioDevice assigned to connection id: {}",
1784 static_cast<int>(conn_id));
1785 return;
1786 }
1787
1788 ase = leAudioDevice->GetAseByValHandle(hdl);
1789
1790 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
1791 if (ase) {
1792 groupStateMachine_->ProcessGattNotifEvent(value, len, ase, leAudioDevice,
1793 group);
1794
1795 return;
1796 }
1797
1798 auto snk_pac_ent = std::find_if(
1799 leAudioDevice->snk_pacs_.begin(), leAudioDevice->snk_pacs_.end(),
1800 [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
1801 if (snk_pac_ent != leAudioDevice->snk_pacs_.end()) {
1802 std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
1803
1804 /* Guard consistency of PAC records structure */
1805 if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len,
1806 value))
1807 return;
1808
1809 log::info("Registering sink PACs");
1810 leAudioDevice->RegisterPACs(&std::get<1>(*snk_pac_ent), &pac_recs);
1811
1812 /* Cached audio set configurations should be considered invalid when
1813 * PACs are updated.
1814 */
1815 if (group) {
1816 /* Changes in PAC record channel counts may change the strategy */
1817 group->InvalidateGroupStrategy();
1818 group->InvalidateCachedConfigurations();
1819 }
1820 if (notify) {
1821 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
1822 }
1823 return;
1824 }
1825
1826 auto src_pac_ent = std::find_if(
1827 leAudioDevice->src_pacs_.begin(), leAudioDevice->src_pacs_.end(),
1828 [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
1829 if (src_pac_ent != leAudioDevice->src_pacs_.end()) {
1830 std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
1831
1832 /* Guard consistency of PAC records structure */
1833 if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len,
1834 value))
1835 return;
1836
1837 log::info("Registering source PACs");
1838 leAudioDevice->RegisterPACs(&std::get<1>(*src_pac_ent), &pac_recs);
1839
1840 /* Cached audio set configurations should be considered invalid when
1841 * PACs are updated.
1842 */
1843 if (group) {
1844 /* Changes in PAC record channel counts may change the strategy */
1845 group->InvalidateGroupStrategy();
1846 group->InvalidateCachedConfigurations();
1847 }
1848 if (notify) {
1849 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
1850 }
1851 return;
1852 }
1853
1854 if (hdl == leAudioDevice->snk_audio_locations_hdls_.val_hdl) {
1855 AudioLocations snk_audio_locations;
1856
1857 bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(
1858 snk_audio_locations, len, value);
1859
1860 /* Value may not change */
1861 if ((leAudioDevice->audio_directions_ &
1862 bluetooth::le_audio::types::kLeAudioDirectionSink) &&
1863 (leAudioDevice->snk_audio_locations_ ^ snk_audio_locations).none())
1864 return;
1865
1866 /* Presence of PAC characteristic for source means support for source
1867 * audio location. Value of 0x00000000 means mono/unspecified
1868 */
1869 leAudioDevice->audio_directions_ |=
1870 bluetooth::le_audio::types::kLeAudioDirectionSink;
1871 leAudioDevice->snk_audio_locations_ = snk_audio_locations;
1872
1873 callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_,
1874 snk_audio_locations.to_ulong());
1875
1876 if (notify) {
1877 btif_storage_set_leaudio_audio_location(
1878 leAudioDevice->address_,
1879 leAudioDevice->snk_audio_locations_.to_ulong(),
1880 leAudioDevice->src_audio_locations_.to_ulong());
1881 if (group && group->IsReleasingOrIdle()) {
1882 UpdateLocationsAndContextsAvailability(group);
1883 }
1884 }
1885 } else if (hdl == leAudioDevice->src_audio_locations_hdls_.val_hdl) {
1886 AudioLocations src_audio_locations;
1887
1888 bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(
1889 src_audio_locations, len, value);
1890
1891 /* Value may not change */
1892 if ((leAudioDevice->audio_directions_ &
1893 bluetooth::le_audio::types::kLeAudioDirectionSource) &&
1894 (leAudioDevice->src_audio_locations_ ^ src_audio_locations).none())
1895 return;
1896
1897 /* Presence of PAC characteristic for source means support for source
1898 * audio location. Value of 0x00000000 means mono/unspecified
1899 */
1900 leAudioDevice->audio_directions_ |=
1901 bluetooth::le_audio::types::kLeAudioDirectionSource;
1902 leAudioDevice->src_audio_locations_ = src_audio_locations;
1903
1904 if (notify) {
1905 btif_storage_set_leaudio_audio_location(
1906 leAudioDevice->address_,
1907 leAudioDevice->snk_audio_locations_.to_ulong(),
1908 leAudioDevice->src_audio_locations_.to_ulong());
1909 if (group && group->IsReleasingOrIdle()) {
1910 UpdateLocationsAndContextsAvailability(group);
1911 }
1912 }
1913 } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) {
1914 BidirectionalPair<AudioContexts> contexts;
1915 if (!bluetooth::le_audio::client_parser::pacs::
1916 ParseAvailableAudioContexts(contexts, len, value)) {
1917 return;
1918 }
1919
1920 leAudioDevice->SetAvailableContexts(contexts);
1921
1922 if (!group) {
1923 return;
1924 }
1925
1926 if (group->IsInTransition()) {
1927 /* Group is in transition.
1928 * if group is going to stream, schedule attaching the device to the
1929 * group.
1930 */
1931
1932 if (group->GetTargetState() ==
1933 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1934 AttachToStreamingGroupIfNeeded(leAudioDevice);
1935 }
1936 return;
1937 }
1938
1939 if (!group->IsStreaming()) {
1940 /* Group is not streaming. Device does not have to be attach to the
1941 * stream, and we can update context availability for the group
1942 */
1943 UpdateLocationsAndContextsAvailability(group);
1944 return;
1945 }
1946
1947 if (leAudioDevice->HaveActiveAse()) {
1948 /* Do nothing, device is streaming */
1949 return;
1950 }
1951
1952 if (leAudioDevice->GetConnectionState() !=
1953 DeviceConnectState::CONNECTED) {
1954 /* Do nothing, wait until device is connected */
1955 return;
1956 }
1957
1958 AttachToStreamingGroupIfNeeded(leAudioDevice);
1959
1960 } else if (hdl == leAudioDevice->audio_supp_cont_hdls_.val_hdl) {
1961 BidirectionalPair<AudioContexts> supp_audio_contexts;
1962 if (bluetooth::le_audio::client_parser::pacs::ParseSupportedAudioContexts(
1963 supp_audio_contexts, len, value)) {
1964 /* Just store if for now */
1965 leAudioDevice->SetSupportedContexts(supp_audio_contexts);
1966
1967 btif_storage_set_leaudio_supported_context_types(
1968 leAudioDevice->address_, supp_audio_contexts.sink.value(),
1969 supp_audio_contexts.source.value());
1970 }
1971 } else if (hdl == leAudioDevice->ctp_hdls_.val_hdl) {
1972 groupStateMachine_->ProcessGattCtpNotification(group, value, len);
1973 } else if (hdl == leAudioDevice->tmap_role_hdl_) {
1974 bluetooth::le_audio::client_parser::tmap::ParseTmapRole(
1975 leAudioDevice->tmap_role_, len, value);
1976 } else {
1977 log::error("Unknown attribute read: 0x{:x}", hdl);
1978 }
1979 }
1980
OnGattReadRsp(uint16_t conn_id,tGATT_STATUS status,uint16_t hdl,uint16_t len,uint8_t * value,void * data)1981 void OnGattReadRsp(uint16_t conn_id, tGATT_STATUS status, uint16_t hdl,
1982 uint16_t len, uint8_t* value, void* data) {
1983 LeAudioCharValueHandle(conn_id, hdl, len, value);
1984 }
1985
GetGroupIfEnabled(int group_id)1986 LeAudioDeviceGroup* GetGroupIfEnabled(int group_id) {
1987 auto group = aseGroups_.FindById(group_id);
1988 if (group == nullptr) {
1989 log::info("Group {} does not exist", group_id);
1990 return nullptr;
1991 }
1992 if (!group->IsEnabled()) {
1993 log::info("Group {} is disabled", group_id);
1994 return nullptr;
1995 }
1996 return group;
1997 }
1998
AddToBackgroundConnectCheckGroupConnected(LeAudioDevice * leAudioDevice)1999 void AddToBackgroundConnectCheckGroupConnected(LeAudioDevice* leAudioDevice) {
2000 /* If device belongs to streaming group, add it on allow list */
2001 auto address = leAudioDevice->address_;
2002 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2003 if (group == nullptr) {
2004 log::info("Group {} is invalid or disabled", leAudioDevice->group_id_);
2005 return;
2006 }
2007
2008 leAudioDevice->SetConnectionState(
2009 DeviceConnectState::CONNECTING_AUTOCONNECT);
2010
2011 /* Cancel previous bakcground connect */
2012 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2013 if (group->IsAnyDeviceConnected()) {
2014 log::info("Group {} in connected state. Adding {} to allow list",
2015 leAudioDevice->group_id_, address);
2016 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
2017 } else {
2018 log::info(
2019 "Adding {} to backgroud connect (default reconnection_mode "
2020 "(0x{:02x}))",
2021 address, reconnection_mode_);
2022 BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2023 }
2024 }
2025
OnGattConnected(tGATT_STATUS status,uint16_t conn_id,tGATT_IF client_if,RawAddress address,tBT_TRANSPORT transport,uint16_t mtu)2026 void OnGattConnected(tGATT_STATUS status, uint16_t conn_id,
2027 tGATT_IF client_if, RawAddress address,
2028 tBT_TRANSPORT transport, uint16_t mtu) {
2029 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2030
2031 log::info("{}, conn_id=0x{:04x}, transport={}, status={} (0x{:02x})",
2032 address, conn_id, bt_transport_text(transport),
2033 gatt_status_text(status), status);
2034
2035 if (transport != BT_TRANSPORT_LE) {
2036 log::warn("Only LE connection is allowed (transport {})",
2037 bt_transport_text(transport));
2038 BTA_GATTC_Close(conn_id);
2039 return;
2040 }
2041
2042 if (!leAudioDevice) return;
2043
2044 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
2045 log::debug("Already connected {}, conn_id=0x{:04x}", address,
2046 leAudioDevice->conn_id_);
2047 return;
2048 }
2049
2050 if (status != GATT_SUCCESS) {
2051 /* Clear current connection request and let it be set again if needed */
2052 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2053
2054 /* autoconnect connection failed, that's ok */
2055 if (status != GATT_ILLEGAL_PARAMETER &&
2056 (leAudioDevice->GetConnectionState() ==
2057 DeviceConnectState::CONNECTING_AUTOCONNECT ||
2058 leAudioDevice->autoconnect_flag_)) {
2059 log::info("Device not available now, do background connect.");
2060 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2061 AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
2062 return;
2063 }
2064
2065 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2066
2067 log::error("Failed to connect to LeAudio leAudioDevice, status: 0x{:02x}",
2068 status);
2069 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2070 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2071 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2072 bluetooth::le_audio::ConnectionStatus::FAILED);
2073 return;
2074 }
2075
2076 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2077 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2078 if (group == nullptr) {
2079 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2080
2081 log::warn(
2082 "LeAudio profile is disabled for group_id: {}. {} is not connected",
2083 leAudioDevice->group_id_, address);
2084 return;
2085 }
2086 }
2087
2088 leAudioDevice->conn_id_ = conn_id;
2089 leAudioDevice->mtu_ = mtu;
2090
2091 /* Remove device from the background connect (it might be either Allow list
2092 * or TA) and add it again with reconnection_mode_. In case it is TA, we are
2093 * sure that device will not be in the allow list for other applications
2094 * which are using background connect.
2095 */
2096 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2097 BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2098
2099 if (bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2100 log::info("{} set preferred PHY to 2M", address);
2101 BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2102 }
2103
2104 BTM_RequestPeerSCA(leAudioDevice->address_, transport);
2105
2106 if (leAudioDevice->GetConnectionState() ==
2107 DeviceConnectState::CONNECTING_AUTOCONNECT) {
2108 leAudioDevice->SetConnectionState(
2109 DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
2110 } else {
2111 leAudioDevice->SetConnectionState(
2112 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
2113 }
2114
2115 /* Check if the device is in allow list and update the flag */
2116 leAudioDevice->UpdateDeviceAllowlistFlag();
2117 if (BTM_SecIsSecurityPending(address)) {
2118 /* if security collision happened, wait for encryption done
2119 * (BTA_GATTC_ENC_CMPL_CB_EVT) */
2120 return;
2121 }
2122
2123 /* verify bond */
2124 if (BTM_IsEncrypted(address, BT_TRANSPORT_LE)) {
2125 /* if link has been encrypted */
2126 OnEncryptionComplete(address, BTM_SUCCESS);
2127 return;
2128 }
2129
2130 int result = BTM_SetEncryption(address, BT_TRANSPORT_LE, nullptr, nullptr,
2131 BTM_BLE_SEC_ENCRYPT);
2132
2133 log::info("Encryption required for {}. Request result: 0x{:02x}", address,
2134 result);
2135
2136 if (result == BTM_ERR_KEY_MISSING) {
2137 log::error("Link key unknown for {}, disconnect profile", address);
2138 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2139 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2140 bluetooth::le_audio::ConnectionStatus::FAILED);
2141
2142 /* If link cannot be enctypted, disconnect profile */
2143 BTA_GATTC_Close(conn_id);
2144 }
2145 }
2146
RegisterKnownNotifications(LeAudioDevice * leAudioDevice,bool gatt_register,bool write_ccc)2147 void RegisterKnownNotifications(LeAudioDevice* leAudioDevice,
2148 bool gatt_register, bool write_ccc) {
2149 log::info("device: {}", leAudioDevice->address_);
2150
2151 if (leAudioDevice->ctp_hdls_.val_hdl == 0) {
2152 log::error(
2153 "Control point characteristic is mandatory - disconnecting device {}",
2154 leAudioDevice->address_);
2155 DisconnectDevice(leAudioDevice);
2156 return;
2157 }
2158
2159 /* GATTC will ommit not registered previously handles */
2160 for (auto pac_tuple : leAudioDevice->snk_pacs_) {
2161 subscribe_for_notification(
2162 leAudioDevice->conn_id_, leAudioDevice->address_,
2163 std::get<0>(pac_tuple), gatt_register, write_ccc);
2164 }
2165 for (auto pac_tuple : leAudioDevice->src_pacs_) {
2166 subscribe_for_notification(
2167 leAudioDevice->conn_id_, leAudioDevice->address_,
2168 std::get<0>(pac_tuple), gatt_register, write_ccc);
2169 }
2170
2171 if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0)
2172 subscribe_for_notification(
2173 leAudioDevice->conn_id_, leAudioDevice->address_,
2174 leAudioDevice->snk_audio_locations_hdls_, gatt_register, write_ccc);
2175 if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0)
2176 subscribe_for_notification(
2177 leAudioDevice->conn_id_, leAudioDevice->address_,
2178 leAudioDevice->src_audio_locations_hdls_, gatt_register, write_ccc);
2179
2180 if (leAudioDevice->audio_avail_hdls_.val_hdl != 0)
2181 subscribe_for_notification(
2182 leAudioDevice->conn_id_, leAudioDevice->address_,
2183 leAudioDevice->audio_avail_hdls_, gatt_register, write_ccc);
2184
2185 if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0)
2186 subscribe_for_notification(
2187 leAudioDevice->conn_id_, leAudioDevice->address_,
2188 leAudioDevice->audio_supp_cont_hdls_, gatt_register, write_ccc);
2189
2190 for (struct ase& ase : leAudioDevice->ases_)
2191 subscribe_for_notification(leAudioDevice->conn_id_,
2192 leAudioDevice->address_, ase.hdls,
2193 gatt_register, write_ccc);
2194
2195 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2196 leAudioDevice->ctp_hdls_, gatt_register,
2197 write_ccc);
2198 }
2199
changeMtuIfPossible(LeAudioDevice * leAudioDevice)2200 void changeMtuIfPossible(LeAudioDevice* leAudioDevice) {
2201 if (leAudioDevice->mtu_ == GATT_DEF_BLE_MTU_SIZE) {
2202 log::info("Configure MTU");
2203 /* Use here kBapMinimumAttMtu, because we know that GATT will request
2204 * default ATT MTU anyways. We also know that GATT will use this
2205 * kBapMinimumAttMtu as an input for Data Length Update procedure in the controller.
2206 */
2207 BtaGattQueue::ConfigureMtu(leAudioDevice->conn_id_, kBapMinimumAttMtu);
2208 }
2209 }
2210
OnEncryptionComplete(const RawAddress & address,uint8_t status)2211 void OnEncryptionComplete(const RawAddress& address, uint8_t status) {
2212 log::info("{} status 0x{:02x}", address, status);
2213 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2214 if (leAudioDevice == NULL ||
2215 (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
2216 log::warn("Skipping device which is {}",
2217 leAudioDevice ? " not connected by service." : " null");
2218 return;
2219 }
2220
2221 if (status != BTM_SUCCESS) {
2222 log::error("Encryption failed status: {}", int{status});
2223 if (leAudioDevice->GetConnectionState() ==
2224 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY) {
2225 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2226 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2227 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2228 bluetooth::le_audio::ConnectionStatus::FAILED);
2229 }
2230
2231 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
2232
2233 BTA_GATTC_Close(leAudioDevice->conn_id_);
2234 return;
2235 }
2236
2237 if (leAudioDevice->encrypted_) {
2238 log::info("link already encrypted, nothing to do");
2239 return;
2240 }
2241
2242 /* If PHY update did not succeed after ACL connection, which can happen
2243 * when remote feature read was not that quick, lets try to change phy here
2244 * one more time
2245 */
2246 if (!leAudioDevice->acl_phy_update_done_ &&
2247 bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2248 log::info("{} set preferred PHY to 2M", leAudioDevice->address_);
2249 BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2250 }
2251
2252 changeMtuIfPossible(leAudioDevice);
2253
2254 leAudioDevice->encrypted_ = true;
2255
2256 /* If we know services, register for notifications */
2257 if (leAudioDevice->known_service_handles_) {
2258 /* This registration will do subscribtion in local GATT as we
2259 * assume remote device keeps bonded CCC values.
2260 */
2261 RegisterKnownNotifications(leAudioDevice, true, false);
2262
2263 /* Make sure remote keeps CCC values as per specification.
2264 * We read only ctp_ccc value. If that one is good, we assume
2265 * remote keeps CCC values correctly.
2266 */
2267 BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
2268 leAudioDevice->ctp_hdls_.ccc_hdl,
2269 OnGattCtpCccReadRspStatic, NULL);
2270 }
2271
2272 /* If we know services and read is not ongoing, this is reconnection and
2273 * just notify connected */
2274 if (leAudioDevice->known_service_handles_ &&
2275 !leAudioDevice->notify_connected_after_read_) {
2276 log::info("Wait for CCC registration and MTU change request");
2277 return;
2278 }
2279
2280 BTA_GATTC_ServiceSearchRequest(
2281 leAudioDevice->conn_id_,
2282 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2283 }
2284
checkGroupConnectionStateAfterMemberDisconnect(int group_id)2285 void checkGroupConnectionStateAfterMemberDisconnect(int group_id) {
2286 /* This is fired t=kGroupConnectedWatchDelayMs after group member
2287 * got disconencted while ather group members were connected.
2288 * We want to check here if there is any group member connected.
2289 * If so we should add other group members to allow list for better
2290 * reconnection experiance. If all group members are disconnected
2291 * i e.g. devices intentionally disconnected for other
2292 * purposes like pairing with other device, then we do nothing here and
2293 * device stay on the default reconnection policy (i.e. targeted
2294 * announcements)
2295 */
2296 auto group = aseGroups_.FindById(group_id);
2297 if (group == nullptr) {
2298 log::info("Group {} is destroyed.", group_id);
2299 return;
2300 }
2301
2302 if (!group->IsAnyDeviceConnected()) {
2303 log::info("Group {} is not connected", group_id);
2304 /* Make sure all devices are in the default reconnection mode */
2305 group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2306 return;
2307 }
2308
2309 /* if group is still connected, make sure that other not connected
2310 * set members are in the allow list for the quick reconnect.
2311 * E.g. for the earbud case, probably one of the earbud is in the case now.
2312 */
2313 group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
2314 }
2315
scheduleGroupConnectedCheck(int group_id)2316 void scheduleGroupConnectedCheck(int group_id) {
2317 log::info("Schedule group_id {} connected check.", group_id);
2318 do_in_main_thread_delayed(
2319 FROM_HERE,
2320 base::BindOnce(
2321 &LeAudioClientImpl::checkGroupConnectionStateAfterMemberDisconnect,
2322 weak_factory_.GetWeakPtr(), group_id),
2323 std::chrono::milliseconds(kGroupConnectedWatchDelayMs));
2324 }
2325
autoConnect(RawAddress address)2326 void autoConnect(RawAddress address) {
2327 auto leAudioDevice = leAudioDevices_.FindByAddress(address);
2328 if (leAudioDevice == nullptr) {
2329 log::warn("Device {} not valid anymore", address);
2330 return;
2331 }
2332
2333 BackgroundConnectIfNeeded(leAudioDevice);
2334 }
2335
scheduleAutoConnect(RawAddress & address)2336 void scheduleAutoConnect(RawAddress& address) {
2337 log::info("Schedule auto connect {}", address);
2338 do_in_main_thread_delayed(
2339 FROM_HERE,
2340 base::BindOnce(&LeAudioClientImpl::autoConnect,
2341 weak_factory_.GetWeakPtr(), address),
2342 std::chrono::milliseconds(kAutoConnectAfterOwnDisconnectDelayMs));
2343 }
2344
recoveryReconnect(RawAddress address)2345 void recoveryReconnect(RawAddress address) {
2346 log::info("Reconnecting to {} after timeout on state machine.", address);
2347 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2348
2349 if (leAudioDevice == nullptr ||
2350 leAudioDevice->GetConnectionState() !=
2351 DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2352 log::warn("Device {}, not interested in recovery connect anymore",
2353 address);
2354 return;
2355 }
2356
2357 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2358
2359 if (group != nullptr) {
2360 leAudioDevice->SetConnectionState(
2361 DeviceConnectState::CONNECTING_AUTOCONNECT);
2362 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2363 } else {
2364 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2365 }
2366 }
2367
scheduleRecoveryReconnect(RawAddress & address)2368 void scheduleRecoveryReconnect(RawAddress& address) {
2369 log::info("Schedule reconnecting to {} after timeout on state machine.",
2370 address);
2371 do_in_main_thread_delayed(
2372 FROM_HERE,
2373 base::BindOnce(&LeAudioClientImpl::recoveryReconnect,
2374 weak_factory_.GetWeakPtr(), address),
2375 std::chrono::milliseconds(kRecoveryReconnectDelayMs));
2376 }
2377
checkIfGroupMember(RawAddress address)2378 void checkIfGroupMember(RawAddress address) {
2379 log::info("checking being a group member: {}", address);
2380 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2381
2382 if (leAudioDevice == nullptr) {
2383 log::warn("Device {}, probably removed", address);
2384 return;
2385 }
2386
2387 if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
2388 disconnectInvalidDevice(leAudioDevice,
2389 ", device not a valid group member",
2390 LeAudioHealthDeviceStatType::INVALID_CSIS);
2391 return;
2392 }
2393 }
2394
2395 /* This is called, when CSIS native module is about to add device to the
2396 * group once the CSIS service will be verified on the remote side.
2397 * After some time (kCsisGroupMemberDelayMs) a checkIfGroupMember will be
2398 * called and will verify if the remote device has a group_id properly set.
2399 * if not, it means there is something wrong with CSIS service on the remote
2400 * side.
2401 */
scheduleGuardForCsisAdd(RawAddress & address)2402 void scheduleGuardForCsisAdd(RawAddress& address) {
2403 log::info("Schedule reconnecting to {} after timeout on state machine.",
2404 address);
2405 do_in_main_thread_delayed(
2406 FROM_HERE,
2407 base::BindOnce(&LeAudioClientImpl::checkIfGroupMember,
2408 weak_factory_.GetWeakPtr(), address),
2409 std::chrono::milliseconds(kCsisGroupMemberDelayMs));
2410 }
2411
OnGattDisconnected(uint16_t conn_id,tGATT_IF client_if,RawAddress address,tGATT_DISCONN_REASON reason)2412 void OnGattDisconnected(uint16_t conn_id, tGATT_IF client_if,
2413 RawAddress address, tGATT_DISCONN_REASON reason) {
2414 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2415
2416 if (!leAudioDevice) {
2417 log::error(", skipping unknown leAudioDevice, address: {}", address);
2418 return;
2419 }
2420
2421 leAudioDevice->acl_asymmetric_ = false;
2422 BtaGattQueue::Clean(leAudioDevice->conn_id_);
2423 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
2424
2425 DeregisterNotifications(leAudioDevice);
2426
2427 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2428 leAudioDevice->conn_id_ = GATT_INVALID_CONN_ID;
2429 leAudioDevice->mtu_ = 0;
2430 leAudioDevice->closing_stream_for_disconnection_ = false;
2431 leAudioDevice->encrypted_ = false;
2432 leAudioDevice->acl_phy_update_done_ = false;
2433
2434 groupStateMachine_->ProcessHciNotifAclDisconnected(group, leAudioDevice);
2435
2436 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2437 leAudioDevice->group_id_, address, ConnectionState::DISCONNECTED,
2438 bluetooth::le_audio::ConnectionStatus::SUCCESS);
2439
2440 if (leAudioDevice->GetConnectionState() == DeviceConnectState::REMOVING) {
2441 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2442 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
2443 group_remove_node(group, address, true);
2444 }
2445 leAudioDevices_.Remove(address);
2446 return;
2447 }
2448
2449 auto connection_state = leAudioDevice->GetConnectionState();
2450 log::info("{}, autoconnect {}, reason 0x{:02x}, connection state {}",
2451 leAudioDevice->address_, leAudioDevice->autoconnect_flag_, reason,
2452 bluetooth::common::ToString(connection_state));
2453
2454 if (connection_state == DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2455 /* We are back after disconnecting device which was in a bad state.
2456 * lets try to reconnected - 30 sec with direct connect and later fallback
2457 * to default background reconnection mode.
2458 * Since GATT notifies us before ACL was dropped, let's wait a bit
2459 * before we do reconnect.
2460 */
2461 scheduleRecoveryReconnect(address);
2462 return;
2463 }
2464
2465 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2466
2467 /* Attempt background re-connect if disconnect was not initiated locally
2468 * or if autoconnect is set and device got disconnected because of some
2469 * issues
2470 */
2471 if (group == nullptr || !group->IsEnabled()) {
2472 log::error("Group id {} ({}) disabled or null", leAudioDevice->group_id_,
2473 fmt::ptr(group));
2474 return;
2475 }
2476
2477 if (reason == GATT_CONN_TERMINATE_LOCAL_HOST) {
2478 if (leAudioDevice->autoconnect_flag_) {
2479 /* In this case ACL might not yet been disconnected */
2480 scheduleAutoConnect(address);
2481 }
2482 return;
2483 }
2484
2485 /* Remote disconnects from us or Timeout happens */
2486 /* In this case ACL is disconnected */
2487 if (reason == GATT_CONN_TIMEOUT) {
2488 leAudioDevice->SetConnectionState(
2489 DeviceConnectState::CONNECTING_AUTOCONNECT);
2490
2491 /* If timeout try to reconnect for 30 sec.*/
2492 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2493 return;
2494 }
2495
2496 /* In other disconnect resons we act based on the autoconnect_flag_ */
2497 if (leAudioDevice->autoconnect_flag_) {
2498 if (group->IsAnyDeviceConnected()) {
2499 /* If all set is disconnecting, let's give it some time.
2500 * If not all get disconnected, and there will be group member
2501 * connected we want to put disconnected devices to allow list
2502 */
2503 scheduleGroupConnectedCheck(leAudioDevice->group_id_);
2504 } else {
2505 group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2506 }
2507 }
2508 }
2509
subscribe_for_notification(uint16_t conn_id,const RawAddress & address,struct bluetooth::le_audio::types::hdl_pair handle_pair,bool gatt_register=true,bool write_ccc=true)2510 bool subscribe_for_notification(
2511 uint16_t conn_id, const RawAddress& address,
2512 struct bluetooth::le_audio::types::hdl_pair handle_pair,
2513 bool gatt_register = true, bool write_ccc = true) {
2514 std::vector<uint8_t> value(2);
2515 uint8_t* ptr = value.data();
2516 uint16_t handle = handle_pair.val_hdl;
2517 uint16_t ccc_handle = handle_pair.ccc_hdl;
2518
2519 log::info("conn id {}, gatt_register: {}, write_ccc: {}", conn_id,
2520 gatt_register, write_ccc);
2521 if (gatt_register && BTA_GATTC_RegisterForNotifications(
2522 gatt_if_, address, handle) != GATT_SUCCESS) {
2523 log::error("cannot register for notification: {}",
2524 static_cast<int>(handle));
2525 return false;
2526 }
2527
2528 if (write_ccc == false) {
2529 log::verbose("CCC is not written to {} (0x{:04x}), handle 0x{:04x}",
2530 address, conn_id, ccc_handle);
2531 return true;
2532 }
2533
2534 UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
2535
2536 BtaGattQueue::WriteDescriptor(
2537 conn_id, ccc_handle, std::move(value), GATT_WRITE,
2538 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
2539 const uint8_t* value, void* data) {
2540 if (instance) instance->OnGattWriteCcc(conn_id, status, handle, data);
2541 },
2542 nullptr);
2543 return true;
2544 }
2545
2546 /* Find the handle for the client characteristics configuration of a given
2547 * characteristics.
2548 */
find_ccc_handle(const gatt::Characteristic & charac)2549 uint16_t find_ccc_handle(const gatt::Characteristic& charac) {
2550 auto iter = std::find_if(
2551 charac.descriptors.begin(), charac.descriptors.end(),
2552 [](const auto& desc) {
2553 return desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG);
2554 });
2555
2556 return iter == charac.descriptors.end() ? 0 : (*iter).handle;
2557 }
2558
ClearDeviceInformationAndStartSearch(LeAudioDevice * leAudioDevice)2559 void ClearDeviceInformationAndStartSearch(LeAudioDevice* leAudioDevice) {
2560 if (!leAudioDevice) {
2561 log::warn("leAudioDevice is null");
2562 return;
2563 }
2564
2565 log::info("{}", leAudioDevice->address_);
2566
2567 if (leAudioDevice->known_service_handles_ == false) {
2568 log::debug("Database already invalidated");
2569 return;
2570 }
2571
2572 leAudioDevice->known_service_handles_ = false;
2573 leAudioDevice->csis_member_ = false;
2574 BtaGattQueue::Clean(leAudioDevice->conn_id_);
2575 DeregisterNotifications(leAudioDevice);
2576
2577 if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
2578 leAudioDevice->SetConnectionState(
2579 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
2580 }
2581
2582 btif_storage_leaudio_clear_service_data(leAudioDevice->address_);
2583
2584 BTA_GATTC_ServiceSearchRequest(
2585 leAudioDevice->conn_id_,
2586 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2587 }
2588
OnServiceChangeEvent(const RawAddress & address)2589 void OnServiceChangeEvent(const RawAddress& address) {
2590 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2591 if (!leAudioDevice) {
2592 log::warn("Skipping unknown leAudioDevice {} ({})", address,
2593 fmt::ptr(leAudioDevice));
2594 return;
2595 }
2596
2597 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
2598 ClearDeviceInformationAndStartSearch(leAudioDevice);
2599 return;
2600 }
2601
2602 /* If device is not connected, just clear the handle information and this
2603 * will trigger service search onGattConnected */
2604 leAudioDevice->known_service_handles_ = false;
2605 btif_storage_leaudio_clear_service_data(address);
2606 }
2607
OnMtuChanged(uint16_t conn_id,uint16_t mtu)2608 void OnMtuChanged(uint16_t conn_id, uint16_t mtu) {
2609 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2610 if (!leAudioDevice) {
2611 log::debug("Unknown connectect id {}", conn_id);
2612 return;
2613 }
2614
2615 /**
2616 * BAP 1.01. 3.6.1
2617 * ATT and EATT transport requirements
2618 * The Unicast Client shall support a minimum ATT_MTU of 64 octets for one
2619 * Unenhanced ATT bearer, or for at least one Enhanced ATT bearer if the
2620 * Unicast Client supports Enhanced ATT bearers.
2621 *
2622 */
2623 if (mtu < 64) {
2624 log::error("Device {} MTU is too low ({}). Disconnecting from LE Audio",
2625 leAudioDevice->address_, mtu);
2626 Disconnect(leAudioDevice->address_);
2627 return;
2628 }
2629
2630 leAudioDevice->mtu_ = mtu;
2631 }
2632
OnPhyUpdate(uint16_t conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)2633 void OnPhyUpdate(uint16_t conn_id, uint8_t tx_phy, uint8_t rx_phy,
2634 tGATT_STATUS status) {
2635 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2636 if (leAudioDevice == nullptr) {
2637 log::debug("Unknown conn_id {:#x}", conn_id);
2638 return;
2639 }
2640
2641 log::info("{}, tx_phy: {:#x}, rx_phy: {:#x} , status: {:#x}",
2642 leAudioDevice->address_, tx_phy, rx_phy, status);
2643
2644 if (status == 0) {
2645 leAudioDevice->acl_phy_update_done_ = true;
2646 }
2647 }
2648
OnGattServiceDiscoveryDone(const RawAddress & address)2649 void OnGattServiceDiscoveryDone(const RawAddress& address) {
2650 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2651 if (!leAudioDevice || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
2652 log::verbose("skipping unknown leAudioDevice, address {} ({})", address,
2653 fmt::ptr(leAudioDevice));
2654 return;
2655 }
2656
2657 if (!leAudioDevice->encrypted_) {
2658 log::debug("Wait for device to be encrypted");
2659 return;
2660 }
2661
2662 if (!leAudioDevice->known_service_handles_)
2663 BTA_GATTC_ServiceSearchRequest(
2664 leAudioDevice->conn_id_,
2665 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2666 }
2667
disconnectInvalidDevice(LeAudioDevice * leAudioDevice,std::string error_string,LeAudioHealthDeviceStatType stat)2668 void disconnectInvalidDevice(LeAudioDevice* leAudioDevice,
2669 std::string error_string,
2670 LeAudioHealthDeviceStatType stat) {
2671 log::error("{}, {}", leAudioDevice->address_, error_string);
2672 if (leAudioHealthStatus_) {
2673 leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice, stat);
2674 }
2675 DisconnectDevice(leAudioDevice);
2676 }
2677
2678 /* This method is called after connection beginning to identify and initialize
2679 * a le audio device. Any missing mandatory attribute will result in reverting
2680 * and cleaning up device.
2681 */
OnServiceSearchComplete(uint16_t conn_id,tGATT_STATUS status)2682 void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) {
2683 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2684
2685 if (!leAudioDevice) {
2686 log::error("skipping unknown leAudioDevice, conn_id: 0x{:x}", conn_id);
2687 return;
2688 }
2689
2690 log::info("test csis_member {}", leAudioDevice->csis_member_);
2691
2692 if (status != GATT_SUCCESS) {
2693 /* close connection and report service discovery complete with error */
2694 log::error("Service discovery failed");
2695
2696 DisconnectDevice(leAudioDevice);
2697 return;
2698 }
2699
2700 if (!leAudioDevice->encrypted_) {
2701 log::warn("Device not yet bonded - waiting for encryption");
2702 return;
2703 }
2704
2705 const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
2706
2707 const gatt::Service* pac_svc = nullptr;
2708 const gatt::Service* ase_svc = nullptr;
2709 const gatt::Service* tmas_svc = nullptr;
2710
2711 std::vector<uint16_t> csis_primary_handles;
2712 uint16_t cas_csis_included_handle = 0;
2713
2714 for (const gatt::Service& tmp : *services) {
2715 if (tmp.uuid ==
2716 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid) {
2717 log::info(
2718 "Found Audio Capability service, handle: 0x{:04x}, device: {}",
2719 tmp.handle, leAudioDevice->address_);
2720 pac_svc = &tmp;
2721 } else if (tmp.uuid ==
2722 bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid) {
2723 log::info(
2724 "Found Audio Stream Endpoint service, handle: 0x{:04x}, device: {}",
2725 tmp.handle, leAudioDevice->address_);
2726 ase_svc = &tmp;
2727 } else if (tmp.uuid == bluetooth::csis::kCsisServiceUuid) {
2728 log::info(
2729 "Found CSIS service, handle: 0x{:04x}, is primary: {}, device: {}",
2730 tmp.handle, tmp.is_primary, leAudioDevice->address_);
2731 if (tmp.is_primary) csis_primary_handles.push_back(tmp.handle);
2732 } else if (tmp.uuid == bluetooth::le_audio::uuid::kCapServiceUuid) {
2733 log::info("Found CAP service, handle: 0x{:04x}, device: {}", tmp.handle,
2734 leAudioDevice->address_);
2735
2736 /* Try to find context for CSIS instances */
2737 for (auto& included_srvc : tmp.included_services) {
2738 if (included_srvc.uuid == bluetooth::csis::kCsisServiceUuid) {
2739 log::info("CSIS included into CAS");
2740 if (bluetooth::csis::CsisClient::IsCsisClientRunning())
2741 cas_csis_included_handle = included_srvc.start_handle;
2742
2743 break;
2744 }
2745 }
2746 } else if (tmp.uuid ==
2747 bluetooth::le_audio::uuid::kTelephonyMediaAudioServiceUuid) {
2748 log::info(
2749 "Found Telephony and Media Audio service, handle: 0x{:04x}, "
2750 "device: {}",
2751 tmp.handle, leAudioDevice->address_);
2752 tmas_svc = &tmp;
2753 }
2754 }
2755
2756 /* Check if CAS includes primary CSIS service */
2757 if (!csis_primary_handles.empty() && cas_csis_included_handle) {
2758 auto iter =
2759 std::find(csis_primary_handles.begin(), csis_primary_handles.end(),
2760 cas_csis_included_handle);
2761 if (iter != csis_primary_handles.end())
2762 leAudioDevice->csis_member_ = true;
2763 }
2764
2765 if (!pac_svc || !ase_svc) {
2766 disconnectInvalidDevice(
2767 leAudioDevice, "No mandatory le audio services found (pacs or ascs)",
2768 LeAudioHealthDeviceStatType::INVALID_DB);
2769 return;
2770 }
2771
2772 /* Refresh PACs handles */
2773 leAudioDevice->ClearPACs();
2774
2775 for (const gatt::Characteristic& charac : pac_svc->characteristics) {
2776 if (charac.uuid == bluetooth::le_audio::uuid::
2777 kSinkPublishedAudioCapabilityCharacteristicUuid) {
2778 struct hdl_pair hdl_pair;
2779 hdl_pair.val_hdl = charac.value_handle;
2780 hdl_pair.ccc_hdl = find_ccc_handle(charac);
2781
2782 if (hdl_pair.ccc_hdl == 0) {
2783 log::info(", Sink PACs ccc not available");
2784 }
2785
2786 if (hdl_pair.ccc_hdl != 0 &&
2787 !subscribe_for_notification(conn_id, leAudioDevice->address_,
2788 hdl_pair)) {
2789 disconnectInvalidDevice(leAudioDevice,
2790 ", cound not subscribe for snk pac char",
2791 LeAudioHealthDeviceStatType::INVALID_DB);
2792 return;
2793 }
2794
2795 /* Obtain initial state of sink PACs */
2796 BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl,
2797 OnGattReadRspStatic, NULL);
2798
2799 leAudioDevice->snk_pacs_.push_back(std::make_tuple(
2800 hdl_pair,
2801 std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
2802
2803 log::info(
2804 "Found Sink PAC characteristic, handle: 0x{:04x}, ccc handle: "
2805 "0x{:04x}, addr: {}",
2806 charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
2807 } else if (charac.uuid ==
2808 bluetooth::le_audio::uuid::
2809 kSourcePublishedAudioCapabilityCharacteristicUuid) {
2810 struct hdl_pair hdl_pair;
2811 hdl_pair.val_hdl = charac.value_handle;
2812 hdl_pair.ccc_hdl = find_ccc_handle(charac);
2813
2814 if (hdl_pair.ccc_hdl == 0) {
2815 log::info(", Source PACs ccc not available");
2816 }
2817
2818 if (hdl_pair.ccc_hdl != 0 &&
2819 !subscribe_for_notification(conn_id, leAudioDevice->address_,
2820 hdl_pair)) {
2821 disconnectInvalidDevice(leAudioDevice,
2822 ", could not subscribe for src pac char",
2823 LeAudioHealthDeviceStatType::INVALID_DB);
2824 return;
2825 }
2826
2827 /* Obtain initial state of source PACs */
2828 BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl,
2829 OnGattReadRspStatic, NULL);
2830
2831 leAudioDevice->src_pacs_.push_back(std::make_tuple(
2832 hdl_pair,
2833 std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
2834
2835 log::info(
2836 "Found Source PAC characteristic, handle: 0x{:04x}, ccc handle: "
2837 "0x{:04x}, addr: {}",
2838 charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
2839 } else if (charac.uuid == bluetooth::le_audio::uuid::
2840 kSinkAudioLocationCharacteristicUuid) {
2841 leAudioDevice->snk_audio_locations_hdls_.val_hdl = charac.value_handle;
2842 leAudioDevice->snk_audio_locations_hdls_.ccc_hdl =
2843 find_ccc_handle(charac);
2844
2845 if (leAudioDevice->snk_audio_locations_hdls_.ccc_hdl == 0) {
2846 log::info(", snk audio locations char doesn't have ccc");
2847 }
2848
2849 if (leAudioDevice->snk_audio_locations_hdls_.ccc_hdl != 0 &&
2850 !subscribe_for_notification(
2851 conn_id, leAudioDevice->address_,
2852 leAudioDevice->snk_audio_locations_hdls_)) {
2853 disconnectInvalidDevice(
2854 leAudioDevice, ", could not subscribe for snk locations char",
2855 LeAudioHealthDeviceStatType::INVALID_DB);
2856 return;
2857 }
2858
2859 /* Obtain initial state of sink audio locations */
2860 BtaGattQueue::ReadCharacteristic(
2861 conn_id, leAudioDevice->snk_audio_locations_hdls_.val_hdl,
2862 OnGattReadRspStatic, NULL);
2863
2864 log::info(
2865 "Found Sink audio locations characteristic, handle: 0x{:04x}, ccc "
2866 "handle: 0x{:04x}, addr: {}",
2867 charac.value_handle,
2868 leAudioDevice->snk_audio_locations_hdls_.ccc_hdl,
2869 leAudioDevice->address_);
2870 } else if (charac.uuid == bluetooth::le_audio::uuid::
2871 kSourceAudioLocationCharacteristicUuid) {
2872 leAudioDevice->src_audio_locations_hdls_.val_hdl = charac.value_handle;
2873 leAudioDevice->src_audio_locations_hdls_.ccc_hdl =
2874 find_ccc_handle(charac);
2875
2876 if (leAudioDevice->src_audio_locations_hdls_.ccc_hdl == 0) {
2877 log::info(", src audio locations char doesn't have ccc");
2878 }
2879
2880 if (leAudioDevice->src_audio_locations_hdls_.ccc_hdl != 0 &&
2881 !subscribe_for_notification(
2882 conn_id, leAudioDevice->address_,
2883 leAudioDevice->src_audio_locations_hdls_)) {
2884 disconnectInvalidDevice(
2885 leAudioDevice, ", could not subscribe for src locations char",
2886 LeAudioHealthDeviceStatType::INVALID_DB);
2887 return;
2888 }
2889
2890 /* Obtain initial state of source audio locations */
2891 BtaGattQueue::ReadCharacteristic(
2892 conn_id, leAudioDevice->src_audio_locations_hdls_.val_hdl,
2893 OnGattReadRspStatic, NULL);
2894
2895 log::info(
2896 "Found Source audio locations characteristic, handle: 0x{:04x}, "
2897 "ccc handle: 0x{:04x}, addr: {}",
2898 charac.value_handle,
2899 leAudioDevice->src_audio_locations_hdls_.ccc_hdl,
2900 leAudioDevice->address_);
2901 } else if (charac.uuid ==
2902 bluetooth::le_audio::uuid::
2903 kAudioContextAvailabilityCharacteristicUuid) {
2904 leAudioDevice->audio_avail_hdls_.val_hdl = charac.value_handle;
2905 leAudioDevice->audio_avail_hdls_.ccc_hdl = find_ccc_handle(charac);
2906
2907 if (leAudioDevice->audio_avail_hdls_.ccc_hdl == 0) {
2908 disconnectInvalidDevice(leAudioDevice,
2909 ", audio avails char doesn't have ccc",
2910 LeAudioHealthDeviceStatType::INVALID_DB);
2911 return;
2912 }
2913
2914 if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
2915 leAudioDevice->audio_avail_hdls_)) {
2916 disconnectInvalidDevice(leAudioDevice,
2917 ", could not subscribe for audio avails char",
2918 LeAudioHealthDeviceStatType::INVALID_DB);
2919 return;
2920 }
2921
2922 /* Obtain initial state */
2923 BtaGattQueue::ReadCharacteristic(
2924 conn_id, leAudioDevice->audio_avail_hdls_.val_hdl,
2925 OnGattReadRspStatic, NULL);
2926
2927 log::info(
2928 "Found Audio Availability Context characteristic, handle: "
2929 "0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
2930 charac.value_handle, leAudioDevice->audio_avail_hdls_.ccc_hdl,
2931 leAudioDevice->address_);
2932 } else if (charac.uuid == bluetooth::le_audio::uuid::
2933 kAudioSupportedContextCharacteristicUuid) {
2934 leAudioDevice->audio_supp_cont_hdls_.val_hdl = charac.value_handle;
2935 leAudioDevice->audio_supp_cont_hdls_.ccc_hdl = find_ccc_handle(charac);
2936
2937 if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl == 0) {
2938 log::info(", audio supported char doesn't have ccc");
2939 }
2940
2941 if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl != 0 &&
2942 !subscribe_for_notification(conn_id, leAudioDevice->address_,
2943 leAudioDevice->audio_supp_cont_hdls_)) {
2944 disconnectInvalidDevice(
2945 leAudioDevice,
2946 ", could not subscribe for audio supported ctx char",
2947 LeAudioHealthDeviceStatType::INVALID_DB);
2948 return;
2949 }
2950
2951 /* Obtain initial state */
2952 BtaGattQueue::ReadCharacteristic(
2953 conn_id, leAudioDevice->audio_supp_cont_hdls_.val_hdl,
2954 OnGattReadRspStatic, NULL);
2955
2956 log::info(
2957 "Found Audio Supported Context characteristic, handle: 0x{:04x}, "
2958 "ccc handle: 0x{:04x}, addr: {}",
2959 charac.value_handle, leAudioDevice->audio_supp_cont_hdls_.ccc_hdl,
2960 leAudioDevice->address_);
2961 }
2962 }
2963
2964 /* Refresh ASE handles */
2965 leAudioDevice->ases_.clear();
2966
2967 for (const gatt::Characteristic& charac : ase_svc->characteristics) {
2968 log::info("Found characteristic, uuid: {}", charac.uuid.ToString());
2969 if (charac.uuid ==
2970 bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid ||
2971 charac.uuid ==
2972 bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid) {
2973 uint16_t ccc_handle = find_ccc_handle(charac);
2974 if (ccc_handle == 0) {
2975 disconnectInvalidDevice(leAudioDevice, ", ASE char doesn't have ccc",
2976 LeAudioHealthDeviceStatType::INVALID_DB);
2977 return;
2978 }
2979 struct bluetooth::le_audio::types::hdl_pair hdls(charac.value_handle,
2980 ccc_handle);
2981 if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
2982 hdls)) {
2983 disconnectInvalidDevice(leAudioDevice,
2984 ", could not subscribe ASE char",
2985 LeAudioHealthDeviceStatType::INVALID_DB);
2986 return;
2987 }
2988
2989 int direction =
2990 charac.uuid ==
2991 bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid
2992 ? bluetooth::le_audio::types::kLeAudioDirectionSink
2993 : bluetooth::le_audio::types::kLeAudioDirectionSource;
2994
2995 leAudioDevice->ases_.emplace_back(charac.value_handle, ccc_handle,
2996 direction);
2997
2998 log::info(
2999 "Found ASE characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, "
3000 "direction: {}, addr: {}",
3001 charac.value_handle, ccc_handle, direction,
3002 leAudioDevice->address_);
3003 } else if (charac.uuid ==
3004 bluetooth::le_audio::uuid::
3005 kAudioStreamEndpointControlPointCharacteristicUuid) {
3006 leAudioDevice->ctp_hdls_.val_hdl = charac.value_handle;
3007 leAudioDevice->ctp_hdls_.ccc_hdl = find_ccc_handle(charac);
3008
3009 if (leAudioDevice->ctp_hdls_.ccc_hdl == 0) {
3010 disconnectInvalidDevice(leAudioDevice, ", ASE ctp doesn't have ccc",
3011 LeAudioHealthDeviceStatType::INVALID_DB);
3012 return;
3013 }
3014
3015 if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3016 leAudioDevice->ctp_hdls_)) {
3017 disconnectInvalidDevice(leAudioDevice,
3018 ", could not subscribe ASE char",
3019 LeAudioHealthDeviceStatType::INVALID_DB);
3020 return;
3021 }
3022
3023 log::info(
3024 "Found ASE Control Point characteristic, handle: 0x{:04x}, ccc "
3025 "handle: 0x{:04x}, addr: {}",
3026 charac.value_handle, leAudioDevice->ctp_hdls_.ccc_hdl,
3027 leAudioDevice->address_);
3028 }
3029 }
3030
3031 if (tmas_svc) {
3032 for (const gatt::Characteristic& charac : tmas_svc->characteristics) {
3033 if (charac.uuid ==
3034 bluetooth::le_audio::uuid::
3035 kTelephonyMediaAudioProfileRoleCharacteristicUuid) {
3036 leAudioDevice->tmap_role_hdl_ = charac.value_handle;
3037
3038 /* Obtain initial state of TMAP role */
3039 BtaGattQueue::ReadCharacteristic(conn_id,
3040 leAudioDevice->tmap_role_hdl_,
3041 OnGattReadRspStatic, NULL);
3042
3043 log::info(
3044 "Found Telephony and Media Profile characteristic, handle: "
3045 "0x{:04x}, device: {}",
3046 leAudioDevice->tmap_role_hdl_, leAudioDevice->address_);
3047 }
3048 }
3049 }
3050
3051 leAudioDevice->known_service_handles_ = true;
3052 leAudioDevice->notify_connected_after_read_ = true;
3053 if (leAudioHealthStatus_) {
3054 leAudioHealthStatus_->AddStatisticForDevice(
3055 leAudioDevice, LeAudioHealthDeviceStatType::VALID_DB);
3056 }
3057
3058 /* If already known group id */
3059 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
3060 AseInitialStateReadRequest(leAudioDevice);
3061 return;
3062 }
3063
3064 /* If device does not belong to any group yet we either add it to the
3065 * group by our selfs now or wait for Csis to do it. In both cases, let's
3066 * check if group is already assigned.
3067 */
3068 int group_id = DeviceGroups::Get()->GetGroupId(
3069 leAudioDevice->address_, bluetooth::le_audio::uuid::kCapServiceUuid);
3070 if (group_id != bluetooth::groups::kGroupUnknown) {
3071 instance->group_add_node(group_id, leAudioDevice->address_);
3072 return;
3073 }
3074
3075 /* CSIS will trigger adding to group */
3076 if (leAudioDevice->csis_member_) {
3077 log::info("{}, waiting for CSIS to create group for device",
3078 leAudioDevice->address_);
3079 scheduleGuardForCsisAdd(leAudioDevice->address_);
3080 return;
3081 }
3082
3083 log::info("{} Not a CSIS member. Create group by our own",
3084 leAudioDevice->address_);
3085
3086 /* If there is no Csis just add device by our own */
3087 DeviceGroups::Get()->AddDevice(leAudioDevice->address_,
3088 bluetooth::le_audio::uuid::kCapServiceUuid);
3089 }
3090
OnGattWriteCcc(uint16_t conn_id,tGATT_STATUS status,uint16_t hdl,void * data)3091 void OnGattWriteCcc(uint16_t conn_id, tGATT_STATUS status, uint16_t hdl,
3092 void* data) {
3093 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3094 std::vector<struct ase>::iterator ase_it;
3095
3096 if (!leAudioDevice) {
3097 log::error("unknown conn_id=0x{:x}", conn_id);
3098 return;
3099 }
3100
3101 if (status == GATT_DATABASE_OUT_OF_SYNC) {
3102 log::info("Database out of sync for {}, conn_id: 0x{:04x}",
3103 leAudioDevice->address_, conn_id);
3104 ClearDeviceInformationAndStartSearch(leAudioDevice);
3105 return;
3106 }
3107
3108 if (status == GATT_SUCCESS) {
3109 log::info("Successfully registered on ccc: 0x{:04x}, device: {}", hdl,
3110 leAudioDevice->address_);
3111
3112 if (leAudioDevice->ctp_hdls_.ccc_hdl == hdl &&
3113 leAudioDevice->known_service_handles_ &&
3114 !leAudioDevice->notify_connected_after_read_) {
3115 /* Reconnection case. Control point is the last CCC LeAudio is
3116 * registering for on reconnection */
3117 connectionReady(leAudioDevice);
3118 }
3119
3120 return;
3121 }
3122
3123 log::error(
3124 "Failed to register for notifications: 0x{:04x}, device: {}, status: "
3125 "0x{:02x}",
3126 hdl, leAudioDevice->address_, status);
3127
3128 ase_it =
3129 std::find_if(leAudioDevice->ases_.begin(), leAudioDevice->ases_.end(),
3130 [&hdl](const struct ase& ase) -> bool {
3131 return ase.hdls.ccc_hdl == hdl;
3132 });
3133
3134 if (ase_it == leAudioDevice->ases_.end()) {
3135 log::error("Unknown ccc handle: 0x{:04x}, device: {}", hdl,
3136 leAudioDevice->address_);
3137 return;
3138 }
3139
3140 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
3141 ase_it->hdls.val_hdl);
3142 }
3143
AttachToStreamingGroupIfNeeded(LeAudioDevice * leAudioDevice)3144 void AttachToStreamingGroupIfNeeded(LeAudioDevice* leAudioDevice) {
3145 if (leAudioDevice->group_id_ != active_group_id_) {
3146 log::info("group {} is not streaming. Nothing to do",
3147 leAudioDevice->group_id_);
3148 return;
3149 }
3150
3151 if (leAudioDevice->HaveActiveAse()) {
3152 log::debug("{} is already configured, nothing to do",
3153 leAudioDevice->address_);
3154 return;
3155 }
3156
3157 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3158
3159 auto group_metadata_contexts =
3160 get_bidirectional(group->GetMetadataContexts());
3161 auto device_available_contexts = leAudioDevice->GetAvailableContexts();
3162 if (!group_metadata_contexts.test_any(device_available_contexts)) {
3163 log::info("{} does is not have required context type",
3164 leAudioDevice->address_);
3165 return;
3166 }
3167
3168 /* Restore configuration */
3169 auto* stream_conf = &group->stream_conf;
3170
3171 if (audio_sender_state_ == AudioState::IDLE &&
3172 audio_receiver_state_ == AudioState::IDLE) {
3173 log::debug("Device not streaming but active - nothing to do");
3174 return;
3175 }
3176
3177 if (!stream_conf->conf) {
3178 log::info("Configuration not yet set. Nothing to do now");
3179 return;
3180 }
3181
3182 log::info("Attaching {} to group: {}", leAudioDevice->address_,
3183 leAudioDevice->group_id_);
3184
3185 for (auto direction :
3186 {bluetooth::le_audio::types::kLeAudioDirectionSink,
3187 bluetooth::le_audio::types::kLeAudioDirectionSource}) {
3188 log::info("Looking for requirements: {} - {}", stream_conf->conf->name,
3189 ((direction == 1 ? "snk" : "src")));
3190 const auto& pacs =
3191 (direction == bluetooth::le_audio::types::kLeAudioDirectionSink)
3192 ? leAudioDevice->snk_pacs_
3193 : leAudioDevice->src_pacs_;
3194 for (const auto& ent : stream_conf->conf->confs.get(direction)) {
3195 if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac(
3196 pacs, ent.codec)) {
3197 log::info("Configuration is not supported by device {}",
3198 leAudioDevice->address_);
3199
3200 /* Reconfigure if newly connected member device cannot support
3201 * current codec configuration */
3202 group->SetPendingConfiguration();
3203 groupStateMachine_->StopStream(group);
3204 stream_setup_start_timestamp_ =
3205 bluetooth::common::time_get_os_boottime_us();
3206 return;
3207 }
3208 }
3209 }
3210
3211 /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
3212 auto ccid_contexts = group->GetMetadataContexts();
3213 if (IsInVoipCall() && !IsInCall()) {
3214 ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
3215 ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
3216 }
3217 BidirectionalPair<std::vector<uint8_t>> ccids = {
3218 .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
3219 ccid_contexts.sink),
3220 .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
3221 ccid_contexts.source)};
3222
3223 if (!groupStateMachine_->AttachToStream(group, leAudioDevice,
3224 std::move(ccids))) {
3225 log::warn("Could not add device {} to the group {} streaming.",
3226 leAudioDevice->address_, group->group_id_);
3227 scheduleAttachDeviceToTheStream(leAudioDevice->address_);
3228 } else {
3229 stream_setup_start_timestamp_ =
3230 bluetooth::common::time_get_os_boottime_us();
3231 }
3232 }
3233
restartAttachToTheStream(const RawAddress & addr)3234 void restartAttachToTheStream(const RawAddress& addr) {
3235 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
3236 if (leAudioDevice == nullptr ||
3237 leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
3238 log::info("Device {} not available anymore", addr);
3239 return;
3240 }
3241 AttachToStreamingGroupIfNeeded(leAudioDevice);
3242 }
3243
scheduleAttachDeviceToTheStream(const RawAddress & addr)3244 void scheduleAttachDeviceToTheStream(const RawAddress& addr) {
3245 log::info("Device {} scheduler for stream", addr);
3246 do_in_main_thread_delayed(
3247 FROM_HERE,
3248 base::BindOnce(&LeAudioClientImpl::restartAttachToTheStream,
3249 weak_factory_.GetWeakPtr(), addr),
3250 std::chrono::milliseconds(kDeviceAttachDelayMs));
3251 }
3252
SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup * group)3253 void SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup* group) {
3254 auto leAudioDevice = group->GetFirstDevice();
3255 callbacks_->OnAudioGroupSelectableCodecConf(
3256 group->group_id_,
3257 bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3258 leAudioDevice->src_pacs_),
3259 bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3260 leAudioDevice->snk_pacs_));
3261 }
3262
SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup * group)3263 void SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup* group) {
3264 // This shall be called when configuration changes
3265 log::debug("{}", group->group_id_);
3266
3267 auto audio_set_conf = group->GetConfiguration(configuration_context_type_);
3268 if (!audio_set_conf) {
3269 log::warn("Stream configuration is not valid for group id {}",
3270 group->group_id_);
3271 return;
3272 }
3273
3274 bluetooth::le_audio::btle_audio_codec_config_t input_config{};
3275 bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(
3276 audio_set_conf->confs.source, input_config);
3277
3278 bluetooth::le_audio::btle_audio_codec_config_t output_config{};
3279 bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(
3280 audio_set_conf->confs.sink, output_config);
3281
3282 callbacks_->OnAudioGroupCurrentCodecConf(group->group_id_, input_config,
3283 output_config);
3284 }
3285
connectionReady(LeAudioDevice * leAudioDevice)3286 void connectionReady(LeAudioDevice* leAudioDevice) {
3287 log::debug(
3288 "{}, {}", leAudioDevice->address_,
3289 bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
3290
3291 L2CA_LockBleConnParamsForProfileConnection(leAudioDevice->address_, false);
3292
3293 if (leAudioDevice->GetConnectionState() ==
3294 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY &&
3295 (leAudioDevice->autoconnect_flag_ == false)) {
3296 btif_storage_set_leaudio_autoconnect(leAudioDevice->address_, true);
3297 leAudioDevice->autoconnect_flag_ = true;
3298 }
3299
3300 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
3301 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
3302 leAudioDevice->group_id_, leAudioDevice->address_,
3303 ConnectionState::CONNECTED,
3304 bluetooth::le_audio::ConnectionStatus::SUCCESS);
3305
3306 if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
3307 log::warn("LeAudio device {} connected with no group",
3308 leAudioDevice->address_);
3309 callbacks_->OnConnectionState(ConnectionState::CONNECTED,
3310 leAudioDevice->address_);
3311 return;
3312 }
3313
3314 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
3315 if (group) {
3316 UpdateLocationsAndContextsAvailability(group, true);
3317 }
3318
3319 /* Notify connected after contexts are notified */
3320 callbacks_->OnConnectionState(ConnectionState::CONNECTED,
3321 leAudioDevice->address_);
3322
3323 AttachToStreamingGroupIfNeeded(leAudioDevice);
3324
3325 if (reconnection_mode_ == BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS) {
3326 /* Add other devices to allow list if there are any not yet connected
3327 * from the group
3328 */
3329 group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
3330 }
3331 }
3332
IsAseAcceptingAudioData(struct ase * ase)3333 bool IsAseAcceptingAudioData(struct ase* ase) {
3334 if (ase == nullptr) return false;
3335 if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) return false;
3336 if (ase->data_path_state != DataPathState::CONFIGURED) return false;
3337
3338 return true;
3339 }
3340
3341 // mix stero signal into mono
mono_blend(const std::vector<uint8_t> & buf,int bytes_per_sample,size_t frames)3342 std::vector<uint8_t> mono_blend(const std::vector<uint8_t>& buf,
3343 int bytes_per_sample, size_t frames) {
3344 std::vector<uint8_t> mono_out;
3345 mono_out.resize(frames * bytes_per_sample);
3346
3347 if (bytes_per_sample == 2) {
3348 int16_t* out = (int16_t*)mono_out.data();
3349 const int16_t* in = (int16_t*)(buf.data());
3350 for (size_t i = 0; i < frames; ++i) {
3351 int accum = 0;
3352 accum += *in++;
3353 accum += *in++;
3354 accum /= 2; // round to 0
3355 *out++ = accum;
3356 }
3357 } else if (bytes_per_sample == 4) {
3358 int32_t* out = (int32_t*)mono_out.data();
3359 const int32_t* in = (int32_t*)(buf.data());
3360 for (size_t i = 0; i < frames; ++i) {
3361 int accum = 0;
3362 accum += *in++;
3363 accum += *in++;
3364 accum /= 2; // round to 0
3365 *out++ = accum;
3366 }
3367 } else {
3368 log::error("Don't know how to mono blend that {}!", bytes_per_sample);
3369 }
3370 return mono_out;
3371 }
3372
PrepareAndSendToTwoCises(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3373 void PrepareAndSendToTwoCises(
3374 const std::vector<uint8_t>& data,
3375 const struct bluetooth::le_audio::stream_parameters& stream_params) {
3376 uint16_t left_cis_handle = 0;
3377 uint16_t right_cis_handle = 0;
3378
3379 uint16_t number_of_required_samples_per_channel =
3380 sw_enc_left->GetNumOfSamplesPerChannel();
3381 uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3382 if (data.size() < bytes_per_sample * 2 /* channels */ *
3383 number_of_required_samples_per_channel) {
3384 log::error("Missing samples. Data size: {} expected: {}", data.size(),
3385 bytes_per_sample * 2 * number_of_required_samples_per_channel);
3386 return;
3387 }
3388
3389 for (auto [cis_handle, audio_location] : stream_params.stream_locations) {
3390 if (audio_location &
3391 bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft)
3392 left_cis_handle = cis_handle;
3393 if (audio_location &
3394 bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight)
3395 right_cis_handle = cis_handle;
3396 }
3397
3398 uint16_t byte_count = stream_params.octets_per_codec_frame;
3399 bool mix_to_mono = (left_cis_handle == 0) || (right_cis_handle == 0);
3400 if (mix_to_mono) {
3401 std::vector<uint8_t> mono = mono_blend(
3402 data, bytes_per_sample, number_of_required_samples_per_channel);
3403 if (left_cis_handle) {
3404 sw_enc_left->Encode(mono.data(), 1, byte_count);
3405 }
3406
3407 if (right_cis_handle) {
3408 sw_enc_left->Encode(mono.data(), 1, byte_count);
3409 }
3410 } else {
3411 sw_enc_left->Encode(data.data(), 2, byte_count);
3412 sw_enc_right->Encode(data.data() + bytes_per_sample, 2, byte_count);
3413 }
3414
3415 log::debug("left_cis_handle: {} right_cis_handle: {}", left_cis_handle,
3416 right_cis_handle);
3417 /* Send data to the controller */
3418 if (left_cis_handle)
3419 IsoManager::GetInstance()->SendIsoData(
3420 left_cis_handle,
3421 (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3422 sw_enc_left->GetDecodedSamples().size() * 2);
3423
3424 if (right_cis_handle)
3425 IsoManager::GetInstance()->SendIsoData(
3426 right_cis_handle,
3427 (const uint8_t*)sw_enc_right->GetDecodedSamples().data(),
3428 sw_enc_right->GetDecodedSamples().size() * 2);
3429 }
3430
PrepareAndSendToSingleCis(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3431 void PrepareAndSendToSingleCis(
3432 const std::vector<uint8_t>& data,
3433 const struct bluetooth::le_audio::stream_parameters& stream_params) {
3434 uint16_t num_channels = stream_params.num_of_channels;
3435 uint16_t cis_handle = stream_params.stream_locations.front().first;
3436
3437 uint16_t number_of_required_samples_per_channel =
3438 sw_enc_left->GetNumOfSamplesPerChannel();
3439 uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3440 if ((int)data.size() < (bytes_per_sample * num_channels *
3441 number_of_required_samples_per_channel)) {
3442 log::error("Missing samples");
3443 return;
3444 }
3445
3446 uint16_t byte_count = stream_params.octets_per_codec_frame;
3447 bool mix_to_mono = (num_channels == 1);
3448 if (mix_to_mono) {
3449 /* Since we always get two channels from framework, lets make it mono here
3450 */
3451 std::vector<uint8_t> mono = mono_blend(
3452 data, bytes_per_sample, number_of_required_samples_per_channel);
3453 sw_enc_left->Encode(mono.data(), 1, byte_count);
3454 } else {
3455 sw_enc_left->Encode((const uint8_t*)data.data(), 2, byte_count);
3456 // Output to the left channel buffer with `byte_count` offset
3457 sw_enc_right->Encode((const uint8_t*)data.data() + 2, 2, byte_count,
3458 &sw_enc_left->GetDecodedSamples(), byte_count);
3459 }
3460
3461 IsoManager::GetInstance()->SendIsoData(
3462 cis_handle, (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3463 sw_enc_left->GetDecodedSamples().size() * 2);
3464 }
3465
3466 const struct bluetooth::le_audio::stream_configuration*
GetStreamSinkConfiguration(LeAudioDeviceGroup * group)3467 GetStreamSinkConfiguration(LeAudioDeviceGroup* group) {
3468 const struct bluetooth::le_audio::stream_configuration* stream_conf =
3469 &group->stream_conf;
3470 log::info("group_id: {}", group->group_id_);
3471 if (stream_conf->stream_params.sink.stream_locations.size() == 0) {
3472 return nullptr;
3473 }
3474
3475 log::info("configuration: {}", stream_conf->conf->name);
3476 return stream_conf;
3477 }
3478
OnAudioDataReady(const std::vector<uint8_t> & data)3479 void OnAudioDataReady(const std::vector<uint8_t>& data) {
3480 if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3481 (audio_sender_state_ != AudioState::STARTED))
3482 return;
3483
3484 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3485 if (!group) {
3486 log::error("There is no streaming group available");
3487 return;
3488 }
3489
3490 auto stream_conf = group->stream_conf;
3491 if ((stream_conf.stream_params.sink.num_of_devices > 2) ||
3492 (stream_conf.stream_params.sink.num_of_devices == 0) ||
3493 stream_conf.stream_params.sink.stream_locations.empty()) {
3494 log::error("Stream configufation is not valid.");
3495 return;
3496 }
3497
3498 if ((stream_conf.stream_params.sink.num_of_devices == 2) ||
3499 (stream_conf.stream_params.sink.stream_locations.size() == 2)) {
3500 /* Streaming to two devices or one device with 2 CISes */
3501 PrepareAndSendToTwoCises(data, stream_conf.stream_params.sink);
3502 } else {
3503 /* Streaming to one device and 1 CIS */
3504 PrepareAndSendToSingleCis(data, stream_conf.stream_params.sink);
3505 }
3506 }
3507
CleanCachedMicrophoneData()3508 void CleanCachedMicrophoneData() {
3509 cached_channel_timestamp_ = 0;
3510 cached_channel_ = nullptr;
3511 }
3512
3513 /* Handles audio data packets coming from the controller */
HandleIncomingCisData(uint8_t * data,uint16_t size,uint16_t cis_conn_hdl,uint32_t timestamp)3514 void HandleIncomingCisData(uint8_t* data, uint16_t size,
3515 uint16_t cis_conn_hdl, uint32_t timestamp) {
3516 /* Get only one channel for MONO microphone */
3517 /* Gather data for channel */
3518 if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3519 (audio_receiver_state_ != AudioState::STARTED))
3520 return;
3521
3522 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3523 if (!group) {
3524 log::error("There is no streaming group available");
3525 return;
3526 }
3527
3528 uint16_t left_cis_handle = 0;
3529 uint16_t right_cis_handle = 0;
3530 for (auto [cis_handle, audio_location] :
3531 group->stream_conf.stream_params.source.stream_locations) {
3532 if (audio_location &
3533 bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) {
3534 left_cis_handle = cis_handle;
3535 }
3536 if (audio_location &
3537 bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
3538 right_cis_handle = cis_handle;
3539 }
3540 }
3541
3542 auto decoder = sw_dec_left.get();
3543 if (cis_conn_hdl == left_cis_handle) {
3544 decoder = sw_dec_left.get();
3545 } else if (cis_conn_hdl == right_cis_handle) {
3546 decoder = sw_dec_right.get();
3547 } else {
3548 log::error("Received data for unknown handle: {:04x}", cis_conn_hdl);
3549 return;
3550 }
3551
3552 if (!left_cis_handle || !right_cis_handle) {
3553 /* mono or just one device connected */
3554 decoder->Decode(data, size);
3555 SendAudioDataToAF(&decoder->GetDecodedSamples());
3556 return;
3557 }
3558 /* both devices are connected */
3559
3560 if (cached_channel_ == nullptr ||
3561 cached_channel_->GetDecodedSamples().empty()) {
3562 /* First packet received, cache it. We need both channel data to send it
3563 * to AF. */
3564 decoder->Decode(data, size);
3565 cached_channel_timestamp_ = timestamp;
3566 cached_channel_ = decoder;
3567 return;
3568 }
3569
3570 /* We received either data for the other audio channel, or another
3571 * packet for same channel */
3572 if (cached_channel_ != decoder) {
3573 /* It's data for the 2nd channel */
3574 if (timestamp == cached_channel_timestamp_) {
3575 /* Ready to mix data and send out to AF */
3576 decoder->Decode(data, size);
3577 SendAudioDataToAF(&sw_dec_left->GetDecodedSamples(),
3578 &sw_dec_right->GetDecodedSamples());
3579
3580 CleanCachedMicrophoneData();
3581 return;
3582 }
3583
3584 /* 2nd Channel is in the future compared to the cached data.
3585 Send the cached data to AF, and keep the new channel data in cache.
3586 This should happen only during stream setup */
3587 SendAudioDataToAF(&decoder->GetDecodedSamples());
3588
3589 decoder->Decode(data, size);
3590 cached_channel_timestamp_ = timestamp;
3591 cached_channel_ = decoder;
3592 return;
3593 }
3594
3595 /* Data for same channel received. 2nd channel is down/not sending
3596 * data */
3597
3598 /* Send the cached data out */
3599 SendAudioDataToAF(&decoder->GetDecodedSamples());
3600
3601 /* Cache the data in case 2nd channel connects */
3602 decoder->Decode(data, size);
3603 cached_channel_timestamp_ = timestamp;
3604 cached_channel_ = decoder;
3605 }
3606
SendAudioDataToAF(std::vector<int16_t> * left,std::vector<int16_t> * right=nullptr)3607 void SendAudioDataToAF(std::vector<int16_t>* left,
3608 std::vector<int16_t>* right = nullptr) {
3609 uint16_t to_write = 0;
3610 uint16_t written = 0;
3611
3612 bool af_is_stereo = (audio_framework_sink_config.num_channels == 2);
3613 bool bt_got_stereo = (left != nullptr) & (right != nullptr);
3614
3615 if (!af_is_stereo) {
3616 if (!bt_got_stereo) {
3617 std::vector<int16_t>* mono = left ? left : right;
3618 /* mono audio over bluetooth, audio framework expects mono */
3619 to_write = sizeof(int16_t) * mono->size();
3620 written = le_audio_sink_hal_client_->SendData((uint8_t*)mono->data(),
3621 to_write);
3622 } else {
3623 /* stereo audio over bluetooth, audio framework expects mono */
3624 for (size_t i = 0; i < left->size(); i++) {
3625 (*left)[i] = ((*left)[i] + (*right)[i]) / 2;
3626 }
3627 to_write = sizeof(int16_t) * left->size();
3628 written = le_audio_sink_hal_client_->SendData((uint8_t*)left->data(),
3629 to_write);
3630 }
3631 } else {
3632 /* mono audio over bluetooth, audio framework expects stereo
3633 * Here we handle stream without checking bt_got_stereo flag.
3634 */
3635 const size_t mono_size = left ? left->size() : right->size();
3636 std::vector<uint16_t> mixed(mono_size * 2);
3637
3638 for (size_t i = 0; i < mono_size; i++) {
3639 mixed[2 * i] = left ? (*left)[i] : (*right)[i];
3640 mixed[2 * i + 1] = right ? (*right)[i] : (*left)[i];
3641 }
3642 to_write = sizeof(int16_t) * mixed.size();
3643 written =
3644 le_audio_sink_hal_client_->SendData((uint8_t*)mixed.data(), to_write);
3645 }
3646
3647 /* TODO: What to do if not all data sinked ? */
3648 if (written != to_write) log::error("not all data sinked");
3649 }
3650
ConfirmLocalAudioSourceStreamingRequest()3651 void ConfirmLocalAudioSourceStreamingRequest() {
3652 le_audio_source_hal_client_->ConfirmStreamingRequest();
3653
3654 LeAudioLogHistory::Get()->AddLogHistory(
3655 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
3656 kLogAfResumeConfirm + "LocalSource",
3657 "s_state: " + ToString(audio_sender_state_) + "-> STARTED");
3658
3659 audio_sender_state_ = AudioState::STARTED;
3660 }
3661
ConfirmLocalAudioSinkStreamingRequest()3662 void ConfirmLocalAudioSinkStreamingRequest() {
3663 le_audio_sink_hal_client_->ConfirmStreamingRequest();
3664
3665 LeAudioLogHistory::Get()->AddLogHistory(
3666 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
3667 kLogAfResumeConfirm + "LocalSink",
3668 "r_state: " + ToString(audio_receiver_state_) + "-> STARTED");
3669
3670 audio_receiver_state_ = AudioState::STARTED;
3671 }
3672
StartSendingAudio(int group_id)3673 void StartSendingAudio(int group_id) {
3674 log::info("");
3675
3676 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
3677 LeAudioDevice* device = group->GetFirstActiveDevice();
3678 log::assert_that(device, "Shouldn't be called without an active device.");
3679
3680 /* Assume 2 ases max just for now. */
3681 auto* stream_conf = GetStreamSinkConfiguration(group);
3682 if (stream_conf == nullptr) {
3683 log::error("could not get sink configuration");
3684 groupStateMachine_->StopStream(group);
3685 return;
3686 }
3687
3688 log::debug("Sink stream config (#{}):\n",
3689 static_cast<int>(
3690 stream_conf->stream_params.sink.stream_locations.size()));
3691 for (auto stream : stream_conf->stream_params.sink.stream_locations) {
3692 log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", stream.first,
3693 stream.second);
3694 }
3695 log::debug("Source stream config (#{}):\n",
3696 static_cast<int>(
3697 stream_conf->stream_params.source.stream_locations.size()));
3698 for (auto stream : stream_conf->stream_params.source.stream_locations) {
3699 log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", stream.first,
3700 stream.second);
3701 }
3702
3703 uint16_t remote_delay_ms = group->GetRemoteDelay(
3704 bluetooth::le_audio::types::kLeAudioDirectionSink);
3705 if (CodecManager::GetInstance()->GetCodecLocation() ==
3706 bluetooth::le_audio::types::CodecLocation::HOST) {
3707 if (sw_enc_left || sw_enc_right) {
3708 log::warn("The encoder instance should have been already released.");
3709 }
3710 sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance(
3711 stream_conf->codec_id);
3712 auto codec_status = sw_enc_left->InitEncoder(
3713 audio_framework_source_config, current_encoder_config_);
3714 if (codec_status !=
3715 bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
3716 log::error("Left channel codec setup failed with err: {}",
3717 codec_status);
3718 groupStateMachine_->StopStream(group);
3719 return;
3720 }
3721
3722 sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance(
3723 stream_conf->codec_id);
3724 codec_status = sw_enc_right->InitEncoder(audio_framework_source_config,
3725 current_encoder_config_);
3726 if (codec_status !=
3727 bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
3728 log::error("Right channel codec setup failed with err: {}",
3729 codec_status);
3730 groupStateMachine_->StopStream(group);
3731 return;
3732 }
3733 }
3734
3735 le_audio_source_hal_client_->UpdateRemoteDelay(remote_delay_ms);
3736 ConfirmLocalAudioSourceStreamingRequest();
3737
3738 if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
3739 /* We update the target audio allocation before streamStarted so that the
3740 * CodecManager would know how to configure the encoder. */
3741 BidirectionalPair<uint16_t> delays_pair = {
3742 .sink = group->GetRemoteDelay(
3743 bluetooth::le_audio::types::kLeAudioDirectionSink),
3744 .source = group->GetRemoteDelay(
3745 bluetooth::le_audio::types::kLeAudioDirectionSource)};
3746 CodecManager::GetInstance()->UpdateActiveAudioConfig(
3747 group->stream_conf.stream_params, delays_pair,
3748 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
3749 weak_factory_.GetWeakPtr(), std::placeholders::_1,
3750 std::placeholders::_2));
3751 }
3752 }
3753
3754 const struct bluetooth::le_audio::stream_configuration*
GetStreamSourceConfiguration(LeAudioDeviceGroup * group)3755 GetStreamSourceConfiguration(LeAudioDeviceGroup* group) {
3756 const struct bluetooth::le_audio::stream_configuration* stream_conf =
3757 &group->stream_conf;
3758 if (stream_conf->stream_params.source.stream_locations.size() == 0) {
3759 return nullptr;
3760 }
3761 log::info("configuration: {}", stream_conf->conf->name);
3762 return stream_conf;
3763 }
3764
StartReceivingAudio(int group_id)3765 void StartReceivingAudio(int group_id) {
3766 log::info("");
3767
3768 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
3769
3770 auto* stream_conf = GetStreamSourceConfiguration(group);
3771 if (!stream_conf) {
3772 log::warn(
3773 "Could not get source configuration for group {} probably microphone "
3774 "not configured",
3775 active_group_id_);
3776 groupStateMachine_->StopStream(group);
3777 return;
3778 }
3779
3780 uint16_t remote_delay_ms = group->GetRemoteDelay(
3781 bluetooth::le_audio::types::kLeAudioDirectionSource);
3782
3783 CleanCachedMicrophoneData();
3784
3785 if (CodecManager::GetInstance()->GetCodecLocation() ==
3786 bluetooth::le_audio::types::CodecLocation::HOST) {
3787 if (sw_dec_left.get() || sw_dec_right.get()) {
3788 log::warn("The decoder instance should have been already released.");
3789 }
3790 sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance(
3791 stream_conf->codec_id);
3792 auto codec_status = sw_dec_left->InitDecoder(current_decoder_config_,
3793 audio_framework_sink_config);
3794 if (codec_status !=
3795 bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
3796 log::error("Left channel codec setup failed with err: {}",
3797 codec_status);
3798 groupStateMachine_->StopStream(group);
3799 return;
3800 }
3801
3802 sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance(
3803 stream_conf->codec_id);
3804 codec_status = sw_dec_right->InitDecoder(current_decoder_config_,
3805 audio_framework_sink_config);
3806 if (codec_status !=
3807 bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
3808 log::error("Right channel codec setup failed with err: {}",
3809 codec_status);
3810 groupStateMachine_->StopStream(group);
3811 return;
3812 }
3813 }
3814 le_audio_sink_hal_client_->UpdateRemoteDelay(remote_delay_ms);
3815 ConfirmLocalAudioSinkStreamingRequest();
3816
3817 if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
3818 /* We update the target audio allocation before streamStarted so that the
3819 * CodecManager would know how to configure the encoder. */
3820 BidirectionalPair<uint16_t> delays_pair = {
3821 .sink = group->GetRemoteDelay(
3822 bluetooth::le_audio::types::kLeAudioDirectionSink),
3823 .source = group->GetRemoteDelay(
3824 bluetooth::le_audio::types::kLeAudioDirectionSource)};
3825 CodecManager::GetInstance()->UpdateActiveAudioConfig(
3826 group->stream_conf.stream_params, delays_pair,
3827 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
3828 weak_factory_.GetWeakPtr(), std::placeholders::_1,
3829 std::placeholders::_2));
3830 }
3831 }
3832
SuspendAudio(void)3833 void SuspendAudio(void) {
3834 CancelStreamingRequest();
3835
3836 if (sw_enc_left) sw_enc_left.reset();
3837 if (sw_enc_right) sw_enc_right.reset();
3838 if (sw_dec_left) sw_dec_left.reset();
3839 if (sw_dec_right) sw_dec_right.reset();
3840 CleanCachedMicrophoneData();
3841 }
3842
StopAudio(void)3843 void StopAudio(void) {
3844 SuspendAudio();
3845 L2CA_SetEcosystemBaseInterval(0 /* clear recommendation */);
3846 }
3847
printCurrentStreamConfiguration(int fd)3848 void printCurrentStreamConfiguration(int fd) {
3849 std::stringstream stream;
3850 auto config_printer = [&stream](LeAudioCodecConfiguration& conf) {
3851 stream << "\tsample rate: " << +conf.sample_rate
3852 << ",\tchan: " << +conf.num_channels
3853 << ",\tbits: " << +conf.bits_per_sample
3854 << ",\tdata_interval_us: " << +conf.data_interval_us << "\n";
3855 };
3856
3857 stream << " Speaker codec config (audio framework) \n";
3858 stream << "\taudio sender state: " << audio_sender_state_ << "\n";
3859 config_printer(audio_framework_source_config);
3860
3861 stream << " Microphone codec config (audio framework) \n";
3862 stream << "\taudio receiver state: " << audio_receiver_state_ << "\n";
3863 config_printer(audio_framework_sink_config);
3864
3865 stream << " Speaker codec config (SW encoder)\n";
3866 config_printer(current_encoder_config_);
3867
3868 stream << " Microphone codec config (SW decoder)\n";
3869 config_printer(current_decoder_config_);
3870
3871 dprintf(fd, "%s", stream.str().c_str());
3872 }
3873
Dump(int fd)3874 void Dump(int fd) {
3875 dprintf(fd, " APP ID: %d \n", gatt_if_);
3876 dprintf(fd, " Active group: %d\n", active_group_id_);
3877 dprintf(fd, " reconnection mode: %s \n",
3878 (reconnection_mode_ == BTM_BLE_BKG_CONNECT_ALLOW_LIST
3879 ? "Allow List"
3880 : "Targeted Announcements"));
3881 dprintf(fd, " configuration: %s (0x%08x)\n",
3882 bluetooth::common::ToString(configuration_context_type_).c_str(),
3883 static_cast<uint16_t>(configuration_context_type_));
3884 dprintf(fd, " local source metadata context type mask: %s\n",
3885 local_metadata_context_types_.source.to_string().c_str());
3886 dprintf(fd, " local sink metadata context type mask: %s\n",
3887 local_metadata_context_types_.sink.to_string().c_str());
3888 dprintf(fd, " TBS state: %s\n", in_call_ ? " In call" : "No calls");
3889 dprintf(fd, " Sink listening mode: %s\n",
3890 sink_monitor_mode_ ? "true" : "false");
3891 if (sink_monitor_notified_status_) {
3892 dprintf(fd, " Local sink notified state: %d\n",
3893 static_cast<int>(sink_monitor_notified_status_.value()));
3894 }
3895 dprintf(fd, " Source monitor mode: %s\n",
3896 source_monitor_mode_ ? "true" : "false");
3897 dprintf(fd, " Codec extensibility: %s\n",
3898 CodecManager::GetInstance()->IsUsingCodecExtensibility() ? "true"
3899 : "false");
3900 dprintf(fd, " Start time: ");
3901 for (auto t : stream_start_history_queue_) {
3902 dprintf(fd, ", %d ms", static_cast<int>(t));
3903 }
3904 dprintf(fd, "\n");
3905 printCurrentStreamConfiguration(fd);
3906 dprintf(fd, " ----------------\n ");
3907 dprintf(fd, " LE Audio Groups:\n");
3908 aseGroups_.Dump(fd, active_group_id_);
3909 dprintf(fd, "\n Not grouped devices:\n");
3910 leAudioDevices_.Dump(fd, bluetooth::groups::kGroupUnknown);
3911
3912 if (leAudioHealthStatus_) {
3913 leAudioHealthStatus_->DebugDump(fd);
3914 }
3915 }
3916
Cleanup()3917 void Cleanup() {
3918 StopVbcCloseTimeout();
3919 if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
3920
3921 if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
3922 /* Bluetooth turned off while streaming */
3923 StopAudio();
3924 SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink,
3925 false);
3926 ClientAudioInterfaceRelease();
3927 } else {
3928 /* There may be not stopped Sink HAL client due to set Listening mode */
3929 if (sink_monitor_mode_) {
3930 SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink,
3931 false);
3932 }
3933 }
3934 groupStateMachine_->Cleanup();
3935 aseGroups_.Cleanup();
3936 lastNotifiedGroupStreamStatusMap_.clear();
3937 leAudioDevices_.Cleanup(gatt_if_);
3938 if (gatt_if_) BTA_GATTC_AppDeregister(gatt_if_);
3939
3940 if (leAudioHealthStatus_) {
3941 leAudioHealthStatus_->Cleanup();
3942 }
3943 }
3944
UpdateConfigAndCheckIfReconfigurationIsNeeded(LeAudioDeviceGroup * group,LeAudioContextType context_type)3945 AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded(
3946 LeAudioDeviceGroup* group, LeAudioContextType context_type) {
3947 log::debug("Checking whether to reconfigure from {} to {}",
3948 ToString(configuration_context_type_), ToString(context_type));
3949
3950 auto audio_set_conf = group->GetConfiguration(context_type);
3951 if (!audio_set_conf) {
3952 return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
3953 }
3954
3955 if (group->IsGroupConfiguredTo(*audio_set_conf) &&
3956 !DsaReconfigureNeeded(group, context_type)) {
3957 // Assign the new configuration context as it reprents the current
3958 // use case even when it eventually ends up being the exact same
3959 // codec and qos configuration.
3960 if (configuration_context_type_ != context_type) {
3961 configuration_context_type_ = context_type;
3962 group->SetConfigurationContextType(context_type);
3963 }
3964 return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
3965 }
3966
3967 log::info("Session reconfiguration needed group: {} for context type: {}",
3968 group->group_id_, ToHexString(context_type));
3969
3970 configuration_context_type_ = context_type;
3971
3972 // Note: The local sink config is based on remote device's source config
3973 // and vice versa.
3974 current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection(
3975 context_type, bluetooth::le_audio::types::kLeAudioDirectionSource);
3976 current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection(
3977 context_type, bluetooth::le_audio::types::kLeAudioDirectionSink);
3978 return AudioReconfigurationResult::RECONFIGURATION_NEEDED;
3979 }
3980
3981 /* Returns true if stream is started */
OnAudioResume(LeAudioDeviceGroup * group,int local_direction)3982 bool OnAudioResume(LeAudioDeviceGroup* group, int local_direction) {
3983 auto remote_direction =
3984 (local_direction == bluetooth::le_audio::types::kLeAudioDirectionSink
3985 ? bluetooth::le_audio::types::kLeAudioDirectionSource
3986 : bluetooth::le_audio::types::kLeAudioDirectionSink);
3987
3988 auto remote_contexts =
3989 DirectionalRealignMetadataAudioContexts(group, remote_direction);
3990 ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts,
3991 remote_direction);
3992
3993 if (!remote_contexts.sink.any() && !remote_contexts.source.any()) {
3994 log::warn("Requested context type not available on the remote side");
3995
3996 if (com::android::bluetooth::flags::leaudio_no_context_validate_streaming_request() &&
3997 source_monitor_mode_) {
3998 callbacks_->OnUnicastMonitorModeStatus(
3999 bluetooth::le_audio::types::kLeAudioDirectionSource,
4000 UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE);
4001
4002 return false;
4003 }
4004
4005 if (leAudioHealthStatus_) {
4006 leAudioHealthStatus_->AddStatisticForGroup(
4007 group, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE);
4008 }
4009 return false;
4010 }
4011
4012 return GroupStream(active_group_id_, configuration_context_type_,
4013 remote_contexts);
4014 }
4015
OnAudioSuspend()4016 void OnAudioSuspend() {
4017 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4018 log::warn(", there is no longer active group");
4019 return;
4020 }
4021
4022 if (stack_config_get_interface()
4023 ->get_pts_le_audio_disable_ases_before_stopping()) {
4024 log::info("Stream disable_timer_ started");
4025 if (alarm_is_scheduled(disable_timer_)) alarm_cancel(disable_timer_);
4026
4027 alarm_set_on_mloop(
4028 disable_timer_, kAudioDisableTimeoutMs,
4029 [](void* data) {
4030 if (instance) instance->GroupSuspend(PTR_TO_INT(data));
4031 },
4032 INT_TO_PTR(active_group_id_));
4033 }
4034
4035 /* Group should tie in time to get requested status */
4036 uint64_t timeoutMs = kAudioSuspentKeepIsoAliveTimeoutMs;
4037 timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp,
4038 timeoutMs);
4039
4040 if (stack_config_get_interface()
4041 ->get_pts_le_audio_disable_ases_before_stopping()) {
4042 timeoutMs += kAudioDisableTimeoutMs;
4043 }
4044
4045 log::debug("Stream suspend_timeout_ started: {} ms",
4046 static_cast<int>(timeoutMs));
4047 if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
4048
4049 alarm_set_on_mloop(
4050 suspend_timeout_, timeoutMs,
4051 [](void* data) {
4052 if (instance) instance->GroupStop(PTR_TO_INT(data));
4053 },
4054 INT_TO_PTR(active_group_id_));
4055 }
4056
OnLocalAudioSourceSuspend()4057 void OnLocalAudioSourceSuspend() {
4058 log::info(
4059 "active group_id: {}, IN: audio_receiver_state_: {}, "
4060 "audio_sender_state_: {}",
4061 active_group_id_, ToString(audio_receiver_state_),
4062 ToString(audio_sender_state_));
4063 LeAudioLogHistory::Get()->AddLogHistory(
4064 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4065 kLogAfSuspend + "LocalSource",
4066 "r_state: " + ToString(audio_receiver_state_) +
4067 ", s_state: " + ToString(audio_sender_state_));
4068
4069 /* Note: This callback is from audio hal driver.
4070 * Bluetooth peer is a Sink for Audio Framework.
4071 * e.g. Peer is a speaker
4072 */
4073 switch (audio_sender_state_) {
4074 case AudioState::READY_TO_START:
4075 case AudioState::STARTED:
4076 audio_sender_state_ = AudioState::READY_TO_RELEASE;
4077 break;
4078 case AudioState::RELEASING:
4079 return;
4080 case AudioState::IDLE:
4081 if (audio_receiver_state_ == AudioState::READY_TO_RELEASE) {
4082 OnAudioSuspend();
4083 }
4084 return;
4085 case AudioState::READY_TO_RELEASE:
4086 break;
4087 }
4088
4089 /* Last suspends group - triggers group stop */
4090 if ((audio_receiver_state_ == AudioState::IDLE) ||
4091 (audio_receiver_state_ == AudioState::READY_TO_RELEASE)) {
4092 OnAudioSuspend();
4093 bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(
4094 active_group_id_);
4095 }
4096
4097 log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}",
4098 ToString(audio_receiver_state_), ToString(audio_sender_state_));
4099
4100 LeAudioLogHistory::Get()->AddLogHistory(
4101 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4102 kLogAfSuspendConfirm + "LocalSource",
4103 "r_state: " + ToString(audio_receiver_state_) +
4104 "s_state: " + ToString(audio_sender_state_));
4105 }
4106
OnLocalAudioSourceResume()4107 void OnLocalAudioSourceResume() {
4108 log::info(
4109 "active group_id: {}, IN: audio_receiver_state_: {}, "
4110 "audio_sender_state_: {}",
4111 active_group_id_, ToString(audio_receiver_state_),
4112 ToString(audio_sender_state_));
4113 LeAudioLogHistory::Get()->AddLogHistory(
4114 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4115 kLogAfResume + "LocalSource",
4116 "r_state: " + ToString(audio_receiver_state_) +
4117 ", s_state: " + ToString(audio_sender_state_));
4118
4119 /* Note: This callback is from audio hal driver.
4120 * Bluetooth peer is a Sink for Audio Framework.
4121 * e.g. Peer is a speaker
4122 */
4123 auto group = aseGroups_.FindById(active_group_id_);
4124 if (!group) {
4125 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4126 return;
4127 }
4128
4129 /* Check if the device resume is allowed */
4130 if (!group->HasCodecConfigurationForDirection(
4131 configuration_context_type_,
4132 bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4133 log::error("invalid resume request for context type: {}",
4134 ToHexString(configuration_context_type_));
4135 CancelLocalAudioSourceStreamingRequest();
4136 return;
4137 }
4138
4139 if (!group
4140 ->GetAllowedContextMask(
4141 bluetooth::le_audio::types::kLeAudioDirectionSink)
4142 .test(configuration_context_type_)) {
4143 log::warn("Block source resume request context type: {}",
4144 ToHexString(configuration_context_type_));
4145 CancelLocalAudioSourceStreamingRequest();
4146 return;
4147 }
4148
4149 log::debug(
4150 "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4151 "{}\n configuration_context_type_: {}\n group {}\n",
4152 active_group_id_, audio_receiver_state_, audio_sender_state_,
4153 ToHexString(configuration_context_type_),
4154 group ? " exist " : " does not exist ");
4155
4156 switch (audio_sender_state_) {
4157 case AudioState::STARTED:
4158 /* Looks like previous Confirm did not get to the Audio Framework*/
4159 ConfirmLocalAudioSourceStreamingRequest();
4160 break;
4161 case AudioState::IDLE:
4162 switch (audio_receiver_state_) {
4163 case AudioState::IDLE:
4164 /* Stream is not started. Try to do it.*/
4165 if (OnAudioResume(
4166 group,
4167 bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4168 audio_sender_state_ = AudioState::READY_TO_START;
4169 } else {
4170 CancelLocalAudioSourceStreamingRequest();
4171 }
4172 break;
4173 case AudioState::READY_TO_START:
4174 audio_sender_state_ = AudioState::READY_TO_START;
4175 if (!IsDirectionAvailableForCurrentConfiguration(
4176 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4177 log::warn(
4178 "sink is not configured. \n audio_receiver_state: {} "
4179 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4180 "Reconfiguring to {}",
4181 ToString(audio_receiver_state_),
4182 ToString(audio_sender_state_),
4183 group->IsPendingConfiguration(),
4184 ToString(configuration_context_type_));
4185 group->PrintDebugState();
4186 SetConfigurationAndStopStreamWhenNeeded(
4187 group, configuration_context_type_);
4188 }
4189 break;
4190 case AudioState::STARTED:
4191 audio_sender_state_ = AudioState::READY_TO_START;
4192 /* If signalling part is completed trigger start sending audio
4193 * here, otherwise it'll be called on group streaming state callback
4194 */
4195 if (group->GetState() ==
4196 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4197 if (IsDirectionAvailableForCurrentConfiguration(
4198 group,
4199 bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4200 StartSendingAudio(active_group_id_);
4201 } else {
4202 log::warn(
4203 "sink is not configured. \n audio_receiver_state: {} "
4204 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4205 "Reconfiguring to {}",
4206 ToString(audio_receiver_state_),
4207 ToString(audio_sender_state_),
4208 group->IsPendingConfiguration(),
4209 ToString(configuration_context_type_));
4210 group->PrintDebugState();
4211 SetConfigurationAndStopStreamWhenNeeded(
4212 group, configuration_context_type_);
4213 }
4214 } else {
4215 log::error(
4216 "called in wrong state. \n audio_receiver_state: {} "
4217 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4218 "Reconfiguring to {}",
4219 ToString(audio_receiver_state_),
4220 ToString(audio_sender_state_),
4221 group->IsPendingConfiguration(),
4222 ToString(configuration_context_type_));
4223 group->PrintDebugState();
4224 CancelStreamingRequest();
4225 }
4226 break;
4227 case AudioState::RELEASING:
4228 /* Group is reconfiguring, reassing state and wait for
4229 * the stream to be configured
4230 */
4231 audio_sender_state_ = audio_receiver_state_;
4232 break;
4233 case AudioState::READY_TO_RELEASE:
4234 /* If the other direction is streaming we can start sending audio */
4235 if (group->GetState() ==
4236 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4237 if (IsDirectionAvailableForCurrentConfiguration(
4238 group,
4239 bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4240 StartSendingAudio(active_group_id_);
4241 } else {
4242 log::warn(
4243 "sink is not configured. \n audio_receiver_state: {} "
4244 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4245 "Reconfiguring to {}",
4246 ToString(audio_receiver_state_),
4247 ToString(audio_sender_state_),
4248 group->IsPendingConfiguration(),
4249 ToString(configuration_context_type_));
4250 group->PrintDebugState();
4251 SetConfigurationAndStopStreamWhenNeeded(
4252 group, configuration_context_type_);
4253 }
4254 } else {
4255 log::error(
4256 "called in wrong state. \n audio_receiver_state: {} "
4257 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4258 "Reconfiguring to {}",
4259 ToString(audio_receiver_state_),
4260 ToString(audio_sender_state_),
4261 group->IsPendingConfiguration(),
4262 ToString(configuration_context_type_));
4263 group->PrintDebugState();
4264 CancelStreamingRequest();
4265 }
4266 break;
4267 }
4268 break;
4269 case AudioState::READY_TO_START:
4270 log::error(
4271 "called in wrong state, ignoring double start request. \n "
4272 "audio_receiver_state: {} \naudio_sender_state: {} \n "
4273 "isPendingConfiguration: {} \n Reconfiguring to {}",
4274 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4275 group->IsPendingConfiguration(),
4276 ToString(configuration_context_type_));
4277 group->PrintDebugState();
4278 break;
4279 case AudioState::READY_TO_RELEASE:
4280 switch (audio_receiver_state_) {
4281 case AudioState::STARTED:
4282 case AudioState::READY_TO_START:
4283 case AudioState::IDLE:
4284 case AudioState::READY_TO_RELEASE:
4285 /* Stream is up just restore it */
4286 if (alarm_is_scheduled(suspend_timeout_))
4287 alarm_cancel(suspend_timeout_);
4288 ConfirmLocalAudioSourceStreamingRequest();
4289 bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(
4290 active_group_id_, configuration_context_type_);
4291 break;
4292 case AudioState::RELEASING:
4293 /* Keep wainting. After release is done, Audio Hal will be notified
4294 */
4295 break;
4296 }
4297 break;
4298 case AudioState::RELEASING:
4299 /* Keep wainting. After release is done, Audio Hal will be notified */
4300 break;
4301 }
4302 }
4303
OnLocalAudioSinkSuspend()4304 void OnLocalAudioSinkSuspend() {
4305 log::info(
4306 "active group_id: {}, IN: audio_receiver_state_: {}, "
4307 "audio_sender_state_: {}",
4308 active_group_id_, ToString(audio_receiver_state_),
4309 ToString(audio_sender_state_));
4310 LeAudioLogHistory::Get()->AddLogHistory(
4311 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4312 kLogAfSuspend + "LocalSink",
4313 "r_state: " + ToString(audio_receiver_state_) +
4314 ", s_state: " + ToString(audio_sender_state_));
4315
4316 StartVbcCloseTimeout();
4317
4318 /* Note: This callback is from audio hal driver.
4319 * Bluetooth peer is a Source for Audio Framework.
4320 * e.g. Peer is microphone.
4321 */
4322 switch (audio_receiver_state_) {
4323 case AudioState::READY_TO_START:
4324 case AudioState::STARTED:
4325 audio_receiver_state_ = AudioState::READY_TO_RELEASE;
4326 break;
4327 case AudioState::RELEASING:
4328 return;
4329 case AudioState::IDLE:
4330 if (audio_sender_state_ == AudioState::READY_TO_RELEASE) {
4331 OnAudioSuspend();
4332 }
4333 return;
4334 case AudioState::READY_TO_RELEASE:
4335 break;
4336 }
4337
4338 /* Last suspends group - triggers group stop */
4339 if ((audio_sender_state_ == AudioState::IDLE) ||
4340 (audio_sender_state_ == AudioState::READY_TO_RELEASE))
4341 OnAudioSuspend();
4342
4343 log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}",
4344 ToString(audio_receiver_state_), ToString(audio_sender_state_));
4345
4346 LeAudioLogHistory::Get()->AddLogHistory(
4347 kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4348 kLogAfSuspendConfirm + "LocalSink",
4349 "r_state: " + ToString(audio_receiver_state_) +
4350 "s_state: " + ToString(audio_sender_state_));
4351 }
4352
IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup * group,uint8_t direction) const4353 inline bool IsDirectionAvailableForCurrentConfiguration(
4354 const LeAudioDeviceGroup* group, uint8_t direction) const {
4355 auto current_config =
4356 group->GetCachedConfiguration(configuration_context_type_);
4357 if (current_config)
4358 return (current_config->confs.get(direction).size() != 0);
4359 return false;
4360 }
4361
notifyAudioLocalSink(UnicastMonitorModeStatus status)4362 void notifyAudioLocalSink(UnicastMonitorModeStatus status) {
4363 if (sink_monitor_notified_status_ != status) {
4364 log::info("Stream monitoring status changed to: {}",
4365 static_cast<int>(status));
4366 sink_monitor_notified_status_ = status;
4367 callbacks_->OnUnicastMonitorModeStatus(
4368 bluetooth::le_audio::types::kLeAudioDirectionSink, status);
4369 }
4370 }
4371
OnLocalAudioSinkResume()4372 void OnLocalAudioSinkResume() {
4373 log::info(
4374 "active group_id: {} IN: audio_receiver_state_: {}, "
4375 "audio_sender_state_: {}",
4376 active_group_id_, ToString(audio_receiver_state_),
4377 ToString(audio_sender_state_));
4378 LeAudioLogHistory::Get()->AddLogHistory(
4379 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4380 kLogAfResume + "LocalSink",
4381 "r_state: " + ToString(audio_receiver_state_) +
4382 ", s_state: " + ToString(audio_sender_state_));
4383
4384 if (sink_monitor_mode_ &&
4385 active_group_id_ == bluetooth::groups::kGroupUnknown) {
4386 if (sink_monitor_notified_status_ !=
4387 UnicastMonitorModeStatus::STREAMING_REQUESTED) {
4388 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_REQUESTED);
4389 }
4390 CancelLocalAudioSinkStreamingRequest();
4391 return;
4392 }
4393
4394 /* Stop the VBC close watchdog if needed */
4395 StopVbcCloseTimeout();
4396
4397 /* Note: This callback is from audio hal driver.
4398 * Bluetooth peer is a Source for Audio Framework.
4399 * e.g. Peer is microphone.
4400 */
4401 auto group = aseGroups_.FindById(active_group_id_);
4402 if (!group) {
4403 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4404 return;
4405 }
4406
4407 /* We need new configuration_context_type_ to be selected before we go any
4408 * further.
4409 */
4410 if (audio_receiver_state_ == AudioState::IDLE) {
4411 ReconfigureOrUpdateRemote(
4412 group, bluetooth::le_audio::types::kLeAudioDirectionSource);
4413 }
4414
4415 /* Check if the device resume is allowed */
4416 if (!group->HasCodecConfigurationForDirection(
4417 configuration_context_type_,
4418 bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4419 log::error("invalid resume request for context type: {}",
4420 ToHexString(configuration_context_type_));
4421 CancelLocalAudioSinkStreamingRequest();
4422 return;
4423 }
4424
4425 if (!group
4426 ->GetAllowedContextMask(
4427 bluetooth::le_audio::types::kLeAudioDirectionSource)
4428 .test(configuration_context_type_)) {
4429 log::warn("Block sink resume request context type: {}",
4430 ToHexString(configuration_context_type_));
4431 CancelLocalAudioSourceStreamingRequest();
4432 return;
4433 }
4434
4435 log::debug(
4436 "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4437 "{}\n configuration_context_type_: {}\n group {}\n",
4438 active_group_id_, audio_receiver_state_, audio_sender_state_,
4439 ToHexString(configuration_context_type_),
4440 group ? " exist " : " does not exist ");
4441
4442 switch (audio_receiver_state_) {
4443 case AudioState::STARTED:
4444 ConfirmLocalAudioSinkStreamingRequest();
4445 break;
4446 case AudioState::IDLE:
4447 switch (audio_sender_state_) {
4448 case AudioState::IDLE:
4449 if (OnAudioResume(
4450 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4451 audio_receiver_state_ = AudioState::READY_TO_START;
4452 } else {
4453 CancelLocalAudioSinkStreamingRequest();
4454 }
4455 break;
4456 case AudioState::READY_TO_START:
4457 audio_receiver_state_ = AudioState::READY_TO_START;
4458 if (!IsDirectionAvailableForCurrentConfiguration(
4459 group,
4460 bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4461 log::warn(
4462 "source is not configured. \n audio_receiver_state: {} "
4463 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4464 "Reconfiguring to {}",
4465 ToString(audio_receiver_state_),
4466 ToString(audio_sender_state_),
4467 group->IsPendingConfiguration(),
4468 ToString(configuration_context_type_));
4469 group->PrintDebugState();
4470 SetConfigurationAndStopStreamWhenNeeded(
4471 group, configuration_context_type_);
4472 }
4473 break;
4474 case AudioState::STARTED:
4475 audio_receiver_state_ = AudioState::READY_TO_START;
4476 /* If signalling part is completed trigger start receiving audio
4477 * here, otherwise it'll be called on group streaming state callback
4478 */
4479 if (group->GetState() ==
4480 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4481 if (IsDirectionAvailableForCurrentConfiguration(
4482 group,
4483 bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4484 StartReceivingAudio(active_group_id_);
4485 } else {
4486 log::warn(
4487 "source is not configured. \n audio_receiver_state: {} "
4488 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4489 "Reconfiguring to {}",
4490 ToString(audio_receiver_state_),
4491 ToString(audio_sender_state_),
4492 group->IsPendingConfiguration(),
4493 ToString(configuration_context_type_));
4494 group->PrintDebugState();
4495 SetConfigurationAndStopStreamWhenNeeded(
4496 group, configuration_context_type_);
4497 }
4498 } else {
4499 log::error(
4500 "called in wrong state. \n audio_receiver_state: {} "
4501 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4502 "Reconfiguring to {}",
4503 ToString(audio_receiver_state_),
4504 ToString(audio_sender_state_),
4505 group->IsPendingConfiguration(),
4506 ToString(configuration_context_type_));
4507 group->PrintDebugState();
4508 CancelStreamingRequest();
4509 }
4510 break;
4511 case AudioState::RELEASING:
4512 /* Group is reconfiguring, reassing state and wait for
4513 * the stream to be configured
4514 */
4515 audio_receiver_state_ = audio_sender_state_;
4516 break;
4517 case AudioState::READY_TO_RELEASE:
4518 /* If the other direction is streaming we can start receiving audio
4519 */
4520 if (group->GetState() ==
4521 AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4522 if (IsDirectionAvailableForCurrentConfiguration(
4523 group,
4524 bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4525 StartReceivingAudio(active_group_id_);
4526 } else {
4527 log::warn(
4528 "source is not configured. \n audio_receiver_state: {} "
4529 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4530 "Reconfiguring to {}",
4531 ToString(audio_receiver_state_),
4532 ToString(audio_sender_state_),
4533 group->IsPendingConfiguration(),
4534 ToString(configuration_context_type_));
4535 group->PrintDebugState();
4536 SetConfigurationAndStopStreamWhenNeeded(
4537 group, configuration_context_type_);
4538 }
4539 } else {
4540 log::error(
4541 "called in wrong state. \n audio_receiver_state: {} "
4542 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4543 "Reconfiguring to {}",
4544 ToString(audio_receiver_state_),
4545 ToString(audio_sender_state_),
4546 group->IsPendingConfiguration(),
4547 ToString(configuration_context_type_));
4548 group->PrintDebugState();
4549 CancelStreamingRequest();
4550 }
4551 break;
4552 }
4553 break;
4554 case AudioState::READY_TO_START:
4555 log::error(
4556 "Double resume request, just ignore it.. \n audio_receiver_state: "
4557 "{} \naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4558 "Reconfiguring to {}",
4559 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4560 group->IsPendingConfiguration(),
4561 ToString(configuration_context_type_));
4562 group->PrintDebugState();
4563 break;
4564 case AudioState::READY_TO_RELEASE:
4565 switch (audio_sender_state_) {
4566 case AudioState::STARTED:
4567 case AudioState::IDLE:
4568 case AudioState::READY_TO_START:
4569 case AudioState::READY_TO_RELEASE:
4570 /* Stream is up just restore it */
4571 if (alarm_is_scheduled(suspend_timeout_))
4572 alarm_cancel(suspend_timeout_);
4573 ConfirmLocalAudioSinkStreamingRequest();
4574 break;
4575 case AudioState::RELEASING:
4576 /* Wait until releasing is completed */
4577 break;
4578 }
4579
4580 break;
4581 case AudioState::RELEASING:
4582 /* Wait until releasing is completed */
4583 break;
4584 }
4585 }
4586
4587 /* Chooses a single context type to use as a key for selecting a single
4588 * audio set configuration. Contexts used for the metadata can be different
4589 * than this, but it's reasonable to select a configuration context from
4590 * the metadata context types.
4591 */
ChooseConfigurationContextType(AudioContexts available_remote_contexts)4592 LeAudioContextType ChooseConfigurationContextType(
4593 AudioContexts available_remote_contexts) {
4594 log::debug("Got contexts={} in config_context={}",
4595 bluetooth::common::ToString(available_remote_contexts),
4596 bluetooth::common::ToString(configuration_context_type_));
4597
4598 if (IsInCall()) {
4599 log::debug("In Call preference used.");
4600 return LeAudioContextType::CONVERSATIONAL;
4601 }
4602
4603 /* Mini policy - always prioritize sink+source configurations so that we are
4604 * sure that for a mixed content we enable all the needed directions.
4605 */
4606 if (available_remote_contexts.any()) {
4607 LeAudioContextType context_priority_list[] = {
4608 /* Highest priority first */
4609 LeAudioContextType::CONVERSATIONAL,
4610 /* Handling RINGTONE will cause the ringtone volume slider to trigger
4611 * reconfiguration. This will be fixed in b/283349711.
4612 */
4613 LeAudioContextType::RINGTONE,
4614 LeAudioContextType::LIVE,
4615 LeAudioContextType::VOICEASSISTANTS,
4616 LeAudioContextType::GAME,
4617 LeAudioContextType::MEDIA,
4618 LeAudioContextType::EMERGENCYALARM,
4619 LeAudioContextType::ALERTS,
4620 LeAudioContextType::INSTRUCTIONAL,
4621 LeAudioContextType::NOTIFICATIONS,
4622 LeAudioContextType::SOUNDEFFECTS,
4623 };
4624 for (auto ct : context_priority_list) {
4625 if (available_remote_contexts.test(ct)) {
4626 log::debug("Selecting configuration context type: {}", ToString(ct));
4627 return ct;
4628 }
4629 }
4630 }
4631
4632 /* Use BAP mandated UNSPECIFIED only if we don't have any other valid
4633 * configuration
4634 */
4635 auto fallback_config = LeAudioContextType::UNSPECIFIED;
4636 if (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) {
4637 fallback_config = configuration_context_type_;
4638 }
4639
4640 log::debug("Selecting configuration context type: {}",
4641 ToString(fallback_config));
4642 return fallback_config;
4643 }
4644
SetConfigurationAndStopStreamWhenNeeded(LeAudioDeviceGroup * group,LeAudioContextType new_context_type)4645 bool SetConfigurationAndStopStreamWhenNeeded(
4646 LeAudioDeviceGroup* group, LeAudioContextType new_context_type) {
4647 auto reconfig_result =
4648 UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type);
4649 /* Even though the reconfiguration may not be needed, this has
4650 * to be set here as it might be the initial configuration.
4651 */
4652 configuration_context_type_ = new_context_type;
4653
4654 log::info("group_id {}, context type {} ({}), {}", group->group_id_,
4655 ToString(new_context_type), ToHexString(new_context_type),
4656 ToString(reconfig_result));
4657 if (reconfig_result ==
4658 AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED) {
4659 return false;
4660 }
4661
4662 if (reconfig_result ==
4663 AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE) {
4664 return false;
4665 }
4666
4667 if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4668 log::debug("Group is not streaming");
4669 return false;
4670 }
4671
4672 if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
4673
4674 /* Need to reconfigure stream */
4675 group->SetPendingConfiguration();
4676 groupStateMachine_->StopStream(group);
4677 return true;
4678 }
4679
OnLocalAudioSourceMetadataUpdate(const std::vector<struct playback_track_metadata_v7> & source_metadata,DsaMode dsa_mode)4680 void OnLocalAudioSourceMetadataUpdate(
4681 const std::vector<struct playback_track_metadata_v7>& source_metadata,
4682 DsaMode dsa_mode) {
4683 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4684 log::warn(", cannot start streaming if no active group set");
4685 return;
4686 }
4687
4688 auto group = aseGroups_.FindById(active_group_id_);
4689 if (!group) {
4690 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4691 return;
4692 }
4693
4694 /* Stop the VBC close timeout timer, since we will reconfigure anyway if the
4695 * VBC was suspended.
4696 */
4697 StopVbcCloseTimeout();
4698
4699 log::info(
4700 "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
4701 "audio_sender_state_: {}, dsa_mode: {}",
4702 group->group_id_, ToString(group->GetState()),
4703 ToString(group->GetTargetState()), ToString(audio_receiver_state_),
4704 ToString(audio_sender_state_), static_cast<int>(dsa_mode));
4705
4706 group->dsa_.mode = dsa_mode;
4707
4708 /* Set the remote sink metadata context from the playback tracks metadata */
4709 local_metadata_context_types_.source =
4710 GetAudioContextsFromSourceMetadata(source_metadata);
4711
4712 local_metadata_context_types_.sink =
4713 ChooseMetadataContextType(local_metadata_context_types_.sink);
4714 local_metadata_context_types_.source =
4715 ChooseMetadataContextType(local_metadata_context_types_.source);
4716
4717 ReconfigureOrUpdateRemote(
4718 group, bluetooth::le_audio::types::kLeAudioDirectionSink);
4719 }
4720
4721 /* Applies some predefined policy on the audio context metadata, including
4722 * special handling of UNSPECIFIED context, which also involves checking
4723 * context support and availability.
4724 */
ApplyRemoteMetadataAudioContextPolicy(LeAudioDeviceGroup * group,BidirectionalPair<AudioContexts> & contexts_pair,int remote_dir)4725 void ApplyRemoteMetadataAudioContextPolicy(
4726 LeAudioDeviceGroup* group,
4727 BidirectionalPair<AudioContexts>& contexts_pair, int remote_dir) {
4728 // We expect at least some context when this direction gets enabled
4729 if (contexts_pair.get(remote_dir).none()) {
4730 log::warn(
4731 "invalid/unknown {} context metadata, using 'UNSPECIFIED' instead",
4732 (remote_dir == bluetooth::le_audio::types::kLeAudioDirectionSink)
4733 ? "sink"
4734 : "source");
4735 contexts_pair.get(remote_dir) =
4736 AudioContexts(LeAudioContextType::UNSPECIFIED);
4737 }
4738
4739 std::tuple<int, int, AudioState*> remote_directions[] = {
4740 {bluetooth::le_audio::types::kLeAudioDirectionSink,
4741 bluetooth::le_audio::types::kLeAudioDirectionSource,
4742 &audio_sender_state_},
4743 {bluetooth::le_audio::types::kLeAudioDirectionSource,
4744 bluetooth::le_audio::types::kLeAudioDirectionSink,
4745 &audio_receiver_state_},
4746 };
4747
4748 /* Align with the context availability */
4749 for (auto entry : remote_directions) {
4750 int dir, other_dir;
4751 AudioState* local_hal_state;
4752 std::tie(dir, other_dir, local_hal_state) = entry;
4753
4754 /* When a certain context became unavailable while it was already in
4755 * an active stream, it means that it is unavailable to other clients
4756 * but we can keep using it.
4757 */
4758 auto group_available_contexts = group->GetAvailableContexts(dir);
4759 if ((*local_hal_state == AudioState::STARTED) ||
4760 (*local_hal_state == AudioState::READY_TO_START)) {
4761 group_available_contexts |= group->GetMetadataContexts().get(dir);
4762 }
4763
4764 log::debug("Checking contexts: {}, against the available contexts: {}",
4765 ToString(contexts_pair.get(dir)),
4766 ToString(group_available_contexts));
4767 auto unavail_contexts =
4768 contexts_pair.get(dir) & ~group_available_contexts;
4769 if (unavail_contexts.none()) continue;
4770
4771 contexts_pair.get(dir) &= group_available_contexts;
4772 auto unavail_but_supported =
4773 (unavail_contexts & group->GetSupportedContexts(dir));
4774 if (unavail_but_supported.none() &&
4775 group_available_contexts.test(LeAudioContextType::UNSPECIFIED)) {
4776 log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED",
4777 ToString(unavail_contexts));
4778 /* All unavailable are also unsupported - replace with UNSPECIFIED if
4779 * available
4780 */
4781 contexts_pair.get(dir).set(LeAudioContextType::UNSPECIFIED);
4782 } else {
4783 log::debug("Some contexts are supported but currently unavailable: {}!",
4784 ToString(unavail_but_supported));
4785 /* Some of the streamed contexts are support but not available and they
4786 * were erased from the metadata.
4787 * TODO: Either filter out these contexts from the stream or do not
4788 * stream at all if the unavail_but_supported contexts are the only
4789 * streamed contexts.
4790 */
4791 }
4792 }
4793
4794 /* Don't mix UNSPECIFIED with any other context
4795 * Note: This has to be in a separate loop - do not merge it with the above.
4796 */
4797 for (auto entry : remote_directions) {
4798 int dir, other_dir;
4799 AudioState* local_hal_state;
4800 std::tie(dir, other_dir, local_hal_state) = entry;
4801
4802 if (contexts_pair.get(dir).test(LeAudioContextType::UNSPECIFIED)) {
4803 /* Try to use the other direction context if not UNSPECIFIED and active
4804 */
4805 if (contexts_pair.get(dir) ==
4806 AudioContexts(LeAudioContextType::UNSPECIFIED)) {
4807 auto is_other_direction_streaming =
4808 (*local_hal_state == AudioState::STARTED) ||
4809 (*local_hal_state == AudioState::READY_TO_START);
4810 if (is_other_direction_streaming &&
4811 (contexts_pair.get(other_dir) !=
4812 AudioContexts(LeAudioContextType::UNSPECIFIED))) {
4813 log::info(
4814 "Other direction is streaming. Aligning other direction "
4815 "metadata to match the current direciton context: {}",
4816 ToString(contexts_pair.get(other_dir)));
4817 contexts_pair.get(dir) = contexts_pair.get(other_dir);
4818 }
4819 } else {
4820 log::debug("Removing UNSPECIFIED from the remote sink context: {}",
4821 ToString(contexts_pair.get(other_dir)));
4822 contexts_pair.get(dir).unset(LeAudioContextType::UNSPECIFIED);
4823 }
4824 }
4825 }
4826
4827 contexts_pair.sink = ChooseMetadataContextType(contexts_pair.sink);
4828 contexts_pair.source = ChooseMetadataContextType(contexts_pair.source);
4829
4830 log::debug("Aligned remote metadata audio context: sink={}, source={}",
4831 ToString(contexts_pair.sink), ToString(contexts_pair.source));
4832 }
4833
OnLocalAudioSinkMetadataUpdate(const std::vector<record_track_metadata_v7> & sink_metadata)4834 void OnLocalAudioSinkMetadataUpdate(
4835 const std::vector<record_track_metadata_v7>& sink_metadata) {
4836 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4837 log::warn(", cannot start streaming if no active group set");
4838 return;
4839 }
4840
4841 auto group = aseGroups_.FindById(active_group_id_);
4842 if (!group) {
4843 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4844 return;
4845 }
4846
4847 log::info(
4848 "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
4849 "audio_sender_state_: {}",
4850 group->group_id_, ToString(group->GetState()),
4851 ToString(group->GetTargetState()), ToString(audio_receiver_state_),
4852 ToString(audio_sender_state_));
4853
4854 /* Set remote source metadata context from the recording tracks metadata */
4855 local_metadata_context_types_.sink =
4856 GetAudioContextsFromSinkMetadata(sink_metadata);
4857
4858 local_metadata_context_types_.sink =
4859 ChooseMetadataContextType(local_metadata_context_types_.sink);
4860 local_metadata_context_types_.source =
4861 ChooseMetadataContextType(local_metadata_context_types_.source);
4862
4863 /* Reconfigure or update only if the stream is already started
4864 * otherwise wait for the local sink to resume.
4865 */
4866 if (audio_receiver_state_ == AudioState::STARTED) {
4867 ReconfigureOrUpdateRemote(
4868 group, bluetooth::le_audio::types::kLeAudioDirectionSource);
4869 }
4870 }
4871
DirectionalRealignMetadataAudioContexts(LeAudioDeviceGroup * group,int remote_direction)4872 BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
4873 LeAudioDeviceGroup* group, int remote_direction) {
4874 auto remote_other_direction =
4875 (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink
4876 ? bluetooth::le_audio::types::kLeAudioDirectionSource
4877 : bluetooth::le_audio::types::kLeAudioDirectionSink);
4878 auto other_direction_hal =
4879 (remote_other_direction ==
4880 bluetooth::le_audio::types::kLeAudioDirectionSource
4881 ? audio_receiver_state_
4882 : audio_sender_state_);
4883 auto is_streaming_other_direction =
4884 (other_direction_hal == AudioState::STARTED) ||
4885 (other_direction_hal == AudioState::READY_TO_START);
4886 auto is_releasing_for_reconfiguration =
4887 (((audio_receiver_state_ == AudioState::RELEASING) ||
4888 (audio_sender_state_ == AudioState::RELEASING)) &&
4889 group->IsPendingConfiguration() &&
4890 IsDirectionAvailableForCurrentConfiguration(group,
4891 remote_other_direction));
4892
4893 // Inject conversational when ringtone is played - this is required for all
4894 // the VoIP applications which are not using the telecom API.
4895 constexpr AudioContexts possible_voip_contexts =
4896 LeAudioContextType::RINGTONE | LeAudioContextType::CONVERSATIONAL;
4897 if (local_metadata_context_types_.source.test_any(possible_voip_contexts) &&
4898 ((remote_direction ==
4899 bluetooth::le_audio::types::kLeAudioDirectionSink) ||
4900 (remote_direction ==
4901 bluetooth::le_audio::types::kLeAudioDirectionSource &&
4902 is_streaming_other_direction))) {
4903 /* Simulate, we are already in the call. Sending RINGTONE when there is
4904 * no incoming call to accept or reject on TBS could confuse the remote
4905 * device and interrupt the stream establish procedure.
4906 */
4907 if (!IsInCall()) {
4908 SetInVoipCall(true);
4909 }
4910 } else if (IsInVoipCall()) {
4911 SetInVoipCall(false);
4912 }
4913
4914 /* Make sure we have CONVERSATIONAL when in a call and it is not mixed
4915 * with any other bidirectional context
4916 */
4917 if (IsInCall() || IsInVoipCall()) {
4918 log::debug("In Call preference used: {}, voip call: {}", IsInCall(),
4919 IsInVoipCall());
4920 local_metadata_context_types_.sink.unset_all(kLeAudioContextAllBidir);
4921 local_metadata_context_types_.source.unset_all(kLeAudioContextAllBidir);
4922 local_metadata_context_types_.sink.set(
4923 LeAudioContextType::CONVERSATIONAL);
4924 local_metadata_context_types_.source.set(
4925 LeAudioContextType::CONVERSATIONAL);
4926 }
4927
4928 BidirectionalPair<AudioContexts> remote_metadata = {
4929 .sink = local_metadata_context_types_.source,
4930 .source = local_metadata_context_types_.sink};
4931
4932 if (IsInVoipCall()) {
4933 log::debug("Unsetting RINGTONE from remote sink");
4934 remote_metadata.sink.unset(LeAudioContextType::RINGTONE);
4935 }
4936
4937 auto is_ongoing_call_on_other_direction =
4938 is_streaming_other_direction && (IsInVoipCall() || IsInCall());
4939
4940 log::debug("local_metadata_context_types_.source= {}",
4941 ToString(local_metadata_context_types_.source));
4942 log::debug("local_metadata_context_types_.sink= {}",
4943 ToString(local_metadata_context_types_.sink));
4944 log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
4945 log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
4946 log::debug(
4947 "remote_direction= {}",
4948 (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource
4949 ? "Source"
4950 : "Sink"));
4951 log::debug("is_streaming_other_direction= {}",
4952 is_streaming_other_direction ? "True" : "False");
4953 log::debug("is_releasing_for_reconfiguration= {}",
4954 is_releasing_for_reconfiguration ? "True" : "False");
4955 log::debug("is_ongoing_call_on_other_direction={}",
4956 is_ongoing_call_on_other_direction ? "True" : "False");
4957
4958 if (remote_metadata.get(remote_other_direction)
4959 .test_any(kLeAudioContextAllBidir) &&
4960 !is_streaming_other_direction) {
4961 log::debug(
4962 "The other direction is not streaming bidirectional, ignore that "
4963 "context.");
4964 remote_metadata.get(remote_other_direction).clear();
4965 }
4966
4967 /* Mixed contexts in the voiceback channel scenarios can confuse the remote
4968 * on how to configure each channel. We should align the other direction
4969 * metadata for the remote device.
4970 */
4971 if (remote_metadata.get(remote_direction)
4972 .test_any(kLeAudioContextAllBidir)) {
4973 log::debug(
4974 "Aligning the other direction remote metadata to add this direction "
4975 "context");
4976
4977 if (is_ongoing_call_on_other_direction) {
4978 /* Other direction is streaming and is in call */
4979 remote_metadata.get(remote_direction)
4980 .unset_all(kLeAudioContextAllBidir);
4981 remote_metadata.get(remote_direction)
4982 .set(LeAudioContextType::CONVERSATIONAL);
4983 } else {
4984 if (!is_streaming_other_direction) {
4985 // Do not take the obsolete metadata
4986 remote_metadata.get(remote_other_direction).clear();
4987 }
4988 remote_metadata.get(remote_other_direction)
4989 .unset_all(kLeAudioContextAllBidir);
4990 remote_metadata.get(remote_other_direction)
4991 .unset_all(kLeAudioContextAllRemoteSinkOnly);
4992 remote_metadata.get(remote_other_direction)
4993 .set_all(remote_metadata.get(remote_direction) &
4994 ~kLeAudioContextAllRemoteSinkOnly);
4995 }
4996 }
4997 log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
4998 log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
4999
5000 if (is_releasing_for_reconfiguration || is_streaming_other_direction) {
5001 log::debug("Other direction is streaming. Taking its contexts {}",
5002 ToString(remote_metadata.get(remote_other_direction)));
5003 /* If current direction has no valid context or the other direction is
5004 * bidirectional scenario, take the other direction context as well
5005 */
5006 if ((remote_metadata.get(remote_direction).none() &&
5007 remote_metadata.get(remote_other_direction).any()) ||
5008 remote_metadata.get(remote_other_direction)
5009 .test_any(kLeAudioContextAllBidir)) {
5010 log::debug(
5011 "Aligning this direction remote metadata to add the other "
5012 "direction context");
5013 /* Turn off bidirectional contexts on this direction to avoid mixing
5014 * with the other direction bidirectional context
5015 */
5016 remote_metadata.get(remote_direction)
5017 .unset_all(kLeAudioContextAllBidir);
5018 remote_metadata.get(remote_direction)
5019 .set_all(remote_metadata.get(remote_other_direction));
5020 }
5021 }
5022
5023 /* Make sure that after alignment no sink only context leaks into the other
5024 * direction. */
5025 remote_metadata.source.unset_all(kLeAudioContextAllRemoteSinkOnly);
5026
5027 log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
5028 log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
5029 return remote_metadata;
5030 }
5031
AdjustForVoiceAssistant(LeAudioDeviceGroup * group,LeAudioContextType new_configuration_context)5032 LeAudioContextType AdjustForVoiceAssistant(
5033 LeAudioDeviceGroup* group, LeAudioContextType new_configuration_context) {
5034 if (!com::android::bluetooth::flags::
5035 le_audio_support_unidirectional_voice_assistant()) {
5036 log::debug(
5037 "Flag le_audio_support_unidirectional_voice_assistant NOT enabled");
5038 return new_configuration_context;
5039 }
5040
5041 /* Some remote devices expect VOICE ASSISTANT to be unidirectional Phone is
5042 * Source and Earbuds are Sink */
5043 if (new_configuration_context != LeAudioContextType::VOICEASSISTANTS) {
5044 return new_configuration_context;
5045 }
5046
5047 auto sink_supported_contexts = group->GetSupportedContexts(
5048 bluetooth::le_audio::types::kLeAudioDirectionSink);
5049 auto source_supported_contexts = group->GetSupportedContexts(
5050 bluetooth::le_audio::types::kLeAudioDirectionSource);
5051
5052 log::debug("group_id: {}, sink_supported: {}, source_supported {}",
5053 group->group_id_, ToString(sink_supported_contexts),
5054 ToString(source_supported_contexts));
5055 if (sink_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS) &&
5056 source_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS)) {
5057 return new_configuration_context;
5058 }
5059
5060 if (sink_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS)) {
5061 log::info(
5062 "group_id {} supports only Sink direction for Voice Assistant. "
5063 "Selecting configurarion context type {}",
5064 group->group_id_, ToString(LeAudioContextType::INSTRUCTIONAL));
5065
5066 return LeAudioContextType::INSTRUCTIONAL;
5067 }
5068
5069 log::warn(
5070 "group_id: {}, unexpected configuration, sink_supported: {}, "
5071 "source_supported {}",
5072 group->group_id_, ToString(sink_supported_contexts),
5073 ToString(source_supported_contexts));
5074 return new_configuration_context;
5075 }
5076
5077 /* Return true if stream is started */
ReconfigureOrUpdateRemote(LeAudioDeviceGroup * group,int remote_direction)5078 bool ReconfigureOrUpdateRemote(LeAudioDeviceGroup* group,
5079 int remote_direction) {
5080 if (stack_config_get_interface()
5081 ->get_pts_force_le_audio_multiple_contexts_metadata()) {
5082 // Use common audio stream contexts exposed by the PTS
5083 auto override_contexts = AudioContexts(0xFFFF);
5084 for (auto device = group->GetFirstDevice(); device != nullptr;
5085 device = group->GetNextDevice(device)) {
5086 override_contexts &= device->GetAvailableContexts();
5087 }
5088 if (override_contexts.value() == 0xFFFF) {
5089 override_contexts = AudioContexts(LeAudioContextType::UNSPECIFIED);
5090 }
5091 log::warn("Overriding local_metadata_context_types_: {} with: {}",
5092 local_metadata_context_types_.source.to_string(),
5093 override_contexts.to_string());
5094
5095 /* Choose the right configuration context */
5096 auto new_configuration_context = AdjustForVoiceAssistant(
5097 group, ChooseConfigurationContextType(override_contexts));
5098
5099 log::debug("new_configuration_context= {}.",
5100 ToString(new_configuration_context));
5101 BidirectionalPair<AudioContexts> remote_contexts = {
5102 .sink = override_contexts, .source = override_contexts};
5103 return GroupStream(active_group_id_, new_configuration_context,
5104 remote_contexts);
5105 }
5106
5107 /* When the local sink and source update their metadata, we need to come up
5108 * with a coherent set of contexts for either one or both directions,
5109 * especially when bidirectional scenarios can be triggered be either sink
5110 * or source metadata update event.
5111 */
5112 auto remote_metadata =
5113 DirectionalRealignMetadataAudioContexts(group, remote_direction);
5114
5115 /* Choose the right configuration context */
5116 auto config_context_candids = get_bidirectional(remote_metadata);
5117 auto new_config_context = AdjustForVoiceAssistant(
5118 group, ChooseConfigurationContextType(config_context_candids));
5119 log::debug("config_context_candids= {}, new_config_context= {}",
5120 ToString(config_context_candids), ToString(new_config_context));
5121
5122 /* For the following contexts we don't actually need HQ audio:
5123 * LeAudioContextType::NOTIFICATIONS
5124 * LeAudioContextType::SOUNDEFFECTS
5125 * LeAudioContextType::INSTRUCTIONAL
5126 * LeAudioContextType::ALERTS
5127 * LeAudioContextType::EMERGENCYALARM
5128 * LeAudioContextType::UNSPECIFIED
5129 * So do not reconfigure if the remote sink is already available at any
5130 * quality and these are the only contributors to the current audio stream.
5131 */
5132 auto no_reconfigure_contexts =
5133 LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
5134 LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
5135 LeAudioContextType::EMERGENCYALARM | LeAudioContextType::UNSPECIFIED;
5136 if (group->IsStreaming() && config_context_candids.any() &&
5137 (config_context_candids & ~no_reconfigure_contexts).none() &&
5138 (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) &&
5139 (configuration_context_type_ != LeAudioContextType::UNSPECIFIED) &&
5140 IsDirectionAvailableForCurrentConfiguration(
5141 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
5142 log::info(
5143 "There is no need to reconfigure for the sonification events, "
5144 "staying with the existing configuration context of {}",
5145 ToString(configuration_context_type_));
5146 new_config_context = configuration_context_type_;
5147 }
5148
5149 /* Do not configure the Voiceback channel if it is already configured.
5150 * WARNING: This eliminates additional reconfigurations but can
5151 * lead to unsatisfying audio quality when that direction was
5152 * already configured with a lower quality.
5153 */
5154 if (remote_direction ==
5155 bluetooth::le_audio::types::kLeAudioDirectionSource) {
5156 const auto has_audio_source_configured =
5157 IsDirectionAvailableForCurrentConfiguration(
5158 group, bluetooth::le_audio::types::kLeAudioDirectionSource) &&
5159 (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5160 if (has_audio_source_configured) {
5161 log::info(
5162 "Audio source is already available in the current configuration "
5163 "context in {}. Not switching to {} right now.",
5164 ToString(configuration_context_type_),
5165 ToString(new_config_context));
5166 new_config_context = configuration_context_type_;
5167 }
5168 }
5169
5170 /* Note that the remote device metadata was so far unfiltered when it comes
5171 * to group context availability, or multiple contexts support flag, so that
5172 * we could choose the correct configuration for the use case. Now we can
5173 * align it to meet the metadata usage.
5174 */
5175 ApplyRemoteMetadataAudioContextPolicy(group, remote_metadata,
5176 remote_direction);
5177 return ReconfigureOrUpdateMetadata(group, new_config_context,
5178 remote_metadata);
5179 }
5180
DsaReconfigureNeeded(LeAudioDeviceGroup * group,LeAudioContextType context)5181 bool DsaReconfigureNeeded(LeAudioDeviceGroup* group,
5182 LeAudioContextType context) {
5183 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
5184 return false;
5185 }
5186
5187 // Reconfigure if DSA mode changed for media streaming
5188 if (context != bluetooth::le_audio::types::LeAudioContextType::MEDIA) {
5189 return false;
5190 }
5191
5192 if (group->dsa_.mode != DsaMode::ISO_SW &&
5193 group->dsa_.mode != DsaMode::ISO_HW) {
5194 return false;
5195 }
5196
5197 if (group->dsa_.active) {
5198 return false;
5199 }
5200
5201 log::info("DSA mode {} requested but not active", group->dsa_.mode);
5202 return true;
5203 }
5204
5205 /* Return true if stream is started */
ReconfigureOrUpdateMetadata(LeAudioDeviceGroup * group,LeAudioContextType new_configuration_context,BidirectionalPair<AudioContexts> remote_contexts)5206 bool ReconfigureOrUpdateMetadata(
5207 LeAudioDeviceGroup* group, LeAudioContextType new_configuration_context,
5208 BidirectionalPair<AudioContexts> remote_contexts) {
5209 if (new_configuration_context != configuration_context_type_ ||
5210 DsaReconfigureNeeded(group, new_configuration_context)) {
5211 log::info(
5212 "Checking whether to change configuration context from {} to {}",
5213 ToString(configuration_context_type_),
5214 ToString(new_configuration_context));
5215
5216 LeAudioLogHistory::Get()->AddLogHistory(
5217 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5218 kLogAfMetadataUpdate + "Reconfigure",
5219 ToString(configuration_context_type_) + "->" +
5220 ToString(new_configuration_context));
5221 auto is_stopping = SetConfigurationAndStopStreamWhenNeeded(
5222 group, new_configuration_context);
5223 if (is_stopping) {
5224 return false;
5225 }
5226 }
5227
5228 if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
5229 log::info(
5230 "The {} configuration did not change. Updating the metadata to "
5231 "sink={}, source={}",
5232 ToString(configuration_context_type_), ToString(remote_contexts.sink),
5233 ToString(remote_contexts.source));
5234
5235 LeAudioLogHistory::Get()->AddLogHistory(
5236 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5237 kLogAfMetadataUpdate + "Updating...",
5238 "Sink: " + ToString(remote_contexts.sink) +
5239 "Source: " + ToString(remote_contexts.source));
5240
5241 return GroupStream(group->group_id_, configuration_context_type_,
5242 remote_contexts);
5243 }
5244 return false;
5245 }
5246
OnGattCtpCccReadRspStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t hdl,uint16_t len,uint8_t * value,void * data)5247 static void OnGattCtpCccReadRspStatic(uint16_t conn_id, tGATT_STATUS status,
5248 uint16_t hdl, uint16_t len,
5249 uint8_t* value, void* data) {
5250 if (!instance) return;
5251
5252 log::debug("conn_id: 0x{:04x}, status: 0x{:02x}", conn_id, status);
5253
5254 LeAudioDevice* leAudioDevice =
5255 instance->leAudioDevices_.FindByConnId(conn_id);
5256
5257 if (!leAudioDevice) {
5258 log::error("LeAudioDevice not found");
5259 return;
5260 }
5261
5262 if (status == GATT_DATABASE_OUT_OF_SYNC) {
5263 log::info("Database out of sync for {}, re-discovering",
5264 leAudioDevice->address_);
5265 instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5266 return;
5267 }
5268
5269 if (status != GATT_SUCCESS || len != 2) {
5270 log::error("Could not read CCC for {}, disconnecting",
5271 leAudioDevice->address_);
5272 instance->Disconnect(leAudioDevice->address_);
5273 return;
5274 }
5275
5276 uint16_t val = *(uint16_t*)value;
5277 if (val == 0) {
5278 log::info("{} forgot CCC values. Re-subscribing",
5279 leAudioDevice->address_);
5280 instance->RegisterKnownNotifications(leAudioDevice, false, true);
5281 } else {
5282 instance->connectionReady(leAudioDevice);
5283 }
5284 }
5285
OnGattReadRspStatic(uint16_t conn_id,tGATT_STATUS status,uint16_t hdl,uint16_t len,uint8_t * value,void * data)5286 static void OnGattReadRspStatic(uint16_t conn_id, tGATT_STATUS status,
5287 uint16_t hdl, uint16_t len, uint8_t* value,
5288 void* data) {
5289 if (!instance) return;
5290
5291 LeAudioDevice* leAudioDevice =
5292 instance->leAudioDevices_.FindByConnId(conn_id);
5293
5294 if (status == GATT_SUCCESS) {
5295 instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
5296 } else if (status == GATT_DATABASE_OUT_OF_SYNC) {
5297 instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5298 return;
5299 } else {
5300 log::error("Failed to read attribute, hdl: 0x{:04x}, status: 0x{:02x}",
5301 hdl, static_cast<int>(status));
5302 return;
5303 }
5304
5305 /* We use data to keep notify connected flag. */
5306 if (data && !!PTR_TO_INT(data)) {
5307 leAudioDevice->notify_connected_after_read_ = false;
5308
5309 /* Update handles, PACs and ASEs when all is read.*/
5310 btif_storage_leaudio_update_handles_bin(leAudioDevice->address_);
5311 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
5312 btif_storage_leaudio_update_ase_bin(leAudioDevice->address_);
5313
5314 btif_storage_set_leaudio_audio_location(
5315 leAudioDevice->address_,
5316 leAudioDevice->snk_audio_locations_.to_ulong(),
5317 leAudioDevice->src_audio_locations_.to_ulong());
5318
5319 instance->connectionReady(leAudioDevice);
5320 }
5321 }
5322
LeAudioHealthSendRecommendation(const RawAddress & address,int group_id,LeAudioHealthBasedAction action)5323 void LeAudioHealthSendRecommendation(const RawAddress& address, int group_id,
5324 LeAudioHealthBasedAction action) {
5325 log::debug("{}, {}, {}", address, group_id, ToString(action));
5326
5327 if (address != RawAddress::kEmpty &&
5328 leAudioDevices_.FindByAddress(address)) {
5329 callbacks_->OnHealthBasedRecommendationAction(address, action);
5330 }
5331
5332 if (group_id != bluetooth::groups::kGroupUnknown &&
5333 aseGroups_.FindById(group_id)) {
5334 callbacks_->OnHealthBasedGroupRecommendationAction(group_id, action);
5335 }
5336 }
5337
IsoCigEventsCb(uint16_t event_type,void * data)5338 void IsoCigEventsCb(uint16_t event_type, void* data) {
5339 switch (event_type) {
5340 case bluetooth::hci::iso_manager::kIsoEventCigOnCreateCmpl: {
5341 auto* evt = static_cast<cig_create_cmpl_evt*>(data);
5342 LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5343 log::assert_that(group, "Group id: {} is null", evt->cig_id);
5344 groupStateMachine_->ProcessHciNotifOnCigCreate(
5345 group, evt->status, evt->cig_id, evt->conn_handles);
5346 } break;
5347 case bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl: {
5348 auto* evt = static_cast<cig_remove_cmpl_evt*>(data);
5349 LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5350 log::assert_that(group, "Group id: {} is null", evt->cig_id);
5351 groupStateMachine_->ProcessHciNotifOnCigRemove(evt->status, group);
5352 remove_group_if_possible(group);
5353 } break;
5354 default:
5355 log::error("Invalid event {}", event_type);
5356 }
5357 }
5358
IsoCisEventsCb(uint16_t event_type,void * data)5359 void IsoCisEventsCb(uint16_t event_type, void* data) {
5360 switch (event_type) {
5361 case bluetooth::hci::iso_manager::kIsoEventCisDataAvailable: {
5362 auto* event =
5363 static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(data);
5364
5365 if (DsaDataConsume(event)) {
5366 return;
5367 }
5368
5369 if (audio_receiver_state_ != AudioState::STARTED) {
5370 log::error("receiver state not ready, current state={}",
5371 ToString(audio_receiver_state_));
5372 break;
5373 }
5374
5375 HandleIncomingCisData(event->p_msg->data + event->p_msg->offset,
5376 event->p_msg->len - event->p_msg->offset,
5377 event->cis_conn_hdl, event->ts);
5378 } break;
5379 case bluetooth::hci::iso_manager::kIsoEventCisEstablishCmpl: {
5380 auto* event =
5381 static_cast<bluetooth::hci::iso_manager::cis_establish_cmpl_evt*>(
5382 data);
5383
5384 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(
5385 event->cig_id, event->cis_conn_hdl);
5386 if (!leAudioDevice) {
5387 log::error("no bonded Le Audio Device with CIS: {}",
5388 event->cis_conn_hdl);
5389 break;
5390 }
5391 LeAudioDeviceGroup* group =
5392 aseGroups_.FindById(leAudioDevice->group_id_);
5393
5394 if (event->max_pdu_mtos > 0)
5395 group->SetTransportLatency(
5396 bluetooth::le_audio::types::kLeAudioDirectionSink,
5397 event->trans_lat_mtos);
5398 if (event->max_pdu_stom > 0)
5399 group->SetTransportLatency(
5400 bluetooth::le_audio::types::kLeAudioDirectionSource,
5401 event->trans_lat_stom);
5402
5403 if (leAudioHealthStatus_ && (event->status != HCI_SUCCESS)) {
5404 leAudioHealthStatus_->AddStatisticForGroup(
5405 group, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
5406 }
5407
5408 groupStateMachine_->ProcessHciNotifCisEstablished(group, leAudioDevice,
5409 event);
5410 } break;
5411 case bluetooth::hci::iso_manager::kIsoEventCisDisconnected: {
5412 auto* event =
5413 static_cast<bluetooth::hci::iso_manager::cis_disconnected_evt*>(
5414 data);
5415
5416 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(
5417 event->cig_id, event->cis_conn_hdl);
5418 if (!leAudioDevice) {
5419 log::error("no bonded Le Audio Device with CIS: {}",
5420 event->cis_conn_hdl);
5421 break;
5422 }
5423 LeAudioDeviceGroup* group =
5424 aseGroups_.FindById(leAudioDevice->group_id_);
5425
5426 groupStateMachine_->ProcessHciNotifCisDisconnected(group, leAudioDevice,
5427 event);
5428 } break;
5429 default:
5430 log::info(", Not handeled ISO event");
5431 break;
5432 }
5433 }
5434
IsoSetupIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5435 void IsoSetupIsoDataPathCb(uint8_t status, uint16_t conn_handle,
5436 uint8_t cig_id) {
5437 LeAudioDevice* leAudioDevice =
5438 leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5439 /* In case device has been disconnected before data path was setup */
5440 if (!leAudioDevice) {
5441 log::warn(
5442 "Device for CIG {} and using cis_handle 0x{:04x} is disconnected.",
5443 cig_id, conn_handle);
5444 return;
5445 }
5446 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5447
5448 instance->groupStateMachine_->ProcessHciNotifSetupIsoDataPath(
5449 group, leAudioDevice, status, conn_handle);
5450 }
5451
IsoRemoveIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5452 void IsoRemoveIsoDataPathCb(uint8_t status, uint16_t conn_handle,
5453 uint8_t cig_id) {
5454 LeAudioDevice* leAudioDevice =
5455 leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5456
5457 /* If CIS has been disconnected just before ACL being disconnected by the
5458 * remote device, leAudioDevice might be already cleared i.e. has no
5459 * information about conn_handle, when the data path remove compete arrives.
5460 */
5461 if (!leAudioDevice) {
5462 log::warn(
5463 "Device for CIG {} and using cis_handle 0x{:04x} is disconnected.",
5464 cig_id, conn_handle);
5465 return;
5466 }
5467
5468 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5469
5470 instance->groupStateMachine_->ProcessHciNotifRemoveIsoDataPath(
5471 group, leAudioDevice, status, conn_handle);
5472 }
5473
IsoLinkQualityReadCb(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)5474 void IsoLinkQualityReadCb(
5475 uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
5476 uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
5477 uint32_t retransmittedPackets, uint32_t crcErrorPackets,
5478 uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
5479 LeAudioDevice* leAudioDevice =
5480 leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5481 if (!leAudioDevice) {
5482 log::warn(
5483 "device under connection handle: 0x{:x}, has been disconnecected in "
5484 "meantime",
5485 conn_handle);
5486 return;
5487 }
5488 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5489
5490 instance->groupStateMachine_->ProcessHciNotifIsoLinkQualityRead(
5491 group, leAudioDevice, conn_handle, txUnackedPackets, txFlushedPackets,
5492 txLastSubeventPackets, retransmittedPackets, crcErrorPackets,
5493 rxUnreceivedPackets, duplicatePackets);
5494 }
5495
HandlePendingDeviceRemove(LeAudioDeviceGroup * group)5496 void HandlePendingDeviceRemove(LeAudioDeviceGroup* group) {
5497 for (auto device = group->GetFirstDevice(); device != nullptr;
5498 device = group->GetNextDevice(device)) {
5499 if (device->GetConnectionState() == DeviceConnectState::REMOVING) {
5500 if (device->closing_stream_for_disconnection_) {
5501 device->closing_stream_for_disconnection_ = false;
5502 log::info("Disconnecting group id: {}, address: {}", group->group_id_,
5503 device->address_);
5504 bool force_acl_disconnect =
5505 device->autoconnect_flag_ && group->IsEnabled();
5506 DisconnectDevice(device, force_acl_disconnect);
5507 }
5508 group_remove_node(group, device->address_, true);
5509 }
5510 }
5511 }
5512
HandlePendingDeviceDisconnection(LeAudioDeviceGroup * group)5513 void HandlePendingDeviceDisconnection(LeAudioDeviceGroup* group) {
5514 log::debug("");
5515
5516 auto leAudioDevice = group->GetFirstDevice();
5517 while (leAudioDevice) {
5518 if (leAudioDevice->closing_stream_for_disconnection_) {
5519 leAudioDevice->closing_stream_for_disconnection_ = false;
5520 log::debug("Disconnecting group id: {}, address: {}", group->group_id_,
5521 leAudioDevice->address_);
5522 bool force_acl_disconnect =
5523 leAudioDevice->autoconnect_flag_ && group->IsEnabled();
5524 DisconnectDevice(leAudioDevice, force_acl_disconnect);
5525 }
5526 leAudioDevice = group->GetNextDevice(leAudioDevice);
5527 }
5528 }
5529
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config & config,uint8_t remote_direction)5530 void UpdateAudioConfigToHal(
5531 const ::bluetooth::le_audio::offload_config& config,
5532 uint8_t remote_direction) {
5533 if ((remote_direction &
5534 bluetooth::le_audio::types::kLeAudioDirectionSink) &&
5535 le_audio_source_hal_client_) {
5536 le_audio_source_hal_client_->UpdateAudioConfigToHal(config);
5537 }
5538 if ((remote_direction &
5539 bluetooth::le_audio::types::kLeAudioDirectionSource) &&
5540 le_audio_sink_hal_client_) {
5541 le_audio_sink_hal_client_->UpdateAudioConfigToHal(config);
5542 }
5543 }
5544
NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id)5545 void NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id) {
5546 if (!osi_property_get_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall,
5547 false)) {
5548 return;
5549 }
5550
5551 /* If group is inactive, phone is in call and Group is not having CIS
5552 * connected, notify upper layer about it, so it can decide to create SCO if
5553 * it is in the handover case
5554 */
5555 if ((IsInCall() || IsInVoipCall()) &&
5556 active_group_id_ == bluetooth::groups::kGroupUnknown) {
5557 callbacks_->OnGroupStatus(group_id, GroupStatus::TURNED_IDLE_DURING_CALL);
5558 }
5559 }
5560
take_stream_time(void)5561 void take_stream_time(void) {
5562 if (stream_setup_start_timestamp_ == 0) {
5563 return;
5564 }
5565
5566 if (stream_start_history_queue_.size() == 10) {
5567 stream_start_history_queue_.pop_back();
5568 }
5569
5570 stream_setup_end_timestamp_ = bluetooth::common::time_get_os_boottime_us();
5571 stream_start_history_queue_.emplace_front(
5572 (stream_setup_end_timestamp_ - stream_setup_start_timestamp_) / 1000);
5573
5574 stream_setup_end_timestamp_ = 0;
5575 stream_setup_start_timestamp_ = 0;
5576 }
5577
notifyGroupStreamStatus(int group_id,GroupStreamStatus groupStreamStatus)5578 void notifyGroupStreamStatus(int group_id,
5579 GroupStreamStatus groupStreamStatus) {
5580 if (!com::android::bluetooth::flags::
5581 leaudio_callback_on_group_stream_status()) {
5582 return;
5583 }
5584
5585 GroupStreamStatus newGroupStreamStatus = GroupStreamStatus::IDLE;
5586 if (groupStreamStatus == GroupStreamStatus::STREAMING) {
5587 newGroupStreamStatus = GroupStreamStatus::STREAMING;
5588 }
5589
5590 auto it = lastNotifiedGroupStreamStatusMap_.find(group_id);
5591
5592 if (it != lastNotifiedGroupStreamStatusMap_.end()) {
5593 if (it->second != newGroupStreamStatus) {
5594 callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
5595 it->second = newGroupStreamStatus;
5596 }
5597 } else {
5598 callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
5599 lastNotifiedGroupStreamStatusMap_.emplace(group_id, newGroupStreamStatus);
5600 }
5601 }
5602
handleAsymmetricPhyForUnicast(LeAudioDeviceGroup * group)5603 void handleAsymmetricPhyForUnicast(LeAudioDeviceGroup* group) {
5604 if (!group->asymmetric_phy_for_unidirectional_cis_supported) return;
5605
5606 auto it = lastNotifiedGroupStreamStatusMap_.find(group->group_id_);
5607
5608 if (it != lastNotifiedGroupStreamStatusMap_.end() &&
5609 it->second == GroupStreamStatus::STREAMING &&
5610 group->GetSduInterval(bluetooth::le_audio::types::kLeAudioDirectionSource) == 0) {
5611 SetAsymmetricBlePhy(group, true);
5612 return;
5613 }
5614
5615 SetAsymmetricBlePhy(group, false);
5616 }
5617
OnStateMachineStatusReportCb(int group_id,GroupStreamStatus status)5618 void OnStateMachineStatusReportCb(int group_id, GroupStreamStatus status) {
5619 log::info(
5620 "status: {} , group_id: {}, audio_sender_state {}, "
5621 "audio_receiver_state {}",
5622 static_cast<int>(status), group_id,
5623 bluetooth::common::ToString(audio_sender_state_),
5624 bluetooth::common::ToString(audio_receiver_state_));
5625 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
5626
5627 notifyGroupStreamStatus(group_id, status);
5628
5629 switch (status) {
5630 case GroupStreamStatus::STREAMING: {
5631 log::assert_that(group_id == active_group_id_,
5632 "invalid group id {}!={}", group_id, active_group_id_);
5633
5634 take_stream_time();
5635
5636 bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(
5637 active_group_id_, configuration_context_type_);
5638
5639 if (leAudioHealthStatus_) {
5640 leAudioHealthStatus_->AddStatisticForGroup(
5641 group, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
5642 }
5643
5644 if (!group) {
5645 log::error("Group {} does not exist anymore. This shall not happen",
5646 group_id);
5647 return;
5648 }
5649
5650 handleAsymmetricPhyForUnicast(group);
5651
5652 if ((audio_sender_state_ == AudioState::IDLE) &&
5653 (audio_receiver_state_ == AudioState::IDLE)) {
5654 /* Audio Framework is not interested in the stream anymore.
5655 * Just stop streaming
5656 */
5657 log::warn("Stopping stream for group {} as AF not interested.",
5658 group_id);
5659 groupStateMachine_->StopStream(group);
5660 return;
5661 }
5662
5663 /* It might happen that the configuration has already changed, while
5664 * the group was in the ongoing reconfiguration. We should stop the
5665 * stream and reconfigure once again.
5666 */
5667 if (group->GetConfigurationContextType() !=
5668 configuration_context_type_) {
5669 log::debug(
5670 "The configuration {} is no longer valid. Stopping the stream to "
5671 "reconfigure to {}",
5672 ToString(group->GetConfigurationContextType()),
5673 ToString(configuration_context_type_));
5674 group->SetPendingConfiguration();
5675 groupStateMachine_->StopStream(group);
5676 stream_setup_start_timestamp_ =
5677 bluetooth::common::time_get_os_boottime_us();
5678 return;
5679 }
5680
5681 BidirectionalPair<uint16_t> delays_pair = {
5682 .sink = group->GetRemoteDelay(
5683 bluetooth::le_audio::types::kLeAudioDirectionSink),
5684 .source = group->GetRemoteDelay(
5685 bluetooth::le_audio::types::kLeAudioDirectionSource)};
5686 CodecManager::GetInstance()->UpdateActiveAudioConfig(
5687 group->stream_conf.stream_params, delays_pair,
5688 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal,
5689 weak_factory_.GetWeakPtr(), std::placeholders::_1,
5690 std::placeholders::_2));
5691
5692 /* When at least one direction is started we can assume new
5693 * configuration here */
5694 bool new_configuration = false;
5695 if (audio_sender_state_ == AudioState::READY_TO_START) {
5696 StartSendingAudio(group_id);
5697 new_configuration = true;
5698 }
5699
5700 if (audio_receiver_state_ == AudioState::READY_TO_START) {
5701 StartReceivingAudio(group_id);
5702 new_configuration = true;
5703 }
5704
5705 if (new_configuration) {
5706 /* Notify Java about new configuration */
5707 SendAudioGroupCurrentCodecConfigChanged(group);
5708 }
5709 break;
5710 }
5711 case GroupStreamStatus::SUSPENDED:
5712 stream_setup_end_timestamp_ = 0;
5713 stream_setup_start_timestamp_ = 0;
5714 /** Stop Audio but don't release all the Audio resources */
5715 SuspendAudio();
5716 break;
5717 case GroupStreamStatus::CONFIGURED_BY_USER: {
5718 // Check which directions were suspended
5719 uint8_t previously_active_directions = 0;
5720 if (audio_sender_state_ >= AudioState::READY_TO_START) {
5721 previously_active_directions |=
5722 bluetooth::le_audio::types::kLeAudioDirectionSink;
5723 }
5724 if (audio_receiver_state_ >= AudioState::READY_TO_START) {
5725 previously_active_directions |=
5726 bluetooth::le_audio::types::kLeAudioDirectionSource;
5727 }
5728
5729 /* We are done with reconfiguration.
5730 * Clean state and if Audio HAL is waiting, cancel the request
5731 * so Audio HAL can Resume again.
5732 */
5733 CancelStreamingRequest();
5734 ReconfigurationComplete(previously_active_directions);
5735 } break;
5736 case GroupStreamStatus::CONFIGURED_AUTONOMOUS:
5737 /* This state is notified only when
5738 * groups stays into CONFIGURED state after
5739 * STREAMING. Peer device uses cache. For the moment
5740 * it is handled same as IDLE
5741 */
5742 case GroupStreamStatus::IDLE: {
5743 if (sw_enc_left) sw_enc_left.reset();
5744 if (sw_enc_right) sw_enc_right.reset();
5745 if (sw_dec_left) sw_dec_left.reset();
5746 if (sw_dec_right) sw_dec_right.reset();
5747 CleanCachedMicrophoneData();
5748
5749 if (group) {
5750 handleAsymmetricPhyForUnicast(group);
5751 UpdateLocationsAndContextsAvailability(group);
5752 if (group->IsPendingConfiguration()) {
5753 SuspendedForReconfiguration();
5754 auto remote_direction =
5755 kLeAudioContextAllRemoteSource.test(configuration_context_type_)
5756 ? bluetooth::le_audio::types::kLeAudioDirectionSource
5757 : bluetooth::le_audio::types::kLeAudioDirectionSink;
5758
5759 /* Reconfiguration to non requiring source scenario */
5760 if (sink_monitor_mode_ &&
5761 (remote_direction ==
5762 bluetooth::le_audio::types::kLeAudioDirectionSink)) {
5763 notifyAudioLocalSink(
5764 UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5765 }
5766
5767 auto remote_contexts =
5768 DirectionalRealignMetadataAudioContexts(group, remote_direction);
5769 ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts,
5770 remote_direction);
5771 if (GroupStream(group->group_id_, configuration_context_type_,
5772 remote_contexts)) {
5773 /* If configuration succeed wait for new status. */
5774 return;
5775 }
5776 log::info("Clear pending configuration flag for group {}",
5777 group->group_id_);
5778 group->ClearPendingConfiguration();
5779 } else {
5780 if (sink_monitor_mode_) {
5781 notifyAudioLocalSink(
5782 UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5783 }
5784
5785 if (source_monitor_mode_) {
5786 callbacks_->OnUnicastMonitorModeStatus(
5787 bluetooth::le_audio::types::kLeAudioDirectionSource,
5788 UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5789 }
5790 }
5791 }
5792
5793 stream_setup_end_timestamp_ = 0;
5794 stream_setup_start_timestamp_ = 0;
5795 CancelStreamingRequest();
5796
5797 if (group) {
5798 NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_);
5799 HandlePendingDeviceRemove(group);
5800 HandlePendingDeviceDisconnection(group);
5801 }
5802 break;
5803 }
5804 case GroupStreamStatus::RELEASING:
5805 case GroupStreamStatus::SUSPENDING:
5806 if (active_group_id_ != bluetooth::groups::kGroupUnknown &&
5807 (active_group_id_ == group->group_id_) &&
5808 !group->IsPendingConfiguration() &&
5809 (audio_sender_state_ == AudioState::STARTED ||
5810 audio_receiver_state_ == AudioState::STARTED)) {
5811 /* If releasing state is happening but it was not initiated either by
5812 * reconfiguration or Audio Framework actions either by the Active group change,
5813 * it means that it is some internal state machine error. This is very unlikely and
5814 * for now just Inactivate the group.
5815 */
5816 log::error("Internal state machine error");
5817 group->PrintDebugState();
5818 groupSetAndNotifyInactive();
5819 }
5820
5821 if (audio_sender_state_ != AudioState::IDLE)
5822 audio_sender_state_ = AudioState::RELEASING;
5823
5824 if (audio_receiver_state_ != AudioState::IDLE)
5825 audio_receiver_state_ = AudioState::RELEASING;
5826
5827 break;
5828 default:
5829 break;
5830 }
5831 }
5832
OnUpdatedCisConfiguration(int group_id,uint8_t direction)5833 void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
5834 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
5835 if (!group) {
5836 log::error("Invalid group_id: {}", group_id);
5837 return;
5838 }
5839 group->UpdateCisConfiguration(direction);
5840 }
5841
5842 private:
5843 tGATT_IF gatt_if_;
5844 bluetooth::le_audio::LeAudioClientCallbacks* callbacks_;
5845 LeAudioDevices leAudioDevices_;
5846 LeAudioDeviceGroups aseGroups_;
5847 LeAudioGroupStateMachine* groupStateMachine_;
5848 int active_group_id_;
5849 LeAudioContextType configuration_context_type_;
5850 static constexpr char kAllowMultipleContextsInMetadata[] =
5851 "persist.bluetooth.leaudio.allow.multiple.contexts";
5852 BidirectionalPair<AudioContexts> local_metadata_context_types_;
5853 uint64_t stream_setup_start_timestamp_;
5854 uint64_t stream_setup_end_timestamp_;
5855 std::deque<uint64_t> stream_start_history_queue_;
5856
5857 /* Microphone (s) */
5858 AudioState audio_receiver_state_;
5859 /* Speaker(s) */
5860 AudioState audio_sender_state_;
5861 /* Keep in call state. */
5862 bool in_call_;
5863 bool in_voip_call_;
5864 /* Listen for streaming status on Sink stream */
5865 bool sink_monitor_mode_;
5866 /* Status which has been notified to Service */
5867 std::optional<UnicastMonitorModeStatus> sink_monitor_notified_status_;
5868 /* Listen for streaming status on Source stream */
5869 bool source_monitor_mode_;
5870
5871 /* Reconnection mode */
5872 tBTM_BLE_CONN_TYPE reconnection_mode_;
5873 static constexpr uint64_t kGroupConnectedWatchDelayMs = 3000;
5874 static constexpr uint64_t kRecoveryReconnectDelayMs = 2000;
5875 static constexpr uint64_t kAutoConnectAfterOwnDisconnectDelayMs = 1000;
5876 static constexpr uint64_t kCsisGroupMemberDelayMs = 5000;
5877
5878 /* LeAudioHealthStatus */
5879 LeAudioHealthStatus* leAudioHealthStatus_ = nullptr;
5880
5881 static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
5882 "persist.bluetooth.leaudio.notify.idle.during.call";
5883
5884 static constexpr uint16_t kBapMinimumAttMtu = 64;
5885
5886 /* Current stream configuration - used to set up the software codecs */
5887 LeAudioCodecConfiguration current_encoder_config_;
5888 LeAudioCodecConfiguration current_decoder_config_;
5889
5890 /* Static Audio Framework session configuration.
5891 * Resampling will be done inside the bt stack
5892 */
5893 LeAudioCodecConfiguration audio_framework_source_config = {
5894 .num_channels = 2,
5895 .sample_rate = bluetooth::audio::le_audio::kSampleRate48000,
5896 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
5897 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
5898 };
5899
5900 LeAudioCodecConfiguration audio_framework_sink_config = {
5901 .num_channels = 2,
5902 .sample_rate = bluetooth::audio::le_audio::kSampleRate16000,
5903 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
5904 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
5905 };
5906
5907 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_left;
5908 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_right;
5909
5910 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_left;
5911 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_right;
5912
5913 std::vector<uint8_t> encoded_data;
5914 std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_;
5915 std::unique_ptr<LeAudioSinkAudioHalClient> le_audio_sink_hal_client_;
5916 static constexpr uint64_t kAudioSuspentKeepIsoAliveTimeoutMs = 5000;
5917 static constexpr uint64_t kAudioDisableTimeoutMs = 3000;
5918 static constexpr char kAudioSuspentKeepIsoAliveTimeoutMsProp[] =
5919 "persist.bluetooth.leaudio.audio.suspend.timeoutms";
5920 alarm_t* close_vbc_timeout_;
5921 alarm_t* suspend_timeout_;
5922 alarm_t* disable_timer_;
5923 static constexpr uint64_t kDeviceAttachDelayMs = 500;
5924
5925 uint32_t cached_channel_timestamp_ = 0;
5926 bluetooth::le_audio::CodecInterface* cached_channel_ = nullptr;
5927
5928 base::WeakPtrFactory<LeAudioClientImpl> weak_factory_{this};
5929
5930 std::map<int, GroupStreamStatus> lastNotifiedGroupStreamStatusMap_;
5931
ClientAudioInterfaceRelease()5932 void ClientAudioInterfaceRelease() {
5933 auto group = aseGroups_.FindById(active_group_id_);
5934 if (!group) {
5935 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
5936 } else {
5937 handleAsymmetricPhyForUnicast(group);
5938 log::info("ClientAudioInterfaceRelease - cleanup");
5939 }
5940
5941 auto result =
5942 CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
5943 le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(),
5944 false);
5945 log::assert_that(result, "Could not update session to codec manager");
5946
5947 if (le_audio_source_hal_client_) {
5948 le_audio_source_hal_client_->Stop();
5949 le_audio_source_hal_client_.reset();
5950 }
5951
5952 if (le_audio_sink_hal_client_) {
5953 /* Keep session set up to monitor streaming request. This is required if
5954 * there is another LE Audio device streaming (e.g. Broadcast) and via
5955 * the session callbacks special action from this Module would be
5956 * required e.g. to Unicast handover.
5957 */
5958 if (!sink_monitor_mode_) {
5959 local_metadata_context_types_.sink.clear();
5960 le_audio_sink_hal_client_->Stop();
5961 le_audio_sink_hal_client_.reset();
5962 }
5963 }
5964 local_metadata_context_types_.source.clear();
5965 configuration_context_type_ = LeAudioContextType::UNINITIALIZED;
5966
5967 bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(
5968 active_group_id_);
5969 }
5970
DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt * event)5971 bool DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt* event) {
5972 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
5973 return false;
5974 }
5975
5976 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
5977 return false;
5978 }
5979 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
5980 if (!group || !group->dsa_.active) {
5981 return false;
5982 }
5983
5984 if (group->dsa_.mode != DsaMode::ISO_SW) {
5985 log::warn("ISO packets received over HCI in DSA mode: {}",
5986 group->dsa_.mode);
5987 return false;
5988 }
5989
5990 if (iso_data_callback == nullptr) {
5991 log::warn("Dsa data consumer not registered");
5992 return false;
5993 }
5994
5995 uint16_t cis_conn_hdl = event->cis_conn_hdl;
5996 uint8_t* data = event->p_msg->data + event->p_msg->offset;
5997 uint16_t size = event->p_msg->len - event->p_msg->offset;
5998 uint32_t timestamp = event->ts;
5999
6000 // Find LE Audio device
6001 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6002 while (leAudioDevice != nullptr) {
6003 if (leAudioDevice->GetDsaCisHandle() == cis_conn_hdl &&
6004 leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURED) {
6005 break;
6006 }
6007 leAudioDevice = group->GetNextDevice(leAudioDevice);
6008 }
6009 if (leAudioDevice == nullptr) {
6010 log::warn("No LE Audio device found for CIS handle: {}", cis_conn_hdl);
6011 return false;
6012 }
6013
6014 bool consumed = iso_data_callback(leAudioDevice->address_, cis_conn_hdl,
6015 data, size, timestamp);
6016 if (consumed) {
6017 return true;
6018 } else {
6019 log::verbose("ISO data consumer not ready to accept data");
6020 return false;
6021 }
6022 }
6023
SetAsymmetricBlePhy(LeAudioDeviceGroup * group,bool asymmetric)6024 void SetAsymmetricBlePhy(LeAudioDeviceGroup* group, bool asymmetric) {
6025 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6026 if (leAudioDevice == nullptr) {
6027 log::error("Shouldn't be called without a device.");
6028 return;
6029 }
6030
6031 for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
6032 tmpDevice = group->GetNextDevice(tmpDevice)) {
6033 log::info(
6034 "tmpDevice->acl_asymmetric_: {}, asymmetric: {}, address: {}, "
6035 "acl_connected: {}",
6036 tmpDevice->acl_asymmetric_ == asymmetric, asymmetric,
6037 tmpDevice->address_,
6038 BTM_IsAclConnectionUp(tmpDevice->address_, BT_TRANSPORT_LE));
6039 if (tmpDevice->acl_asymmetric_ == asymmetric ||
6040 !BTM_IsAclConnectionUp(tmpDevice->address_, BT_TRANSPORT_LE))
6041 continue;
6042
6043 log::info("SetAsymmetricBlePhy: {} for {}", asymmetric,
6044 tmpDevice->address_);
6045 BTM_BleSetPhy(tmpDevice->address_, PHY_LE_2M,
6046 asymmetric ? PHY_LE_1M : PHY_LE_2M, 0);
6047 tmpDevice->acl_asymmetric_ = asymmetric;
6048 }
6049 }
6050 };
6051
le_audio_health_status_callback(const RawAddress & addr,int group_id,LeAudioHealthBasedAction action)6052 static void le_audio_health_status_callback(const RawAddress& addr,
6053 int group_id,
6054 LeAudioHealthBasedAction action) {
6055 if (instance) {
6056 instance->LeAudioHealthSendRecommendation(addr, group_id, action);
6057 }
6058 }
6059
6060 /* This is a generic callback method for gatt client which handles every client
6061 * application events.
6062 */
le_audio_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)6063 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
6064 if (!p_data || !instance) return;
6065
6066 log::info("event = {}", static_cast<int>(event));
6067
6068 switch (event) {
6069 case BTA_GATTC_DEREG_EVT:
6070 break;
6071
6072 case BTA_GATTC_NOTIF_EVT:
6073 instance->LeAudioCharValueHandle(
6074 p_data->notify.conn_id, p_data->notify.handle, p_data->notify.len,
6075 static_cast<uint8_t*>(p_data->notify.value), true);
6076
6077 if (!p_data->notify.is_notify)
6078 BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
6079
6080 break;
6081
6082 case BTA_GATTC_OPEN_EVT:
6083 instance->OnGattConnected(p_data->open.status, p_data->open.conn_id,
6084 p_data->open.client_if, p_data->open.remote_bda,
6085 p_data->open.transport, p_data->open.mtu);
6086 break;
6087
6088 case BTA_GATTC_ENC_CMPL_CB_EVT: {
6089 uint8_t encryption_status;
6090 if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
6091 encryption_status = BTM_SUCCESS;
6092 } else {
6093 encryption_status = BTM_FAILED_ON_SECURITY;
6094 }
6095 instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda,
6096 encryption_status);
6097 } break;
6098
6099 case BTA_GATTC_CLOSE_EVT:
6100 instance->OnGattDisconnected(
6101 p_data->close.conn_id, p_data->close.client_if,
6102 p_data->close.remote_bda, p_data->close.reason);
6103 break;
6104
6105 case BTA_GATTC_SEARCH_CMPL_EVT:
6106 instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id,
6107 p_data->search_cmpl.status);
6108 break;
6109
6110 case BTA_GATTC_SRVC_DISC_DONE_EVT:
6111 instance->OnGattServiceDiscoveryDone(p_data->service_changed.remote_bda);
6112 break;
6113
6114 case BTA_GATTC_SRVC_CHG_EVT:
6115 instance->OnServiceChangeEvent(p_data->remote_bda);
6116 break;
6117 case BTA_GATTC_CFG_MTU_EVT:
6118 instance->OnMtuChanged(p_data->cfg_mtu.conn_id, p_data->cfg_mtu.mtu);
6119 break;
6120 case BTA_GATTC_PHY_UPDATE_EVT:
6121 instance->OnPhyUpdate(
6122 p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
6123 p_data->phy_update.rx_phy, p_data->phy_update.status);
6124 break;
6125 default:
6126 break;
6127 }
6128 }
6129
6130 class LeAudioStateMachineHciCallbacksImpl : public CigCallbacks {
6131 public:
OnCigEvent(uint8_t event,void * data)6132 void OnCigEvent(uint8_t event, void* data) override {
6133 if (instance) instance->IsoCigEventsCb(event, data);
6134 }
6135
OnCisEvent(uint8_t event,void * data)6136 void OnCisEvent(uint8_t event, void* data) override {
6137 if (instance) instance->IsoCisEventsCb(event, data);
6138 }
6139
OnSetupIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6140 void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle,
6141 uint8_t cig_id) override {
6142 if (instance) instance->IsoSetupIsoDataPathCb(status, conn_handle, cig_id);
6143 }
6144
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6145 void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle,
6146 uint8_t cig_id) override {
6147 if (instance) instance->IsoRemoveIsoDataPathCb(status, conn_handle, cig_id);
6148 }
6149
OnIsoLinkQualityRead(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)6150 void OnIsoLinkQualityRead(
6151 uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
6152 uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
6153 uint32_t retransmittedPackets, uint32_t crcErrorPackets,
6154 uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
6155 if (instance)
6156 instance->IsoLinkQualityReadCb(conn_handle, cig_id, txUnackedPackets,
6157 txFlushedPackets, txLastSubeventPackets,
6158 retransmittedPackets, crcErrorPackets,
6159 rxUnreceivedPackets, duplicatePackets);
6160 }
6161 };
6162
6163 LeAudioStateMachineHciCallbacksImpl stateMachineHciCallbacksImpl;
6164
6165 class CallbacksImpl : public LeAudioGroupStateMachine::Callbacks {
6166 public:
StatusReportCb(int group_id,GroupStreamStatus status)6167 void StatusReportCb(int group_id, GroupStreamStatus status) override {
6168 if (instance) instance->OnStateMachineStatusReportCb(group_id, status);
6169 }
6170
OnStateTransitionTimeout(int group_id)6171 void OnStateTransitionTimeout(int group_id) override {
6172 if (instance) instance->OnLeAudioDeviceSetStateTimeout(group_id);
6173 }
6174
OnDeviceAutonomousStateTransitionTimeout(LeAudioDevice * leAudioDevice)6175 void OnDeviceAutonomousStateTransitionTimeout(
6176 LeAudioDevice* leAudioDevice) override {
6177 if (instance)
6178 instance->OnDeviceAutonomousStateTransitionTimeout(leAudioDevice);
6179 }
6180
OnUpdatedCisConfiguration(int group_id,uint8_t direction)6181 void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
6182 if (instance) instance->OnUpdatedCisConfiguration(group_id, direction);
6183 }
6184 };
6185
6186 CallbacksImpl stateMachineCallbacksImpl;
6187
6188 class SourceCallbacksImpl : public LeAudioSourceAudioHalClient::Callbacks {
6189 public:
OnAudioDataReady(const std::vector<uint8_t> & data)6190 void OnAudioDataReady(const std::vector<uint8_t>& data) override {
6191 if (instance) instance->OnAudioDataReady(data);
6192 }
OnAudioSuspend(void)6193 void OnAudioSuspend(void) override {
6194 if (instance) instance->OnLocalAudioSourceSuspend();
6195 }
6196
OnAudioResume(void)6197 void OnAudioResume(void) override {
6198 if (instance) instance->OnLocalAudioSourceResume();
6199 }
6200
OnAudioMetadataUpdate(std::vector<struct playback_track_metadata_v7> source_metadata,DsaMode dsa_mode)6201 void OnAudioMetadataUpdate(
6202 std::vector<struct playback_track_metadata_v7> source_metadata,
6203 DsaMode dsa_mode) override {
6204 if (instance)
6205 instance->OnLocalAudioSourceMetadataUpdate(source_metadata, dsa_mode);
6206 }
6207 };
6208
6209 class SinkCallbacksImpl : public LeAudioSinkAudioHalClient::Callbacks {
6210 public:
OnAudioSuspend(void)6211 void OnAudioSuspend(void) override {
6212 if (instance) instance->OnLocalAudioSinkSuspend();
6213 }
OnAudioResume(void)6214 void OnAudioResume(void) override {
6215 if (instance) instance->OnLocalAudioSinkResume();
6216 }
6217
OnAudioMetadataUpdate(std::vector<record_track_metadata_v7> sink_metadata)6218 void OnAudioMetadataUpdate(
6219 std::vector<record_track_metadata_v7> sink_metadata) override {
6220 if (instance) instance->OnLocalAudioSinkMetadataUpdate(sink_metadata);
6221 }
6222 };
6223
6224 SourceCallbacksImpl audioSinkReceiverImpl;
6225 SinkCallbacksImpl audioSourceReceiverImpl;
6226
6227 class DeviceGroupsCallbacksImpl : public DeviceGroupsCallbacks {
6228 public:
OnGroupAdded(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)6229 void OnGroupAdded(const RawAddress& address, const bluetooth::Uuid& uuid,
6230 int group_id) override {
6231 if (instance) instance->OnGroupAddedCb(address, uuid, group_id);
6232 }
OnGroupMemberAdded(const RawAddress & address,int group_id)6233 void OnGroupMemberAdded(const RawAddress& address, int group_id) override {
6234 if (instance) instance->OnGroupMemberAddedCb(address, group_id);
6235 }
OnGroupMemberRemoved(const RawAddress & address,int group_id)6236 void OnGroupMemberRemoved(const RawAddress& address, int group_id) override {
6237 if (instance) instance->OnGroupMemberRemovedCb(address, group_id);
6238 }
OnGroupRemoved(const bluetooth::Uuid & uuid,int group_id)6239 void OnGroupRemoved(const bluetooth::Uuid& uuid, int group_id) {
6240 /* to implement if needed */
6241 }
OnGroupAddFromStorage(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)6242 void OnGroupAddFromStorage(const RawAddress& address,
6243 const bluetooth::Uuid& uuid, int group_id) {
6244 /* to implement if needed */
6245 }
6246 };
6247
6248 class DeviceGroupsCallbacksImpl;
6249 DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl;
6250
6251 } // namespace
6252
AddFromStorage(const RawAddress & addr,bool autoconnect,int sink_audio_location,int source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases)6253 void LeAudioClient::AddFromStorage(
6254 const RawAddress& addr, bool autoconnect, int sink_audio_location,
6255 int source_audio_location, int sink_supported_context_types,
6256 int source_supported_context_types, const std::vector<uint8_t>& handles,
6257 const std::vector<uint8_t>& sink_pacs,
6258 const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases) {
6259 if (!instance) {
6260 log::error("Not initialized yet");
6261 return;
6262 }
6263
6264 instance->AddFromStorage(addr, autoconnect, sink_audio_location,
6265 source_audio_location, sink_supported_context_types,
6266 source_supported_context_types, handles, sink_pacs,
6267 source_pacs, ases);
6268 }
6269
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6270 bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr,
6271 std::vector<uint8_t>& out) {
6272 if (!instance) {
6273 log::error("Not initialized yet");
6274 return false;
6275 }
6276
6277 return instance->GetHandlesForStorage(addr, out);
6278 }
6279
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6280 bool LeAudioClient::GetSinkPacsForStorage(const RawAddress& addr,
6281 std::vector<uint8_t>& out) {
6282 if (!instance) {
6283 log::error("Not initialized yet");
6284 return false;
6285 }
6286
6287 return instance->GetSinkPacsForStorage(addr, out);
6288 }
6289
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6290 bool LeAudioClient::GetSourcePacsForStorage(const RawAddress& addr,
6291 std::vector<uint8_t>& out) {
6292 if (!instance) {
6293 log::error("Not initialized yet");
6294 return false;
6295 }
6296
6297 return instance->GetSourcePacsForStorage(addr, out);
6298 }
6299
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6300 bool LeAudioClient::GetAsesForStorage(const RawAddress& addr,
6301 std::vector<uint8_t>& out) {
6302 if (!instance) {
6303 log::error("Not initialized yet");
6304 return false;
6305 }
6306
6307 return instance->GetAsesForStorage(addr, out);
6308 }
6309
IsLeAudioClientRunning(void)6310 bool LeAudioClient::IsLeAudioClientRunning(void) { return instance != nullptr; }
6311
IsLeAudioClientInStreaming(void)6312 bool LeAudioClient::IsLeAudioClientInStreaming(void) {
6313 if (!instance) {
6314 return false;
6315 }
6316 return instance->IsInStreaming();
6317 }
6318
Get()6319 LeAudioClient* LeAudioClient::Get() {
6320 log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
6321 return instance;
6322 }
6323
6324 /* Initializer of main le audio implementation class and its instance */
Initialize(bluetooth::le_audio::LeAudioClientCallbacks * callbacks_,base::Closure initCb,base::Callback<bool ()> hal_2_1_verifier,const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> & offloading_preference)6325 void LeAudioClient::Initialize(
6326 bluetooth::le_audio::LeAudioClientCallbacks* callbacks_,
6327 base::Closure initCb, base::Callback<bool()> hal_2_1_verifier,
6328 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>&
6329 offloading_preference) {
6330 std::scoped_lock<std::mutex> lock(instance_mutex);
6331 if (instance) {
6332 log::error("Already initialized");
6333 return;
6334 }
6335
6336 if (!bluetooth::shim::GetController()
6337 ->SupportsBleConnectedIsochronousStreamCentral() &&
6338 !bluetooth::shim::GetController()
6339 ->SupportsBleConnectedIsochronousStreamPeripheral()) {
6340 log::error(
6341 "Controller reports no ISO support. LeAudioClient Init aborted.");
6342 return;
6343 }
6344
6345 log::assert_that(
6346 std::move(hal_2_1_verifier).Run(),
6347 "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
6348 "disable LE Audio Profile, or update your HAL");
6349
6350 IsoManager::GetInstance()->Start();
6351
6352 audioSinkReceiver = &audioSinkReceiverImpl;
6353 audioSourceReceiver = &audioSourceReceiverImpl;
6354 stateMachineHciCallbacks = &stateMachineHciCallbacksImpl;
6355 stateMachineCallbacks = &stateMachineCallbacksImpl;
6356 device_group_callbacks = &deviceGroupsCallbacksImpl;
6357 instance = new LeAudioClientImpl(callbacks_, stateMachineCallbacks, initCb);
6358
6359 IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks);
6360 CodecManager::GetInstance()->Start(offloading_preference);
6361 ContentControlIdKeeper::GetInstance()->Start();
6362
6363 callbacks_->OnInitialized();
6364
6365 auto cm = CodecManager::GetInstance();
6366 callbacks_->OnAudioLocalCodecCapabilities(cm->GetLocalAudioInputCodecCapa(),
6367 cm->GetLocalAudioOutputCodecCapa());
6368 }
6369
DebugDump(int fd)6370 void LeAudioClient::DebugDump(int fd) {
6371 std::scoped_lock<std::mutex> lock(instance_mutex);
6372 DeviceGroups::DebugDump(fd);
6373
6374 dprintf(fd, "LeAudio Manager: \n");
6375 if (instance)
6376 instance->Dump(fd);
6377 else
6378 dprintf(fd, " Not initialized \n");
6379
6380 LeAudioSinkAudioHalClient::DebugDump(fd);
6381 LeAudioSourceAudioHalClient::DebugDump(fd);
6382 bluetooth::le_audio::AudioSetConfigurationProvider::DebugDump(fd);
6383 IsoManager::GetInstance()->Dump(fd);
6384 LeAudioLogHistory::DebugDump(fd);
6385 dprintf(fd, "\n");
6386 }
6387
Cleanup(void)6388 void LeAudioClient::Cleanup(void) {
6389 std::scoped_lock<std::mutex> lock(instance_mutex);
6390 if (!instance) {
6391 log::error("Not initialized");
6392 return;
6393 }
6394
6395 LeAudioClientImpl* ptr = instance;
6396 instance = nullptr;
6397 ptr->Cleanup();
6398 delete ptr;
6399 ptr = nullptr;
6400
6401 CodecManager::GetInstance()->Stop();
6402 ContentControlIdKeeper::GetInstance()->Stop();
6403 LeAudioGroupStateMachine::Cleanup();
6404
6405 if (!LeAudioBroadcaster::IsLeAudioBroadcasterRunning())
6406 IsoManager::GetInstance()->Stop();
6407
6408 bluetooth::le_audio::MetricsCollector::Get()->Flush();
6409 }
6410
RegisterIsoDataConsumer(LeAudioIsoDataCallback callback)6411 bool LeAudioClient::RegisterIsoDataConsumer(LeAudioIsoDataCallback callback) {
6412 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
6413 return false;
6414 }
6415
6416 log::info("ISO data consumer changed");
6417 iso_data_callback = callback;
6418 return true;
6419 }
6420