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