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