1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - 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 <bluetooth/log.h>
20 #include <lc3.h>
21
22 #include <mutex>
23
24 #include "bta/include/bta_le_audio_broadcaster_api.h"
25 #include "bta/le_audio/broadcaster/state_machine.h"
26 #include "bta/le_audio/codec_interface.h"
27 #include "bta/le_audio/content_control_id_keeper.h"
28 #include "bta/le_audio/le_audio_types.h"
29 #include "bta/le_audio/le_audio_utils.h"
30 #include "bta/le_audio/metrics_collector.h"
31 #include "bta_le_audio_api.h"
32 #include "common/strings.h"
33 #include "hci/controller_interface.h"
34 #include "internal_include/stack_config.h"
35 #include "main/shim/entry.h"
36 #include "os/log.h"
37 #include "osi/include/properties.h"
38 #include "stack/include/bt_types.h"
39 #include "stack/include/btm_api_types.h"
40 #include "stack/include/btm_iso_api.h"
41
42 using bluetooth::common::ToString;
43 using bluetooth::hci::IsoManager;
44 using bluetooth::hci::iso_manager::big_create_cmpl_evt;
45 using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
46 using bluetooth::hci::iso_manager::BigCallbacks;
47 using bluetooth::le_audio::BasicAudioAnnouncementData;
48 using bluetooth::le_audio::BasicAudioAnnouncementSubgroup;
49 using bluetooth::le_audio::BroadcastId;
50 using bluetooth::le_audio::CodecManager;
51 using bluetooth::le_audio::ContentControlIdKeeper;
52 using bluetooth::le_audio::DsaMode;
53 using bluetooth::le_audio::LeAudioCodecConfiguration;
54 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
55 using bluetooth::le_audio::PublicBroadcastAnnouncementData;
56 using bluetooth::le_audio::broadcaster::BigConfig;
57 using bluetooth::le_audio::broadcaster::BroadcastConfiguration;
58 using bluetooth::le_audio::broadcaster::BroadcastQosConfig;
59 using bluetooth::le_audio::broadcaster::BroadcastStateMachine;
60 using bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig;
61 using bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig;
62 using bluetooth::le_audio::broadcaster::IBroadcastStateMachineCallbacks;
63 using bluetooth::le_audio::types::AudioContexts;
64 using bluetooth::le_audio::types::CodecLocation;
65 using bluetooth::le_audio::types::kLeAudioCodingFormatLC3;
66 using bluetooth::le_audio::types::LeAudioContextType;
67 using bluetooth::le_audio::types::LeAudioLtvMap;
68 using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata;
69
70 using namespace bluetooth;
71
72 namespace {
73 class LeAudioBroadcasterImpl;
74 LeAudioBroadcasterImpl* instance;
75 std::mutex instance_mutex;
76
77 /* Class definitions */
78
79 /* LeAudioBroadcasterImpl class represents main implementation class for le
80 * audio broadcaster feature in the stack.
81 *
82 * This class may be bonded with Test socket which allows to drive an instance
83 * for test purposes.
84 */
85 class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
86 enum class AudioDataPathState {
87 INACTIVE,
88 ACTIVE,
89 SUSPENDED,
90 };
91
92 public:
LeAudioBroadcasterImpl(bluetooth::le_audio::LeAudioBroadcasterCallbacks * callbacks_)93 LeAudioBroadcasterImpl(
94 bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_)
95 : callbacks_(callbacks_),
96 current_phy_(PHY_LE_2M),
97 audio_data_path_state_(AudioDataPathState::INACTIVE),
98 le_audio_source_hal_client_(nullptr) {
99 log::info("");
100
101 /* Register State machine callbacks */
102 BroadcastStateMachine::Initialize(&state_machine_callbacks_,
103 &state_machine_adv_callbacks_);
104
105 GenerateBroadcastIds();
106 }
107
108 ~LeAudioBroadcasterImpl() override = default;
109
GenerateBroadcastIds(void)110 void GenerateBroadcastIds(void) {
111 btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand) {
112 if (!instance) return;
113
114 /* LE Rand returns 8 octets. Lets' make 2 outstanding Broadcast Ids out
115 * of it */
116 for (int i = 0; i < 8; i += 4) {
117 BroadcastId broadcast_id = 0;
118 /* Broadcast ID should be 3 octets long (BAP v1.0 spec.) */
119 STREAM_TO_UINT24(broadcast_id, rand);
120 if (broadcast_id == bluetooth::le_audio::kBroadcastIdInvalid) continue;
121 instance->available_broadcast_ids_.emplace_back(broadcast_id);
122 }
123
124 if (instance->available_broadcast_ids_.empty()) {
125 log::fatal("Unable to generate proper broadcast identifiers.");
126 }
127 }));
128 }
129
CleanUp()130 void CleanUp() {
131 log::info("Broadcaster");
132 broadcasts_.clear();
133 callbacks_ = nullptr;
134 is_iso_running_ = false;
135
136 if (!LeAudioClient::IsLeAudioClientRunning())
137 IsoManager::GetInstance()->Stop();
138
139 queued_start_broadcast_request_ = std::nullopt;
140 queued_create_broadcast_request_ = std::nullopt;
141
142 if (le_audio_source_hal_client_) {
143 le_audio_source_hal_client_->Stop();
144 auto result =
145 CodecManager::GetInstance()->UpdateActiveBroadcastAudioHalClient(
146 le_audio_source_hal_client_.get(), false);
147 log::assert_that(result, "Could not update session in codec manager");
148 le_audio_source_hal_client_.reset();
149 }
150 }
151
Stop()152 void Stop() {
153 log::info("Broadcaster");
154
155 for (auto& sm_pair : broadcasts_) {
156 StopAudioBroadcast(sm_pair.first);
157 }
158 }
159
preparePublicAnnouncement(uint8_t features,const LeAudioLtvMap & metadata)160 static PublicBroadcastAnnouncementData preparePublicAnnouncement(
161 uint8_t features, const LeAudioLtvMap& metadata) {
162 PublicBroadcastAnnouncementData announcement;
163
164 /* Prepare the announcement */
165 announcement.features = features;
166 announcement.metadata = metadata.Values();
167 return announcement;
168 }
169
prepareBasicAnnouncement(const std::vector<BroadcastSubgroupCodecConfig> & subgroup_configs,const std::vector<LeAudioLtvMap> & metadata_group)170 static BasicAudioAnnouncementData prepareBasicAnnouncement(
171 const std::vector<BroadcastSubgroupCodecConfig>& subgroup_configs,
172 const std::vector<LeAudioLtvMap>& metadata_group) {
173 BasicAudioAnnouncementData announcement;
174
175 /* Prepare the announcement */
176 announcement.presentation_delay_us = 40000; /* us */
177
178 log::assert_that(subgroup_configs.size() == metadata_group.size(),
179 "The number of metadata subgroups {} does not match the "
180 "number of subgroup configurations {}.",
181 metadata_group.size(), subgroup_configs.size());
182
183 uint8_t subgroup_idx = 0;
184 uint8_t bis_index = 0;
185 while (subgroup_idx < subgroup_configs.size() &&
186 subgroup_idx < metadata_group.size()) {
187 const auto& subgroup_config = subgroup_configs.at(subgroup_idx);
188 const auto& metadata = metadata_group.at(subgroup_idx);
189
190 auto const& codec_id = subgroup_config.GetLeAudioCodecId();
191 auto const subgroup_codec_spec =
192 subgroup_config.GetCommonBisCodecSpecData();
193 auto opt_vendor_spec_data = subgroup_config.GetVendorCodecSpecData();
194
195 /* Note: Currently we have a single audio source configured with a one
196 * set of codec/pcm parameters thus we can use a single subgroup
197 * for all the BISes. Configure common BIS codec params at the
198 * subgroup level.
199 */
200 BasicAudioAnnouncementSubgroup config = {
201 .codec_config =
202 {
203 .codec_id = codec_id.coding_format,
204 .vendor_company_id = codec_id.vendor_company_id,
205 .vendor_codec_id = codec_id.vendor_codec_id,
206 .codec_specific_params =
207 opt_vendor_spec_data.has_value()
208 ? std::map<uint8_t, std::vector<uint8_t>>{}
209 : subgroup_codec_spec.Values(),
210 .vendor_codec_specific_params =
211 std::move(opt_vendor_spec_data),
212 },
213 .metadata = metadata.Values(),
214 .bis_configs = {},
215 };
216
217 for (uint8_t bis_cfg_idx = 0;
218 bis_cfg_idx < subgroup_config.GetAllBisConfigCount();
219 ++bis_cfg_idx) {
220 auto bis_cfg_num_of_bises = subgroup_config.GetNumBis(bis_cfg_idx);
221 for (uint8_t bis_num = 0; bis_num < bis_cfg_num_of_bises; ++bis_num) {
222 // Internally BISes are indexed from 0 in each subgroup, but the BT
223 // spec requires the indices to start from 1 in the entire BIG.
224 ++bis_index;
225
226 // Check for vendor byte array
227 bluetooth::le_audio::BasicAudioAnnouncementBisConfig bis_config;
228 auto vendor_config =
229 subgroup_config.GetBisVendorCodecSpecData(bis_num);
230 if (vendor_config) {
231 bis_config.vendor_codec_specific_params = vendor_config.value();
232 }
233
234 // Check for non vendor LTVs
235 auto config_ltv =
236 subgroup_config.GetBisCodecSpecData(bis_num, bis_cfg_idx);
237 if (config_ltv) {
238 // Remove the part which is common with the parent subgroup
239 // parameters
240 config_ltv->RemoveAllTypes(subgroup_codec_spec);
241 bis_config.codec_specific_params = config_ltv->Values();
242 }
243
244 bis_config.bis_index = bis_index;
245 config.bis_configs.push_back(std::move(bis_config));
246 }
247 }
248
249 announcement.subgroup_configs.push_back(config);
250 ++subgroup_idx;
251 }
252
253 return announcement;
254 }
255
UpdateStreamingContextTypeOnAllSubgroups(const AudioContexts & contexts)256 void UpdateStreamingContextTypeOnAllSubgroups(const AudioContexts& contexts) {
257 log::debug("context_type_map={}", contexts.to_string());
258
259 auto ccids = ContentControlIdKeeper::GetInstance()->GetAllCcids(contexts);
260 if (ccids.empty()) {
261 log::warn("No content providers available for context_type_map={}.",
262 contexts.to_string());
263 }
264
265 std::vector<uint8_t> stream_context_vec(2);
266 auto pp = stream_context_vec.data();
267 UINT16_TO_STREAM(pp, contexts.value());
268
269 for (auto const& kv_it : broadcasts_) {
270 auto& broadcast = kv_it.second;
271 if (broadcast->GetState() == BroadcastStateMachine::State::STREAMING) {
272 auto announcement = broadcast->GetBroadcastAnnouncement();
273 bool broadcast_update = false;
274
275 // Replace context type and CCID list
276 for (auto& subgroup : announcement.subgroup_configs) {
277 auto subgroup_ltv = LeAudioLtvMap(subgroup.metadata);
278 bool subgroup_update = false;
279
280 auto existing_context =
281 subgroup_ltv.Find(bluetooth::le_audio::types::
282 kLeAudioMetadataTypeStreamingAudioContext);
283 if (existing_context) {
284 if (memcmp(stream_context_vec.data(), existing_context->data(),
285 existing_context->size()) != 0) {
286 subgroup_ltv.Add(bluetooth::le_audio::types::
287 kLeAudioMetadataTypeStreamingAudioContext,
288 stream_context_vec);
289 subgroup_update = true;
290 }
291 } else {
292 subgroup_ltv.Add(bluetooth::le_audio::types::
293 kLeAudioMetadataTypeStreamingAudioContext,
294 stream_context_vec);
295 subgroup_update = true;
296 }
297
298 auto existing_ccid_list = subgroup_ltv.Find(
299 bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
300 if (existing_ccid_list) {
301 if (ccids.empty()) {
302 subgroup_ltv.Remove(
303 bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
304 subgroup_update = true;
305
306 } else if (!std::is_permutation(ccids.begin(), ccids.end(),
307 existing_ccid_list->begin())) {
308 subgroup_ltv.Add(
309 bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList,
310 ccids);
311 subgroup_update = true;
312 }
313 } else if (!ccids.empty()) {
314 subgroup_ltv.Add(
315 bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList,
316 ccids);
317 subgroup_update = true;
318 }
319
320 if (subgroup_update) {
321 subgroup.metadata = subgroup_ltv.Values();
322 broadcast_update = true;
323 }
324 }
325
326 if (broadcast_update) {
327 broadcast->UpdateBroadcastAnnouncement(std::move(announcement));
328 }
329 }
330 }
331 }
332
UpdateMetadata(uint32_t broadcast_id,const std::string & broadcast_name,const std::vector<uint8_t> & public_metadata,const std::vector<std::vector<uint8_t>> & subgroup_metadata)333 void UpdateMetadata(
334 uint32_t broadcast_id, const std::string& broadcast_name,
335 const std::vector<uint8_t>& public_metadata,
336 const std::vector<std::vector<uint8_t>>& subgroup_metadata) override {
337 std::vector<LeAudioLtvMap> subgroup_ltvs;
338
339 if (broadcasts_.count(broadcast_id) == 0) {
340 log::error("No such broadcast_id={}", broadcast_id);
341 return;
342 }
343
344 log::info("For broadcast_id={}", broadcast_id);
345
346 for (const std::vector<uint8_t>& metadata : subgroup_metadata) {
347 /* Prepare the announcement format */
348 bool is_metadata_valid;
349 auto ltv = LeAudioLtvMap::Parse(metadata.data(), metadata.size(), is_metadata_valid);
350 if (!is_metadata_valid) {
351 log::error("Invalid metadata provided.");
352 return;
353 }
354
355 auto context_type = AudioContexts(LeAudioContextType::MEDIA);
356
357 /* Adds multiple contexts and CCIDs regardless of the incoming audio
358 * context. Android has only two CCIDs, one for Media and one for
359 * Conversational context. Even though we are not broadcasting
360 * Conversational streams, some PTS test cases wants multiple CCIDs.
361 */
362 if (stack_config_get_interface()
363 ->get_pts_force_le_audio_multiple_contexts_metadata()) {
364 context_type =
365 LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL;
366 auto stream_context_vec =
367 ltv.Find(bluetooth::le_audio::types::
368 kLeAudioMetadataTypeStreamingAudioContext);
369 if (stream_context_vec) {
370 auto pp = stream_context_vec.value().data();
371 if (stream_context_vec.value().size() < 2) {
372 log::error("stream_context_vec.value() size < 2");
373 return;
374 }
375 UINT16_TO_STREAM(pp, context_type.value());
376 }
377 }
378
379 auto stream_context_vec =
380 ltv.Find(bluetooth::le_audio::types::
381 kLeAudioMetadataTypeStreamingAudioContext);
382 if (stream_context_vec) {
383 auto pp = stream_context_vec.value().data();
384 if (stream_context_vec.value().size() < 2) {
385 log::error("stream_context_vec.value() size < 2");
386 return;
387 }
388 STREAM_TO_UINT16(context_type.value_ref(), pp);
389 }
390
391 // Append the CCID list
392 auto ccid_vec =
393 ContentControlIdKeeper::GetInstance()->GetAllCcids(context_type);
394 if (!ccid_vec.empty()) {
395 ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList,
396 ccid_vec);
397 }
398
399 // Push to subgroup ltvs
400 subgroup_ltvs.push_back(ltv);
401 }
402
403 if (broadcasts_[broadcast_id]->IsPublicBroadcast()) {
404 // Only update broadcast name and public metadata if current broadcast is
405 // public Otherwise ignore those fields
406 bool is_public_metadata_valid;
407 LeAudioLtvMap public_ltv =
408 LeAudioLtvMap::Parse(public_metadata.data(), public_metadata.size(),
409 is_public_metadata_valid);
410 if (!is_public_metadata_valid) {
411 log::error("Invalid public metadata provided.");
412 return;
413 }
414 PublicBroadcastAnnouncementData pb_announcement =
415 preparePublicAnnouncement(broadcasts_[broadcast_id]
416 ->GetPublicBroadcastAnnouncement()
417 .features,
418 public_ltv);
419
420 broadcasts_[broadcast_id]->UpdatePublicBroadcastAnnouncement(
421 broadcast_id, broadcast_name, pb_announcement);
422 }
423
424 auto& subgroup_configs = broadcasts_[broadcast_id]->GetCodecConfig();
425 BasicAudioAnnouncementData announcement =
426 prepareBasicAnnouncement(subgroup_configs, subgroup_ltvs);
427
428 broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
429 std::move(announcement));
430 }
431
432 /* Choose the dominating audio context when multiple contexts are mixed */
ChooseConfigurationContextType(AudioContexts audio_contexts)433 LeAudioContextType ChooseConfigurationContextType(
434 AudioContexts audio_contexts) {
435 log::debug("Got contexts={}", bluetooth::common::ToString(audio_contexts));
436
437 /* Prioritize the most common use cases. */
438 if (audio_contexts.any()) {
439 LeAudioContextType context_priority_list[] = {
440 LeAudioContextType::LIVE, LeAudioContextType::GAME,
441 LeAudioContextType::MEDIA, LeAudioContextType::EMERGENCYALARM,
442 LeAudioContextType::ALERTS, LeAudioContextType::INSTRUCTIONAL,
443 LeAudioContextType::NOTIFICATIONS, LeAudioContextType::SOUNDEFFECTS,
444 };
445 for (auto ct : context_priority_list) {
446 if (audio_contexts.test(ct)) {
447 log::debug("Selecting configuration context type: {}", ToString(ct));
448 return ct;
449 }
450 }
451 }
452
453 auto fallback_config = LeAudioContextType::MEDIA;
454 log::debug("Selecting configuration context type: {}",
455 ToString(fallback_config));
456 return fallback_config;
457 }
458
CreateAudioBroadcast(bool is_public,const std::string & broadcast_name,const std::optional<bluetooth::le_audio::BroadcastCode> & broadcast_code,const std::vector<uint8_t> & public_metadata,const std::vector<uint8_t> & subgroup_quality,const std::vector<std::vector<uint8_t>> & subgroup_metadata)459 void CreateAudioBroadcast(
460 bool is_public, const std::string& broadcast_name,
461 const std::optional<bluetooth::le_audio::BroadcastCode>& broadcast_code,
462 const std::vector<uint8_t>& public_metadata,
463 const std::vector<uint8_t>& subgroup_quality,
464 const std::vector<std::vector<uint8_t>>& subgroup_metadata) override {
465 uint8_t public_features = 0;
466 LeAudioLtvMap public_ltv;
467 std::vector<LeAudioLtvMap> subgroup_ltvs;
468
469 if (queued_create_broadcast_request_) {
470 log::error("Not processed yet queued broadcast");
471 callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
472 false);
473 return;
474 }
475
476 if (is_public) {
477 // Prepare public broadcast announcement format
478 bool is_metadata_valid;
479 public_ltv = LeAudioLtvMap::Parse(
480 public_metadata.data(), public_metadata.size(), is_metadata_valid);
481 if (!is_metadata_valid) {
482 log::error("Invalid metadata provided.");
483 callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
484 false);
485 return;
486 }
487 // Prepare public features byte
488 // bit 0 Encryption broadcast stream encrypted or not
489 // bit 1 Standard quality audio configuration present or not
490 // bit 2 High quality audio configuration present or not
491 // bit 3-7 RFU
492 public_features = static_cast<uint8_t>(broadcast_code ? 1 : 0);
493 }
494
495 auto broadcast_id = available_broadcast_ids_.back();
496 available_broadcast_ids_.pop_back();
497 if (available_broadcast_ids_.size() == 0) GenerateBroadcastIds();
498
499 auto context_type = AudioContexts(LeAudioContextType::MEDIA);
500
501 /* Adds multiple contexts and CCIDs regardless of the incoming audio
502 * context. Android has only two CCIDs, one for Media and one for
503 * Conversational context. Even though we are not broadcasting
504 * Conversational streams, some PTS test cases wants multiple CCIDs.
505 */
506 if (stack_config_get_interface()
507 ->get_pts_force_le_audio_multiple_contexts_metadata()) {
508 context_type =
509 LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL;
510 }
511
512 for (const uint8_t quality : subgroup_quality) {
513 if (quality == bluetooth::le_audio::QUALITY_STANDARD) {
514 public_features |= bluetooth::le_audio::kLeAudioQualityStandard;
515 } else if (quality == bluetooth::le_audio::QUALITY_HIGH) {
516 public_features |= bluetooth::le_audio::kLeAudioQualityHigh;
517 }
518 }
519
520 for (const std::vector<uint8_t>& metadata : subgroup_metadata) {
521 /* Prepare the announcement format */
522 bool is_metadata_valid;
523 auto ltv = LeAudioLtvMap::Parse(metadata.data(), metadata.size(), is_metadata_valid);
524 if (!is_metadata_valid) {
525 log::error("Invalid metadata provided.");
526 callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
527 false);
528 return;
529 }
530
531 if (stack_config_get_interface()
532 ->get_pts_force_le_audio_multiple_contexts_metadata()) {
533 auto stream_context_vec =
534 ltv.Find(bluetooth::le_audio::types::
535 kLeAudioMetadataTypeStreamingAudioContext);
536 if (stream_context_vec) {
537 if (stream_context_vec.value().size() < 2) {
538 log::error("kLeAudioMetadataTypeStreamingAudioContext size < 2");
539 callbacks_->OnBroadcastCreated(
540 bluetooth::le_audio::kBroadcastIdInvalid, false);
541 return;
542 }
543 auto pp = stream_context_vec.value().data();
544 UINT16_TO_STREAM(pp, context_type.value());
545 }
546 }
547
548 auto stream_context_vec =
549 ltv.Find(bluetooth::le_audio::types::
550 kLeAudioMetadataTypeStreamingAudioContext);
551 if (stream_context_vec) {
552 if (stream_context_vec.value().size() < 2) {
553 log::error("kLeAudioMetadataTypeStreamingAudioContext size < 2");
554 callbacks_->OnBroadcastCreated(
555 bluetooth::le_audio::kBroadcastIdInvalid, false);
556 return;
557 }
558
559 auto pp = stream_context_vec.value().data();
560 STREAM_TO_UINT16(context_type.value_ref(), pp);
561 }
562
563 // Append the CCID list
564 auto ccid_vec =
565 ContentControlIdKeeper::GetInstance()->GetAllCcids(context_type);
566 if (!ccid_vec.empty()) {
567 ltv.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList,
568 ccid_vec);
569 }
570
571 // Push to subgroup ltvs
572 subgroup_ltvs.push_back(ltv);
573 }
574
575 // Prepare the configuration requirements for each subgroup.
576 // Note: For now, each subgroup contains exactly the same content, but
577 // differs in codec configuration.
578 CodecManager::BroadcastConfigurationRequirements requirements;
579 for (auto& idx : subgroup_quality) {
580 requirements.subgroup_quality.push_back(
581 {ChooseConfigurationContextType(context_type), idx});
582 }
583
584 if (!le_audio_source_hal_client_) {
585 le_audio_source_hal_client_ =
586 LeAudioSourceAudioHalClient::AcquireBroadcast();
587 if (!le_audio_source_hal_client_) {
588 log::error("Could not acquire le audio");
589 return;
590 }
591 auto result =
592 CodecManager::GetInstance()->UpdateActiveBroadcastAudioHalClient(
593 le_audio_source_hal_client_.get(), true);
594 log::assert_that(result, "Could not update session in codec manager");
595 }
596
597 auto config = CodecManager::GetInstance()->GetBroadcastConfig(requirements);
598 if (!config) {
599 log::error("No valid broadcast offload config");
600 callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
601 false);
602 return;
603 }
604
605 if (public_features & bluetooth::le_audio::kLeAudioQualityHigh &&
606 config->GetSamplingFrequencyHzMax() < 48000) {
607 log::warn(
608 "Preferred quality isn't supported. Fallback to standard audio "
609 "quality");
610 public_features &= (0xFFFF & ~bluetooth::le_audio::kLeAudioQualityHigh);
611 public_features |= bluetooth::le_audio::kLeAudioQualityStandard;
612 }
613
614 BroadcastStateMachineConfig msg = {
615 .is_public = is_public,
616 .broadcast_id = broadcast_id,
617 .broadcast_name = broadcast_name,
618 .streaming_phy = GetStreamingPhy(),
619 .config = *config,
620 .announcement =
621 prepareBasicAnnouncement(config->subgroups, subgroup_ltvs),
622 .broadcast_code = std::move(broadcast_code)};
623 if (is_public) {
624 msg.public_announcement =
625 preparePublicAnnouncement(public_features, public_ltv);
626 }
627
628 // If there is ongoing ISO traffic, it might be a unicast stream
629 if (is_iso_running_) {
630 log::info("Iso is still active. Queueing broadcast creation for later.");
631 if (queued_create_broadcast_request_) {
632 log::warn(
633 "Already queued. Updating queued broadcast creation with the new "
634 "configuration.");
635 }
636 queued_create_broadcast_request_ = std::move(msg);
637 return;
638 }
639
640 InstantiateBroadcast(std::move(msg));
641 }
642
InstantiateBroadcast(BroadcastStateMachineConfig msg)643 void InstantiateBroadcast(BroadcastStateMachineConfig msg) {
644 log::info("CreateAudioBroadcast");
645
646 /* Put the new broadcast on the initialization queue, notify the error and
647 * drop the pending broadcast data if init fails.
648 */
649 pending_broadcasts_.push_back(
650 BroadcastStateMachine::CreateInstance(std::move(msg)));
651 if (!pending_broadcasts_.back()->Initialize()) {
652 pending_broadcasts_.pop_back();
653 callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
654 false);
655 }
656 }
657
SuspendAudioBroadcast(uint32_t broadcast_id)658 void SuspendAudioBroadcast(uint32_t broadcast_id) override {
659 log::info("broadcast_id={}", broadcast_id);
660
661 if (broadcasts_.count(broadcast_id) != 0) {
662 log::info("Stopping AudioHalClient");
663 if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop();
664 broadcasts_[broadcast_id]->SetMuted(true);
665 broadcasts_[broadcast_id]->ProcessMessage(
666 BroadcastStateMachine::Message::SUSPEND, nullptr);
667 } else {
668 log::error("No such broadcast_id={}", broadcast_id);
669 }
670 }
671
IsAnyoneStreaming()672 static bool IsAnyoneStreaming() {
673 if (!instance) return false;
674
675 auto const& iter =
676 std::find_if(instance->broadcasts_.cbegin(),
677 instance->broadcasts_.cend(), [](auto const& sm) {
678 return sm.second->GetState() ==
679 BroadcastStateMachine::State::STREAMING;
680 });
681 return (iter != instance->broadcasts_.cend());
682 }
683
StartAudioBroadcast(uint32_t broadcast_id)684 void StartAudioBroadcast(uint32_t broadcast_id) override {
685 log::info("Starting broadcast_id={}", broadcast_id);
686
687 if (queued_start_broadcast_request_) {
688 log::error("Not processed yet start broadcast request");
689 return;
690 }
691
692 if (is_iso_running_) {
693 queued_start_broadcast_request_ = broadcast_id;
694 return;
695 }
696
697 if (IsAnyoneStreaming()) {
698 log::error("Stop the other broadcast first!");
699 return;
700 }
701
702 if (broadcasts_.count(broadcast_id) != 0) {
703 if (!le_audio_source_hal_client_) {
704 le_audio_source_hal_client_ =
705 LeAudioSourceAudioHalClient::AcquireBroadcast();
706 if (!le_audio_source_hal_client_) {
707 log::error("Could not acquire le audio");
708 return;
709 }
710
711 auto result =
712 CodecManager::GetInstance()->UpdateActiveBroadcastAudioHalClient(
713 le_audio_source_hal_client_.get(), true);
714 log::assert_that(result, "Could not update session in codec manager");
715 }
716
717 broadcasts_[broadcast_id]->ProcessMessage(
718 BroadcastStateMachine::Message::START, nullptr);
719 bluetooth::le_audio::MetricsCollector::Get()->OnBroadcastStateChanged(
720 true);
721 } else {
722 log::error("No such broadcast_id={}", broadcast_id);
723 }
724 }
725
StopAudioBroadcast(uint32_t broadcast_id)726 void StopAudioBroadcast(uint32_t broadcast_id) override {
727 if (broadcasts_.count(broadcast_id) == 0) {
728 log::error("no such broadcast_id={}", broadcast_id);
729 return;
730 }
731
732 log::info("Stopping AudioHalClient, broadcast_id={}", broadcast_id);
733
734 if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop();
735 broadcasts_[broadcast_id]->SetMuted(true);
736 broadcasts_[broadcast_id]->ProcessMessage(
737 BroadcastStateMachine::Message::STOP, nullptr);
738 bluetooth::le_audio::MetricsCollector::Get()->OnBroadcastStateChanged(
739 false);
740 }
741
DestroyAudioBroadcast(uint32_t broadcast_id)742 void DestroyAudioBroadcast(uint32_t broadcast_id) override {
743 log::info("Destroying broadcast_id={}", broadcast_id);
744 broadcasts_.erase(broadcast_id);
745
746 if (broadcasts_.empty() && le_audio_source_hal_client_) {
747 auto result =
748 CodecManager::GetInstance()->UpdateActiveBroadcastAudioHalClient(
749 le_audio_source_hal_client_.get(), false);
750 log::assert_that(result, "Could not update session in codec manager");
751 le_audio_source_hal_client_.reset();
752 }
753 }
754
GetBroadcastMetadataOpt(bluetooth::le_audio::BroadcastId broadcast_id)755 std::optional<bluetooth::le_audio::BroadcastMetadata> GetBroadcastMetadataOpt(
756 bluetooth::le_audio::BroadcastId broadcast_id) {
757 bluetooth::le_audio::BroadcastMetadata metadata;
758 for (auto const& kv_it : broadcasts_) {
759 if (kv_it.second->GetBroadcastId() == broadcast_id) {
760 metadata.is_public = kv_it.second->IsPublicBroadcast();
761 metadata.broadcast_id = kv_it.second->GetBroadcastId();
762 metadata.broadcast_name = kv_it.second->GetBroadcastName();
763 metadata.adv_sid = kv_it.second->GetAdvertisingSid();
764 metadata.pa_interval = kv_it.second->GetPaInterval();
765 metadata.addr = kv_it.second->GetOwnAddress();
766 metadata.addr_type = kv_it.second->GetOwnAddressType();
767 metadata.broadcast_code = kv_it.second->GetBroadcastCode();
768 metadata.basic_audio_announcement =
769 kv_it.second->GetBroadcastAnnouncement();
770 metadata.public_announcement =
771 kv_it.second->GetPublicBroadcastAnnouncement();
772 return metadata;
773 }
774 }
775 return std::nullopt;
776 }
777
GetBroadcastMetadata(uint32_t broadcast_id)778 void GetBroadcastMetadata(uint32_t broadcast_id) override {
779 if (broadcasts_.count(broadcast_id) == 0) {
780 log::error("No such broadcast_id={}", broadcast_id);
781 return;
782 }
783
784 auto meta = GetBroadcastMetadataOpt(broadcast_id);
785 if (!meta) {
786 log::error("No metadata for broadcast_id={}", broadcast_id);
787 return;
788 }
789 callbacks_->OnBroadcastMetadataChanged(broadcast_id,
790 std::move(meta.value()));
791 }
792
GetAllBroadcastStates(void)793 void GetAllBroadcastStates(void) override {
794 for (auto const& kv_it : broadcasts_) {
795 callbacks_->OnBroadcastStateChanged(
796 kv_it.second->GetBroadcastId(),
797 static_cast<bluetooth::le_audio::BroadcastState>(
798 kv_it.second->GetState()));
799 }
800 }
801
IsValidBroadcast(uint32_t broadcast_id,uint8_t addr_type,RawAddress addr,base::Callback<void (uint8_t,uint8_t,RawAddress,bool)> cb)802 void IsValidBroadcast(
803 uint32_t broadcast_id, uint8_t addr_type, RawAddress addr,
804 base::Callback<void(uint8_t /* broadcast_id */, uint8_t /* addr_type */,
805 RawAddress /* addr */, bool /* is_local */)>
806 cb) override {
807 if (broadcasts_.count(broadcast_id) == 0) {
808 log::error("No such broadcast_id={}", broadcast_id);
809 std::move(cb).Run(broadcast_id, addr_type, addr, false);
810 return;
811 }
812
813 broadcasts_[broadcast_id]->RequestOwnAddress(base::Bind(
814 [](uint32_t broadcast_id, uint8_t req_address_type,
815 RawAddress req_address,
816 base::Callback<void(uint8_t /* broadcast_id */,
817 uint8_t /* addr_type */, RawAddress /* addr */,
818 bool /* is_local */)>
819 cb,
820 uint8_t rcv_address_type, RawAddress rcv_address) {
821 bool is_local = (req_address_type == rcv_address_type) &&
822 (req_address == rcv_address);
823 std::move(cb).Run(broadcast_id, req_address_type, req_address,
824 is_local);
825 },
826 broadcast_id, addr_type, addr, std::move(cb)));
827 }
828
SetStreamingPhy(uint8_t phy)829 void SetStreamingPhy(uint8_t phy) override { current_phy_ = phy; }
830
GetStreamingPhy(void) const831 uint8_t GetStreamingPhy(void) const override { return current_phy_; }
832
BroadcastIdFromBigHandle(uint8_t big_handle) const833 BroadcastId BroadcastIdFromBigHandle(uint8_t big_handle) const {
834 auto pair_it =
835 std::find_if(broadcasts_.begin(), broadcasts_.end(),
836 [big_handle](auto const& entry) {
837 return entry.second->GetAdvertisingSid() == big_handle;
838 });
839 if (pair_it != broadcasts_.end()) {
840 return pair_it->second->GetBroadcastId();
841 }
842 return bluetooth::le_audio::kBroadcastIdInvalid;
843 }
844
OnSetupIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t big_handle)845 void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle,
846 uint8_t big_handle) override {
847 auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
848 log::assert_that(broadcasts_.count(broadcast_id) != 0,
849 "assert failed: broadcasts_.count(broadcast_id) != 0");
850 broadcasts_[broadcast_id]->OnSetupIsoDataPath(status, conn_handle);
851 }
852
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t big_handle)853 void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle,
854 uint8_t big_handle) override {
855 auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
856 log::assert_that(broadcasts_.count(broadcast_id) != 0,
857 "assert failed: broadcasts_.count(broadcast_id) != 0");
858 broadcasts_[broadcast_id]->OnRemoveIsoDataPath(status, conn_handle);
859 }
860
OnBigEvent(uint8_t event,void * data)861 void OnBigEvent(uint8_t event, void* data) override {
862 switch (event) {
863 case bluetooth::hci::iso_manager::kIsoEventBigOnCreateCmpl: {
864 auto* evt = static_cast<big_create_cmpl_evt*>(data);
865 auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
866 log::assert_that(broadcasts_.count(broadcast_id) != 0,
867 "assert failed: broadcasts_.count(broadcast_id) != 0");
868 broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT,
869 evt);
870
871 } break;
872 case bluetooth::hci::iso_manager::kIsoEventBigOnTerminateCmpl: {
873 auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
874 auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
875 log::assert_that(broadcasts_.count(broadcast_id) != 0,
876 "assert failed: broadcasts_.count(broadcast_id) != 0");
877 broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT,
878 evt);
879 auto result =
880 CodecManager::GetInstance()->UpdateActiveBroadcastAudioHalClient(
881 le_audio_source_hal_client_.get(), false);
882 log::assert_that(result, "Could not update session in codec manager");
883 le_audio_source_hal_client_.reset();
884 } break;
885 default:
886 log::error("Invalid event={}", event);
887 }
888 }
889
IsoTrafficEventCb(bool is_active)890 void IsoTrafficEventCb(bool is_active) {
891 is_iso_running_ = is_active;
892 log::info("is_iso_running: {}", is_iso_running_);
893 if (!is_iso_running_) {
894 if (queued_start_broadcast_request_) {
895 auto broadcast_id = *queued_start_broadcast_request_;
896 queued_start_broadcast_request_ = std::nullopt;
897
898 log::info("Start queued broadcast.");
899 StartAudioBroadcast(broadcast_id);
900 }
901 if (queued_create_broadcast_request_) {
902 auto broadcast_msg = std::move(*queued_create_broadcast_request_);
903 queued_create_broadcast_request_ = std::nullopt;
904
905 log::info("Create queued broadcast.");
906 InstantiateBroadcast(std::move(broadcast_msg));
907 }
908 }
909 }
910
Dump(int fd)911 void Dump(int fd) {
912 std::stringstream stream;
913
914 stream << " Number of broadcasts: " << broadcasts_.size() << "\n";
915 for (auto& broadcast_pair : broadcasts_) {
916 auto& broadcast = broadcast_pair.second;
917 if (broadcast) stream << *broadcast;
918 }
919
920 dprintf(fd, "%s", stream.str().c_str());
921 }
922
923 private:
924 static class BroadcastStateMachineCallbacks
925 : public IBroadcastStateMachineCallbacks {
OnStateMachineCreateStatus(uint32_t broadcast_id,bool initialized)926 void OnStateMachineCreateStatus(uint32_t broadcast_id,
927 bool initialized) override {
928 auto pending_broadcast = std::find_if(
929 instance->pending_broadcasts_.begin(),
930 instance->pending_broadcasts_.end(), [broadcast_id](auto& sm) {
931 return (sm->GetBroadcastId() == broadcast_id);
932 });
933 log::assert_that(pending_broadcast != instance->pending_broadcasts_.end(),
934 "assert failed: pending_broadcast != "
935 "instance->pending_broadcasts_.end()");
936 log::assert_that(
937 instance->broadcasts_.count(broadcast_id) == 0,
938 "assert failed: instance->broadcasts_.count(broadcast_id) == 0");
939
940 if (initialized) {
941 const uint32_t broadcast_id = (*pending_broadcast)->GetBroadcastId();
942 log::info("broadcast_id={} state={}", broadcast_id,
943 ToString((*pending_broadcast)->GetState()));
944
945 instance->broadcasts_[broadcast_id] = std::move(*pending_broadcast);
946 } else {
947 log::error("Failed creating broadcast!");
948 }
949 instance->pending_broadcasts_.erase(pending_broadcast);
950 instance->callbacks_->OnBroadcastCreated(broadcast_id, initialized);
951 }
952
OnStateMachineDestroyed(uint32_t broadcast_id)953 void OnStateMachineDestroyed(uint32_t broadcast_id) override {
954 /* This is a special case when state machine destructor calls this
955 * callback. It may happen during the Cleanup() call when all state
956 * machines are erased and instance can already be set to null to avoid
957 * unnecessary calls.
958 */
959 if (instance) instance->callbacks_->OnBroadcastDestroyed(broadcast_id);
960 }
961
getStreamerCount()962 static int getStreamerCount() {
963 return std::count_if(instance->broadcasts_.begin(),
964 instance->broadcasts_.end(), [](auto const& sm) {
965 log::verbose("broadcast_id={}, state={}",
966 sm.second->GetBroadcastId(),
967 ToString(sm.second->GetState()));
968 return sm.second->GetState() ==
969 BroadcastStateMachine::State::STREAMING;
970 });
971 }
972
OnStateMachineEvent(uint32_t broadcast_id,BroadcastStateMachine::State state,const void * data)973 void OnStateMachineEvent(uint32_t broadcast_id,
974 BroadcastStateMachine::State state,
975 const void* data) override {
976 log::info("broadcast_id={} state={}", broadcast_id, ToString(state));
977
978 switch (state) {
979 case BroadcastStateMachine::State::STOPPED:
980 /* Pass through */
981 case BroadcastStateMachine::State::CONFIGURING:
982 /* Pass through */
983 case BroadcastStateMachine::State::CONFIGURED:
984 /* Pass through */
985 case BroadcastStateMachine::State::STOPPING:
986 /* Nothing to do here? */
987 break;
988 case BroadcastStateMachine::State::STREAMING:
989 if (getStreamerCount() == 1) {
990 log::info("Starting AudioHalClient");
991
992 if (instance->broadcasts_.count(broadcast_id) != 0) {
993 const auto& broadcast = instance->broadcasts_.at(broadcast_id);
994 const auto& broadcast_config = broadcast->GetBroadcastConfig();
995
996 // Reconfigure encoder instances for the new stream requirements
997 audio_receiver_.CheckAndReconfigureEncoders(broadcast_config);
998
999 broadcast->SetMuted(false);
1000 auto is_started = instance->le_audio_source_hal_client_->Start(
1001 broadcast_config.GetAudioHalClientConfig(), &audio_receiver_);
1002 if (!is_started) {
1003 /* Audio Source setup failed - stop the broadcast */
1004 instance->StopAudioBroadcast(broadcast_id);
1005 return;
1006 }
1007
1008 instance->audio_data_path_state_ = AudioDataPathState::ACTIVE;
1009 }
1010 }
1011 break;
1012 };
1013
1014 instance->callbacks_->OnBroadcastStateChanged(
1015 broadcast_id,
1016 static_cast<bluetooth::le_audio::BroadcastState>(state));
1017 }
1018
OnOwnAddressResponse(uint32_t broadcast_id,uint8_t addr_type,RawAddress addr)1019 void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type,
1020 RawAddress addr) override {
1021 /* Not used currently */
1022 }
1023
OnBigCreated(const std::vector<uint16_t> & conn_handle)1024 void OnBigCreated(const std::vector<uint16_t>& conn_handle) {
1025 CodecManager::GetInstance()->UpdateBroadcastConnHandle(
1026 conn_handle,
1027 std::bind(
1028 &LeAudioSourceAudioHalClient::UpdateBroadcastAudioConfigToHal,
1029 instance->le_audio_source_hal_client_.get(),
1030 std::placeholders::_1));
1031 }
1032 } state_machine_callbacks_;
1033
1034 static class BroadcastAdvertisingCallbacks : public AdvertisingCallbacks {
OnAdvertisingSetStarted(int reg_id,uint8_t advertiser_id,int8_t tx_power,uint8_t status)1035 void OnAdvertisingSetStarted(int reg_id, uint8_t advertiser_id,
1036 int8_t tx_power, uint8_t status) {
1037 if (!instance) return;
1038
1039 if (reg_id == BroadcastStateMachine::kLeAudioBroadcastRegId &&
1040 !instance->pending_broadcasts_.empty()) {
1041 instance->pending_broadcasts_.back()->OnCreateAnnouncement(
1042 advertiser_id, tx_power, status);
1043 } else {
1044 log::warn(
1045 "Ignored OnAdvertisingSetStarted callback reg_id:{} "
1046 "advertiser_id:{}",
1047 reg_id, advertiser_id);
1048 }
1049 }
1050
OnAdvertisingEnabled(uint8_t advertiser_id,bool enable,uint8_t status)1051 void OnAdvertisingEnabled(uint8_t advertiser_id, bool enable,
1052 uint8_t status) {
1053 if (!instance) return;
1054
1055 auto const& iter = std::find_if(
1056 instance->broadcasts_.cbegin(), instance->broadcasts_.cend(),
1057 [advertiser_id](auto const& sm) {
1058 return sm.second->GetAdvertisingSid() == advertiser_id;
1059 });
1060 if (iter != instance->broadcasts_.cend()) {
1061 iter->second->OnEnableAnnouncement(enable, status);
1062 } else {
1063 log::warn("Ignored OnAdvertisingEnabled callback advertiser_id:{}",
1064 advertiser_id);
1065 }
1066 }
1067
OnAdvertisingDataSet(uint8_t advertiser_id,uint8_t status)1068 void OnAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
1069 log::warn(
1070 "Not being used, ignored OnAdvertisingDataSet callback "
1071 "advertiser_id:{}",
1072 advertiser_id);
1073 }
1074
OnScanResponseDataSet(uint8_t advertiser_id,uint8_t status)1075 void OnScanResponseDataSet(uint8_t advertiser_id, uint8_t status) {
1076 log::warn(
1077 "Not being used, ignored OnScanResponseDataSet callback "
1078 "advertiser_id:{}",
1079 advertiser_id);
1080 }
1081
OnAdvertisingParametersUpdated(uint8_t advertiser_id,int8_t tx_power,uint8_t status)1082 void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power,
1083 uint8_t status) {
1084 log::warn(
1085 "Not being used, ignored OnAdvertisingParametersUpdated callback "
1086 "advertiser_id:{}",
1087 advertiser_id);
1088 }
1089
OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id,uint8_t status)1090 void OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id,
1091 uint8_t status) {
1092 log::warn(
1093 "Not being used, ignored OnPeriodicAdvertisingParametersUpdated "
1094 "callback advertiser_id:{}",
1095 advertiser_id);
1096 }
1097
OnPeriodicAdvertisingDataSet(uint8_t advertiser_id,uint8_t status)1098 void OnPeriodicAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
1099 log::warn(
1100 "Not being used, ignored OnPeriodicAdvertisingDataSet callback "
1101 "advertiser_id:{}",
1102 advertiser_id);
1103 }
1104
OnPeriodicAdvertisingEnabled(uint8_t advertiser_id,bool enable,uint8_t status)1105 void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable,
1106 uint8_t status) {
1107 log::warn(
1108 "Not being used, ignored OnPeriodicAdvertisingEnabled callback "
1109 "advertiser_id:{}",
1110 advertiser_id);
1111 }
1112
OnOwnAddressRead(uint8_t advertiser_id,uint8_t address_type,RawAddress address)1113 void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type,
1114 RawAddress address) {
1115 log::warn(
1116 "Not being used, ignored OnOwnAddressRead callback advertiser_id:{}",
1117 advertiser_id);
1118 }
1119 } state_machine_adv_callbacks_;
1120
1121 static class LeAudioSourceCallbacksImpl
1122 : public LeAudioSourceAudioHalClient::Callbacks {
1123 public:
1124 LeAudioSourceCallbacksImpl() = default;
CheckAndReconfigureEncoders(const BroadcastConfiguration & broadcast_config)1125 void CheckAndReconfigureEncoders(
1126 const BroadcastConfiguration& broadcast_config) {
1127 /* TODO: Move software codec instance management to the Codec Manager */
1128 if (CodecManager::GetInstance()->GetCodecLocation() ==
1129 CodecLocation::ADSP) {
1130 return;
1131 }
1132
1133 auto codec_config = broadcast_config.GetAudioHalClientConfig();
1134
1135 /* Note: Currently we support only a single subgroup software encoding.
1136 * In future consider mirroring the same data in a different quality
1137 * subgroups.
1138 */
1139 auto const& subgroup_config = broadcast_config.subgroups.at(0);
1140
1141 auto const& codec_id = subgroup_config.GetLeAudioCodecId();
1142 /* TODO: We should act smart and reuse current configurations */
1143 sw_enc_.clear();
1144 while (sw_enc_.size() != subgroup_config.GetNumChannelsTotal()) {
1145 auto codec =
1146 bluetooth::le_audio::CodecInterface::CreateInstance(codec_id);
1147
1148 auto codec_status = codec->InitEncoder(codec_config, codec_config);
1149 if (codec_status !=
1150 bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
1151 log::error("Channel {} codec setup failed with err: {}",
1152 (uint32_t)sw_enc_.size(), codec_status);
1153 return;
1154 }
1155
1156 sw_enc_.emplace_back(std::move(codec));
1157 }
1158
1159 broadcast_config_ = broadcast_config;
1160 }
1161
sendBroadcastData(const std::unique_ptr<BroadcastStateMachine> & broadcast,std::vector<std::unique_ptr<bluetooth::le_audio::CodecInterface>> & encoders)1162 static void sendBroadcastData(
1163 const std::unique_ptr<BroadcastStateMachine>& broadcast,
1164 std::vector<std::unique_ptr<bluetooth::le_audio::CodecInterface>>&
1165 encoders) {
1166 auto const& config = broadcast->GetBigConfig();
1167 if (config == std::nullopt) {
1168 log::error(
1169 "Broadcast broadcast_id={} has no valid BIS configurations in "
1170 "state={}",
1171 broadcast->GetBroadcastId(), ToString(broadcast->GetState()));
1172 return;
1173 }
1174
1175 if (config->connection_handles.size() < encoders.size()) {
1176 log::error("Not enough BIS'es to broadcast all channels!");
1177 return;
1178 }
1179
1180 for (uint8_t chan = 0; chan < encoders.size(); ++chan) {
1181 IsoManager::GetInstance()->SendIsoData(
1182 config->connection_handles[chan],
1183 (const uint8_t*)encoders[chan]->GetDecodedSamples().data(),
1184 encoders[chan]->GetDecodedSamples().size() * 2);
1185 }
1186 }
1187
OnAudioDataReady(const std::vector<uint8_t> & data)1188 virtual void OnAudioDataReady(const std::vector<uint8_t>& data) override {
1189 if (!instance) return;
1190
1191 log::verbose("Received {} bytes.", data.size());
1192
1193 if (!broadcast_config_.has_value() ||
1194 (broadcast_config_->subgroups.size() == 0)) {
1195 log::error("Codec was not configured properly");
1196 return;
1197 }
1198
1199 /* Note: Currently we support only a single subgroup.
1200 * In future consider mirroring the same data in a different quality
1201 * subgroups.
1202 */
1203 auto const& subgroup_config = broadcast_config_->subgroups.at(0);
1204
1205 /* Constants for the channel data configuration */
1206 const auto num_bis = subgroup_config.GetNumBis();
1207 const auto bytes_per_sample = (subgroup_config.GetBitsPerSample() / 8);
1208
1209 /* Prepare encoded data for all channels */
1210 for (uint8_t bis_idx = 0; bis_idx < num_bis; ++bis_idx) {
1211 auto initial_channel_offset = bis_idx * bytes_per_sample;
1212 sw_enc_[bis_idx]->Encode(
1213 data.data() + initial_channel_offset, num_bis,
1214 subgroup_config.GetBisOctetsPerCodecFrame(bis_idx));
1215 }
1216
1217 /* Currently there is no way to broadcast multiple distinct streams.
1218 * We just receive all system sounds mixed into a one stream and each
1219 * broadcast gets the same data.
1220 */
1221 for (auto& broadcast_pair : instance->broadcasts_) {
1222 auto& broadcast = broadcast_pair.second;
1223 if ((broadcast->GetState() ==
1224 BroadcastStateMachine::State::STREAMING) &&
1225 !broadcast->IsMuted())
1226 sendBroadcastData(broadcast, sw_enc_);
1227 }
1228 log::verbose("All data sent.");
1229 }
1230
OnAudioSuspend(void)1231 virtual void OnAudioSuspend(void) override {
1232 log::info("");
1233 /* TODO: Should we suspend all broadcasts - remove BIGs? */
1234 if (instance)
1235 instance->audio_data_path_state_ = AudioDataPathState::SUSPENDED;
1236 }
1237
OnAudioResume(void)1238 virtual void OnAudioResume(void) override {
1239 log::info("");
1240 if (!instance) return;
1241
1242 /* TODO: Should we resume all broadcasts - recreate BIGs? */
1243 instance->audio_data_path_state_ = AudioDataPathState::ACTIVE;
1244
1245 if (!IsAnyoneStreaming()) {
1246 instance->le_audio_source_hal_client_->CancelStreamingRequest();
1247 return;
1248 }
1249
1250 instance->le_audio_source_hal_client_->ConfirmStreamingRequest();
1251 }
1252
OnAudioMetadataUpdate(const std::vector<struct playback_track_metadata_v7> source_metadata,DsaMode dsa_mode)1253 virtual void OnAudioMetadataUpdate(
1254 const std::vector<struct playback_track_metadata_v7> source_metadata,
1255 DsaMode dsa_mode) override {
1256 log::info("");
1257 if (!instance) return;
1258
1259 /* TODO: Should we take supported contexts from ASCS? */
1260 auto contexts = GetAudioContextsFromSourceMetadata(source_metadata);
1261 if (contexts.any()) {
1262 /* NOTICE: We probably don't want to change the stream configuration
1263 * on each metadata change, so just update the context type metadata.
1264 * Since we are not able to identify individual track streams and
1265 * they are all mixed inside a single data stream, we will update
1266 * the metadata of all BIS subgroups with the same combined context.
1267 */
1268 instance->UpdateStreamingContextTypeOnAllSubgroups(contexts);
1269 }
1270 }
1271
1272 private:
1273 std::optional<BroadcastConfiguration> broadcast_config_;
1274 std::vector<std::unique_ptr<bluetooth::le_audio::CodecInterface>> sw_enc_;
1275 } audio_receiver_;
1276
1277 bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_;
1278 std::map<uint32_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
1279 std::vector<std::unique_ptr<BroadcastStateMachine>> pending_broadcasts_;
1280 std::optional<BroadcastStateMachineConfig> queued_create_broadcast_request_;
1281 std::optional<uint32_t> queued_start_broadcast_request_;
1282
1283 /* Some BIG params are set globally */
1284 uint8_t current_phy_;
1285 AudioDataPathState audio_data_path_state_;
1286 std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_;
1287 std::vector<BroadcastId> available_broadcast_ids_;
1288
1289 // Flag to track iso state
1290 bool is_iso_running_ = false;
1291 };
1292
1293 /* Static members definitions */
1294 LeAudioBroadcasterImpl::BroadcastStateMachineCallbacks
1295 LeAudioBroadcasterImpl::state_machine_callbacks_;
1296 LeAudioBroadcasterImpl::LeAudioSourceCallbacksImpl
1297 LeAudioBroadcasterImpl::audio_receiver_;
1298 LeAudioBroadcasterImpl::BroadcastAdvertisingCallbacks
1299 LeAudioBroadcasterImpl::state_machine_adv_callbacks_;
1300 } /* namespace */
1301
Initialize(bluetooth::le_audio::LeAudioBroadcasterCallbacks * callbacks,base::Callback<bool ()> audio_hal_verifier)1302 void LeAudioBroadcaster::Initialize(
1303 bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks,
1304 base::Callback<bool()> audio_hal_verifier) {
1305 std::scoped_lock<std::mutex> lock(instance_mutex);
1306 log::info("");
1307 if (instance) {
1308 log::error("Already initialized");
1309 return;
1310 }
1311
1312 if (!bluetooth::shim::GetController()->SupportsBleIsochronousBroadcaster() &&
1313 !osi_property_get_bool("persist.bluetooth.fake_iso_support", false)) {
1314 log::warn("Isochronous Broadcast not supported by the controller!");
1315 return;
1316 }
1317
1318 if (!std::move(audio_hal_verifier).Run()) {
1319 log::fatal("HAL requirements not met. Init aborted.");
1320 }
1321
1322 IsoManager::GetInstance()->Start();
1323
1324 instance = new LeAudioBroadcasterImpl(callbacks);
1325 /* Register HCI event handlers */
1326 IsoManager::GetInstance()->RegisterBigCallbacks(instance);
1327 /* Register for active traffic */
1328 IsoManager::GetInstance()->RegisterOnIsoTrafficActiveCallback(
1329 [](bool is_active) {
1330 if (instance) instance->IsoTrafficEventCb(is_active);
1331 });
1332 }
1333
IsLeAudioBroadcasterRunning()1334 bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return instance; }
1335
Get(void)1336 LeAudioBroadcaster* LeAudioBroadcaster::Get(void) {
1337 log::info("");
1338 log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
1339 return instance;
1340 }
1341
Stop(void)1342 void LeAudioBroadcaster::Stop(void) {
1343 log::info("");
1344
1345 if (instance) {
1346 instance->Stop();
1347 }
1348 }
1349
Cleanup(void)1350 void LeAudioBroadcaster::Cleanup(void) {
1351 std::scoped_lock<std::mutex> lock(instance_mutex);
1352 log::info("");
1353
1354 if (instance == nullptr) return;
1355
1356 LeAudioBroadcasterImpl* ptr = instance;
1357 instance = nullptr;
1358
1359 ptr->CleanUp();
1360 delete ptr;
1361 }
1362
DebugDump(int fd)1363 void LeAudioBroadcaster::DebugDump(int fd) {
1364 std::scoped_lock<std::mutex> lock(instance_mutex);
1365 dprintf(fd, "Le Audio Broadcaster:\n");
1366 if (instance) instance->Dump(fd);
1367 dprintf(fd, "\n");
1368 }
1369