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