• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #include <mutex>
21 
22 #include "bta/include/bta_le_audio_api.h"
23 #include "bta/include/bta_le_audio_broadcaster_api.h"
24 #include "bta/le_audio/broadcaster/state_machine.h"
25 #include "bta/le_audio/content_control_id_keeper.h"
26 #include "bta/le_audio/le_audio_types.h"
27 #include "bta/le_audio/le_audio_utils.h"
28 #include "bta/le_audio/metrics_collector.h"
29 #include "device/include/controller.h"
30 #include "embdrv/lc3/include/lc3.h"
31 #include "gd/common/strings.h"
32 #include "internal_include/stack_config.h"
33 #include "osi/include/log.h"
34 #include "osi/include/properties.h"
35 #include "stack/include/btm_api_types.h"
36 #include "stack/include/btm_iso_api.h"
37 
38 using bluetooth::common::ToString;
39 using bluetooth::hci::IsoManager;
40 using bluetooth::hci::iso_manager::big_create_cmpl_evt;
41 using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
42 using bluetooth::hci::iso_manager::BigCallbacks;
43 using bluetooth::le_audio::BasicAudioAnnouncementData;
44 using bluetooth::le_audio::BasicAudioAnnouncementSubgroup;
45 using bluetooth::le_audio::BroadcastId;
46 using bluetooth::le_audio::PublicBroadcastAnnouncementData;
47 using le_audio::CodecManager;
48 using le_audio::ContentControlIdKeeper;
49 using le_audio::LeAudioCodecConfiguration;
50 using le_audio::LeAudioSourceAudioHalClient;
51 using le_audio::broadcaster::BigConfig;
52 using le_audio::broadcaster::BroadcastCodecWrapper;
53 using le_audio::broadcaster::BroadcastQosConfig;
54 using le_audio::broadcaster::BroadcastStateMachine;
55 using le_audio::broadcaster::BroadcastStateMachineConfig;
56 using le_audio::broadcaster::IBroadcastStateMachineCallbacks;
57 using le_audio::types::AudioContexts;
58 using le_audio::types::CodecLocation;
59 using le_audio::types::kLeAudioCodingFormatLC3;
60 using le_audio::types::LeAudioContextType;
61 using le_audio::types::LeAudioLtvMap;
62 using le_audio::utils::GetAllowedAudioContextsFromSourceMetadata;
63 
64 namespace {
65 class LeAudioBroadcasterImpl;
66 LeAudioBroadcasterImpl* instance;
67 std::mutex instance_mutex;
68 
69 /* Class definitions */
70 
71 /* LeAudioBroadcasterImpl class represents main implementation class for le
72  * audio broadcaster feature in the stack.
73  *
74  * This class may be bonded with Test socket which allows to drive an instance
75  * for test purposes.
76  */
77 class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
78   enum class AudioDataPathState {
79     INACTIVE,
80     ACTIVE,
81     SUSPENDED,
82   };
83 
84  public:
LeAudioBroadcasterImpl(bluetooth::le_audio::LeAudioBroadcasterCallbacks * callbacks_)85   LeAudioBroadcasterImpl(
86       bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_)
87       : callbacks_(callbacks_),
88         current_phy_(PHY_LE_2M),
89         audio_data_path_state_(AudioDataPathState::INACTIVE),
90         le_audio_source_hal_client_(nullptr) {
91     LOG_INFO();
92 
93     /* Register State machine callbacks */
94     BroadcastStateMachine::Initialize(&state_machine_callbacks_);
95 
96     GenerateBroadcastIds();
97   }
98 
99   ~LeAudioBroadcasterImpl() override = default;
100 
GenerateBroadcastIds(void)101   void GenerateBroadcastIds(void) {
102     btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand) {
103       if (!instance) return;
104 
105       /* LE Rand returns 8 octets. Lets' make 2 outstanding Broadcast Ids out
106        * of it */
107       for (int i = 0; i < 8; i += 4) {
108         BroadcastId broadcast_id = 0;
109         /* Broadcast ID should be 3 octets long (BAP v1.0 spec.) */
110         STREAM_TO_UINT24(broadcast_id, rand);
111         if (broadcast_id == bluetooth::le_audio::kBroadcastIdInvalid) continue;
112         instance->available_broadcast_ids_.emplace_back(broadcast_id);
113       }
114 
115       if (instance->available_broadcast_ids_.empty()) {
116         LOG_ALWAYS_FATAL("Unable to generate proper broadcast identifiers.");
117       }
118     }));
119   }
120 
CleanUp()121   void CleanUp() {
122     LOG_INFO("Broadcaster");
123     broadcasts_.clear();
124     callbacks_ = nullptr;
125 
126     if (le_audio_source_hal_client_) {
127       le_audio_source_hal_client_->Stop();
128       le_audio_source_hal_client_.reset();
129     }
130   }
131 
Stop()132   void Stop() {
133     LOG_INFO("Broadcaster");
134 
135     for (auto& sm_pair : broadcasts_) {
136       StopAudioBroadcast(sm_pair.first);
137     }
138   }
139 
preparePublicAnnouncement(uint8_t features,const LeAudioLtvMap & metadata)140   static PublicBroadcastAnnouncementData preparePublicAnnouncement(
141       uint8_t features, const LeAudioLtvMap& metadata) {
142     PublicBroadcastAnnouncementData announcement;
143 
144     /* Prepare the announcement */
145     announcement.features = features;
146     announcement.metadata = metadata.Values();
147     return announcement;
148   }
149 
prepareBasicAnnouncement(const BroadcastCodecWrapper & codec_config,const std::vector<LeAudioLtvMap> & metadata_group)150   static BasicAudioAnnouncementData prepareBasicAnnouncement(
151       const BroadcastCodecWrapper& codec_config,
152       const std::vector<LeAudioLtvMap>& metadata_group) {
153     BasicAudioAnnouncementData announcement;
154 
155     /* Prepare the announcement */
156     announcement.presentation_delay = 0x004E20; /* TODO: Use the proper value */
157 
158     auto const& codec_id = codec_config.GetLeAudioCodecId();
159 
160     for (const LeAudioLtvMap& metadata : metadata_group) {
161       /* Note: Currently we have a single audio source configured with a one
162        *       set of codec/pcm parameters thus we can use a single subgroup
163        *       for all the BISes. Configure common BIS codec params at the
164        *       subgroup level.
165        */
166       BasicAudioAnnouncementSubgroup config = {
167           .codec_config =
168               {
169                   .codec_id = codec_id.coding_format,
170                   .vendor_company_id = codec_id.vendor_company_id,
171                   .vendor_codec_id = codec_id.vendor_codec_id,
172                   .codec_specific_params =
173                       codec_config.GetSubgroupCodecSpecData().Values(),
174               },
175           .metadata = metadata.Values(),
176           .bis_configs = {},
177       };
178       /* BIS indices range is [1-31] - BASS, Sec.3.2 Broadcast Receive State. */
179       for (size_t i = 0; i < codec_config.GetNumChannels(); ++i) {
180         config.bis_configs.push_back(
181             {.codec_specific_params =
182                  codec_config.GetBisCodecSpecData(i + 1).Values(),
183              .bis_index = static_cast<uint8_t>(i + 1)});
184       }
185 
186       announcement.subgroup_configs.push_back(config);
187     }
188 
189     return announcement;
190   }
191 
UpdateStreamingContextTypeOnAllSubgroups(const AudioContexts & contexts)192   void UpdateStreamingContextTypeOnAllSubgroups(const AudioContexts& contexts) {
193     LOG_DEBUG("%s context_type_map=%s", __func__, contexts.to_string().c_str());
194 
195     auto ccids = ContentControlIdKeeper::GetInstance()->GetAllCcids(contexts);
196     if (ccids.empty()) {
197       LOG_WARN("%s No content providers available for context_type_map=%s.",
198                __func__, contexts.to_string().c_str());
199     }
200 
201     std::vector<uint8_t> stream_context_vec(2);
202     auto pp = stream_context_vec.data();
203     UINT16_TO_STREAM(pp, contexts.value());
204 
205     for (auto const& kv_it : broadcasts_) {
206       auto& broadcast = kv_it.second;
207       if (broadcast->GetState() == BroadcastStateMachine::State::STREAMING) {
208         auto announcement = broadcast->GetBroadcastAnnouncement();
209         bool broadcast_update = false;
210 
211         // Replace context type and CCID list
212         for (auto& subgroup : announcement.subgroup_configs) {
213           auto subgroup_ltv = LeAudioLtvMap(subgroup.metadata);
214           bool subgroup_update = false;
215 
216           auto existing_context = subgroup_ltv.Find(
217               le_audio::types::kLeAudioMetadataTypeStreamingAudioContext);
218           if (existing_context) {
219             if (memcmp(stream_context_vec.data(), existing_context->data(),
220                        existing_context->size()) != 0) {
221               subgroup_ltv.Add(
222                   le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
223                   stream_context_vec);
224               subgroup_update = true;
225             }
226           } else {
227             subgroup_ltv.Add(
228                 le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
229                 stream_context_vec);
230             subgroup_update = true;
231           }
232 
233           auto existing_ccid_list =
234               subgroup_ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
235           if (existing_ccid_list) {
236             if (ccids.empty()) {
237               subgroup_ltv.Remove(
238                   le_audio::types::kLeAudioMetadataTypeCcidList);
239               subgroup_update = true;
240 
241             } else if (!std::is_permutation(ccids.begin(), ccids.end(),
242                                             existing_ccid_list->begin())) {
243               subgroup_ltv.Add(le_audio::types::kLeAudioMetadataTypeCcidList,
244                                ccids);
245               subgroup_update = true;
246             }
247           } else if (!ccids.empty()) {
248             subgroup_ltv.Add(le_audio::types::kLeAudioMetadataTypeCcidList,
249                              ccids);
250             subgroup_update = true;
251           }
252 
253           if (subgroup_update) {
254             subgroup.metadata = subgroup_ltv.Values();
255             broadcast_update = true;
256           }
257         }
258 
259         if (broadcast_update) {
260           broadcast->UpdateBroadcastAnnouncement(std::move(announcement));
261         }
262       }
263     }
264   }
265 
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)266   void UpdateMetadata(
267       uint32_t broadcast_id, const std::string& broadcast_name,
268       const std::vector<uint8_t>& public_metadata,
269       const std::vector<std::vector<uint8_t>>& subgroup_metadata) override {
270     std::vector<LeAudioLtvMap> subgroup_ltvs;
271 
272     if (broadcasts_.count(broadcast_id) == 0) {
273       LOG_ERROR("No such broadcast_id=%d", broadcast_id);
274       return;
275     }
276 
277     LOG_INFO("For broadcast_id=%d", broadcast_id);
278 
279     auto& codec_config = broadcasts_[broadcast_id]->GetCodecConfig();
280 
281     for (const std::vector<uint8_t>& metadata : subgroup_metadata) {
282       /* Prepare the announcement format */
283       bool is_metadata_valid;
284       auto ltv = LeAudioLtvMap::Parse(metadata.data(), metadata.size(), is_metadata_valid);
285       if (!is_metadata_valid) {
286         LOG_ERROR("Invalid metadata provided.");
287         return;
288       }
289 
290       auto context_type = AudioContexts(LeAudioContextType::MEDIA);
291 
292       /* Adds multiple contexts and CCIDs regardless of the incoming audio
293        * context. Android has only two CCIDs, one for Media and one for
294        * Conversational context. Even though we are not broadcasting
295        * Conversational streams, some PTS test cases wants multiple CCIDs.
296        */
297       if (stack_config_get_interface()
298               ->get_pts_force_le_audio_multiple_contexts_metadata()) {
299         context_type =
300             LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL;
301         auto stream_context_vec = ltv.Find(
302             le_audio::types::kLeAudioMetadataTypeStreamingAudioContext);
303         if (stream_context_vec) {
304           auto pp = stream_context_vec.value().data();
305           if (stream_context_vec.value().size() < 2) {
306             LOG_ERROR("stream_context_vec.value() size < 2");
307             return;
308           }
309           UINT16_TO_STREAM(pp, context_type.value());
310         }
311       }
312 
313       auto stream_context_vec =
314           ltv.Find(le_audio::types::kLeAudioMetadataTypeStreamingAudioContext);
315       if (stream_context_vec) {
316         auto pp = stream_context_vec.value().data();
317         if (stream_context_vec.value().size() < 2) {
318           LOG_ERROR("stream_context_vec.value() size < 2");
319           return;
320         }
321         STREAM_TO_UINT16(context_type.value_ref(), pp);
322       }
323 
324       // Append the CCID list
325       auto ccid_vec =
326           ContentControlIdKeeper::GetInstance()->GetAllCcids(context_type);
327       if (!ccid_vec.empty()) {
328         ltv.Add(le_audio::types::kLeAudioMetadataTypeCcidList, ccid_vec);
329       }
330 
331       // Push to subgroup ltvs
332       subgroup_ltvs.push_back(ltv);
333     }
334 
335     if (broadcasts_[broadcast_id]->IsPublicBroadcast()) {
336       // Only update broadcast name and public metadata if current broadcast is
337       // public Otherwise ignore those fields
338       bool is_public_metadata_valid;
339       LeAudioLtvMap public_ltv =
340           LeAudioLtvMap::Parse(public_metadata.data(), public_metadata.size(),
341                                is_public_metadata_valid);
342       if (!is_public_metadata_valid) {
343         LOG_ERROR("Invalid public metadata provided.");
344         return;
345       }
346       PublicBroadcastAnnouncementData pb_announcement =
347           preparePublicAnnouncement(broadcasts_[broadcast_id]
348                                         ->GetPublicBroadcastAnnouncement()
349                                         .features,
350                                     public_ltv);
351 
352       broadcasts_[broadcast_id]->UpdatePublicBroadcastAnnouncement(
353           broadcast_id, broadcast_name, pb_announcement);
354     }
355 
356     BasicAudioAnnouncementData announcement =
357         prepareBasicAnnouncement(codec_config, subgroup_ltvs);
358 
359     broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
360         std::move(announcement));
361   }
362 
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)363   void CreateAudioBroadcast(
364       bool is_public, const std::string& broadcast_name,
365       const std::optional<bluetooth::le_audio::BroadcastCode>& broadcast_code,
366       const std::vector<uint8_t>& public_metadata,
367       const std::vector<uint8_t>& subgroup_quality,
368       const std::vector<std::vector<uint8_t>>& subgroup_metadata) override {
369     uint8_t public_features = 0;
370     LeAudioLtvMap public_ltv;
371     std::vector<LeAudioLtvMap> subgroup_ltvs;
372 
373     if (is_public) {
374       // Prepare public broadcast announcement format
375       bool is_metadata_valid;
376       public_ltv = LeAudioLtvMap::Parse(
377           public_metadata.data(), public_metadata.size(), is_metadata_valid);
378       if (!is_metadata_valid) {
379         LOG_ERROR("Invalid metadata provided.");
380         return;
381       }
382       // Prepare public features byte
383       // bit 0 Encryption broadcast stream encrypted or not
384       // bit 1 Standard quality audio configuration present or not
385       // bit 2 High quality audio configuration present or not
386       // bit 3-7 RFU
387       public_features = static_cast<uint8_t>(broadcast_code ? 1 : 0);
388     }
389 
390     auto broadcast_id = available_broadcast_ids_.back();
391     available_broadcast_ids_.pop_back();
392     if (available_broadcast_ids_.size() == 0) GenerateBroadcastIds();
393 
394     auto context_type = AudioContexts(LeAudioContextType::MEDIA);
395 
396     /* Adds multiple contexts and CCIDs regardless of the incoming audio
397      * context. Android has only two CCIDs, one for Media and one for
398      * Conversational context. Even though we are not broadcasting
399      * Conversational streams, some PTS test cases wants multiple CCIDs.
400      */
401     if (stack_config_get_interface()
402             ->get_pts_force_le_audio_multiple_contexts_metadata()) {
403       context_type =
404           LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL;
405     }
406 
407     for (const uint8_t quality : subgroup_quality) {
408       if (quality == bluetooth::le_audio::QUALITY_STANDARD) {
409         public_features |= bluetooth::le_audio::kLeAudioQualityStandard;
410       } else if (quality == bluetooth::le_audio::QUALITY_HIGH) {
411         public_features |= bluetooth::le_audio::kLeAudioQualityHigh;
412       }
413     }
414 
415     for (const std::vector<uint8_t>& metadata : subgroup_metadata) {
416       /* Prepare the announcement format */
417       bool is_metadata_valid;
418       auto ltv = LeAudioLtvMap::Parse(metadata.data(), metadata.size(), is_metadata_valid);
419       if (!is_metadata_valid) {
420         LOG_ERROR("Invalid metadata provided.");
421         return;
422       }
423 
424       if (stack_config_get_interface()
425               ->get_pts_force_le_audio_multiple_contexts_metadata()) {
426         auto stream_context_vec = ltv.Find(
427             le_audio::types::kLeAudioMetadataTypeStreamingAudioContext);
428         if (stream_context_vec) {
429           if (stream_context_vec.value().size() < 2) {
430             LOG_ERROR("kLeAudioMetadataTypeStreamingAudioContext size < 2");
431             return;
432           }
433           auto pp = stream_context_vec.value().data();
434           UINT16_TO_STREAM(pp, context_type.value());
435         }
436       }
437 
438       auto stream_context_vec =
439           ltv.Find(le_audio::types::kLeAudioMetadataTypeStreamingAudioContext);
440       if (stream_context_vec) {
441         if (stream_context_vec.value().size() < 2) {
442           LOG_ERROR("kLeAudioMetadataTypeStreamingAudioContext size < 2");
443           return;
444         }
445 
446         auto pp = stream_context_vec.value().data();
447         STREAM_TO_UINT16(context_type.value_ref(), pp);
448       }
449 
450       // Append the CCID list
451       auto ccid_vec =
452           ContentControlIdKeeper::GetInstance()->GetAllCcids(context_type);
453       if (!ccid_vec.empty()) {
454         ltv.Add(le_audio::types::kLeAudioMetadataTypeCcidList, ccid_vec);
455       }
456 
457       // Push to subgroup ltvs
458       subgroup_ltvs.push_back(ltv);
459     }
460 
461     if (CodecManager::GetInstance()->GetCodecLocation() ==
462         CodecLocation::ADSP) {
463       auto offload_config =
464           CodecManager::GetInstance()->GetBroadcastOffloadConfig();
465       if (offload_config == nullptr) {
466         LOG_ERROR("No valid broadcast offload config");
467         return;
468       }
469       BroadcastCodecWrapper codec_config(
470           {.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
471            .vendor_company_id =
472                le_audio::types::kLeAudioVendorCompanyIdUndefined,
473            .vendor_codec_id = le_audio::types::kLeAudioVendorCodecIdUndefined},
474           {.num_channels =
475                static_cast<uint8_t>(offload_config->stream_map.size()),
476            .sample_rate = offload_config->sampling_rate,
477            .bits_per_sample = offload_config->bits_per_sample,
478            .data_interval_us = offload_config->frame_duration},
479           offload_config->codec_bitrate, offload_config->octets_per_frame);
480       BroadcastQosConfig qos_config(offload_config->retransmission_number,
481                                     offload_config->max_transport_latency);
482 
483       BroadcastStateMachineConfig msg = {
484           .is_public = is_public,
485           .broadcast_name = broadcast_name,
486           .broadcast_id = broadcast_id,
487           .streaming_phy = GetStreamingPhy(),
488           .codec_wrapper = codec_config,
489           .qos_config = qos_config,
490           .announcement = prepareBasicAnnouncement(codec_config, subgroup_ltvs),
491           .broadcast_code = std::move(broadcast_code)};
492       if (is_public) {
493         msg.public_announcement =
494             preparePublicAnnouncement(public_features, public_ltv);
495       }
496       pending_broadcasts_.push_back(
497           std::move(BroadcastStateMachine::CreateInstance(std::move(msg))));
498     } else {
499       auto codec_qos_pair =
500           le_audio::broadcaster::getStreamConfigForContext(context_type);
501       BroadcastStateMachineConfig msg = {
502           .is_public = is_public,
503           .broadcast_name = broadcast_name,
504           .broadcast_id = broadcast_id,
505           .streaming_phy = GetStreamingPhy(),
506           .codec_wrapper = codec_qos_pair.first,
507           .qos_config = codec_qos_pair.second,
508           .announcement =
509               prepareBasicAnnouncement(codec_qos_pair.first, subgroup_ltvs),
510           .broadcast_code = std::move(broadcast_code)};
511       if (is_public) {
512         msg.public_announcement =
513             preparePublicAnnouncement(public_features, public_ltv);
514       }
515       /* Create the broadcaster instance - we'll receive it's init state in the
516        * async callback
517        */
518       pending_broadcasts_.push_back(
519           std::move(BroadcastStateMachine::CreateInstance(std::move(msg))));
520     }
521 
522     LOG_INFO("CreateAudioBroadcast");
523 
524     // Notify the error instead just fail silently
525     if (!pending_broadcasts_.back()->Initialize()) {
526       pending_broadcasts_.pop_back();
527       callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid,
528                                      false);
529     }
530   }
531 
SuspendAudioBroadcast(uint32_t broadcast_id)532   void SuspendAudioBroadcast(uint32_t broadcast_id) override {
533     LOG_INFO("broadcast_id=%d", broadcast_id);
534 
535     if (broadcasts_.count(broadcast_id) != 0) {
536       LOG_INFO("Stopping AudioHalClient");
537       if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop();
538       broadcasts_[broadcast_id]->SetMuted(true);
539       broadcasts_[broadcast_id]->ProcessMessage(
540           BroadcastStateMachine::Message::SUSPEND, nullptr);
541     } else {
542       LOG_ERROR("No such broadcast_id=%d", broadcast_id);
543     }
544   }
545 
IsAnyoneStreaming()546   static bool IsAnyoneStreaming() {
547     if (!instance) return false;
548 
549     auto const& iter =
550         std::find_if(instance->broadcasts_.cbegin(),
551                      instance->broadcasts_.cend(), [](auto const& sm) {
552                        return sm.second->GetState() ==
553                               BroadcastStateMachine::State::STREAMING;
554                      });
555     return (iter != instance->broadcasts_.cend());
556   }
557 
StartAudioBroadcast(uint32_t broadcast_id)558   void StartAudioBroadcast(uint32_t broadcast_id) override {
559     LOG_INFO("Starting broadcast_id=%d", broadcast_id);
560 
561     if (IsAnyoneStreaming()) {
562       LOG_ERROR("Stop the other broadcast first!");
563       return;
564     }
565 
566     if (broadcasts_.count(broadcast_id) != 0) {
567       if (!le_audio_source_hal_client_) {
568         le_audio_source_hal_client_ =
569             LeAudioSourceAudioHalClient::AcquireBroadcast();
570         if (!le_audio_source_hal_client_) {
571           LOG_ERROR("Could not acquire le audio");
572           return;
573         }
574       }
575 
576       broadcasts_[broadcast_id]->ProcessMessage(
577           BroadcastStateMachine::Message::START, nullptr);
578       le_audio::MetricsCollector::Get()->OnBroadcastStateChanged(true);
579     } else {
580       LOG_ERROR("No such broadcast_id=%d", broadcast_id);
581     }
582   }
583 
StopAudioBroadcast(uint32_t broadcast_id)584   void StopAudioBroadcast(uint32_t broadcast_id) override {
585     if (broadcasts_.count(broadcast_id) == 0) {
586       LOG_ERROR("no such broadcast_id=%d", broadcast_id);
587       return;
588     }
589 
590     LOG_INFO("Stopping AudioHalClient, broadcast_id=%d", broadcast_id);
591 
592     if (le_audio_source_hal_client_) le_audio_source_hal_client_->Stop();
593     broadcasts_[broadcast_id]->SetMuted(true);
594     broadcasts_[broadcast_id]->ProcessMessage(
595         BroadcastStateMachine::Message::STOP, nullptr);
596     le_audio::MetricsCollector::Get()->OnBroadcastStateChanged(false);
597   }
598 
DestroyAudioBroadcast(uint32_t broadcast_id)599   void DestroyAudioBroadcast(uint32_t broadcast_id) override {
600     LOG_INFO("Destroying broadcast_id=%d", broadcast_id);
601     broadcasts_.erase(broadcast_id);
602   }
603 
GetBroadcastMetadataOpt(bluetooth::le_audio::BroadcastId broadcast_id)604   std::optional<bluetooth::le_audio::BroadcastMetadata> GetBroadcastMetadataOpt(
605       bluetooth::le_audio::BroadcastId broadcast_id) {
606     bluetooth::le_audio::BroadcastMetadata metadata;
607     for (auto const& kv_it : broadcasts_) {
608       if (kv_it.second->GetBroadcastId() == broadcast_id) {
609         metadata.is_public = kv_it.second->IsPublicBroadcast();
610         metadata.broadcast_id = kv_it.second->GetBroadcastId();
611         metadata.broadcast_name = kv_it.second->GetBroadcastName();
612         metadata.adv_sid = kv_it.second->GetAdvertisingSid();
613         metadata.pa_interval = kv_it.second->GetPaInterval();
614         metadata.addr = kv_it.second->GetOwnAddress();
615         metadata.addr_type = kv_it.second->GetOwnAddressType();
616         metadata.broadcast_code = kv_it.second->GetBroadcastCode();
617         metadata.basic_audio_announcement =
618             kv_it.second->GetBroadcastAnnouncement();
619         metadata.public_announcement =
620             kv_it.second->GetPublicBroadcastAnnouncement();
621         return metadata;
622       }
623     }
624     return std::nullopt;
625   }
626 
GetBroadcastMetadata(uint32_t broadcast_id)627   void GetBroadcastMetadata(uint32_t broadcast_id) override {
628     if (broadcasts_.count(broadcast_id) == 0) {
629       LOG_ERROR("No such broadcast_id=%d", broadcast_id);
630       return;
631     }
632 
633     auto meta = GetBroadcastMetadataOpt(broadcast_id);
634     if (!meta) {
635       LOG_ERROR("No metadata for broadcast_id=%d", broadcast_id);
636       return;
637     }
638     callbacks_->OnBroadcastMetadataChanged(broadcast_id,
639                                            std::move(meta.value()));
640   }
641 
GetAllBroadcastStates(void)642   void GetAllBroadcastStates(void) override {
643     for (auto const& kv_it : broadcasts_) {
644       callbacks_->OnBroadcastStateChanged(
645           kv_it.second->GetBroadcastId(),
646           static_cast<bluetooth::le_audio::BroadcastState>(
647               kv_it.second->GetState()));
648     }
649   }
650 
IsValidBroadcast(uint32_t broadcast_id,uint8_t addr_type,RawAddress addr,base::Callback<void (uint8_t,uint8_t,RawAddress,bool)> cb)651   void IsValidBroadcast(
652       uint32_t broadcast_id, uint8_t addr_type, RawAddress addr,
653       base::Callback<void(uint8_t /* broadcast_id */, uint8_t /* addr_type */,
654                           RawAddress /* addr */, bool /* is_local */)>
655           cb) override {
656     if (broadcasts_.count(broadcast_id) == 0) {
657       LOG_ERROR("No such broadcast_id=%d", broadcast_id);
658       std::move(cb).Run(broadcast_id, addr_type, addr, false);
659       return;
660     }
661 
662     broadcasts_[broadcast_id]->RequestOwnAddress(base::Bind(
663         [](uint32_t broadcast_id, uint8_t req_address_type,
664            RawAddress req_address,
665            base::Callback<void(uint8_t /* broadcast_id */,
666                                uint8_t /* addr_type */, RawAddress /* addr */,
667                                bool /* is_local */)>
668                cb,
669            uint8_t rcv_address_type, RawAddress rcv_address) {
670           bool is_local = (req_address_type == rcv_address_type) &&
671                           (req_address == rcv_address);
672           std::move(cb).Run(broadcast_id, req_address_type, req_address,
673                             is_local);
674         },
675         broadcast_id, addr_type, addr, std::move(cb)));
676   }
677 
SetStreamingPhy(uint8_t phy)678   void SetStreamingPhy(uint8_t phy) override { current_phy_ = phy; }
679 
GetStreamingPhy(void) const680   uint8_t GetStreamingPhy(void) const override { return current_phy_; }
681 
BroadcastIdFromBigHandle(uint8_t big_handle) const682   BroadcastId BroadcastIdFromBigHandle(uint8_t big_handle) const {
683     auto pair_it =
684         std::find_if(broadcasts_.begin(), broadcasts_.end(),
685                      [big_handle](auto const& entry) {
686                        return entry.second->GetAdvertisingSid() == big_handle;
687                      });
688     if (pair_it != broadcasts_.end()) {
689       return pair_it->second->GetBroadcastId();
690     }
691     return bluetooth::le_audio::kBroadcastIdInvalid;
692   }
693 
OnSetupIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t big_handle)694   void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle,
695                           uint8_t big_handle) override {
696     auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
697     CHECK(broadcasts_.count(broadcast_id) != 0);
698     broadcasts_[broadcast_id]->OnSetupIsoDataPath(status, conn_handle);
699   }
700 
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t big_handle)701   void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle,
702                            uint8_t big_handle) override {
703     auto broadcast_id = BroadcastIdFromBigHandle(big_handle);
704     CHECK(broadcasts_.count(broadcast_id) != 0);
705     broadcasts_[broadcast_id]->OnRemoveIsoDataPath(status, conn_handle);
706   }
707 
OnBigEvent(uint8_t event,void * data)708   void OnBigEvent(uint8_t event, void* data) override {
709     switch (event) {
710       case bluetooth::hci::iso_manager::kIsoEventBigOnCreateCmpl: {
711         auto* evt = static_cast<big_create_cmpl_evt*>(data);
712         auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
713         CHECK(broadcasts_.count(broadcast_id) != 0);
714         broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT,
715                                                   evt);
716 
717       } break;
718       case bluetooth::hci::iso_manager::kIsoEventBigOnTerminateCmpl: {
719         auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
720         auto broadcast_id = BroadcastIdFromBigHandle(evt->big_id);
721         CHECK(broadcasts_.count(broadcast_id) != 0);
722         broadcasts_[broadcast_id]->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT,
723                                                   evt);
724         le_audio_source_hal_client_.reset();
725       } break;
726       default:
727         LOG_ERROR("Invalid event=%d", event);
728     }
729   }
730 
Dump(int fd)731   void Dump(int fd) {
732     std::stringstream stream;
733 
734     stream << "    Number of broadcasts: " << broadcasts_.size() << "\n";
735     for (auto& broadcast_pair : broadcasts_) {
736       auto& broadcast = broadcast_pair.second;
737       if (broadcast) stream << *broadcast;
738     }
739 
740     dprintf(fd, "%s", stream.str().c_str());
741   }
742 
743  private:
744   static class BroadcastStateMachineCallbacks
745       : public IBroadcastStateMachineCallbacks {
OnStateMachineCreateStatus(uint32_t broadcast_id,bool initialized)746     void OnStateMachineCreateStatus(uint32_t broadcast_id,
747                                     bool initialized) override {
748       auto pending_broadcast = std::find_if(
749           instance->pending_broadcasts_.begin(),
750           instance->pending_broadcasts_.end(), [broadcast_id](auto& sm) {
751             return (sm->GetBroadcastId() == broadcast_id);
752           });
753       LOG_ASSERT(pending_broadcast != instance->pending_broadcasts_.end());
754       LOG_ASSERT(instance->broadcasts_.count(broadcast_id) == 0);
755 
756       if (initialized) {
757         const uint32_t broadcast_id = (*pending_broadcast)->GetBroadcastId();
758         LOG_INFO("broadcast_id=%d state=%s", broadcast_id,
759                  ToString((*pending_broadcast)->GetState()).c_str());
760 
761         instance->broadcasts_[broadcast_id] = std::move(*pending_broadcast);
762       } else {
763         LOG_ERROR("Failed creating broadcast!");
764       }
765       instance->pending_broadcasts_.erase(pending_broadcast);
766       instance->callbacks_->OnBroadcastCreated(broadcast_id, initialized);
767     }
768 
OnStateMachineDestroyed(uint32_t broadcast_id)769     void OnStateMachineDestroyed(uint32_t broadcast_id) override {
770       /* This is a special case when state machine destructor calls this
771        * callback. It may happen during the Cleanup() call when all state
772        * machines are erased and instance can already be set to null to avoid
773        * unnecessary calls.
774        */
775       if (instance) instance->callbacks_->OnBroadcastDestroyed(broadcast_id);
776     }
777 
getStreamerCount()778     static int getStreamerCount() {
779       return std::count_if(instance->broadcasts_.begin(),
780                            instance->broadcasts_.end(), [](auto const& sm) {
781                              LOG_VERBOSE(
782                                  "broadcast_id=%d, state=%s",
783                                  sm.second->GetBroadcastId(),
784                                  ToString(sm.second->GetState()).c_str());
785                              return sm.second->GetState() ==
786                                     BroadcastStateMachine::State::STREAMING;
787                            });
788     }
789 
OnStateMachineEvent(uint32_t broadcast_id,BroadcastStateMachine::State state,const void * data)790     void OnStateMachineEvent(uint32_t broadcast_id,
791                              BroadcastStateMachine::State state,
792                              const void* data) override {
793       LOG_INFO("broadcast_id=%d state=%s", broadcast_id,
794                ToString(state).c_str());
795 
796       switch (state) {
797         case BroadcastStateMachine::State::STOPPED:
798           /* Pass through */
799         case BroadcastStateMachine::State::CONFIGURING:
800           /* Pass through */
801         case BroadcastStateMachine::State::CONFIGURED:
802           /* Pass through */
803         case BroadcastStateMachine::State::STOPPING:
804           /* Nothing to do here? */
805           break;
806         case BroadcastStateMachine::State::STREAMING:
807           if (getStreamerCount() == 1) {
808             LOG_INFO("Starting AudioHalClient");
809 
810             if (instance->broadcasts_.count(broadcast_id) != 0) {
811               const auto& broadcast = instance->broadcasts_.at(broadcast_id);
812 
813               // Reconfigure encoder instance for the new stream requirements
814               audio_receiver_.setCurrentCodecConfig(
815                   broadcast->GetCodecConfig());
816               audio_receiver_.CheckAndReconfigureEncoders();
817 
818               broadcast->SetMuted(false);
819               auto cfg = static_cast<const LeAudioCodecConfiguration*>(data);
820               auto is_started = instance->le_audio_source_hal_client_->Start(
821                   *cfg, &audio_receiver_);
822               if (!is_started) {
823                 /* Audio Source setup failed - stop the broadcast */
824                 instance->StopAudioBroadcast(broadcast_id);
825                 return;
826               }
827 
828               instance->audio_data_path_state_ = AudioDataPathState::ACTIVE;
829             }
830           }
831           break;
832       };
833 
834       instance->callbacks_->OnBroadcastStateChanged(
835           broadcast_id,
836           static_cast<bluetooth::le_audio::BroadcastState>(state));
837     }
838 
OnOwnAddressResponse(uint32_t broadcast_id,uint8_t addr_type,RawAddress addr)839     void OnOwnAddressResponse(uint32_t broadcast_id, uint8_t addr_type,
840                               RawAddress addr) override {
841       /* Not used currently */
842     }
843 
OnBigCreated(const std::vector<uint16_t> & conn_handle)844     void OnBigCreated(const std::vector<uint16_t>& conn_handle) {
845       CodecManager::GetInstance()->UpdateBroadcastConnHandle(
846           conn_handle,
847           std::bind(
848               &LeAudioSourceAudioHalClient::UpdateBroadcastAudioConfigToHal,
849               instance->le_audio_source_hal_client_.get(),
850               std::placeholders::_1));
851     }
852   } state_machine_callbacks_;
853 
854   static class LeAudioSourceCallbacksImpl
855       : public LeAudioSourceAudioHalClient::Callbacks {
856    public:
LeAudioSourceCallbacksImpl()857     LeAudioSourceCallbacksImpl()
858         : codec_wrapper_(le_audio::broadcaster::getStreamConfigForContext(
859                              AudioContexts(LeAudioContextType::UNSPECIFIED))
860                              .first) {}
861 
CheckAndReconfigureEncoders()862     void CheckAndReconfigureEncoders() {
863       auto const& codec_id = codec_wrapper_.GetLeAudioCodecId();
864       if (codec_id.coding_format != kLeAudioCodingFormatLC3) {
865         LOG_ERROR("Invalid codec ID: [%d:%d:%d]", codec_id.coding_format,
866                   codec_id.vendor_company_id, codec_id.vendor_codec_id);
867         return;
868       }
869 
870       if (enc_audio_buffers_.size() != codec_wrapper_.GetNumChannels()) {
871         enc_audio_buffers_.resize(codec_wrapper_.GetNumChannels());
872       }
873 
874       const int dt_us = codec_wrapper_.GetDataIntervalUs();
875       const int sr_hz = codec_wrapper_.GetSampleRate();
876       const auto encoder_bytes = lc3_encoder_size(dt_us, sr_hz);
877       const auto channel_bytes = codec_wrapper_.GetMaxSduSizePerChannel();
878 
879       /* TODO: We should act smart and reuse current configurations */
880       encoders_.clear();
881       encoders_mem_.clear();
882       while (encoders_.size() < codec_wrapper_.GetNumChannels()) {
883         auto& encoder_buf = enc_audio_buffers_.at(encoders_.size());
884         encoder_buf.resize(channel_bytes);
885 
886         encoders_mem_.emplace_back(malloc(encoder_bytes), &std::free);
887         encoders_.emplace_back(
888             lc3_setup_encoder(dt_us, sr_hz, 0, encoders_mem_.back().get()));
889       }
890     }
891 
getCurrentCodecConfig(void) const892     const BroadcastCodecWrapper& getCurrentCodecConfig(void) const {
893       return codec_wrapper_;
894     }
895 
setCurrentCodecConfig(BroadcastCodecWrapper const & config)896     void setCurrentCodecConfig(BroadcastCodecWrapper const& config) {
897       codec_wrapper_ = config;
898     }
899 
encodeLc3Channel(lc3_encoder_t encoder,std::vector<uint8_t> & out_buffer,const std::vector<uint8_t> & data,int initial_channel_offset,int pitch_samples,int num_channels)900     void encodeLc3Channel(lc3_encoder_t encoder,
901                           std::vector<uint8_t>& out_buffer,
902                           const std::vector<uint8_t>& data,
903                           int initial_channel_offset, int pitch_samples,
904                           int num_channels) {
905       auto encoder_status =
906           lc3_encode(encoder, LC3_PCM_FORMAT_S16,
907                      (int16_t*)(data.data() + initial_channel_offset),
908                      pitch_samples, out_buffer.size(), out_buffer.data());
909       if (encoder_status != 0) {
910         LOG_ERROR("Encoding error=%d", encoder_status);
911       }
912     }
913 
sendBroadcastData(const std::unique_ptr<BroadcastStateMachine> & broadcast,std::vector<std::vector<uint8_t>> & encoded_channels)914     static void sendBroadcastData(
915         const std::unique_ptr<BroadcastStateMachine>& broadcast,
916         std::vector<std::vector<uint8_t>>& encoded_channels) {
917       auto const& config = broadcast->GetBigConfig();
918       if (config == std::nullopt) {
919         LOG_ERROR(
920             "Broadcast broadcast_id=%d has no valid BIS configurations in "
921             "state=%s",
922             broadcast->GetBroadcastId(),
923             ToString(broadcast->GetState()).c_str());
924         return;
925       }
926 
927       if (config->connection_handles.size() < encoded_channels.size()) {
928         LOG_ERROR("Not enough BIS'es to broadcast all channels!");
929         return;
930       }
931 
932       for (uint8_t chan = 0; chan < encoded_channels.size(); ++chan) {
933         IsoManager::GetInstance()->SendIsoData(config->connection_handles[chan],
934                                                encoded_channels[chan].data(),
935                                                encoded_channels[chan].size());
936       }
937     }
938 
OnAudioDataReady(const std::vector<uint8_t> & data)939     virtual void OnAudioDataReady(const std::vector<uint8_t>& data) override {
940       if (!instance) return;
941 
942       LOG_VERBOSE("Received %zu bytes.", data.size());
943 
944       /* Constants for the channel data configuration */
945       const auto num_channels = codec_wrapper_.GetNumChannels();
946       const auto bytes_per_sample = (codec_wrapper_.GetBitsPerSample() / 8);
947 
948       /* Prepare encoded data for all channels */
949       for (uint8_t chan = 0; chan < num_channels; ++chan) {
950         /* TODO: Use encoder agnostic wrapper */
951         encodeLc3Channel(encoders_[chan], enc_audio_buffers_[chan], data,
952                          chan * bytes_per_sample, num_channels, num_channels);
953       }
954 
955       /* Currently there is no way to broadcast multiple distinct streams.
956        * We just receive all system sounds mixed into a one stream and each
957        * broadcast gets the same data.
958        */
959       for (auto& broadcast_pair : instance->broadcasts_) {
960         auto& broadcast = broadcast_pair.second;
961         if ((broadcast->GetState() ==
962              BroadcastStateMachine::State::STREAMING) &&
963             !broadcast->IsMuted())
964           sendBroadcastData(broadcast, enc_audio_buffers_);
965       }
966       LOG_VERBOSE("All data sent.");
967     }
968 
OnAudioSuspend(std::promise<void> do_suspend_promise)969     virtual void OnAudioSuspend(
970         std::promise<void> do_suspend_promise) override {
971       LOG_INFO();
972       /* TODO: Should we suspend all broadcasts - remove BIGs? */
973       do_suspend_promise.set_value();
974       if (instance)
975         instance->audio_data_path_state_ = AudioDataPathState::SUSPENDED;
976     }
977 
OnAudioResume(void)978     virtual void OnAudioResume(void) override {
979       LOG_INFO();
980       if (!instance) return;
981 
982       /* TODO: Should we resume all broadcasts - recreate BIGs? */
983       instance->audio_data_path_state_ = AudioDataPathState::ACTIVE;
984 
985       if (!IsAnyoneStreaming()) {
986         instance->le_audio_source_hal_client_->CancelStreamingRequest();
987         return;
988       }
989 
990       instance->le_audio_source_hal_client_->ConfirmStreamingRequest();
991     }
992 
OnAudioMetadataUpdate(std::vector<struct playback_track_metadata> source_metadata)993     virtual void OnAudioMetadataUpdate(
994         std::vector<struct playback_track_metadata> source_metadata) override {
995       LOG_INFO();
996       if (!instance) return;
997 
998       /* TODO: Should we take supported contexts from ASCS? */
999       auto supported_context_types = le_audio::types::kLeAudioContextAllTypes;
1000       auto contexts = GetAllowedAudioContextsFromSourceMetadata(
1001           source_metadata, supported_context_types);
1002       if (contexts.any()) {
1003         /* NOTICE: We probably don't want to change the stream configuration
1004          * on each metadata change, so just update the context type metadata.
1005          * Since we are not able to identify individual track streams and
1006          * they are all mixed inside a single data stream, we will update
1007          * the metadata of all BIS subgroups with the same combined context.
1008          */
1009         instance->UpdateStreamingContextTypeOnAllSubgroups(contexts);
1010       }
1011     }
1012 
1013    private:
1014     BroadcastCodecWrapper codec_wrapper_;
1015     std::vector<lc3_encoder_t> encoders_;
1016     std::vector<std::unique_ptr<void, decltype(&std::free)>> encoders_mem_;
1017     std::vector<std::vector<uint8_t>> enc_audio_buffers_;
1018   } audio_receiver_;
1019 
1020   bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks_;
1021   std::map<uint32_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
1022   std::vector<std::unique_ptr<BroadcastStateMachine>> pending_broadcasts_;
1023 
1024   /* Some BIG params are set globally */
1025   uint8_t current_phy_;
1026   AudioDataPathState audio_data_path_state_;
1027   std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_;
1028   std::vector<BroadcastId> available_broadcast_ids_;
1029 };
1030 
1031 /* Static members definitions */
1032 LeAudioBroadcasterImpl::BroadcastStateMachineCallbacks
1033     LeAudioBroadcasterImpl::state_machine_callbacks_;
1034 LeAudioBroadcasterImpl::LeAudioSourceCallbacksImpl
1035     LeAudioBroadcasterImpl::audio_receiver_;
1036 
1037 } /* namespace */
1038 
Initialize(bluetooth::le_audio::LeAudioBroadcasterCallbacks * callbacks,base::Callback<bool ()> audio_hal_verifier)1039 void LeAudioBroadcaster::Initialize(
1040     bluetooth::le_audio::LeAudioBroadcasterCallbacks* callbacks,
1041     base::Callback<bool()> audio_hal_verifier) {
1042   std::scoped_lock<std::mutex> lock(instance_mutex);
1043   LOG_INFO();
1044   if (instance) {
1045     LOG_ERROR("Already initialized");
1046     return;
1047   }
1048 
1049   if (!controller_get_interface()->supports_ble_isochronous_broadcaster() &&
1050       !osi_property_get_bool("persist.bluetooth.fake_iso_support", false)) {
1051     LOG_WARN("Isochronous Broadcast not supported by the controller!");
1052     return;
1053   }
1054 
1055   if (!std::move(audio_hal_verifier).Run()) {
1056     LOG_ALWAYS_FATAL("HAL requirements not met. Init aborted.");
1057   }
1058 
1059   IsoManager::GetInstance()->Start();
1060 
1061   instance = new LeAudioBroadcasterImpl(callbacks);
1062   /* Register HCI event handlers */
1063   IsoManager::GetInstance()->RegisterBigCallbacks(instance);
1064 }
1065 
IsLeAudioBroadcasterRunning()1066 bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return instance; }
1067 
Get(void)1068 LeAudioBroadcaster* LeAudioBroadcaster::Get(void) {
1069   LOG_INFO();
1070   CHECK(instance);
1071   return instance;
1072 }
1073 
Stop(void)1074 void LeAudioBroadcaster::Stop(void) {
1075   LOG_INFO();
1076 
1077   if (instance) {
1078     instance->Stop();
1079   }
1080 }
1081 
Cleanup(void)1082 void LeAudioBroadcaster::Cleanup(void) {
1083   std::scoped_lock<std::mutex> lock(instance_mutex);
1084   LOG_INFO();
1085 
1086   if (instance == nullptr) return;
1087 
1088   LeAudioBroadcasterImpl* ptr = instance;
1089   instance = nullptr;
1090 
1091   ptr->CleanUp();
1092   delete ptr;
1093 }
1094 
DebugDump(int fd)1095 void LeAudioBroadcaster::DebugDump(int fd) {
1096   std::scoped_lock<std::mutex> lock(instance_mutex);
1097   dprintf(fd, "Le Audio Broadcaster:\n");
1098   if (instance) instance->Dump(fd);
1099   dprintf(fd, "\n");
1100 }
1101