• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <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