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