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