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 <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 #include <hardware/audio.h>
21
22 #include <chrono>
23
24 #include "bta/include/bta_le_audio_api.h"
25 #include "bta/include/bta_le_audio_broadcaster_api.h"
26 #include "bta/le_audio/broadcaster/mock_state_machine.h"
27 #include "bta/le_audio/content_control_id_keeper.h"
28 #include "bta/le_audio/le_audio_types.h"
29 #include "bta/le_audio/mock_iso_manager.h"
30 #include "bta/test/common/mock_controller.h"
31 #include "device/include/controller.h"
32 #include "stack/include/btm_iso_api.h"
33
34 using namespace std::chrono_literals;
35
36 using le_audio::types::AudioContexts;
37 using le_audio::types::LeAudioContextType;
38
39 using testing::_;
40 using testing::AtLeast;
41 using testing::DoAll;
42 using testing::Matcher;
43 using testing::Mock;
44 using testing::NotNull;
45 using testing::Return;
46 using testing::ReturnRef;
47 using testing::SaveArg;
48 using testing::Test;
49
50 using namespace bluetooth::le_audio;
51
52 using le_audio::LeAudioCodecConfiguration;
53 using le_audio::LeAudioSourceAudioHalClient;
54 using le_audio::broadcaster::BigConfig;
55 using le_audio::broadcaster::BroadcastCodecWrapper;
56
57 std::map<std::string, int> mock_function_count_map;
58
59 // Disables most likely false-positives from base::SplitString()
__asan_default_options()60 extern "C" const char* __asan_default_options() {
61 return "detect_container_overflow=0";
62 }
63
64 static base::Callback<void(BT_OCTET8)> generator_cb;
65
btsnd_hcic_ble_rand(base::Callback<void (BT_OCTET8)> cb)66 void btsnd_hcic_ble_rand(base::Callback<void(BT_OCTET8)> cb) {
67 generator_cb = cb;
68 }
69
70 std::atomic<int> num_async_tasks;
71 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()72 bluetooth::common::MessageLoopThread* get_main_thread() {
73 return &message_loop_thread;
74 }
invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size)75 void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {}
76
do_in_main_thread(const base::Location & from_here,base::OnceClosure task)77 bt_status_t do_in_main_thread(const base::Location& from_here,
78 base::OnceClosure task) {
79 // Wrap the task with task counter so we could later know if there are
80 // any callbacks scheduled and we should wait before performing some actions
81 if (!message_loop_thread.DoInThread(
82 from_here,
83 base::BindOnce(
84 [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
85 std::move(task).Run();
86 num_async_tasks--;
87 },
88 std::move(task), std::ref(num_async_tasks)))) {
89 LOG(ERROR) << __func__ << ": failed from " << from_here.ToString();
90 return BT_STATUS_FAIL;
91 }
92 num_async_tasks++;
93 return BT_STATUS_SUCCESS;
94 }
95
96 static base::MessageLoop* message_loop_;
get_main_message_loop()97 base::MessageLoop* get_main_message_loop() { return message_loop_; }
98
init_message_loop_thread()99 static void init_message_loop_thread() {
100 num_async_tasks = 0;
101 message_loop_thread.StartUp();
102 if (!message_loop_thread.IsRunning()) {
103 FAIL() << "unable to create message loop thread.";
104 }
105
106 if (!message_loop_thread.EnableRealTimeScheduling())
107 LOG(ERROR) << "Unable to set real time scheduling";
108
109 message_loop_ = message_loop_thread.message_loop();
110 if (message_loop_ == nullptr) FAIL() << "unable to get message loop.";
111 }
112
cleanup_message_loop_thread()113 static void cleanup_message_loop_thread() {
114 message_loop_ = nullptr;
115 message_loop_thread.ShutDown();
116 }
117
118 namespace le_audio {
119 class MockAudioHalClientEndpoint;
120 MockAudioHalClientEndpoint* mock_audio_source_;
121 bool is_audio_hal_acquired;
122
123 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireBroadcast()124 LeAudioSourceAudioHalClient::AcquireBroadcast() {
125 if (mock_audio_source_) {
126 std::unique_ptr<LeAudioSourceAudioHalClient> ptr(
127 (LeAudioSourceAudioHalClient*)mock_audio_source_);
128 is_audio_hal_acquired = true;
129 return std::move(ptr);
130 }
131 return nullptr;
132 }
133
134 static constexpr uint8_t default_ccid = 0xDE;
135 static constexpr auto default_context =
136 static_cast<std::underlying_type<LeAudioContextType>::type>(
137 LeAudioContextType::ALERTS);
138 static constexpr BroadcastCode default_code = {
139 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
140 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
141 static const std::vector<uint8_t> default_metadata = {
142 le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
143 le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
144 default_context & 0x00FF, (default_context & 0xFF00) >> 8};
145
146 static constexpr uint8_t media_ccid = 0xC0;
147 static constexpr auto media_context =
148 static_cast<std::underlying_type<LeAudioContextType>::type>(
149 LeAudioContextType::MEDIA);
150 static const std::vector<uint8_t> media_metadata = {
151 le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
152 le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
153 media_context & 0x00FF, (media_context & 0xFF00) >> 8};
154
155 class MockLeAudioBroadcasterCallbacks
156 : public bluetooth::le_audio::LeAudioBroadcasterCallbacks {
157 public:
158 MOCK_METHOD((void), OnBroadcastCreated, (uint32_t broadcast_id, bool success),
159 (override));
160 MOCK_METHOD((void), OnBroadcastDestroyed, (uint32_t broadcast_id),
161 (override));
162 MOCK_METHOD((void), OnBroadcastStateChanged,
163 (uint32_t broadcast_id,
164 bluetooth::le_audio::BroadcastState state),
165 (override));
166 MOCK_METHOD((void), OnBroadcastMetadataChanged,
167 (uint32_t broadcast_id,
168 const BroadcastMetadata& broadcast_metadata),
169 (override));
170 };
171
172 class MockAudioHalClientEndpoint : public LeAudioSourceAudioHalClient {
173 public:
174 MockAudioHalClientEndpoint() = default;
175 MOCK_METHOD((bool), Start,
176 (const LeAudioCodecConfiguration& codecConfiguration,
177 LeAudioSourceAudioHalClient::Callbacks* audioReceiver),
178 (override));
179 MOCK_METHOD((void), Stop, (), (override));
180 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
181 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
182 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
183 MOCK_METHOD((void), UpdateAudioConfigToHal,
184 (const ::le_audio::offload_config&), (override));
185 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
186 (const ::le_audio::broadcast_offload_config&), (override));
187 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
188 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
189
190 MOCK_METHOD((void), OnDestroyed, ());
~MockAudioHalClientEndpoint()191 virtual ~MockAudioHalClientEndpoint() { OnDestroyed(); }
192 };
193
194 class BroadcasterTest : public Test {
195 protected:
SetUp()196 void SetUp() override {
197 init_message_loop_thread();
198
199 mock_function_count_map.clear();
200 ON_CALL(controller_interface_, SupportsBleIsochronousBroadcaster)
201 .WillByDefault(Return(true));
202
203 controller::SetMockControllerInterface(&controller_interface_);
204 iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
205 ASSERT_NE(iso_manager_, nullptr);
206 iso_manager_->Start();
207
208 is_audio_hal_acquired = false;
209 mock_audio_source_ = new MockAudioHalClientEndpoint();
210 ON_CALL(*mock_audio_source_, Start).WillByDefault(Return(true));
211 ON_CALL(*mock_audio_source_, OnDestroyed).WillByDefault([]() {
212 mock_audio_source_ = nullptr;
213 is_audio_hal_acquired = false;
214 });
215
216 ASSERT_FALSE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
217 LeAudioBroadcaster::Initialize(&mock_broadcaster_callbacks_,
218 base::Bind([]() -> bool { return true; }));
219
220 ContentControlIdKeeper::GetInstance()->Start();
221 ContentControlIdKeeper::GetInstance()->SetCcid(0x0004, media_ccid);
222
223 /* Simulate random generator */
224 uint8_t random[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
225 generator_cb.Run(random);
226 }
227
TearDown()228 void TearDown() override {
229 // Message loop cleanup should wait for all the 'till now' scheduled calls
230 // so it should be called right at the very begginning of teardown.
231 cleanup_message_loop_thread();
232
233 // This is required since Stop() and Cleanup() may trigger some callbacks.
234 Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_);
235
236 LeAudioBroadcaster::Stop();
237 LeAudioBroadcaster::Cleanup();
238 ASSERT_FALSE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
239
240 iso_manager_->Stop();
241
242 controller::SetMockControllerInterface(nullptr);
243 }
244
InstantiateBroadcast(std::vector<uint8_t> metadata=default_metadata,BroadcastCode code=default_code)245 uint32_t InstantiateBroadcast(
246 std::vector<uint8_t> metadata = default_metadata,
247 BroadcastCode code = default_code) {
248 uint32_t broadcast_id = LeAudioBroadcaster::kInstanceIdUndefined;
249 EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastCreated(_, true))
250 .WillOnce(SaveArg<0>(&broadcast_id));
251 LeAudioBroadcaster::Get()->CreateAudioBroadcast(metadata, code);
252
253 return broadcast_id;
254 }
255
256 protected:
257 MockLeAudioBroadcasterCallbacks mock_broadcaster_callbacks_;
258 controller::MockControllerInterface controller_interface_;
259 bluetooth::hci::IsoManager* iso_manager_;
260 };
261
TEST_F(BroadcasterTest,Initialize)262 TEST_F(BroadcasterTest, Initialize) {
263 ASSERT_NE(LeAudioBroadcaster::Get(), nullptr);
264 ASSERT_TRUE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
265 }
266
TEST_F(BroadcasterTest,GetStreamingPhy)267 TEST_F(BroadcasterTest, GetStreamingPhy) {
268 LeAudioBroadcaster::Get()->SetStreamingPhy(1);
269 ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 1);
270 LeAudioBroadcaster::Get()->SetStreamingPhy(2);
271 ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 2);
272 }
273
TEST_F(BroadcasterTest,CreateAudioBroadcast)274 TEST_F(BroadcasterTest, CreateAudioBroadcast) {
275 auto broadcast_id = InstantiateBroadcast();
276 ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
277 ASSERT_EQ(broadcast_id,
278 MockBroadcastStateMachine::GetLastInstance()->GetBroadcastId());
279
280 auto& instance_config = MockBroadcastStateMachine::GetLastInstance()->cfg;
281 ASSERT_EQ(instance_config.broadcast_code, default_code);
282 for (auto& subgroup : instance_config.announcement.subgroup_configs) {
283 ASSERT_EQ(types::LeAudioLtvMap(subgroup.metadata).RawPacket(),
284 default_metadata);
285 }
286 // Note: There shall be a separate test to verify audio parameters
287 }
288
TEST_F(BroadcasterTest,SuspendAudioBroadcast)289 TEST_F(BroadcasterTest, SuspendAudioBroadcast) {
290 auto broadcast_id = InstantiateBroadcast();
291 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
292
293 EXPECT_CALL(mock_broadcaster_callbacks_,
294 OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED))
295 .Times(1);
296
297 EXPECT_CALL(*mock_audio_source_, Stop).Times(AtLeast(1));
298 LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
299 }
300
TEST_F(BroadcasterTest,StartAudioBroadcast)301 TEST_F(BroadcasterTest, StartAudioBroadcast) {
302 auto broadcast_id = InstantiateBroadcast();
303 LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
304
305 EXPECT_CALL(mock_broadcaster_callbacks_,
306 OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
307 .Times(1);
308
309 LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
310 EXPECT_CALL(*mock_audio_source_, Start)
311 .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
312
313 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
314 ASSERT_NE(audio_receiver, nullptr);
315
316 // NOTICE: This is really an implementation specific part, we fake the BIG
317 // config as the mocked state machine does not even call the
318 // IsoManager to prepare one (and that's good since IsoManager is also
319 // a mocked one).
320 BigConfig big_cfg;
321 big_cfg.big_id =
322 MockBroadcastStateMachine::GetLastInstance()->GetAdvertisingSid();
323 big_cfg.connection_handles = {0x10, 0x12};
324 big_cfg.max_pdu = 128;
325 MockBroadcastStateMachine::GetLastInstance()->SetExpectedBigConfig(big_cfg);
326
327 // Inject the audio and verify call on the Iso manager side.
328 EXPECT_CALL(*MockIsoManager::GetInstance(), SendIsoData).Times(1);
329 std::vector<uint8_t> sample_data(320, 0);
330 audio_receiver->OnAudioDataReady(sample_data);
331 }
332
TEST_F(BroadcasterTest,StartAudioBroadcastMedia)333 TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
334 auto broadcast_id = InstantiateBroadcast(media_metadata);
335 LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
336
337 EXPECT_CALL(mock_broadcaster_callbacks_,
338 OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
339 .Times(1);
340
341 LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
342 EXPECT_CALL(*mock_audio_source_, Start)
343 .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
344
345 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
346 ASSERT_NE(audio_receiver, nullptr);
347
348 // NOTICE: This is really an implementation specific part, we fake the BIG
349 // config as the mocked state machine does not even call the
350 // IsoManager to prepare one (and that's good since IsoManager is also
351 // a mocked one).
352 BigConfig big_cfg;
353 big_cfg.big_id =
354 MockBroadcastStateMachine::GetLastInstance()->GetAdvertisingSid();
355 big_cfg.connection_handles = {0x10, 0x12};
356 big_cfg.max_pdu = 128;
357 MockBroadcastStateMachine::GetLastInstance()->SetExpectedBigConfig(big_cfg);
358
359 // Inject the audio and verify call on the Iso manager side.
360 EXPECT_CALL(*MockIsoManager::GetInstance(), SendIsoData).Times(2);
361 std::vector<uint8_t> sample_data(1920, 0);
362 audio_receiver->OnAudioDataReady(sample_data);
363 }
364
TEST_F(BroadcasterTest,StopAudioBroadcast)365 TEST_F(BroadcasterTest, StopAudioBroadcast) {
366 auto broadcast_id = InstantiateBroadcast();
367 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
368
369 EXPECT_CALL(mock_broadcaster_callbacks_,
370 OnBroadcastStateChanged(broadcast_id, BroadcastState::STOPPED))
371 .Times(1);
372
373 EXPECT_CALL(*mock_audio_source_, Stop).Times(AtLeast(1));
374 LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
375 }
376
TEST_F(BroadcasterTest,DestroyAudioBroadcast)377 TEST_F(BroadcasterTest, DestroyAudioBroadcast) {
378 auto broadcast_id = InstantiateBroadcast();
379
380 EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastDestroyed(broadcast_id))
381 .Times(1);
382 LeAudioBroadcaster::Get()->DestroyAudioBroadcast(broadcast_id);
383
384 // Expect not being able to interact with this Broadcast
385 EXPECT_CALL(mock_broadcaster_callbacks_,
386 OnBroadcastStateChanged(broadcast_id, _))
387 .Times(0);
388
389 EXPECT_CALL(*mock_audio_source_, Stop).Times(0);
390 LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
391
392 EXPECT_CALL(*mock_audio_source_, Start).Times(0);
393 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
394
395 EXPECT_CALL(*mock_audio_source_, Stop).Times(0);
396 LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
397 }
398
TEST_F(BroadcasterTest,GetBroadcastAllStates)399 TEST_F(BroadcasterTest, GetBroadcastAllStates) {
400 auto broadcast_id = InstantiateBroadcast();
401 auto broadcast_id2 = InstantiateBroadcast();
402 ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
403 ASSERT_NE(broadcast_id2, LeAudioBroadcaster::kInstanceIdUndefined);
404 ASSERT_NE(broadcast_id, broadcast_id2);
405
406 /* In the current implementation state machine switches to the correct state
407 * on itself, therefore here when we use mocked state machine this is not
408 * being verified.
409 */
410 EXPECT_CALL(mock_broadcaster_callbacks_,
411 OnBroadcastStateChanged(broadcast_id, _))
412 .Times(1);
413 EXPECT_CALL(mock_broadcaster_callbacks_,
414 OnBroadcastStateChanged(broadcast_id2, _))
415 .Times(1);
416
417 LeAudioBroadcaster::Get()->GetAllBroadcastStates();
418 }
419
TEST_F(BroadcasterTest,UpdateMetadata)420 TEST_F(BroadcasterTest, UpdateMetadata) {
421 auto broadcast_id = InstantiateBroadcast();
422 std::vector<uint8_t> ccid_list;
423 EXPECT_CALL(*MockBroadcastStateMachine::GetLastInstance(),
424 UpdateBroadcastAnnouncement)
425 .WillOnce(
426 [&](bluetooth::le_audio::BasicAudioAnnouncementData announcement) {
427 for (auto subgroup : announcement.subgroup_configs) {
428 if (subgroup.metadata.count(
429 types::kLeAudioMetadataTypeCcidList)) {
430 ccid_list =
431 subgroup.metadata.at(types::kLeAudioMetadataTypeCcidList);
432 break;
433 }
434 }
435 });
436
437 ContentControlIdKeeper::GetInstance()->SetCcid(0x0400, default_ccid);
438 LeAudioBroadcaster::Get()->UpdateMetadata(
439 broadcast_id,
440 std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04}));
441
442 ASSERT_EQ(2u, ccid_list.size());
443 ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), media_ccid));
444 ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), default_ccid));
445 }
446
prepareAnnouncement(const BroadcastCodecWrapper & codec_config,std::map<uint8_t,std::vector<uint8_t>> metadata)447 static BasicAudioAnnouncementData prepareAnnouncement(
448 const BroadcastCodecWrapper& codec_config,
449 std::map<uint8_t, std::vector<uint8_t>> metadata) {
450 BasicAudioAnnouncementData announcement;
451
452 announcement.presentation_delay = 0x004E20;
453 auto const& codec_id = codec_config.GetLeAudioCodecId();
454
455 announcement.subgroup_configs = {{
456 .codec_config =
457 {
458 .codec_id = codec_id.coding_format,
459 .vendor_company_id = codec_id.vendor_company_id,
460 .vendor_codec_id = codec_id.vendor_codec_id,
461 .codec_specific_params =
462 codec_config.GetSubgroupCodecSpecData().Values(),
463 },
464 .metadata = std::move(metadata),
465 .bis_configs = {},
466 }};
467
468 for (uint8_t i = 0; i < codec_config.GetNumChannels(); ++i) {
469 announcement.subgroup_configs[0].bis_configs.push_back(
470 {.codec_specific_params =
471 codec_config.GetBisCodecSpecData(i + 1).Values(),
472 .bis_index = static_cast<uint8_t>(i + 1)});
473 }
474
475 return announcement;
476 }
477
TEST_F(BroadcasterTest,UpdateMetadataFromAudioTrackMetadata)478 TEST_F(BroadcasterTest, UpdateMetadataFromAudioTrackMetadata) {
479 ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
480 auto broadcast_id = InstantiateBroadcast();
481
482 LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
483 EXPECT_CALL(*mock_audio_source_, Start)
484 .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
485
486 LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
487 ASSERT_NE(audio_receiver, nullptr);
488
489 auto sm = MockBroadcastStateMachine::GetLastInstance();
490 std::vector<uint8_t> ccid_list;
491 std::vector<uint8_t> context_types_map;
492 EXPECT_CALL(*sm, UpdateBroadcastAnnouncement)
493 .WillOnce(
494 [&](bluetooth::le_audio::BasicAudioAnnouncementData announcement) {
495 for (auto subgroup : announcement.subgroup_configs) {
496 if (subgroup.metadata.count(
497 types::kLeAudioMetadataTypeCcidList)) {
498 ccid_list =
499 subgroup.metadata.at(types::kLeAudioMetadataTypeCcidList);
500 }
501 if (subgroup.metadata.count(
502 types::kLeAudioMetadataTypeStreamingAudioContext)) {
503 context_types_map = subgroup.metadata.at(
504 types::kLeAudioMetadataTypeStreamingAudioContext);
505 }
506 }
507 });
508
509 std::map<uint8_t, std::vector<uint8_t>> meta = {};
510 BroadcastCodecWrapper codec_config(
511 {.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
512 .vendor_company_id = le_audio::types::kLeAudioVendorCompanyIdUndefined,
513 .vendor_codec_id = le_audio::types::kLeAudioVendorCodecIdUndefined},
514 {.num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
515 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
516 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
517 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
518 32000, 40);
519 auto announcement = prepareAnnouncement(codec_config, meta);
520
521 ON_CALL(*sm, GetBroadcastAnnouncement())
522 .WillByDefault(ReturnRef(announcement));
523
524 std::vector<struct playback_track_metadata> multitrack_source_metadata = {
525 {{AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_SONIFICATION, 0},
526 {AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, 0},
527 {AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, AUDIO_CONTENT_TYPE_SPEECH,
528 0},
529 {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
530
531 audio_receiver->OnAudioMetadataUpdate(multitrack_source_metadata);
532
533 // Verify ccid
534 ASSERT_NE(ccid_list.size(), 0u);
535 ASSERT_TRUE(std::find(ccid_list.begin(), ccid_list.end(), media_ccid) !=
536 ccid_list.end());
537
538 // Verify context type
539 ASSERT_NE(context_types_map.size(), 0u);
540 AudioContexts context_type;
541 auto pp = context_types_map.data();
542 STREAM_TO_UINT16(context_type.value_ref(), pp);
543 ASSERT_TRUE(context_type.test_all(LeAudioContextType::MEDIA |
544 LeAudioContextType::GAME));
545 }
546
TEST_F(BroadcasterTest,GetMetadata)547 TEST_F(BroadcasterTest, GetMetadata) {
548 auto broadcast_id = InstantiateBroadcast();
549 bluetooth::le_audio::BroadcastMetadata metadata;
550
551 static const uint8_t test_adv_sid = 0x14;
552 std::optional<bluetooth::le_audio::BroadcastCode> test_broadcast_code =
553 bluetooth::le_audio::BroadcastCode({1, 2, 3, 4, 5, 6});
554
555 auto sm = MockBroadcastStateMachine::GetLastInstance();
556
557 std::map<uint8_t, std::vector<uint8_t>> meta = {};
558 BroadcastCodecWrapper codec_config(
559 {.coding_format = le_audio::types::kLeAudioCodingFormatLC3,
560 .vendor_company_id = le_audio::types::kLeAudioVendorCompanyIdUndefined,
561 .vendor_codec_id = le_audio::types::kLeAudioVendorCodecIdUndefined},
562 {.num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
563 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
564 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
565 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
566 32000, 40);
567 auto announcement = prepareAnnouncement(codec_config, meta);
568
569 ON_CALL(*sm, GetAdvertisingSid()).WillByDefault(Return(test_adv_sid));
570 ON_CALL(*sm, GetBroadcastCode()).WillByDefault(Return(test_broadcast_code));
571 ON_CALL(*sm, GetBroadcastAnnouncement())
572 .WillByDefault(ReturnRef(announcement));
573
574 EXPECT_CALL(mock_broadcaster_callbacks_,
575 OnBroadcastMetadataChanged(broadcast_id, _))
576 .Times(1)
577 .WillOnce(SaveArg<1>(&metadata));
578 LeAudioBroadcaster::Get()->GetBroadcastMetadata(broadcast_id);
579
580 ASSERT_NE(LeAudioBroadcaster::kInstanceIdUndefined, metadata.broadcast_id);
581 ASSERT_EQ(sm->GetBroadcastId(), metadata.broadcast_id);
582 ASSERT_EQ(sm->GetBroadcastCode(), metadata.broadcast_code);
583 ASSERT_EQ(sm->GetBroadcastAnnouncement(), metadata.basic_audio_announcement);
584 ASSERT_EQ(sm->GetPaInterval(), metadata.pa_interval);
585 ASSERT_EQ(sm->GetOwnAddress(), metadata.addr);
586 ASSERT_EQ(sm->GetOwnAddressType(), metadata.addr_type);
587 ASSERT_EQ(sm->GetAdvertisingSid(), metadata.adv_sid);
588 }
589
TEST_F(BroadcasterTest,SetStreamingPhy)590 TEST_F(BroadcasterTest, SetStreamingPhy) {
591 LeAudioBroadcaster::Get()->SetStreamingPhy(2);
592 // From now on new streams should be using Phy = 2.
593 InstantiateBroadcast();
594 ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 2);
595
596 // From now on new streams should be using Phy = 1.
597 LeAudioBroadcaster::Get()->SetStreamingPhy(1);
598 InstantiateBroadcast();
599 ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 1);
600 ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 1);
601 }
602
TEST_F(BroadcasterTest,StreamParamsAlerts)603 TEST_F(BroadcasterTest, StreamParamsAlerts) {
604 uint8_t expected_channels = 1u;
605 InstantiateBroadcast();
606 auto config = MockBroadcastStateMachine::GetLastInstance()->cfg;
607
608 // Check audio configuration
609 ASSERT_EQ(config.codec_wrapper.GetNumChannels(), expected_channels);
610 // Matches number of bises in the announcement
611 ASSERT_EQ(config.announcement.subgroup_configs[0].bis_configs.size(),
612 expected_channels);
613 // Note: Num of bises at IsoManager level is verified by state machine tests
614 }
615
TEST_F(BroadcasterTest,StreamParamsMedia)616 TEST_F(BroadcasterTest, StreamParamsMedia) {
617 uint8_t expected_channels = 2u;
618 ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
619 InstantiateBroadcast(media_metadata);
620 auto config = MockBroadcastStateMachine::GetLastInstance()->cfg;
621
622 // Check audio configuration
623 ASSERT_EQ(config.codec_wrapper.GetNumChannels(), expected_channels);
624
625 auto& subgroup = config.announcement.subgroup_configs[0];
626
627 // Matches number of bises in the announcement
628 ASSERT_EQ(subgroup.bis_configs.size(), expected_channels);
629 // Verify CCID for Media
630 auto ccid_list_opt = types::LeAudioLtvMap(subgroup.metadata)
631 .Find(le_audio::types::kLeAudioMetadataTypeCcidList);
632 ASSERT_TRUE(ccid_list_opt.has_value());
633 auto ccid_list = ccid_list_opt.value();
634 ASSERT_EQ(1u, ccid_list.size());
635 ASSERT_EQ(media_ccid, ccid_list[0]);
636 // Note: Num of bises at IsoManager level is verified by state machine tests
637 }
638
639 } // namespace le_audio
640