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 "state_machine.h"
19
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include "../le_audio_types.h"
24 #include "ble_advertiser.h"
25 #include "btm_iso_api.h"
26 #include "mock_ble_advertising_manager.h"
27 #include "mock_iso_manager.h"
28 #include "stack/include/ble_advertiser.h"
29 #include "state_machine.h"
30 #include "test/common/mock_functions.h"
31
32 using namespace bluetooth::hci::iso_manager;
33
34 using bluetooth::hci::IsoManager;
35 using bluetooth::le_audio::BasicAudioAnnouncementData;
36 using testing::_;
37 using testing::Mock;
38 using testing::SaveArg;
39 using testing::Test;
40
41 // Disables most likely false-positives from base::SplitString()
__asan_default_options()42 extern "C" const char* __asan_default_options() {
43 return "detect_container_overflow=0";
44 }
45
btsnd_hcic_ble_rand(base::Callback<void (BT_OCTET8)> cb)46 void btsnd_hcic_ble_rand(base::Callback<void(BT_OCTET8)> cb) {}
47
48 namespace le_audio {
49 namespace broadcaster {
50 namespace {
51 // bit 0: encrypted, bit 1: standard quality present
52 static const uint8_t test_public_broadcast_features = 0x3;
53 static const std::string test_broadcast_name = "Test";
54 static const std::vector<uint8_t> default_public_metadata = {
55 5, le_audio::types::kLeAudioMetadataTypeProgramInfo, 0x1, 0x2, 0x3, 0x4};
56
57 class MockBroadcastStatMachineCallbacks
58 : public IBroadcastStateMachineCallbacks {
59 public:
60 MockBroadcastStatMachineCallbacks() = default;
61 MockBroadcastStatMachineCallbacks(const MockBroadcastStatMachineCallbacks&) =
62 delete;
63 MockBroadcastStatMachineCallbacks& operator=(
64 const MockBroadcastStatMachineCallbacks&) = delete;
65
66 ~MockBroadcastStatMachineCallbacks() override = default;
67
68 MOCK_METHOD((void), OnStateMachineCreateStatus,
69 (uint32_t broadcast_id, bool initialized), (override));
70 MOCK_METHOD((void), OnStateMachineDestroyed, (uint32_t broadcast_id),
71 (override));
72 MOCK_METHOD((void), OnStateMachineEvent,
73 (uint32_t broadcast_id, BroadcastStateMachine::State state,
74 const void* data),
75 (override));
76 MOCK_METHOD((void), OnOwnAddressResponse,
77 (uint32_t broadcast_id, uint8_t addr_type, RawAddress addr),
78 (override));
79 MOCK_METHOD((void), OnBigCreated, (const std::vector<uint16_t>& conn_handle),
80 (override));
81 };
82
83 class StateMachineTest : public Test {
84 protected:
SetUp()85 void SetUp() override {
86 reset_mock_function_count_map();
87 BleAdvertisingManager::Initialize(nullptr);
88
89 ble_advertising_manager_ = BleAdvertisingManager::Get();
90 mock_ble_advertising_manager_ =
91 static_cast<MockBleAdvertisingManager*>(ble_advertising_manager_.get());
92
93 sm_callbacks_.reset(new MockBroadcastStatMachineCallbacks());
94 BroadcastStateMachine::Initialize(sm_callbacks_.get());
95
96 ON_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet)
97 .WillByDefault([](base::Callback<void(uint8_t, int8_t, uint8_t)> cb,
98 tBTM_BLE_ADV_PARAMS* params,
99 std::vector<uint8_t> advertise_data,
100 std::vector<uint8_t> scan_response_data,
101 tBLE_PERIODIC_ADV_PARAMS* periodic_params,
102 std::vector<uint8_t> periodic_data, uint16_t duration,
103 uint8_t maxExtAdvEvents,
104 base::Callback<void(uint8_t, uint8_t)> timeout_cb) {
105 static uint8_t advertiser_id = 1;
106 uint8_t tx_power = 32;
107 uint8_t status = 0;
108 cb.Run(advertiser_id++, tx_power, status);
109 });
110
111 ON_CALL(*mock_ble_advertising_manager_, Enable)
112 .WillByDefault(
113 [](uint8_t advertiser_id, bool enable,
114 base::Callback<void(uint8_t /* status */)> cb, uint16_t duration,
115 uint8_t maxExtAdvEvents,
116 base::Callback<void(uint8_t /* status */)> timeout_cb) {
117 cb.Run(0);
118 });
119
120 ON_CALL(*mock_ble_advertising_manager_, GetOwnAddress)
121 .WillByDefault(
122 [](uint8_t inst_id, BleAdvertisingManager::GetAddressCallback cb) {
123 uint8_t address_type = 0x02;
124 RawAddress address;
125 const uint8_t addr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
126 address.FromOctets(addr);
127 cb.Run(address_type, address);
128 });
129
130 ON_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus)
131 .WillByDefault([this](uint32_t broadcast_id, bool initialized) {
132 auto instance_it =
133 std::find_if(pending_broadcasts_.begin(),
134 pending_broadcasts_.end(), [broadcast_id](auto& up) {
135 return (up->GetBroadcastId() == broadcast_id);
136 });
137 if (instance_it != pending_broadcasts_.end()) {
138 if (initialized) {
139 broadcasts_[broadcast_id] = std::move(*instance_it);
140 }
141 pending_broadcasts_.erase(instance_it);
142 }
143 instance_creation_promise_.set_value(broadcast_id);
144 });
145
146 ON_CALL(*(sm_callbacks_.get()), OnStateMachineDestroyed)
147 .WillByDefault([this](uint32_t broadcast_id) {
148 if (broadcasts_.count(broadcast_id)) {
149 instance_destruction_promise_.set_value(broadcast_id);
150 }
151 });
152
153 ConfigureIsoManagerMock();
154 }
155
ConfigureIsoManagerMock()156 void ConfigureIsoManagerMock() {
157 iso_manager_ = IsoManager::GetInstance();
158 ASSERT_NE(iso_manager_, nullptr);
159 iso_manager_->Start();
160
161 mock_iso_manager_ = MockIsoManager::GetInstance();
162 ASSERT_NE(mock_iso_manager_, nullptr);
163
164 ON_CALL(*mock_iso_manager_, CreateBig)
165 .WillByDefault([this](uint8_t big_id, big_create_params p) {
166 auto bit =
167 std::find_if(broadcasts_.begin(), broadcasts_.end(),
168 [big_id](auto const& entry) {
169 return entry.second->GetAdvertisingSid() == big_id;
170 });
171 if (bit == broadcasts_.end()) return;
172
173 big_create_cmpl_evt evt;
174 evt.big_id = big_id;
175
176 // For test convenience lets encode big_id into conn_hdl MSB.
177 // NOTE: In current implementation big_id is equal to advertising SID.
178 // This is an important detail exploited by the IsoManager mock
179 static uint8_t conn_lsb = 1;
180 uint16_t conn_msb = ((uint16_t)big_id) << 8;
181 for (auto i = 0; i < p.num_bis; ++i) {
182 evt.conn_handles.push_back(conn_msb | conn_lsb++);
183 }
184
185 bit->second->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
186 });
187
188 ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
189 .WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) {
190 // Get the big_id encoded in conn_handle's MSB
191 uint8_t big_id = conn_handle >> 8;
192 auto bit =
193 std::find_if(broadcasts_.begin(), broadcasts_.end(),
194 [big_id](auto const& entry) {
195 return entry.second->GetAdvertisingSid() == big_id;
196 });
197 if (bit == broadcasts_.end()) return;
198 bit->second->OnSetupIsoDataPath(0, conn_handle);
199 });
200
201 ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
202 .WillByDefault([this](uint16_t conn_handle, uint8_t iso_direction) {
203 // Get the big_id encoded in conn_handle's MSB
204 uint8_t big_id = conn_handle >> 8;
205 auto bit =
206 std::find_if(broadcasts_.begin(), broadcasts_.end(),
207 [big_id](auto const& entry) {
208 return entry.second->GetAdvertisingSid() == big_id;
209 });
210 if (bit == broadcasts_.end()) return;
211 bit->second->OnRemoveIsoDataPath(0, conn_handle);
212 });
213
214 ON_CALL(*mock_iso_manager_, TerminateBig)
215 .WillByDefault([this](uint8_t big_id, uint8_t reason) {
216 // Get the big_id encoded in conn_handle's MSB
217 auto bit =
218 std::find_if(broadcasts_.begin(), broadcasts_.end(),
219 [big_id](auto const& entry) {
220 return entry.second->GetAdvertisingSid() == big_id;
221 });
222 if (bit == broadcasts_.end()) return;
223
224 big_terminate_cmpl_evt evt;
225 evt.big_id = big_id;
226 evt.reason = reason;
227
228 bit->second->HandleHciEvent(HCI_BLE_TERM_BIG_CPL_EVT, &evt);
229 });
230 }
231
TearDown()232 void TearDown() override {
233 iso_manager_->Stop();
234 mock_iso_manager_ = nullptr;
235
236 broadcasts_.clear();
237 sm_callbacks_.reset();
238 }
239
InstantiateStateMachine(le_audio::types::LeAudioContextType context=le_audio::types::LeAudioContextType::UNSPECIFIED)240 uint32_t InstantiateStateMachine(
241 le_audio::types::LeAudioContextType context =
242 le_audio::types::LeAudioContextType::UNSPECIFIED) {
243 // We will get the state machine create status update in an async callback
244 // so let's wait for it here.
245 instance_creation_promise_ = std::promise<uint32_t>();
246 std::future<uint32_t> instance_future =
247 instance_creation_promise_.get_future();
248
249 static uint8_t broadcast_id_lsb = 1;
250
251 auto codec_qos_pair =
252 getStreamConfigForContext(types::AudioContexts(context));
253 auto broadcast_id = broadcast_id_lsb++;
254 pending_broadcasts_.push_back(BroadcastStateMachine::CreateInstance({
255 .is_public = true,
256 .broadcast_name = test_broadcast_name,
257 .broadcast_id = broadcast_id,
258 // .streaming_phy = ,
259 .codec_wrapper = codec_qos_pair.first,
260 .qos_config = codec_qos_pair.second,
261 // .announcement = ,
262 // .broadcast_code = ,
263 }));
264 pending_broadcasts_.back()->Initialize();
265 return instance_future.get();
266 }
267
268 base::WeakPtr<BleAdvertisingManager> ble_advertising_manager_;
269
270 MockBleAdvertisingManager* mock_ble_advertising_manager_;
271 IsoManager* iso_manager_;
272 MockIsoManager* mock_iso_manager_;
273
274 std::map<uint32_t, std::unique_ptr<BroadcastStateMachine>> broadcasts_;
275 std::vector<std::unique_ptr<BroadcastStateMachine>> pending_broadcasts_;
276 std::unique_ptr<MockBroadcastStatMachineCallbacks> sm_callbacks_;
277 std::promise<uint32_t> instance_creation_promise_;
278 std::promise<uint8_t> instance_destruction_promise_;
279 };
280
TEST_F(StateMachineTest,CreateInstanceFailed)281 TEST_F(StateMachineTest, CreateInstanceFailed) {
282 EXPECT_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet)
283 .WillOnce([](base::Callback<void(uint8_t, int8_t, uint8_t)> cb,
284 tBTM_BLE_ADV_PARAMS* params,
285 std::vector<uint8_t> advertise_data,
286 std::vector<uint8_t> scan_response_data,
287 tBLE_PERIODIC_ADV_PARAMS* periodic_params,
288 std::vector<uint8_t> periodic_data, uint16_t duration,
289 uint8_t maxExtAdvEvents,
290 base::Callback<void(uint8_t, uint8_t)> timeout_cb) {
291 uint8_t advertiser_id = 1;
292 uint8_t tx_power = 0;
293 uint8_t status = 1;
294 cb.Run(advertiser_id, tx_power, status);
295 });
296
297 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, false))
298 .Times(1);
299
300 auto broadcast_id = InstantiateStateMachine();
301 ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
302 ASSERT_TRUE(pending_broadcasts_.empty());
303 ASSERT_TRUE(broadcasts_.empty());
304 }
305
TEST_F(StateMachineTest,CreateInstanceTimeout)306 TEST_F(StateMachineTest, CreateInstanceTimeout) {
307 EXPECT_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet)
308 .WillOnce([](base::Callback<void(uint8_t, int8_t, uint8_t)> cb,
309 tBTM_BLE_ADV_PARAMS* params,
310 std::vector<uint8_t> advertise_data,
311 std::vector<uint8_t> scan_response_data,
312 tBLE_PERIODIC_ADV_PARAMS* periodic_params,
313 std::vector<uint8_t> periodic_data, uint16_t duration,
314 uint8_t maxExtAdvEvents,
315 base::Callback<void(uint8_t, uint8_t)> timeout_cb) {
316 uint8_t advertiser_id = 1;
317 uint8_t status = 1;
318 timeout_cb.Run(advertiser_id, status);
319 });
320
321 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, false))
322 .Times(1);
323
324 auto broadcast_id = InstantiateStateMachine();
325 ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
326 ASSERT_TRUE(pending_broadcasts_.empty());
327 ASSERT_TRUE(broadcasts_.empty());
328 }
329
TEST_F(StateMachineTest,CreateInstanceSuccess)330 TEST_F(StateMachineTest, CreateInstanceSuccess) {
331 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
332 .Times(1);
333
334 auto broadcast_id = InstantiateStateMachine();
335 ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
336 ASSERT_TRUE(pending_broadcasts_.empty());
337 ASSERT_FALSE(broadcasts_.empty());
338 ASSERT_EQ(broadcasts_[broadcast_id]->GetBroadcastId(), broadcast_id);
339 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
340 BroadcastStateMachine::State::CONFIGURED);
341 }
342
TEST_F(StateMachineTest,DestroyInstanceSuccess)343 TEST_F(StateMachineTest, DestroyInstanceSuccess) {
344 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
345 .Times(1);
346
347 auto broadcast_id = InstantiateStateMachine();
348 ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
349 ASSERT_FALSE(broadcasts_.empty());
350
351 instance_destruction_promise_ = std::promise<uint8_t>();
352 std::future<uint8_t> instance_future =
353 instance_destruction_promise_.get_future();
354
355 broadcasts_.clear();
356 EXPECT_EQ(instance_future.get(), broadcast_id);
357 }
358
TEST_F(StateMachineTest,GetAdvertisingAddress)359 TEST_F(StateMachineTest, GetAdvertisingAddress) {
360 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
361 .Times(1);
362
363 auto broadcast_id = InstantiateStateMachine();
364 EXPECT_CALL(*(sm_callbacks_.get()), OnOwnAddressResponse(broadcast_id, _, _))
365 .Times(1);
366 broadcasts_[broadcast_id]->RequestOwnAddress();
367 }
368
TEST_F(StateMachineTest,Mute)369 TEST_F(StateMachineTest, Mute) {
370 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
371 .Times(1);
372
373 auto broadcast_id = InstantiateStateMachine();
374 ASSERT_TRUE(pending_broadcasts_.empty());
375 ASSERT_FALSE(broadcasts_.empty());
376
377 ASSERT_FALSE(broadcasts_[broadcast_id]->IsMuted());
378 broadcasts_[broadcast_id]->SetMuted(true);
379 ASSERT_TRUE(broadcasts_[broadcast_id]->IsMuted());
380 broadcasts_[broadcast_id]->SetMuted(false);
381 ASSERT_FALSE(broadcasts_[broadcast_id]->IsMuted());
382 }
383
prepareAnnouncement(const BroadcastCodecWrapper & codec_config,std::map<uint8_t,std::vector<uint8_t>> metadata)384 static BasicAudioAnnouncementData prepareAnnouncement(
385 const BroadcastCodecWrapper& codec_config,
386 std::map<uint8_t, std::vector<uint8_t>> metadata) {
387 BasicAudioAnnouncementData announcement;
388
389 announcement.presentation_delay = 0x004E20;
390 auto const& codec_id = codec_config.GetLeAudioCodecId();
391
392 announcement.subgroup_configs = {{
393 .codec_config =
394 {
395 .codec_id = codec_id.coding_format,
396 .vendor_company_id = codec_id.vendor_company_id,
397 .vendor_codec_id = codec_id.vendor_codec_id,
398 .codec_specific_params =
399 codec_config.GetSubgroupCodecSpecData().Values(),
400 },
401 .metadata = std::move(metadata),
402 .bis_configs = {},
403 }};
404
405 for (uint8_t i = 0; i < codec_config.GetNumChannels(); ++i) {
406 announcement.subgroup_configs[0].bis_configs.push_back(
407 {.codec_specific_params =
408 codec_config.GetBisCodecSpecData(i + 1).Values(),
409 .bis_index = static_cast<uint8_t>(i + 1)});
410 }
411
412 return announcement;
413 }
414
TEST_F(StateMachineTest,UpdateAnnouncement)415 TEST_F(StateMachineTest, UpdateAnnouncement) {
416 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
417 .Times(1);
418
419 auto broadcast_id = InstantiateStateMachine();
420 std::map<uint8_t, std::vector<uint8_t>> metadata = {};
421 BroadcastCodecWrapper codec_config(
422 {.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
423 .vendor_company_id = le_audio::types::kLeAudioVendorCompanyIdUndefined,
424 .vendor_codec_id = le_audio::types::kLeAudioVendorCodecIdUndefined},
425 {.num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
426 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
427 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
428 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
429 32000, 40);
430 auto announcement = prepareAnnouncement(codec_config, metadata);
431
432 auto adv_sid = broadcasts_[broadcast_id]->GetAdvertisingSid();
433 std::vector<uint8_t> data;
434 EXPECT_CALL(*mock_ble_advertising_manager_,
435 SetPeriodicAdvertisingData(adv_sid, _, _))
436 .Times(2)
437 .WillRepeatedly(SaveArg<1>(&data));
438 broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
439 std::move(announcement));
440
441 uint8_t first_len = data.size();
442 ASSERT_NE(first_len, 0); // Non-zero length
443 ASSERT_EQ(data[1], BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
444 ASSERT_EQ(data[2], (kBasicAudioAnnouncementServiceUuid & 0x00FF));
445 ASSERT_EQ(data[3], ((kBasicAudioAnnouncementServiceUuid >> 8) & 0x00FF));
446 // The rest of the packet data is already covered by the announcement tests
447
448 // Verify that changes in the announcement makes a difference
449 metadata = {{0x01, {0x03}}};
450 announcement = prepareAnnouncement(codec_config, metadata);
451 broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(
452 std::move(announcement));
453 uint8_t second_len = data.size();
454
455 // These should differ by the difference in metadata
456 ASSERT_EQ(first_len + types::LeAudioLtvMap(metadata).RawPacketSize(),
457 second_len);
458 }
459
TEST_F(StateMachineTest,ProcessMessageStartWhenConfigured)460 TEST_F(StateMachineTest, ProcessMessageStartWhenConfigured) {
461 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
462 .Times(1);
463
464 auto sound_context = le_audio::types::LeAudioContextType::MEDIA;
465 uint8_t num_channels = 2;
466
467 auto broadcast_id = InstantiateStateMachine(sound_context);
468 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
469 BroadcastStateMachine::State::CONFIGURED);
470
471 uint8_t num_bises = 0;
472 EXPECT_CALL(*mock_iso_manager_, CreateBig)
473 .WillOnce([this, &num_bises](uint8_t big_id, big_create_params p) {
474 auto bit =
475 std::find_if(broadcasts_.begin(), broadcasts_.end(),
476 [big_id](auto const& entry) {
477 return entry.second->GetAdvertisingSid() == big_id;
478 });
479 if (bit == broadcasts_.end()) return;
480
481 num_bises = p.num_bis;
482
483 big_create_cmpl_evt evt;
484 evt.big_id = big_id;
485
486 // For test convenience lets encode big_id into conn_hdl's
487 // MSB
488 static uint8_t conn_lsb = 1;
489 uint16_t conn_msb = ((uint16_t)big_id) << 8;
490 for (auto i = 0; i < p.num_bis; ++i) {
491 evt.conn_handles.push_back(conn_msb | conn_lsb++);
492 }
493
494 bit->second->HandleHciEvent(HCI_BLE_CREATE_BIG_CPL_EVT, &evt);
495 });
496
497 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(num_channels);
498 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
499 EXPECT_CALL(*(sm_callbacks_.get()),
500 OnStateMachineEvent(broadcast_id,
501 BroadcastStateMachine::State::STREAMING, _))
502 .Times(1);
503 broadcasts_[broadcast_id]->ProcessMessage(
504 BroadcastStateMachine::Message::START);
505
506 // Verify the right number of BISes in the BIG being created
507 ASSERT_EQ(num_bises, num_channels);
508 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
509 BroadcastStateMachine::State::STREAMING);
510 }
511
TEST_F(StateMachineTest,ProcessMessageStopWhenConfigured)512 TEST_F(StateMachineTest, ProcessMessageStopWhenConfigured) {
513 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
514 .Times(1);
515
516 auto broadcast_id =
517 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
518 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
519 BroadcastStateMachine::State::CONFIGURED);
520
521 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
522 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
523 EXPECT_CALL(*(sm_callbacks_.get()),
524 OnStateMachineEvent(broadcast_id,
525 BroadcastStateMachine::State::STOPPING, _))
526 .Times(1);
527 EXPECT_CALL(*(sm_callbacks_.get()),
528 OnStateMachineEvent(broadcast_id,
529 BroadcastStateMachine::State::STOPPED, _))
530 .Times(1);
531 broadcasts_[broadcast_id]->ProcessMessage(
532 BroadcastStateMachine::Message::STOP);
533
534 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
535 BroadcastStateMachine::State::STOPPED);
536 }
537
TEST_F(StateMachineTest,ProcessMessageSuspendWhenConfigured)538 TEST_F(StateMachineTest, ProcessMessageSuspendWhenConfigured) {
539 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
540 .Times(1);
541
542 auto broadcast_id =
543 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
544 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
545 BroadcastStateMachine::State::CONFIGURED);
546
547 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
548 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
549 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
550 .Times(0);
551 broadcasts_[broadcast_id]->ProcessMessage(
552 BroadcastStateMachine::Message::SUSPEND);
553 // There shall be no change in state
554 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
555 BroadcastStateMachine::State::CONFIGURED);
556 }
557
TEST_F(StateMachineTest,ProcessMessageStartWhenStreaming)558 TEST_F(StateMachineTest, ProcessMessageStartWhenStreaming) {
559 auto broadcast_id =
560 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
561
562 broadcasts_[broadcast_id]->ProcessMessage(
563 BroadcastStateMachine::Message::START);
564 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
565 BroadcastStateMachine::State::STREAMING);
566
567 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
568 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
569 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
570 .Times(0);
571 broadcasts_[broadcast_id]->ProcessMessage(
572 BroadcastStateMachine::Message::START);
573
574 // There shall be no change in state
575 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
576 BroadcastStateMachine::State::STREAMING);
577 }
578
TEST_F(StateMachineTest,ProcessMessageStopWhenStreaming)579 TEST_F(StateMachineTest, ProcessMessageStopWhenStreaming) {
580 auto broadcast_id =
581 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
582
583 broadcasts_[broadcast_id]->ProcessMessage(
584 BroadcastStateMachine::Message::START);
585 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
586 BroadcastStateMachine::State::STREAMING);
587
588 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
589 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(2);
590 EXPECT_CALL(*(sm_callbacks_.get()),
591 OnStateMachineEvent(broadcast_id,
592 BroadcastStateMachine::State::STOPPING, _))
593 .Times(1);
594 EXPECT_CALL(*(sm_callbacks_.get()),
595 OnStateMachineEvent(broadcast_id,
596 BroadcastStateMachine::State::STOPPED, _))
597 .Times(1);
598 broadcasts_[broadcast_id]->ProcessMessage(
599 BroadcastStateMachine::Message::STOP);
600
601 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
602 BroadcastStateMachine::State::STOPPED);
603 }
604
TEST_F(StateMachineTest,ProcessMessageSuspendWhenStreaming)605 TEST_F(StateMachineTest, ProcessMessageSuspendWhenStreaming) {
606 auto broadcast_id =
607 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
608
609 broadcasts_[broadcast_id]->ProcessMessage(
610 BroadcastStateMachine::Message::START);
611 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
612 BroadcastStateMachine::State::STREAMING);
613
614 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
615 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(2);
616 EXPECT_CALL(*(sm_callbacks_.get()),
617 OnStateMachineEvent(broadcast_id,
618 BroadcastStateMachine::State::CONFIGURED, _))
619 .Times(1);
620 broadcasts_[broadcast_id]->ProcessMessage(
621 BroadcastStateMachine::Message::SUSPEND);
622
623 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
624 BroadcastStateMachine::State::CONFIGURED);
625 }
626
TEST_F(StateMachineTest,ProcessMessageStartWhenStopped)627 TEST_F(StateMachineTest, ProcessMessageStartWhenStopped) {
628 auto broadcast_id =
629 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
630
631 broadcasts_[broadcast_id]->ProcessMessage(
632 BroadcastStateMachine::Message::STOP);
633 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
634 BroadcastStateMachine::State::STOPPED);
635
636 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(2);
637 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
638 EXPECT_CALL(*(sm_callbacks_.get()),
639 OnStateMachineEvent(broadcast_id,
640 BroadcastStateMachine::State::CONFIGURING, _))
641 .Times(1);
642 EXPECT_CALL(*(sm_callbacks_.get()),
643 OnStateMachineEvent(broadcast_id,
644 BroadcastStateMachine::State::STREAMING, _))
645 .Times(1);
646 broadcasts_[broadcast_id]->ProcessMessage(
647 BroadcastStateMachine::Message::START);
648
649 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
650 BroadcastStateMachine::State::STREAMING);
651 }
652
TEST_F(StateMachineTest,ProcessMessageStopWhenStopped)653 TEST_F(StateMachineTest, ProcessMessageStopWhenStopped) {
654 auto broadcast_id =
655 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
656
657 broadcasts_[broadcast_id]->ProcessMessage(
658 BroadcastStateMachine::Message::STOP);
659 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
660 BroadcastStateMachine::State::STOPPED);
661
662 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
663 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
664 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
665 .Times(0);
666 broadcasts_[broadcast_id]->ProcessMessage(
667 BroadcastStateMachine::Message::STOP);
668
669 // There shall be no change in state
670 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
671 BroadcastStateMachine::State::STOPPED);
672 }
673
TEST_F(StateMachineTest,ProcessMessageSuspendWhenStopped)674 TEST_F(StateMachineTest, ProcessMessageSuspendWhenStopped) {
675 auto broadcast_id =
676 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
677
678 broadcasts_[broadcast_id]->ProcessMessage(
679 BroadcastStateMachine::Message::STOP);
680 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
681 BroadcastStateMachine::State::STOPPED);
682
683 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(0);
684 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath).Times(0);
685 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineEvent(broadcast_id, _, _))
686 .Times(0);
687 broadcasts_[broadcast_id]->ProcessMessage(
688 BroadcastStateMachine::Message::SUSPEND);
689
690 // There shall be no change in state
691 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
692 BroadcastStateMachine::State::STOPPED);
693 }
694
TEST_F(StateMachineTest,OnSetupIsoDataPathError)695 TEST_F(StateMachineTest, OnSetupIsoDataPathError) {
696 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
697 .Times(1);
698
699 auto broadcast_id =
700 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
701 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
702 BroadcastStateMachine::State::CONFIGURED);
703
704 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath)
705 .WillOnce([this](uint16_t conn_handle, iso_data_path_params p) {
706 // Get the big_id encoded in conn_handle's MSB
707 uint8_t big_id = conn_handle >> 8;
708 auto bit =
709 std::find_if(broadcasts_.begin(), broadcasts_.end(),
710 [big_id](auto const& entry) {
711 return entry.second->GetAdvertisingSid() == big_id;
712 });
713 if (bit == broadcasts_.end()) return;
714 bit->second->OnSetupIsoDataPath(0, conn_handle);
715 })
716 .WillOnce([this](uint16_t conn_handle, iso_data_path_params p) {
717 // Get the big_id encoded in conn_handle's MSB
718 uint8_t big_id = conn_handle >> 8;
719 auto bit =
720 std::find_if(broadcasts_.begin(), broadcasts_.end(),
721 [big_id](auto const& entry) {
722 return entry.second->GetAdvertisingSid() == big_id;
723 });
724 if (bit == broadcasts_.end()) return;
725 bit->second->OnSetupIsoDataPath(1, conn_handle);
726 })
727 .RetiresOnSaturation();
728 broadcasts_[broadcast_id]->ProcessMessage(
729 BroadcastStateMachine::Message::START);
730
731 // On datapath setup failure we should go back to configured with BIG being
732 // destroyed. Maybe it will work out next time for the new BIG.
733 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
734 BroadcastStateMachine::State::CONFIGURED);
735
736 // And still be able to start again
737 ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
738 .WillByDefault([this](uint16_t conn_handle, iso_data_path_params p) {
739 // Get the big_id encoded in conn_handle's MSB
740 uint8_t big_id = conn_handle >> 8;
741 auto bit =
742 std::find_if(broadcasts_.begin(), broadcasts_.end(),
743 [big_id](auto const& entry) {
744 return entry.second->GetAdvertisingSid() == big_id;
745 });
746 if (bit == broadcasts_.end()) return;
747 bit->second->OnSetupIsoDataPath(0, conn_handle);
748 });
749 EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath).Times(2);
750
751 broadcasts_[broadcast_id]->ProcessMessage(
752 BroadcastStateMachine::Message::START);
753 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
754 BroadcastStateMachine::State::STREAMING);
755 }
756
TEST_F(StateMachineTest,OnRemoveIsoDataPathError)757 TEST_F(StateMachineTest, OnRemoveIsoDataPathError) {
758 auto broadcast_id =
759 InstantiateStateMachine(le_audio::types::LeAudioContextType::MEDIA);
760
761 broadcasts_[broadcast_id]->ProcessMessage(
762 BroadcastStateMachine::Message::START);
763 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
764 BroadcastStateMachine::State::STREAMING);
765
766 EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath)
767 .WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) {
768 // Get the big_id encoded in conn_handle's MSB
769 uint8_t big_id = conn_handle >> 8;
770 auto bit =
771 std::find_if(broadcasts_.begin(), broadcasts_.end(),
772 [big_id](auto const& entry) {
773 return entry.second->GetAdvertisingSid() == big_id;
774 });
775 if (bit == broadcasts_.end()) return;
776 bit->second->OnRemoveIsoDataPath(0, conn_handle);
777 })
778 .WillOnce([this](uint16_t conn_handle, uint8_t iso_direction) {
779 // Get the big_id encoded in conn_handle's MSB
780 uint8_t big_id = conn_handle >> 8;
781 auto bit =
782 std::find_if(broadcasts_.begin(), broadcasts_.end(),
783 [big_id](auto const& entry) {
784 return entry.second->GetAdvertisingSid() == big_id;
785 });
786 if (bit == broadcasts_.end()) return;
787 bit->second->OnRemoveIsoDataPath(1, conn_handle);
788 })
789 .RetiresOnSaturation();
790 broadcasts_[broadcast_id]->ProcessMessage(
791 BroadcastStateMachine::Message::SUSPEND);
792
793 // On datapath teardown failure we should stay in CONFIGURED with BIG being
794 // destroyed.
795 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
796 BroadcastStateMachine::State::CONFIGURED);
797
798 // And still be able to start again
799 broadcasts_[broadcast_id]->ProcessMessage(
800 BroadcastStateMachine::Message::START);
801 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
802 BroadcastStateMachine::State::STREAMING);
803 }
804
TEST_F(StateMachineTest,GetConfig)805 TEST_F(StateMachineTest, GetConfig) {
806 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
807 .Times(1);
808
809 auto sound_context = le_audio::types::LeAudioContextType::MEDIA;
810 uint8_t num_channels = 2;
811
812 auto broadcast_id = InstantiateStateMachine(sound_context);
813 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
814 BroadcastStateMachine::State::CONFIGURED);
815
816 std::optional<BigConfig> const& big_cfg =
817 broadcasts_[broadcast_id]->GetBigConfig();
818 ASSERT_FALSE(big_cfg.has_value());
819
820 broadcasts_[broadcast_id]->ProcessMessage(
821 BroadcastStateMachine::Message::START);
822 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
823 BroadcastStateMachine::State::STREAMING);
824
825 ASSERT_TRUE(big_cfg.has_value());
826 ASSERT_EQ(big_cfg->status, 0);
827 // This is an implementation specific thing
828 ASSERT_EQ(big_cfg->big_id, broadcasts_[broadcast_id]->GetAdvertisingSid());
829 ASSERT_EQ(big_cfg->connection_handles.size(), num_channels);
830 }
831
TEST_F(StateMachineTest,GetBroadcastId)832 TEST_F(StateMachineTest, GetBroadcastId) {
833 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
834 .Times(1);
835
836 auto broadcast_id = InstantiateStateMachine();
837 ASSERT_NE(bluetooth::le_audio::kBroadcastIdInvalid, broadcast_id);
838 ASSERT_EQ(broadcasts_[broadcast_id]->GetState(),
839 BroadcastStateMachine::State::CONFIGURED);
840 }
841
TEST_F(StateMachineTest,IsPublicBroadcast)842 TEST_F(StateMachineTest, IsPublicBroadcast) {
843 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
844 .Times(1);
845
846 auto broadcast_id = InstantiateStateMachine();
847 ASSERT_EQ(broadcasts_[broadcast_id]->IsPublicBroadcast(), true);
848 }
849
TEST_F(StateMachineTest,GetBroadcastName)850 TEST_F(StateMachineTest, GetBroadcastName) {
851 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
852 .Times(1);
853
854 auto broadcast_id = InstantiateStateMachine();
855 ASSERT_EQ(broadcasts_[broadcast_id]->GetBroadcastName(), test_broadcast_name);
856 }
857
TEST_F(StateMachineTest,GetBroadcastAnnouncement)858 TEST_F(StateMachineTest, GetBroadcastAnnouncement) {
859 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
860 .Times(1);
861
862 auto broadcast_id = InstantiateStateMachine();
863 std::map<uint8_t, std::vector<uint8_t>> metadata = {};
864 BroadcastCodecWrapper codec_config(
865 {.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
866 .vendor_company_id = le_audio::types::kLeAudioVendorCompanyIdUndefined,
867 .vendor_codec_id = le_audio::types::kLeAudioVendorCodecIdUndefined},
868 {.num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
869 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
870 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
871 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
872 32000, 40);
873 auto announcement = prepareAnnouncement(codec_config, metadata);
874 broadcasts_[broadcast_id]->UpdateBroadcastAnnouncement(announcement);
875
876 ASSERT_EQ(announcement,
877 broadcasts_[broadcast_id]->GetBroadcastAnnouncement());
878 }
879
TEST_F(StateMachineTest,GetPublicBroadcastAnnouncement)880 TEST_F(StateMachineTest, GetPublicBroadcastAnnouncement) {
881 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
882 .Times(1);
883
884 auto broadcast_id = InstantiateStateMachine();
885 bool is_public_metadata_valid;
886 types::LeAudioLtvMap public_ltv = types::LeAudioLtvMap::Parse(
887 default_public_metadata.data(), default_public_metadata.size(),
888 is_public_metadata_valid);
889 bluetooth::le_audio::PublicBroadcastAnnouncementData pb_announcement = {
890 .features = test_public_broadcast_features,
891 .metadata = public_ltv.Values()};
892
893 broadcasts_[broadcast_id]->UpdatePublicBroadcastAnnouncement(
894 broadcast_id, test_broadcast_name, pb_announcement);
895
896 ASSERT_EQ(pb_announcement,
897 broadcasts_[broadcast_id]->GetPublicBroadcastAnnouncement());
898 }
899
TEST_F(StateMachineTest,AnnouncementTest)900 TEST_F(StateMachineTest, AnnouncementTest) {
901 tBTM_BLE_ADV_PARAMS adv_params;
902 std::vector<uint8_t> a_data;
903 std::vector<uint8_t> p_data;
904
905 EXPECT_CALL(*mock_ble_advertising_manager_, StartAdvertisingSet)
906 .WillOnce([&p_data, &a_data, &adv_params](
907 base::Callback<void(uint8_t, int8_t, uint8_t)> cb,
908 tBTM_BLE_ADV_PARAMS* params,
909 std::vector<uint8_t> advertise_data,
910 std::vector<uint8_t> scan_response_data,
911 tBLE_PERIODIC_ADV_PARAMS* periodic_params,
912 std::vector<uint8_t> periodic_data, uint16_t duration,
913 uint8_t maxExtAdvEvents,
914 base::Callback<void(uint8_t, uint8_t)> timeout_cb) {
915 uint8_t advertiser_id = 1;
916 uint8_t tx_power = 0;
917 uint8_t status = 0;
918
919 // Since we are not using these buffers in this callback it is safe to
920 // move them.
921 a_data = std::move(advertise_data);
922 p_data = std::move(periodic_data);
923
924 adv_params = *params;
925
926 cb.Run(advertiser_id, tx_power, status);
927 });
928
929 EXPECT_CALL(*(sm_callbacks_.get()), OnStateMachineCreateStatus(_, true))
930 .Times(1);
931
932 auto broadcast_id = InstantiateStateMachine();
933 ASSERT_NE(broadcast_id, BroadcastStateMachine::kAdvSidUndefined);
934
935 // Check ext. advertising data for Broadcast Announcement UUID
936 ASSERT_NE(a_data[0], 0); // size
937 ASSERT_EQ(a_data[1], 0x16); // BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE
938 ASSERT_EQ(a_data[2], (kBroadcastAudioAnnouncementServiceUuid & 0x00FF));
939 ASSERT_EQ(a_data[3],
940 ((kBroadcastAudioAnnouncementServiceUuid >> 8) & 0x00FF));
941 ASSERT_EQ(a_data[4], (broadcast_id & 0x0000FF));
942 ASSERT_EQ(a_data[5], ((broadcast_id >> 8) & 0x0000FF));
943 ASSERT_EQ(a_data[6], ((broadcast_id >> 16) & 0x0000FF));
944
945 ASSERT_NE(a_data[7], 0); // size
946 ASSERT_EQ(a_data[8], 0x16); // BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE
947 ASSERT_EQ(a_data[9], (kPublicBroadcastAnnouncementServiceUuid & 0x00FF));
948 ASSERT_EQ(a_data[10],
949 ((kPublicBroadcastAnnouncementServiceUuid >> 8) & 0x00FF));
950
951 // Check periodic data for Basic Announcement UUID
952 ASSERT_NE(p_data[0], 0); // size
953 ASSERT_EQ(p_data[1], 0x16); // BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE
954 ASSERT_EQ(p_data[2], (kBasicAudioAnnouncementServiceUuid & 0x00FF));
955 ASSERT_EQ(p_data[3], ((kBasicAudioAnnouncementServiceUuid >> 8) & 0x00FF));
956
957 // Check advertising parameters
958 ASSERT_EQ(adv_params.own_address_type, BLE_ADDR_RANDOM);
959 }
960
961 } // namespace
962 } // namespace broadcaster
963 } // namespace le_audio
964