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 "bta/le_audio/broadcaster/state_machine.h"
19 
20 #include <bind_helpers.h>
21 #include <bluetooth/log.h>
22 
23 #include <functional>
24 #include <iostream>
25 
26 #include "base/functional/bind.h"
27 #include "base/functional/callback.h"
28 #include "bta/le_audio/broadcaster/broadcaster_types.h"
29 #include "bta/le_audio/codec_manager.h"
30 #include "bta/le_audio/le_audio_types.h"
31 #include "common/strings.h"
32 #include "hci/le_advertising_manager.h"
33 #include "os/log.h"
34 #include "osi/include/properties.h"
35 #include "stack/include/btm_iso_api.h"
36 
37 using bluetooth::common::ToString;
38 using bluetooth::hci::IsoManager;
39 using bluetooth::hci::iso_manager::big_create_cmpl_evt;
40 using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
41 
42 using bluetooth::le_audio::CodecManager;
43 using bluetooth::le_audio::types::CodecLocation;
44 
45 using namespace bluetooth::le_audio::broadcaster;
46 using namespace bluetooth;
47 
48 namespace {
49 
50 // Advertising channels. These should be kept the same as those defined in the
51 // stack.
52 const int kAdvertisingChannel37 = (1 << 0);
53 const int kAdvertisingChannel38 = (1 << 1);
54 const int kAdvertisingChannel39 = (1 << 2);
55 const int kAdvertisingChannelAll =
56     (kAdvertisingChannel37 | kAdvertisingChannel38 | kAdvertisingChannel39);
57 
58 class BroadcastStateMachineImpl : public BroadcastStateMachine {
59  public:
BroadcastStateMachineImpl(BroadcastStateMachineConfig msg)60   BroadcastStateMachineImpl(BroadcastStateMachineConfig msg)
61       : active_config_(std::nullopt),
62         sm_config_(std::move(msg)),
63         suspending_(false) {}
64 
~BroadcastStateMachineImpl()65   ~BroadcastStateMachineImpl() {
66     if (GetState() == State::STREAMING) TerminateBig();
67     DestroyBroadcastAnnouncement();
68     if (callbacks_) callbacks_->OnStateMachineDestroyed(GetBroadcastId());
69   }
70 
Initialize()71   bool Initialize() override {
72     static constexpr uint8_t sNumBisMax = 31;
73 
74     if (sm_config_.config.GetNumBisTotal() > sNumBisMax) {
75       log::error(
76           "Channel count of {} exceeds the maximum number of possible BISes, "
77           "which is {}",
78           sm_config_.config.GetNumBisTotal(), sNumBisMax);
79       return false;
80     }
81 
82     CreateBroadcastAnnouncement(
83         sm_config_.is_public, sm_config_.broadcast_name,
84         sm_config_.broadcast_id, sm_config_.public_announcement,
85         sm_config_.announcement, sm_config_.streaming_phy);
86     return true;
87   }
88 
GetCodecConfig() const89   const std::vector<BroadcastSubgroupCodecConfig>& GetCodecConfig()
90       const override {
91     return sm_config_.config.subgroups;
92   }
93 
GetBroadcastConfig() const94   const BroadcastConfiguration& GetBroadcastConfig() const override {
95     return sm_config_.config;
96   }
97 
GetBigConfig() const98   std::optional<BigConfig> const& GetBigConfig() const override {
99     return active_config_;
100   }
101 
GetStateMachineConfig() const102   BroadcastStateMachineConfig const& GetStateMachineConfig() const override {
103     return sm_config_;
104   }
105 
RequestOwnAddress(base::Callback<void (uint8_t,RawAddress)> cb)106   void RequestOwnAddress(
107       base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)>
108           cb) override {
109     uint8_t advertising_sid = GetAdvertisingSid();
110     advertiser_if_->GetOwnAddress(advertising_sid, cb);
111   }
112 
RequestOwnAddress(void)113   void RequestOwnAddress(void) override {
114     auto broadcast_id = GetBroadcastId();
115     RequestOwnAddress(
116         base::Bind(&IBroadcastStateMachineCallbacks::OnOwnAddressResponse,
117                    base::Unretained(this->callbacks_), broadcast_id));
118   }
119 
GetOwnAddress()120   RawAddress GetOwnAddress() override { return addr_; }
121 
GetOwnAddressType()122   uint8_t GetOwnAddressType() override { return addr_type_; }
123 
GetBroadcastId() const124   bluetooth::le_audio::BroadcastId GetBroadcastId() const override {
125     return sm_config_.broadcast_id;
126   }
127 
GetBroadcastCode() const128   std::optional<bluetooth::le_audio::BroadcastCode> GetBroadcastCode()
129       const override {
130     return sm_config_.broadcast_code;
131   }
132 
133   const bluetooth::le_audio::BasicAudioAnnouncementData&
GetBroadcastAnnouncement() const134   GetBroadcastAnnouncement() const override {
135     return sm_config_.announcement;
136   }
137 
IsPublicBroadcast()138   bool IsPublicBroadcast() override { return sm_config_.is_public; }
139 
GetBroadcastName()140   std::string GetBroadcastName() override { return sm_config_.broadcast_name; }
141 
142   const bluetooth::le_audio::PublicBroadcastAnnouncementData&
GetPublicBroadcastAnnouncement() const143   GetPublicBroadcastAnnouncement() const override {
144     return sm_config_.public_announcement;
145   }
146 
OnCreateAnnouncement(uint8_t advertising_sid,int8_t tx_power,uint8_t status)147   void OnCreateAnnouncement(uint8_t advertising_sid, int8_t tx_power,
148                             uint8_t status) {
149     log::info("advertising_sid={} tx_power={} status={}", advertising_sid,
150               tx_power, status);
151 
152     /* If this callback gets called the advertising_sid is valid even though the
153      * status can be other than SUCCESS.
154      */
155     advertising_sid_ = advertising_sid;
156 
157     if (status !=
158         bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) {
159       log::error("Creating Announcement failed");
160       callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), false);
161       return;
162     }
163 
164     advertiser_if_->GetOwnAddress(
165         advertising_sid,
166         base::Bind(&BroadcastStateMachineImpl::OnAddressResponse,
167                    base::Unretained(this)));
168   }
169 
OnEnableAnnouncement(bool enable,uint8_t status)170   void OnEnableAnnouncement(bool enable, uint8_t status) {
171     log::info("operation={}, broadcast_id={}, status={}",
172               enable ? "enable" : "disable", GetBroadcastId(), status);
173 
174     if (status ==
175         bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) {
176       /* Periodic is enabled but without BIGInfo. Stream is suspended. */
177       if (enable) {
178         SetState(State::CONFIGURED);
179         /* Target state is always STREAMING state - start it now. */
180         ProcessMessage(Message::START);
181       } else {
182         /* User wanted to stop the announcement - report target state reached */
183         SetState(State::STOPPED);
184         callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
185       }
186     } else {
187       // Handle error case
188       if (enable) {
189         /* Error on enabling */
190         SetState(State::STOPPED);
191       } else {
192         /* Error on disabling */
193         SetState(State::CONFIGURED);
194       }
195       callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
196     }
197   }
198 
UpdatePublicBroadcastAnnouncement(uint32_t broadcast_id,const std::string & broadcast_name,const bluetooth::le_audio::PublicBroadcastAnnouncementData & announcement)199   void UpdatePublicBroadcastAnnouncement(
200       uint32_t broadcast_id, const std::string& broadcast_name,
201       const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement)
202       override {
203     std::vector<uint8_t> adv_data;
204     PrepareAdvertisingData(true, broadcast_name, broadcast_id, announcement,
205                            adv_data);
206 
207     sm_config_.broadcast_name = broadcast_name;
208     sm_config_.public_announcement = announcement;
209     advertiser_if_->SetData(advertising_sid_, false, adv_data,
210                             base::DoNothing());
211   }
212 
UpdateBroadcastAnnouncement(bluetooth::le_audio::BasicAudioAnnouncementData announcement)213   void UpdateBroadcastAnnouncement(
214       bluetooth::le_audio::BasicAudioAnnouncementData announcement) override {
215     std::vector<uint8_t> periodic_data;
216     PreparePeriodicData(announcement, periodic_data);
217 
218     sm_config_.announcement = std::move(announcement);
219     advertiser_if_->SetPeriodicAdvertisingData(advertising_sid_, periodic_data,
220                                                base::DoNothing());
221   }
222 
ProcessMessage(Message msg,const void * data=nullptr)223   void ProcessMessage(Message msg, const void* data = nullptr) override {
224     log::info("broadcast_id={}, state={}, message={}", GetBroadcastId(),
225               ToString(GetState()), ToString(msg));
226     switch (msg) {
227       case Message::START:
228         start_msg_handlers[StateMachine::GetState()](data);
229         break;
230       case Message::STOP:
231         stop_msg_handlers[StateMachine::GetState()](data);
232         break;
233       case Message::SUSPEND:
234         suspend_msg_handlers[StateMachine::GetState()](data);
235         break;
236     };
237   }
238 
239   static IBroadcastStateMachineCallbacks* callbacks_;
240   static BleAdvertiserInterface* advertiser_if_;
241 
242  private:
243   std::optional<BigConfig> active_config_;
244   BroadcastStateMachineConfig sm_config_;
245   bool suspending_;
246 
247   /* Message handlers for each possible state */
248   typedef std::function<void(const void*)> msg_handler_t;
249   const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT>
250       start_msg_handlers{
251           /* in STOPPED state */
__anon4b5c62470202() 252           [this](const void*) {
253             SetState(State::CONFIGURING);
254             callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
255             EnableAnnouncement();
256           },
257           /* in CONFIGURING state */
__anon4b5c62470302() 258           [](const void*) { /* Do nothing */ },
259           /* in CONFIGURED state */
__anon4b5c62470402() 260           [this](const void*) { CreateBig(); },
261           /* in STOPPING state */
__anon4b5c62470502() 262           [](const void*) { /* Do nothing */ },
263           /* in STREAMING state */
__anon4b5c62470602() 264           [](const void*) { /* Do nothing */ }};
265 
266   const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT>
267       stop_msg_handlers{
268           /* in STOPPED state */
__anon4b5c62470702() 269           [](const void*) { /* Already stopped */ },
270           /* in CONFIGURING state */
__anon4b5c62470802() 271           [](const void*) { /* Do nothing */ },
272           /* in CONFIGURED state */
__anon4b5c62470902() 273           [this](const void*) {
274             SetState(State::STOPPING);
275             callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
276             DisableAnnouncement();
277           },
278           /* in STOPPING state */
__anon4b5c62470a02() 279           [](const void*) { /* Do nothing */ },
280           /* in STREAMING state */
__anon4b5c62470b02() 281           [this](const void*) {
282             if ((active_config_ != std::nullopt) && !suspending_) {
283               suspending_ = false;
284               SetState(State::STOPPING);
285               callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
286               TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
287             }
288           }};
289 
290   const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT>
291       suspend_msg_handlers{
292           /* in STOPPED state */
__anon4b5c62470c02() 293           [](const void*) { /* Do nothing */ },
294           /* in CONFIGURING state */
__anon4b5c62470d02() 295           [](const void*) { /* Do nothing */ },
296           /* in CONFIGURED state */
__anon4b5c62470e02() 297           [](const void*) { /* Already suspended */ },
298           /* in STOPPING state */
__anon4b5c62470f02() 299           [](const void*) { /* Do nothing */ },
300           /* in STREAMING state */
__anon4b5c62471002() 301           [this](const void*) {
302             if ((active_config_ != std::nullopt) && !suspending_) {
303               suspending_ = true;
304               TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
305             }
306           }};
307 
308   const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT>
309       resume_msg_handlers{/* in STOPPED state */
__anon4b5c62471102() 310                           [](const void*) { /* Do nothing */ },
311                           /* in CONFIGURING state */
__anon4b5c62471202() 312                           [](const void*) { /* Do nothing */ },
313                           /* in CONFIGURED state */
__anon4b5c62471302() 314                           [this](const void*) { CreateBig(); },
315                           /* in STOPPING state */
__anon4b5c62471402() 316                           [](const void*) { /* Do nothing */ },
317                           /* in STREAMING state */
__anon4b5c62471502() 318                           [](const void*) { /* Already streaming */ }};
319 
OnAddressResponse(uint8_t addr_type,RawAddress addr)320   void OnAddressResponse(uint8_t addr_type, RawAddress addr) {
321     log::info("own address={}, type={}", addr, addr_type);
322     addr_ = addr;
323     addr_type_ = addr_type;
324 
325     /* Ext. advertisings are already on */
326     SetState(State::CONFIGURED);
327 
328     callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true);
329     callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED);
330   }
331 
CreateBroadcastAnnouncement(bool is_public,const std::string & broadcast_name,bluetooth::le_audio::BroadcastId & broadcast_id,const bluetooth::le_audio::PublicBroadcastAnnouncementData & public_announcement,const bluetooth::le_audio::BasicAudioAnnouncementData & announcement,uint8_t streaming_phy)332   void CreateBroadcastAnnouncement(
333       bool is_public, const std::string& broadcast_name,
334       bluetooth::le_audio::BroadcastId& broadcast_id,
335       const bluetooth::le_audio::PublicBroadcastAnnouncementData&
336           public_announcement,
337       const bluetooth::le_audio::BasicAudioAnnouncementData& announcement,
338       uint8_t streaming_phy) {
339     log::info("is_public={}, broadcast_name={}, public_features={}",
340               is_public ? "public" : "non-public", broadcast_name,
341               public_announcement.features);
342     if (advertiser_if_ != nullptr) {
343       AdvertiseParameters adv_params;
344       PeriodicAdvertisingParameters periodic_params;
345       std::vector<uint8_t> adv_data;
346       std::vector<uint8_t> periodic_data;
347 
348       PrepareAdvertisingData(is_public, broadcast_name, broadcast_id,
349                              public_announcement, adv_data);
350       PreparePeriodicData(announcement, periodic_data);
351 
352       adv_params.min_interval = 0x00A0; /* 160 * 0,625 = 100ms */
353       adv_params.max_interval = 0x0140; /* 320 * 0,625 = 200ms */
354       adv_params.advertising_event_properties = 0;
355       adv_params.channel_map = kAdvertisingChannelAll;
356       adv_params.tx_power = 8;
357       adv_params.primary_advertising_phy = PHY_LE_1M;
358       adv_params.secondary_advertising_phy = streaming_phy;
359       adv_params.scan_request_notification_enable = 0;
360       adv_params.own_address_type = kBroadcastAdvertisingType;
361 
362       periodic_params.max_interval = BroadcastStateMachine::kPaIntervalMax;
363       periodic_params.min_interval = BroadcastStateMachine::kPaIntervalMin;
364       periodic_params.periodic_advertising_properties = 0;
365       periodic_params.enable = true;
366 
367       /* Status and timeout callbacks are handled by OnAdvertisingSetStarted()
368        * which returns the status and handle to be used later in CreateBIG
369        * command.
370        */
371       advertiser_if_->StartAdvertisingSet(
372           kAdvertiserClientIdLeAudio, kLeAudioBroadcastRegId, base::DoNothing(),
373           adv_params, adv_data, std::vector<uint8_t>(), periodic_params,
374           periodic_data, 0 /* duration */, 0 /* maxExtAdvEvents */,
375           base::DoNothing());
376     }
377   }
378 
DestroyBroadcastAnnouncement()379   void DestroyBroadcastAnnouncement() {
380     advertiser_if_->Unregister(GetAdvertisingSid());
381   }
382 
EnableAnnouncement()383   void EnableAnnouncement() {
384     log::info("broadcast_id={}", GetBroadcastId());
385     // Callback is handled by OnAdvertisingEnabled() which returns the status
386     advertiser_if_->Enable(GetAdvertisingSid(), true, base::DoNothing(), 0,
387                            0, /* Enable until stopped */
388                            base::DoNothing());
389   }
390 
CreateBig(void)391   void CreateBig(void) {
392     log::info("broadcast_id={}", GetBroadcastId());
393     /* TODO: Figure out how to decide on the currently hard-codded params. */
394     struct bluetooth::hci::iso_manager::big_create_params big_params = {
395         .adv_handle = GetAdvertisingSid(),
396         .num_bis = sm_config_.config.GetNumBisTotal(),
397         .sdu_itv = sm_config_.config.GetSduIntervalUs(),
398         .max_sdu_size = sm_config_.config.GetMaxSduOctets(),
399         .max_transport_latency = sm_config_.config.qos.getMaxTransportLatency(),
400         .rtn = sm_config_.config.qos.getRetransmissionNumber(),
401         .phy = sm_config_.streaming_phy,
402         .packing = 0x00, /* Sequencial */
403         .framing = 0x00, /* Unframed */
404         .enc = static_cast<uint8_t>(sm_config_.broadcast_code ? 1 : 0),
405         .enc_code = sm_config_.broadcast_code ? *sm_config_.broadcast_code
406                                               : std::array<uint8_t, 16>({0}),
407     };
408 
409     IsoManager::GetInstance()->CreateBig(GetAdvertisingSid(),
410                                          std::move(big_params));
411   }
412 
DisableAnnouncement(void)413   void DisableAnnouncement(void) {
414     log::info("broadcast_id={}", GetBroadcastId());
415     // Callback is handled by OnAdvertisingEnabled() which returns the status
416     advertiser_if_->Enable(GetAdvertisingSid(), false, base::DoNothing(), 0, 0,
417                            base::DoNothing());
418   }
419 
TerminateBig()420   void TerminateBig() {
421     log::info("suspending={}", suspending_);
422     /* Terminate with reason: Connection Terminated By Local Host */
423     IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x16);
424   }
425 
OnSetupIsoDataPath(uint8_t status,uint16_t conn_hdl)426   void OnSetupIsoDataPath(uint8_t status, uint16_t conn_hdl) override {
427     log::assert_that(active_config_ != std::nullopt,
428                      "assert failed: active_config_ != std::nullopt");
429 
430     if (status != 0) {
431       log::error("Failure creating data path. Tearing down the BIG now.");
432       suspending_ = true;
433       TerminateBig();
434       return;
435     }
436 
437     /* Look for the next BIS handle */
438     auto handle_it = std::find_if(
439         active_config_->connection_handles.begin(),
440         active_config_->connection_handles.end(),
441         [conn_hdl](const auto& handle) { return conn_hdl == handle; });
442     log::assert_that(
443         handle_it != active_config_->connection_handles.end(),
444         "assert failed: handle_it != active_config_->connection_handles.end()");
445     handle_it = std::next(handle_it);
446 
447     if (handle_it == active_config_->connection_handles.end()) {
448       /* It was the last BIS to set up - change state to streaming */
449       SetState(State::STREAMING);
450       callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), nullptr);
451     } else {
452       /* Note: We would feed a watchdog here if we had one */
453       /* There are more BISes to set up data path for */
454       log::info("There is more data paths to set up.");
455       TriggerIsoDatapathSetup(*handle_it);
456     }
457   }
458 
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle)459   void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle) override {
460     log::assert_that(active_config_ != std::nullopt,
461                      "assert failed: active_config_ != std::nullopt");
462 
463     if (status != 0) {
464       log::error("Failure removing data path. Tearing down the BIG now.");
465       TerminateBig();
466       return;
467     }
468 
469     /* Look for the next BIS handle */
470     auto handle_it = std::find_if(
471         active_config_->connection_handles.begin(),
472         active_config_->connection_handles.end(),
473         [conn_handle](const auto& handle) { return conn_handle == handle; });
474     log::assert_that(
475         handle_it != active_config_->connection_handles.end(),
476         "assert failed: handle_it != active_config_->connection_handles.end()");
477     handle_it = std::next(handle_it);
478 
479     if (handle_it == active_config_->connection_handles.end()) {
480       /* It was the last one to set up - start tearing down the BIG */
481       TerminateBig();
482     } else {
483       /* Note: We would feed a watchdog here if we had one */
484       /* There are more BISes to tear down data path for */
485       log::info("There is more data paths to tear down.");
486       TriggerIsoDatapathTeardown(*handle_it);
487     }
488   }
489 
TriggerIsoDatapathSetup(uint16_t conn_handle)490   void TriggerIsoDatapathSetup(uint16_t conn_handle) {
491     log::info("conn_hdl={}", conn_handle);
492     log::assert_that(active_config_ != std::nullopt,
493                      "assert failed: active_config_ != std::nullopt");
494 
495     /* Note: If coding format is transparent, 'codec_id_company' and
496      * 'codec_id_vendor' shall be ignored.
497      */
498     auto& iso_datapath_config = sm_config_.config.data_path.isoDataPathConfig;
499     bluetooth::hci::iso_manager::iso_data_path_params param = {
500         .data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionIn,
501         .data_path_id =
502             static_cast<uint8_t>(sm_config_.config.data_path.dataPathId),
503         .codec_id_format = static_cast<uint8_t>(
504             iso_datapath_config.isTransparent
505                 ? bluetooth::hci::kIsoCodingFormatTransparent
506                 : iso_datapath_config.codecId.coding_format),
507         .codec_id_company = static_cast<uint16_t>(
508             iso_datapath_config.isTransparent
509                 ? 0x0000
510                 : iso_datapath_config.codecId.vendor_company_id),
511         .codec_id_vendor = static_cast<uint16_t>(
512             iso_datapath_config.isTransparent
513                 ? 0x0000
514                 : iso_datapath_config.codecId.vendor_codec_id),
515         .controller_delay = iso_datapath_config.controllerDelayUs,
516         .codec_conf = iso_datapath_config.configuration,
517     };
518     IsoManager::GetInstance()->SetupIsoDataPath(conn_handle, std::move(param));
519   }
520 
TriggerIsoDatapathTeardown(uint16_t conn_handle)521   void TriggerIsoDatapathTeardown(uint16_t conn_handle) {
522     log::info("conn_hdl={}", conn_handle);
523     log::assert_that(active_config_ != std::nullopt,
524                      "assert failed: active_config_ != std::nullopt");
525 
526     SetMuted(true);
527     IsoManager::GetInstance()->RemoveIsoDataPath(
528         conn_handle,
529         bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput);
530   }
531 
HandleHciEvent(uint16_t event,void * data)532   void HandleHciEvent(uint16_t event, void* data) override {
533     switch (event) {
534       case HCI_BLE_CREATE_BIG_CPL_EVT: {
535         auto* evt = static_cast<big_create_cmpl_evt*>(data);
536 
537         if (evt->big_id != GetAdvertisingSid()) {
538           log::error("State={}, Event={}, Unknown big, big_id={}",
539                      ToString(GetState()), event, evt->big_id);
540           break;
541         }
542 
543         if (evt->status == 0x00) {
544           log::info("BIG create BIG complete, big_id={}", evt->big_id);
545           active_config_ = {
546               .status = evt->status,
547               .big_id = evt->big_id,
548               .big_sync_delay = evt->big_sync_delay,
549               .transport_latency_big = evt->transport_latency_big,
550               .phy = evt->phy,
551               .nse = evt->nse,
552               .bn = evt->bn,
553               .pto = evt->pto,
554               .irc = evt->irc,
555               .max_pdu = evt->max_pdu,
556               .iso_interval = evt->iso_interval,
557               .connection_handles = evt->conn_handles,
558           };
559           callbacks_->OnBigCreated(evt->conn_handles);
560           TriggerIsoDatapathSetup(evt->conn_handles[0]);
561         } else {
562           log::error(
563               "State={} Event={}. Unable to create big, big_id={}, status={}",
564               ToString(GetState()), event, evt->big_id, evt->status);
565         }
566       } break;
567       case HCI_BLE_TERM_BIG_CPL_EVT: {
568         auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
569 
570         log::info("BIG terminate BIG cmpl, reason={} big_id={}", evt->reason,
571                   evt->big_id);
572 
573         if (evt->big_id != GetAdvertisingSid()) {
574           log::error("State={} Event={}, unknown adv.sid={}",
575                      ToString(GetState()), event, evt->big_id);
576           break;
577         }
578 
579         active_config_ = std::nullopt;
580 
581         /* Go back to configured if BIG is inactive (we are still announcing) */
582         SetState(State::CONFIGURED);
583 
584         /* Check if we got this HCI event due to STOP or SUSPEND message. */
585         if (suspending_) {
586           callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), evt);
587           suspending_ = false;
588         } else {
589           DisableAnnouncement();
590         }
591       } break;
592       default:
593         log::error("State={} Unknown event={}", ToString(GetState()), event);
594         break;
595     }
596   }
597 };
598 
599 IBroadcastStateMachineCallbacks* BroadcastStateMachineImpl::callbacks_ =
600     nullptr;
601 BleAdvertiserInterface* BroadcastStateMachineImpl::advertiser_if_ = nullptr;
602 } /* namespace */
603 
CreateInstance(BroadcastStateMachineConfig msg)604 std::unique_ptr<BroadcastStateMachine> BroadcastStateMachine::CreateInstance(
605     BroadcastStateMachineConfig msg) {
606   return std::make_unique<BroadcastStateMachineImpl>(std::move(msg));
607 }
608 
Initialize(IBroadcastStateMachineCallbacks * callbacks,AdvertisingCallbacks * adv_callbacks)609 void BroadcastStateMachine::Initialize(
610     IBroadcastStateMachineCallbacks* callbacks,
611     AdvertisingCallbacks* adv_callbacks) {
612   BroadcastStateMachineImpl::callbacks_ = callbacks;
613   /* Get gd le advertiser interface */
614   BroadcastStateMachineImpl::advertiser_if_ =
615       bluetooth::shim::get_ble_advertiser_instance();
616   if (BroadcastStateMachineImpl::advertiser_if_ != nullptr) {
617     log::info("Advertiser_instance acquired");
618     BroadcastStateMachineImpl::advertiser_if_->RegisterCallbacksNative(
619         adv_callbacks, kAdvertiserClientIdLeAudio);
620   } else {
621     log::error("Could not acquire advertiser_instance!");
622     BroadcastStateMachineImpl::advertiser_if_ = nullptr;
623   }
624 }
625 
626 namespace bluetooth::le_audio {
627 namespace broadcaster {
628 
operator <<(std::ostream & os,const BroadcastStateMachine::Message & msg)629 std::ostream& operator<<(std::ostream& os,
630                          const BroadcastStateMachine::Message& msg) {
631   static const char* char_value_[BroadcastStateMachine::MESSAGE_COUNT] = {
632       "START", "SUSPEND", "STOP"};
633   os << char_value_[static_cast<uint8_t>(msg)];
634   return os;
635 }
636 
operator <<(std::ostream & os,const BroadcastStateMachine::State & state)637 std::ostream& operator<<(std::ostream& os,
638                          const BroadcastStateMachine::State& state) {
639   static const char* char_value_[BroadcastStateMachine::STATE_COUNT] = {
640       "STOPPED", "CONFIGURING", "CONFIGURED", "STOPPING", "STREAMING"};
641   os << char_value_[static_cast<uint8_t>(state)];
642   return os;
643 }
644 
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BigConfig & config)645 std::ostream& operator<<(
646     std::ostream& os,
647     const bluetooth::le_audio::broadcaster::BigConfig& config) {
648   os << "\n";
649   os << "        Status: 0x" << std::hex << +config.status << std::dec << "\n";
650   os << "        BIG ID: " << +config.big_id << "\n";
651   os << "        Sync delay: " << config.big_sync_delay << "\n";
652   os << "        Transport Latency: " << config.transport_latency_big << "\n";
653   os << "        Phy: " << +config.phy << "\n";
654   os << "        Nse: " << +config.nse << "\n";
655   os << "        Bn: " << +config.bn << "\n";
656   os << "        Pto: " << +config.pto << "\n";
657   os << "        Irc: " << +config.irc << "\n";
658   os << "        Max pdu: " << config.max_pdu << "\n";
659   os << "        Iso interval: " << config.iso_interval << "\n";
660   os << "        Connection handles (BISes): [";
661   for (auto& el : config.connection_handles) {
662     os << std::hex << +el << std::dec << ":";
663   }
664   os << "]";
665   return os;
666 }
667 
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig & config)668 std::ostream& operator<<(
669     std::ostream& os,
670     const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig&
671         config) {
672   const char* const PHYS[] = {"NONE", "1M", "2M", "CODED"};
673 
674   os << "\n";
675   os << "        Broadcast ID: " << config.broadcast_id << "\n";
676   os << "        Streaming PHY: "
677      << ((config.streaming_phy > 3) ? std::to_string(config.streaming_phy)
678                                     : PHYS[config.streaming_phy])
679      << "\n";
680   os << "        Subgroups: {\n";
681   for (auto const& subgroup : config.config.subgroups) {
682     os << "          " << subgroup << "\n";
683   }
684   os << "        }\n";
685   os << "        Qos Config: " << config.config.qos << "\n";
686   if (config.broadcast_code) {
687     os << "        Broadcast Code: [";
688     for (auto& el : *config.broadcast_code) {
689       os << std::hex << +el << ":";
690     }
691     os << "]\n";
692   } else {
693     os << "        Broadcast Code: NONE\n";
694   }
695 
696   std::vector<uint8_t> an_raw;
697   ToRawPacket(config.announcement, an_raw);
698   os << "        Announcement RAW: [";
699   for (auto& el : an_raw) {
700     os << std::hex << +el << ":";
701   }
702   os << "]";
703 
704   return os;
705 }
706 
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachine & machine)707 std::ostream& operator<<(
708     std::ostream& os,
709     const bluetooth::le_audio::broadcaster::BroadcastStateMachine& machine) {
710   os << "    Broadcast state machine: {"
711      << "      Advertising SID: " << +machine.GetAdvertisingSid() << "\n"
712      << "      State: " << machine.GetState() << "\n";
713   os << "      State Machine Config: " << machine.GetStateMachineConfig()
714      << "\n";
715 
716   if (machine.GetBigConfig()) {
717     os << "      BigConfig: " << *machine.GetBigConfig() << "\n";
718   } else {
719     os << "      BigConfig: NONE\n";
720   }
721   os << "    }\n";
722   return os;
723 }
724 
725 }  // namespace broadcaster
726 }  // namespace bluetooth::le_audio
727