• 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 <bluetooth/log.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <hardware/audio.h>
22 
23 #include <chrono>
24 
25 #include "bta/include/bta_le_audio_api.h"
26 #include "bta/include/bta_le_audio_broadcaster_api.h"
27 #include "bta/le_audio/audio_hal_client/audio_hal_client.h"
28 #include "bta/le_audio/broadcaster/broadcast_configuration_provider.h"
29 #include "bta/le_audio/broadcaster/mock_state_machine.h"
30 #include "bta/le_audio/content_control_id_keeper.h"
31 #include "bta/le_audio/le_audio_types.h"
32 #include "bta/le_audio/mock_codec_manager.h"
33 #include "hci/controller_interface_mock.h"
34 #include "stack/include/btm_iso_api.h"
35 #include "test/common/mock_functions.h"
36 #include "test/mock/mock_main_shim_entry.h"
37 #include "test/mock/mock_stack_btm_iso.h"
38 
39 using namespace std::chrono_literals;
40 
41 using bluetooth::le_audio::types::AudioContexts;
42 using bluetooth::le_audio::types::LeAudioContextType;
43 
44 using testing::_;
45 using testing::AtLeast;
46 using testing::DoAll;
47 using testing::Invoke;
48 using testing::Matcher;
49 using testing::Mock;
50 using testing::NotNull;
51 using testing::Return;
52 using testing::ReturnRef;
53 using testing::SaveArg;
54 using testing::Test;
55 
56 using namespace bluetooth::le_audio;
57 using namespace bluetooth;
58 
59 using bluetooth::le_audio::DsaMode;
60 using bluetooth::le_audio::LeAudioCodecConfiguration;
61 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
62 using bluetooth::le_audio::broadcaster::BigConfig;
63 using bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig;
64 
65 // Disables most likely false-positives from base::SplitString()
__asan_default_options()66 extern "C" const char* __asan_default_options() {
67   return "detect_container_overflow=0";
68 }
69 
70 static base::Callback<void(BT_OCTET8)> generator_cb;
71 
btsnd_hcic_ble_rand(base::Callback<void (BT_OCTET8)> cb)72 void btsnd_hcic_ble_rand(base::Callback<void(BT_OCTET8)> cb) {
73   generator_cb = cb;
74 }
75 
76 namespace server_configurable_flags {
GetServerConfigurableFlag(const std::string & experiment_category_name,const std::string & experiment_flag_name,const std::string & default_value)77 std::string GetServerConfigurableFlag(
78     const std::string& experiment_category_name,
79     const std::string& experiment_flag_name, const std::string& default_value) {
80   return "";
81 }
82 }  // namespace server_configurable_flags
83 
84 std::atomic<int> num_async_tasks;
85 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()86 bluetooth::common::MessageLoopThread* get_main_thread() {
87   return &message_loop_thread;
88 }
invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size)89 void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {}
90 
do_in_main_thread(const base::Location & from_here,base::OnceClosure task)91 bt_status_t do_in_main_thread(const base::Location& from_here,
92                               base::OnceClosure task) {
93   // Wrap the task with task counter so we could later know if there are
94   // any callbacks scheduled and we should wait before performing some actions
95   if (!message_loop_thread.DoInThread(
96           from_here,
97           base::BindOnce(
98               [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
99                 std::move(task).Run();
100                 num_async_tasks--;
101               },
102               std::move(task), std::ref(num_async_tasks)))) {
103     log::error("failed from {}", from_here.ToString());
104     return BT_STATUS_FAIL;
105   }
106   num_async_tasks++;
107   return BT_STATUS_SUCCESS;
108 }
109 
110 static base::MessageLoop* message_loop_;
get_main_message_loop()111 base::MessageLoop* get_main_message_loop() { return message_loop_; }
112 
init_message_loop_thread()113 static void init_message_loop_thread() {
114   num_async_tasks = 0;
115   message_loop_thread.StartUp();
116   if (!message_loop_thread.IsRunning()) {
117     FAIL() << "unable to create message loop thread.";
118   }
119 
120   if (!message_loop_thread.EnableRealTimeScheduling())
121     log::error("Unable to set real time scheduling");
122 
123   message_loop_ = message_loop_thread.message_loop();
124   if (message_loop_ == nullptr) FAIL() << "unable to get message loop.";
125 }
126 
cleanup_message_loop_thread()127 static void cleanup_message_loop_thread() {
128   message_loop_ = nullptr;
129   message_loop_thread.ShutDown();
130 }
131 
IsLeAudioClientRunning(void)132 bool LeAudioClient::IsLeAudioClientRunning(void) { return false; }
133 
134 namespace bluetooth::le_audio {
135 namespace broadcaster {
GetBroadcastConfig(const std::vector<std::pair<types::LeAudioContextType,uint8_t>> & subgroup_quality)136 BroadcastConfiguration GetBroadcastConfig(
137     const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&
138         subgroup_quality) {
139   BroadcastConfiguration config = {
140       .subgroups = {},
141       .qos = qos_config_4_60,  // default QoS value for reliability
142       .data_path = lc3_data_path,
143       .sduIntervalUs = 10000,
144       .phy = 0x02,   // PHY_LE_2M
145       .packing = 0,  // Sequential
146       .framing = 0,  // Unframed
147   };
148 
149   for (auto [context, quality] : subgroup_quality) {
150     // Select QoS - Check for low latency contexts
151     if (AudioContexts(context).test_any(
152             types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE |
153             types::LeAudioContextType::INSTRUCTIONAL |
154             types::LeAudioContextType::SOUNDEFFECTS)) {
155       config.qos = qos_config_2_10;
156     }
157 
158     // Select codec quality
159     if (quality == bluetooth::le_audio::QUALITY_STANDARD) {
160       // STANDARD
161       config.subgroups.push_back(lc3_mono_16_2);
162     } else {
163       // HIGH
164       config.subgroups.push_back(lc3_stereo_48_4);
165     }
166   }
167   return config;
168 }
169 }  // namespace broadcaster
170 
171 class MockAudioHalClientEndpoint;
172 MockAudioHalClientEndpoint* mock_audio_source_;
173 bool is_audio_hal_acquired;
174 void (*iso_active_callback)(bool);
175 
176 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireBroadcast()177 LeAudioSourceAudioHalClient::AcquireBroadcast() {
178   if (mock_audio_source_) {
179     std::unique_ptr<LeAudioSourceAudioHalClient> ptr(
180         (LeAudioSourceAudioHalClient*)mock_audio_source_);
181     is_audio_hal_acquired = true;
182     return std::move(ptr);
183   }
184   return nullptr;
185 }
186 
187 static constexpr uint8_t default_ccid = 0xDE;
188 static constexpr auto default_context =
189     static_cast<std::underlying_type<LeAudioContextType>::type>(
190         LeAudioContextType::ALERTS);
191 std::vector<uint8_t> default_subgroup_qualities = {
192     bluetooth::le_audio::QUALITY_STANDARD};
193 static constexpr BroadcastCode default_code = {
194     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
195     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
196 static const std::vector<uint8_t> default_metadata = {
197     bluetooth::le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
198     bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
199     default_context & 0x00FF, (default_context & 0xFF00) >> 8};
200 static const std::vector<uint8_t> default_public_metadata = {
201     5,   bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfo,
202     0x1, 0x2,
203     0x3, 0x4};
204 // bit 0: encrypted, bit 1: standard quality present
205 static const uint8_t test_public_broadcast_features = 0x3;
206 
207 static constexpr uint8_t media_ccid = 0xC0;
208 static constexpr auto media_context =
209     static_cast<std::underlying_type<LeAudioContextType>::type>(
210         LeAudioContextType::MEDIA);
211 static const std::vector<uint8_t> media_metadata = {
212     bluetooth::le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
213     bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
214     media_context & 0x00FF, (media_context & 0xFF00) >> 8};
215 static const std::string test_broadcast_name = "Test";
216 
217 class MockLeAudioBroadcasterCallbacks
218     : public bluetooth::le_audio::LeAudioBroadcasterCallbacks {
219  public:
220   MOCK_METHOD((void), OnBroadcastCreated, (uint32_t broadcast_id, bool success),
221               (override));
222   MOCK_METHOD((void), OnBroadcastDestroyed, (uint32_t broadcast_id),
223               (override));
224   MOCK_METHOD((void), OnBroadcastStateChanged,
225               (uint32_t broadcast_id,
226                bluetooth::le_audio::BroadcastState state),
227               (override));
228   MOCK_METHOD((void), OnBroadcastMetadataChanged,
229               (uint32_t broadcast_id,
230                const BroadcastMetadata& broadcast_metadata),
231               (override));
232 };
233 
234 class MockAudioHalClientEndpoint : public LeAudioSourceAudioHalClient {
235  public:
236   MockAudioHalClientEndpoint() = default;
237   MOCK_METHOD((bool), Start,
238               (const LeAudioCodecConfiguration& codecConfiguration,
239                LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
240                ::bluetooth::le_audio::DsaModes dsa_modes),
241               (override));
242   MOCK_METHOD((void), Stop, (), (override));
243   MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
244   MOCK_METHOD((void), CancelStreamingRequest, (), (override));
245   MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
246   MOCK_METHOD((void), UpdateAudioConfigToHal,
247               (const ::bluetooth::le_audio::offload_config&), (override));
248   MOCK_METHOD(
249       (std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
250       ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
251        (const std::optional<
252            std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
253       (const override));
254   MOCK_METHOD(
255       (std::optional<::le_audio::set_configurations::AudioSetConfiguration>),
256       GetUnicastConfig,
257       (const CodecManager::UnicastConfigurationRequirements& requirements),
258       (const override));
259   MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
260               (const ::bluetooth::le_audio::broadcast_offload_config&),
261               (override));
262   MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
263   MOCK_METHOD((void), ReconfigurationComplete, (), (override));
264 
265   MOCK_METHOD((void), OnDestroyed, ());
~MockAudioHalClientEndpoint()266   virtual ~MockAudioHalClientEndpoint() { OnDestroyed(); }
267 };
268 
269 class BroadcasterTest : public Test {
270  protected:
SetUp()271   void SetUp() override {
272     init_message_loop_thread();
273 
274     reset_mock_function_count_map();
275     bluetooth::hci::testing::mock_controller_ = &mock_controller_;
276     ON_CALL(mock_controller_, SupportsBleIsochronousBroadcaster)
277         .WillByDefault(Return(true));
278 
279     iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
280     ASSERT_NE(iso_manager_, nullptr);
281     iso_manager_->Start();
282 
283     mock_iso_manager_ = MockIsoManager::GetInstance();
284     ON_CALL(*mock_iso_manager_, RegisterBigCallbacks(_))
285         .WillByDefault(SaveArg<0>(&big_callbacks_));
286 
287     ConfigAudioHalClientMock();
288 
289     EXPECT_CALL(*MockIsoManager::GetInstance(),
290                 RegisterOnIsoTrafficActiveCallbacks)
291         .WillOnce(SaveArg<0>(&iso_active_callback));
292 
293     ASSERT_FALSE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
294     LeAudioBroadcaster::Initialize(&mock_broadcaster_callbacks_,
295                                    base::Bind([]() -> bool { return true; }));
296 
297     ContentControlIdKeeper::GetInstance()->Start();
298     ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA,
299                                                    media_ccid);
300 
301     /* Simulate random generator */
302     uint8_t random[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
303     generator_cb.Run(random);
304 
305     ConfigCodecManagerMock(types::CodecLocation::HOST);
306 
307     ON_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(_, _, _))
308         .WillByDefault(Return(true));
309     ON_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(_, _))
310         .WillByDefault(Return(true));
311     ON_CALL(*mock_codec_manager_, GetBroadcastConfig)
312         .WillByDefault(
313             Invoke([](const bluetooth::le_audio::CodecManager::
314                           BroadcastConfigurationRequirements& requirements) {
315               return std::make_unique<broadcaster::BroadcastConfiguration>(
316                   bluetooth::le_audio::broadcaster::GetBroadcastConfig(
317                       requirements.subgroup_quality));
318             }));
319   }
320 
ConfigAudioHalClientMock()321   void ConfigAudioHalClientMock() {
322     is_audio_hal_acquired = false;
323     mock_audio_source_ = new MockAudioHalClientEndpoint();
324     ON_CALL(*mock_audio_source_, Start).WillByDefault(Return(true));
325     ON_CALL(*mock_audio_source_, OnDestroyed).WillByDefault([]() {
326       mock_audio_source_ = nullptr;
327       is_audio_hal_acquired = false;
328     });
329   }
330 
ConfigCodecManagerMock(types::CodecLocation location)331   void ConfigCodecManagerMock(types::CodecLocation location) {
332     codec_manager_ = le_audio::CodecManager::GetInstance();
333     ASSERT_NE(codec_manager_, nullptr);
334     std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
335         mock_offloading_preference(0);
336     codec_manager_->Start(mock_offloading_preference);
337     mock_codec_manager_ = MockCodecManager::GetInstance();
338     ASSERT_NE(mock_codec_manager_, nullptr);
339     ON_CALL(*mock_codec_manager_, GetCodecLocation())
340         .WillByDefault(Return(location));
341   }
342 
TearDown()343   void TearDown() override {
344     // Message loop cleanup should wait for all the 'till now' scheduled calls
345     // so it should be called right at the very begginning of teardown.
346     cleanup_message_loop_thread();
347 
348     // This is required since Stop() and Cleanup() may trigger some callbacks.
349     Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_);
350 
351     Mock::VerifyAndClearExpectations(MockIsoManager::GetInstance());
352     Mock::VerifyAndClearExpectations(
353         MockBroadcastStateMachine::GetLastInstance());
354 
355     LeAudioBroadcaster::Stop();
356     LeAudioBroadcaster::Cleanup();
357     ASSERT_FALSE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
358 
359     ContentControlIdKeeper::GetInstance()->Stop();
360 
361     bluetooth::hci::testing::mock_controller_ = nullptr;
362     delete mock_audio_source_;
363     iso_active_callback = nullptr;
364     delete mock_audio_source_;
365     iso_manager_->Stop();
366     if (codec_manager_) {
367       codec_manager_->Stop();
368       mock_codec_manager_ = nullptr;
369     }
370   }
371 
InstantiateBroadcast(std::vector<uint8_t> metadata=default_metadata,BroadcastCode code=default_code,std::vector<uint8_t> quality_array=default_subgroup_qualities,bool is_queued=false)372   uint32_t InstantiateBroadcast(
373       std::vector<uint8_t> metadata = default_metadata,
374       BroadcastCode code = default_code,
375       std::vector<uint8_t> quality_array = default_subgroup_qualities,
376       bool is_queued = false) {
377     uint32_t broadcast_id = LeAudioBroadcaster::kInstanceIdUndefined;
378     if (!is_queued) {
379       EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastCreated(_, true))
380           .WillOnce(SaveArg<0>(&broadcast_id));
381     }
382 
383     std::vector<std::vector<uint8_t>> metadata_array;
384     for (uint8_t i = 0; i < quality_array.size(); i++) {
385       // use the same default_metadata for each subgroup
386       metadata_array.push_back(metadata);
387     }
388 
389     // Add multiple subgroup settings with the same content
390     LeAudioBroadcaster::Get()->CreateAudioBroadcast(
391         true, test_broadcast_name, code, default_public_metadata, quality_array,
392         metadata_array);
393 
394     return broadcast_id;
395   }
396 
InjectBigCreateComplete(uint8_t big_id,uint8_t status)397   void InjectBigCreateComplete(uint8_t big_id, uint8_t status) {
398     std::vector<uint16_t> conn_handles = {0x10, 0x12};
399 
400     hci::iso_manager::big_create_cmpl_evt evt = {
401         .status = status,
402         .big_id = big_id,
403         .big_sync_delay = 1231,
404         .transport_latency_big = 1234,
405         .phy = 2,
406         .nse = 3,
407         .bn = 2,
408         .pto = 2,
409         .irc = 2,
410         .max_pdu = 128,
411         .iso_interval = 10,
412         .conn_handles = conn_handles,
413     };
414 
415     big_callbacks_->OnBigEvent(
416         bluetooth::hci::iso_manager::kIsoEventBigOnCreateCmpl, &evt);
417   }
418 
InjectBigTerminateComplete(uint8_t big_id,uint8_t reason)419   void InjectBigTerminateComplete(uint8_t big_id, uint8_t reason) {
420     hci::iso_manager::big_terminate_cmpl_evt evt = {.big_id = big_id,
421                                                     .reason = reason};
422     big_callbacks_->OnBigEvent(
423         bluetooth::hci::iso_manager::kIsoEventBigOnTerminateCmpl, &evt);
424   }
425 
426  protected:
427   MockLeAudioBroadcasterCallbacks mock_broadcaster_callbacks_;
428   bluetooth::hci::testing::MockControllerInterface mock_controller_;
429   bluetooth::hci::IsoManager* iso_manager_;
430   MockIsoManager* mock_iso_manager_;
431   bluetooth::hci::iso_manager::BigCallbacks* big_callbacks_ = nullptr;
432 
433   le_audio::CodecManager* codec_manager_ = nullptr;
434   MockCodecManager* mock_codec_manager_ = nullptr;
435 };
436 
TEST_F(BroadcasterTest,Initialize)437 TEST_F(BroadcasterTest, Initialize) {
438   ASSERT_NE(LeAudioBroadcaster::Get(), nullptr);
439   ASSERT_TRUE(LeAudioBroadcaster::IsLeAudioBroadcasterRunning());
440 }
441 
TEST_F(BroadcasterTest,GetStreamingPhy)442 TEST_F(BroadcasterTest, GetStreamingPhy) {
443   LeAudioBroadcaster::Get()->SetStreamingPhy(1);
444   ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 1);
445   LeAudioBroadcaster::Get()->SetStreamingPhy(2);
446   ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 2);
447 }
448 
TEST_F(BroadcasterTest,CreateAudioBroadcast)449 TEST_F(BroadcasterTest, CreateAudioBroadcast) {
450   auto broadcast_id = InstantiateBroadcast();
451   ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
452   ASSERT_EQ(broadcast_id,
453             MockBroadcastStateMachine::GetLastInstance()->GetBroadcastId());
454 
455   auto& instance_config = MockBroadcastStateMachine::GetLastInstance()->cfg;
456   ASSERT_EQ(instance_config.broadcast_code, default_code);
457   for (auto& subgroup : instance_config.announcement.subgroup_configs) {
458     ASSERT_EQ(types::LeAudioLtvMap(subgroup.metadata).RawPacket(),
459               default_metadata);
460   }
461   // Note: There shall be a separate test to verify audio parameters
462 }
463 
TEST_F(BroadcasterTest,CreateAudioBroadcastMultiGroups)464 TEST_F(BroadcasterTest, CreateAudioBroadcastMultiGroups) {
465   // Test with two subgroups
466   auto broadcast_id =
467       InstantiateBroadcast(default_metadata, default_code,
468                            {bluetooth::le_audio::QUALITY_STANDARD,
469                             bluetooth::le_audio::QUALITY_STANDARD});
470   ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
471   ASSERT_EQ(broadcast_id,
472             MockBroadcastStateMachine::GetLastInstance()->GetBroadcastId());
473 
474   auto& instance_config = MockBroadcastStateMachine::GetLastInstance()->cfg;
475   ASSERT_EQ(instance_config.broadcast_code, default_code);
476   ASSERT_EQ(instance_config.announcement.subgroup_configs.size(), (uint8_t) 2);
477   for (auto& subgroup : instance_config.announcement.subgroup_configs) {
478     ASSERT_EQ(types::LeAudioLtvMap(subgroup.metadata).RawPacket(),
479               default_metadata);
480   }
481 }
482 
TEST_F(BroadcasterTest,SuspendAudioBroadcast)483 TEST_F(BroadcasterTest, SuspendAudioBroadcast) {
484   EXPECT_CALL(*mock_codec_manager_,
485               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
486       .Times(1);
487   auto broadcast_id = InstantiateBroadcast();
488   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
489   Mock::VerifyAndClearExpectations(mock_codec_manager_);
490 
491   EXPECT_CALL(mock_broadcaster_callbacks_,
492               OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED))
493       .Times(1);
494 
495   EXPECT_CALL(*mock_audio_source_, Stop).Times(AtLeast(1));
496   EXPECT_CALL(*mock_codec_manager_,
497               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, _))
498       .Times(0);
499   LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
500   Mock::VerifyAndClearExpectations(mock_codec_manager_);
501 }
502 
TEST_F(BroadcasterTest,StartAudioBroadcast)503 TEST_F(BroadcasterTest, StartAudioBroadcast) {
504   EXPECT_CALL(*mock_codec_manager_,
505               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
506       .Times(1);
507   auto broadcast_id = InstantiateBroadcast();
508   Mock::VerifyAndClearExpectations(mock_codec_manager_);
509 
510   EXPECT_CALL(*mock_codec_manager_,
511               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
512       .Times(0);
513   EXPECT_CALL(*mock_codec_manager_,
514               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false))
515       .Times(0);
516   LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
517 
518   EXPECT_CALL(mock_broadcaster_callbacks_,
519               OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
520       .Times(1);
521 
522   LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
523   EXPECT_CALL(*mock_audio_source_, Start)
524       .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
525 
526   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
527   ASSERT_NE(audio_receiver, nullptr);
528 
529   // NOTICE: This is really an implementation specific part, we fake the BIG
530   //         config as the mocked state machine does not even call the
531   //         IsoManager to prepare one (and that's good since IsoManager is also
532   //         a mocked one).
533   BigConfig big_cfg;
534   big_cfg.big_id =
535       MockBroadcastStateMachine::GetLastInstance()->GetAdvertisingSid();
536   big_cfg.connection_handles = {0x10, 0x12};
537   big_cfg.max_pdu = 128;
538   MockBroadcastStateMachine::GetLastInstance()->SetExpectedBigConfig(big_cfg);
539 
540   // Inject the audio and verify call on the Iso manager side.
541   EXPECT_CALL(*MockIsoManager::GetInstance(), SendIsoData).Times(1);
542   std::vector<uint8_t> sample_data(320, 0);
543   audio_receiver->OnAudioDataReady(sample_data);
544 
545   Mock::VerifyAndClearExpectations(mock_codec_manager_);
546 }
547 
TEST_F(BroadcasterTest,StartAudioBroadcastMedia)548 TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
549   EXPECT_CALL(*mock_codec_manager_,
550               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
551       .Times(1);
552   auto broadcast_id = InstantiateBroadcast(media_metadata, default_code,
553                                            {bluetooth::le_audio::QUALITY_HIGH});
554   Mock::VerifyAndClearExpectations(mock_codec_manager_);
555 
556   LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
557 
558   EXPECT_CALL(mock_broadcaster_callbacks_,
559               OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
560       .Times(1);
561 
562   LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
563   EXPECT_CALL(*mock_audio_source_, Start)
564       .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
565   EXPECT_CALL(*mock_codec_manager_,
566               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
567       .Times(0);
568   EXPECT_CALL(*mock_codec_manager_,
569               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false))
570       .Times(0);
571 
572   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
573   ASSERT_NE(audio_receiver, nullptr);
574 
575   // NOTICE: This is really an implementation specific part, we fake the BIG
576   //         config as the mocked state machine does not even call the
577   //         IsoManager to prepare one (and that's good since IsoManager is also
578   //         a mocked one).
579 
580   auto mock_state_machine = MockBroadcastStateMachine::GetLastInstance();
581   BigConfig big_cfg;
582   big_cfg.big_id = mock_state_machine->GetAdvertisingSid();
583   big_cfg.connection_handles = {0x10, 0x12};
584   big_cfg.max_pdu = 128;
585   mock_state_machine->SetExpectedBigConfig(big_cfg);
586 
587   // Inject the audio and verify call on the Iso manager side.
588   EXPECT_CALL(*MockIsoManager::GetInstance(), SendIsoData).Times(2);
589   std::vector<uint8_t> sample_data(1920, 0);
590   audio_receiver->OnAudioDataReady(sample_data);
591   Mock::VerifyAndClearExpectations(mock_codec_manager_);
592 }
593 
TEST_F(BroadcasterTest,StopAudioBroadcast)594 TEST_F(BroadcasterTest, StopAudioBroadcast) {
595   EXPECT_CALL(*mock_codec_manager_,
596               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
597       .Times(1);
598   EXPECT_CALL(*mock_codec_manager_,
599               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false))
600       .Times(1);
601   auto broadcast_id = InstantiateBroadcast();
602   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
603 
604   // NOTICE: This is really an implementation specific part, we fake the BIG
605   //         config as the mocked state machine does not even call the
606   //         IsoManager to prepare one (and that's good since IsoManager is also
607   //         a mocked one).
608 
609   auto mock_state_machine = MockBroadcastStateMachine::GetLastInstance();
610   BigConfig big_cfg;
611   big_cfg.big_id = mock_state_machine->GetAdvertisingSid();
612   big_cfg.connection_handles = {0x10, 0x12};
613   big_cfg.max_pdu = 128;
614   mock_state_machine->SetExpectedBigConfig(big_cfg);
615 
616   InjectBigCreateComplete(big_cfg.big_id, 0x00);
617   EXPECT_CALL(mock_broadcaster_callbacks_,
618               OnBroadcastStateChanged(broadcast_id, BroadcastState::STOPPED))
619       .Times(1);
620 
621   EXPECT_CALL(*mock_audio_source_, Stop).Times(AtLeast(1));
622   LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
623   InjectBigTerminateComplete(big_cfg.big_id, 0x16);
624   Mock::VerifyAndClearExpectations(mock_codec_manager_);
625 }
626 
TEST_F(BroadcasterTest,DestroyAudioBroadcast)627 TEST_F(BroadcasterTest, DestroyAudioBroadcast) {
628   EXPECT_CALL(*mock_codec_manager_,
629               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
630       .Times(1);
631 
632   auto broadcast_id = InstantiateBroadcast();
633 
634   Mock::VerifyAndClearExpectations(mock_codec_manager_);
635 
636   EXPECT_CALL(*mock_codec_manager_,
637               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false))
638       .Times(1);
639   EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastDestroyed(broadcast_id))
640       .Times(1);
641   LeAudioBroadcaster::Get()->DestroyAudioBroadcast(broadcast_id);
642 
643   Mock::VerifyAndClearExpectations(mock_codec_manager_);
644   ASSERT_EQ(mock_audio_source_, nullptr);
645 
646   /* Create a mock again for the test purpose */
647   ConfigAudioHalClientMock();
648 
649   EXPECT_CALL(*mock_codec_manager_,
650               UpdateActiveBroadcastAudioHalClient(mock_audio_source_, _))
651       .Times(0);
652 
653   // Expect not being able to interact with this Broadcast
654   EXPECT_CALL(mock_broadcaster_callbacks_,
655               OnBroadcastStateChanged(broadcast_id, _))
656       .Times(0);
657 
658   EXPECT_CALL(*mock_audio_source_, Stop).Times(0);
659   LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
660 
661   EXPECT_CALL(*mock_audio_source_, Start).Times(0);
662   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
663 
664   EXPECT_CALL(*mock_audio_source_, Stop).Times(0);
665   LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
666 
667   Mock::VerifyAndClearExpectations(mock_codec_manager_);
668   Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_);
669   // Verify the expectations before the CleanUp, which may call Stop()
670   Mock::VerifyAndClearExpectations(mock_audio_source_);
671 }
672 
TEST_F(BroadcasterTest,GetBroadcastAllStates)673 TEST_F(BroadcasterTest, GetBroadcastAllStates) {
674   auto broadcast_id = InstantiateBroadcast();
675   auto broadcast_id2 = InstantiateBroadcast();
676   ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
677   ASSERT_NE(broadcast_id2, LeAudioBroadcaster::kInstanceIdUndefined);
678   ASSERT_NE(broadcast_id, broadcast_id2);
679 
680   /* In the current implementation state machine switches to the correct state
681    * on itself, therefore here when we use mocked state machine this is not
682    * being verified.
683    */
684   EXPECT_CALL(mock_broadcaster_callbacks_,
685               OnBroadcastStateChanged(broadcast_id, _))
686       .Times(1);
687   EXPECT_CALL(mock_broadcaster_callbacks_,
688               OnBroadcastStateChanged(broadcast_id2, _))
689       .Times(1);
690 
691   LeAudioBroadcaster::Get()->GetAllBroadcastStates();
692 }
693 
TEST_F(BroadcasterTest,UpdateMetadata)694 TEST_F(BroadcasterTest, UpdateMetadata) {
695   auto broadcast_id = InstantiateBroadcast();
696   std::vector<uint8_t> ccid_list;
697   std::vector<uint8_t> expected_public_meta;
698   std::string expected_broadcast_name;
699 
700   EXPECT_CALL(*MockBroadcastStateMachine::GetLastInstance(),
701               UpdateBroadcastAnnouncement)
702       .WillOnce(
703           [&](bluetooth::le_audio::BasicAudioAnnouncementData announcement) {
704             for (auto subgroup : announcement.subgroup_configs) {
705               if (subgroup.metadata.count(
706                       types::kLeAudioMetadataTypeCcidList)) {
707                 ccid_list =
708                     subgroup.metadata.at(types::kLeAudioMetadataTypeCcidList);
709                 break;
710               }
711             }
712           });
713 
714   EXPECT_CALL(*MockBroadcastStateMachine::GetLastInstance(),
715               UpdatePublicBroadcastAnnouncement)
716       .WillOnce([&](uint32_t broadcast_id, const std::string& broadcast_name,
717                     const bluetooth::le_audio::PublicBroadcastAnnouncementData&
718                         announcement) {
719         expected_broadcast_name = broadcast_name;
720         expected_public_meta =
721             types::LeAudioLtvMap(announcement.metadata).RawPacket();
722       });
723 
724   ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::ALERTS,
725                                                  default_ccid);
726 
727   LeAudioBroadcaster::Get()->UpdateMetadata(
728       broadcast_id, test_broadcast_name, default_public_metadata,
729       {std::vector<uint8_t>({0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x04})});
730 
731   ASSERT_EQ(2u, ccid_list.size());
732   ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), media_ccid));
733   ASSERT_NE(0, std::count(ccid_list.begin(), ccid_list.end(), default_ccid));
734   ASSERT_EQ(expected_broadcast_name, test_broadcast_name);
735   ASSERT_EQ(expected_public_meta, default_public_metadata);
736 }
737 
prepareAnnouncement(const BroadcastSubgroupCodecConfig & codec_config,std::map<uint8_t,std::vector<uint8_t>> metadata)738 static BasicAudioAnnouncementData prepareAnnouncement(
739     const BroadcastSubgroupCodecConfig& codec_config,
740     std::map<uint8_t, std::vector<uint8_t>> metadata) {
741   BasicAudioAnnouncementData announcement;
742 
743   announcement.presentation_delay_us = 40000;
744   auto const& codec_id = codec_config.GetLeAudioCodecId();
745   auto const subgroup_codec_spec = codec_config.GetCommonBisCodecSpecData();
746 
747   // Note: This is a single subgroup announcement.
748   announcement.subgroup_configs = {{
749       .codec_config =
750           {
751               .codec_id = codec_id.coding_format,
752               .vendor_company_id = codec_id.vendor_company_id,
753               .vendor_codec_id = codec_id.vendor_codec_id,
754               .codec_specific_params = subgroup_codec_spec.Values(),
755           },
756       .metadata = std::move(metadata),
757       .bis_configs = {},
758   }};
759 
760   uint8_t bis_count = 0;
761   for (uint8_t cfg_idx = 0; cfg_idx < codec_config.GetAllBisConfigCount();
762        ++cfg_idx) {
763     for (uint8_t bis_num = 0; bis_num < codec_config.GetNumBis(cfg_idx);
764          ++bis_num) {
765       ++bis_count;
766 
767       // Check for vendor byte array
768       bluetooth::le_audio::BasicAudioAnnouncementBisConfig bis_config;
769       auto vendor_config = codec_config.GetBisVendorCodecSpecData(bis_num);
770       if (vendor_config) {
771         bis_config.vendor_codec_specific_params = vendor_config.value();
772       }
773 
774       // Check for non vendor LTVs
775       auto config_ltv = codec_config.GetBisCodecSpecData(bis_num, cfg_idx);
776       if (config_ltv) {
777         bis_config.codec_specific_params = config_ltv->Values();
778       }
779 
780       // Internally BISes are indexed from 0 in each subgroup, but the BT spec
781       // requires the indices to be indexed from 1 in the entire BIG.
782       bis_config.bis_index = bis_count;
783       announcement.subgroup_configs[0].bis_configs.push_back(
784           std::move(bis_config));
785     }
786   }
787 
788   return announcement;
789 }
790 
TEST_F(BroadcasterTest,UpdateMetadataFromAudioTrackMetadata)791 TEST_F(BroadcasterTest, UpdateMetadataFromAudioTrackMetadata) {
792   ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA,
793                                                  media_ccid);
794   auto broadcast_id = InstantiateBroadcast();
795 
796   LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
797   EXPECT_CALL(*mock_audio_source_, Start)
798       .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)));
799 
800   LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
801   ASSERT_NE(audio_receiver, nullptr);
802 
803   auto sm = MockBroadcastStateMachine::GetLastInstance();
804   std::vector<uint8_t> ccid_list;
805   std::vector<uint8_t> context_types_map;
806   EXPECT_CALL(*sm, UpdateBroadcastAnnouncement)
807       .WillOnce(
808           [&](bluetooth::le_audio::BasicAudioAnnouncementData announcement) {
809             for (auto subgroup : announcement.subgroup_configs) {
810               if (subgroup.metadata.count(
811                       types::kLeAudioMetadataTypeCcidList)) {
812                 ccid_list =
813                     subgroup.metadata.at(types::kLeAudioMetadataTypeCcidList);
814               }
815               if (subgroup.metadata.count(
816                       types::kLeAudioMetadataTypeStreamingAudioContext)) {
817                 context_types_map = subgroup.metadata.at(
818                     types::kLeAudioMetadataTypeStreamingAudioContext);
819               }
820             }
821           });
822 
823   std::map<uint8_t, std::vector<uint8_t>> meta = {};
824   auto codec_config = broadcaster::lc3_mono_16_2;
825   auto announcement = prepareAnnouncement(codec_config, meta);
826 
827   ON_CALL(*sm, GetBroadcastAnnouncement())
828       .WillByDefault(ReturnRef(announcement));
829 
830   std::vector<struct playback_track_metadata> multitrack_source_metadata = {
831       {{AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_SONIFICATION, 0},
832        {AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, 0},
833        {AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, AUDIO_CONTENT_TYPE_SPEECH,
834         0},
835        {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
836 
837   std::vector<playback_track_metadata_v7> tracks_vec;
838   tracks_vec.reserve(multitrack_source_metadata.size());
839   for (const auto& track : multitrack_source_metadata) {
840     playback_track_metadata_v7 desc_track = {
841         .base =
842             {
843                 .usage = static_cast<audio_usage_t>(track.usage),
844                 .content_type =
845                     static_cast<audio_content_type_t>(track.content_type),
846                 .gain = track.gain,
847             },
848     };
849     tracks_vec.push_back(desc_track);
850   }
851 
852   audio_receiver->OnAudioMetadataUpdate(std::move(tracks_vec),
853                                         DsaMode::DISABLED);
854 
855   // Verify ccid
856   ASSERT_NE(ccid_list.size(), 0u);
857   ASSERT_TRUE(std::find(ccid_list.begin(), ccid_list.end(), media_ccid) !=
858               ccid_list.end());
859 
860   // Verify context type
861   ASSERT_NE(context_types_map.size(), 0u);
862   AudioContexts context_type;
863   auto pp = context_types_map.data();
864   STREAM_TO_UINT16(context_type.value_ref(), pp);
865   ASSERT_TRUE(context_type.test_all(LeAudioContextType::MEDIA |
866                                     LeAudioContextType::GAME));
867 }
868 
TEST_F(BroadcasterTest,GetMetadata)869 TEST_F(BroadcasterTest, GetMetadata) {
870   auto broadcast_id = InstantiateBroadcast();
871   bluetooth::le_audio::BroadcastMetadata metadata;
872 
873   static const uint8_t test_adv_sid = 0x14;
874   std::optional<bluetooth::le_audio::BroadcastCode> test_broadcast_code =
875       bluetooth::le_audio::BroadcastCode({1, 2, 3, 4, 5, 6});
876 
877   auto sm = MockBroadcastStateMachine::GetLastInstance();
878 
879   std::map<uint8_t, std::vector<uint8_t>> meta = {};
880   auto codec_config = broadcaster::lc3_mono_16_2;
881   auto announcement = prepareAnnouncement(codec_config, meta);
882 
883   bool is_public_metadata_valid;
884   types::LeAudioLtvMap public_ltv = types::LeAudioLtvMap::Parse(
885       default_public_metadata.data(), default_public_metadata.size(),
886       is_public_metadata_valid);
887   PublicBroadcastAnnouncementData pb_announcement = {
888       .features = test_public_broadcast_features,
889       .metadata = public_ltv.Values()};
890 
891   ON_CALL(*sm, IsPublicBroadcast()).WillByDefault(Return(true));
892   ON_CALL(*sm, GetBroadcastName()).WillByDefault(Return(test_broadcast_name));
893   ON_CALL(*sm, GetBroadcastCode()).WillByDefault(Return(test_broadcast_code));
894   ON_CALL(*sm, GetAdvertisingSid()).WillByDefault(Return(test_adv_sid));
895   ON_CALL(*sm, GetBroadcastAnnouncement())
896       .WillByDefault(ReturnRef(announcement));
897   ON_CALL(*sm, GetPublicBroadcastAnnouncement())
898       .WillByDefault(ReturnRef(pb_announcement));
899 
900   EXPECT_CALL(mock_broadcaster_callbacks_,
901               OnBroadcastMetadataChanged(broadcast_id, _))
902       .Times(1)
903       .WillOnce(SaveArg<1>(&metadata));
904   LeAudioBroadcaster::Get()->GetBroadcastMetadata(broadcast_id);
905 
906   ASSERT_NE(LeAudioBroadcaster::kInstanceIdUndefined, metadata.broadcast_id);
907   ASSERT_EQ(sm->GetBroadcastId(), metadata.broadcast_id);
908   ASSERT_EQ(sm->GetBroadcastCode(), metadata.broadcast_code);
909   ASSERT_EQ(sm->GetBroadcastAnnouncement(), metadata.basic_audio_announcement);
910   ASSERT_EQ(sm->GetPaInterval(), metadata.pa_interval);
911   ASSERT_EQ(sm->GetOwnAddress(), metadata.addr);
912   ASSERT_EQ(sm->GetOwnAddressType(), metadata.addr_type);
913   ASSERT_EQ(sm->GetAdvertisingSid(), metadata.adv_sid);
914   ASSERT_EQ(sm->IsPublicBroadcast(), metadata.is_public);
915   ASSERT_EQ(sm->GetBroadcastName(), metadata.broadcast_name);
916   ASSERT_EQ(sm->GetPublicBroadcastAnnouncement(), metadata.public_announcement);
917 }
918 
TEST_F(BroadcasterTest,SetStreamingPhy)919 TEST_F(BroadcasterTest, SetStreamingPhy) {
920   LeAudioBroadcaster::Get()->SetStreamingPhy(2);
921   // From now on new streams should be using Phy = 2.
922   InstantiateBroadcast();
923   ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 2);
924 
925   // From now on new streams should be using Phy = 1.
926   LeAudioBroadcaster::Get()->SetStreamingPhy(1);
927   InstantiateBroadcast();
928   ASSERT_EQ(MockBroadcastStateMachine::GetLastInstance()->cfg.streaming_phy, 1);
929   ASSERT_EQ(LeAudioBroadcaster::Get()->GetStreamingPhy(), 1);
930 }
931 
TEST_F(BroadcasterTest,StreamParamsAlerts)932 TEST_F(BroadcasterTest, StreamParamsAlerts) {
933   uint8_t expected_channels = 1u;
934   InstantiateBroadcast();
935   auto config = MockBroadcastStateMachine::GetLastInstance()->cfg;
936 
937   // Check audio configuration
938   ASSERT_EQ(config.config.subgroups.at(0).GetNumChannelsTotal(),
939             expected_channels);
940 
941   // Matches number of bises in the announcement
942   ASSERT_EQ(config.announcement.subgroup_configs[0].bis_configs.size(),
943             expected_channels);
944   // Note: Num of bises at IsoManager level is verified by state machine tests
945 }
946 
TEST_F(BroadcasterTest,StreamParamsMedia)947 TEST_F(BroadcasterTest, StreamParamsMedia) {
948   uint8_t expected_channels = 2u;
949   ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA,
950                                                  media_ccid);
951   InstantiateBroadcast(media_metadata, default_code,
952                        {bluetooth::le_audio::QUALITY_HIGH});
953 
954   auto config = MockBroadcastStateMachine::GetLastInstance()->cfg;
955 
956   // Check audio configuration
957   ASSERT_EQ(config.config.subgroups.at(0).GetNumBis(), expected_channels);
958   ASSERT_EQ(config.config.subgroups.at(0).GetNumChannelsTotal(),
959             expected_channels);
960   // Note there is one BIS configuration applied to both (stereo) BISes
961   ASSERT_EQ(config.config.subgroups.at(0).GetAllBisConfigCount(),
962             (unsigned long)1);
963   ASSERT_EQ(config.config.subgroups.at(0).GetNumBis(0),
964             (unsigned long)expected_channels);
965 
966   // Matches number of bises in the announcement
967   ASSERT_EQ(config.announcement.subgroup_configs.size(), 1ul);
968 
969   auto& announcement_subgroup = config.announcement.subgroup_configs[0];
970   ASSERT_EQ(announcement_subgroup.bis_configs.size(), expected_channels);
971   // Verify CCID for Media
972   auto ccid_list_opt =
973       types::LeAudioLtvMap(announcement_subgroup.metadata)
974           .Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
975   ASSERT_TRUE(ccid_list_opt.has_value());
976   auto ccid_list = ccid_list_opt.value();
977   ASSERT_EQ(1u, ccid_list.size());
978   ASSERT_EQ(media_ccid, ccid_list[0]);
979   // Note: Num of bises at IsoManager level is verified by state machine tests
980 }
981 
TEST_F(BroadcasterTest,QueuedBroadcast)982 TEST_F(BroadcasterTest, QueuedBroadcast) {
983   uint32_t broadcast_id = LeAudioBroadcaster::kInstanceIdUndefined;
984 
985   iso_active_callback(true);
986 
987   EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastCreated(_, true))
988       .WillOnce(SaveArg<0>(&broadcast_id));
989 
990   /* Trigger broadcast create but due to active ISO, queue request */
991   InstantiateBroadcast(default_metadata, default_code,
992                        default_subgroup_qualities, true);
993 
994   /* Notify about ISO being free, check if broadcast would be created */
995   iso_active_callback(false);
996   ASSERT_NE(broadcast_id, LeAudioBroadcaster::kInstanceIdUndefined);
997   ASSERT_EQ(broadcast_id,
998             MockBroadcastStateMachine::GetLastInstance()->GetBroadcastId());
999 
1000   auto& instance_config = MockBroadcastStateMachine::GetLastInstance()->cfg;
1001   ASSERT_EQ(instance_config.broadcast_code, default_code);
1002   for (auto& subgroup : instance_config.announcement.subgroup_configs) {
1003     ASSERT_EQ(types::LeAudioLtvMap(subgroup.metadata).RawPacket(),
1004               default_metadata);
1005   }
1006 }
1007 
TEST_F(BroadcasterTest,QueuedBroadcastBusyIso)1008 TEST_F(BroadcasterTest, QueuedBroadcastBusyIso) {
1009   iso_active_callback(true);
1010 
1011   EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastCreated(_, true))
1012       .Times(0);
1013 
1014   /* Trigger broadcast create but due to active ISO, queue request */
1015   InstantiateBroadcast(default_metadata, default_code,
1016                        default_subgroup_qualities, true);
1017 }
1018 
1019 constexpr types::LeAudioCodecId kLeAudioCodecIdVendor1 = {
1020     .coding_format = types::kLeAudioCodingFormatVendorSpecific,
1021     // Not a particualr vendor - just some random numbers
1022     .vendor_company_id = 0xC0,
1023     .vendor_codec_id = 0xDE,
1024 };
1025 
1026 static const types::DataPathConfiguration vendor_data_path = {
1027     .dataPathId = bluetooth::hci::iso_manager::kIsoDataPathHci,
1028     .dataPathConfig = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1029                        0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
1030     .isoDataPathConfig =
1031         {
1032             .codecId = kLeAudioCodecIdVendor1,
1033             .isTransparent = true,
1034             .controllerDelayUs = 0x00000000,  // irrlevant for transparent mode
1035             .configuration = {0x1F, 0x2E, 0x3D, 0x4C, 0x5B, 0x6A, 0x79, 0x88,
1036                               0x97, 0xA6, 0xB5, 0xC4, 0xD3, 0xE2, 0xF1},
1037         },
1038 };
1039 
1040 // Quality subgroup configurations
1041 static const broadcaster::BroadcastSubgroupCodecConfig vendor_stereo_16_2 =
1042     broadcaster::BroadcastSubgroupCodecConfig(
1043         kLeAudioCodecIdVendor1,
1044         {broadcaster::BroadcastSubgroupBisCodecConfig{
1045             // num_bis
1046             2,
1047             // bis_channel_cnt
1048             1,
1049             // codec_specific
1050             types::LeAudioLtvMap({
1051                 LTV_ENTRY_SAMPLING_FREQUENCY(
1052                     codec_spec_conf::kLeAudioSamplingFreq16000Hz),
1053                 LTV_ENTRY_FRAME_DURATION(
1054                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
1055                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(50),
1056             }),
1057             // vendor_codec_specific
1058             std::vector<uint8_t>{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
1059                                  0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
1060                                  0xF0},
1061         }},
1062         // bits_per_sample
1063         24,
1064         // vendor_codec_specific
1065         std::vector<uint8_t>{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
1066                              0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF});
1067 
1068 static const broadcaster::BroadcastConfiguration vendor_stereo_16_2_1 = {
1069     // subgroup list, qos configuration, data path configuration
1070     .subgroups = {vendor_stereo_16_2},
1071     .qos = broadcaster::qos_config_2_10,
1072     .data_path = vendor_data_path,
1073     .sduIntervalUs = 5000,
1074     .maxSduOctets = 128,
1075     .phy = 0x01,   // PHY_LE_1M
1076     .packing = 1,  // Interleaved
1077     .framing = 1,  // Framed
1078 };
1079 
TEST_F(BroadcasterTest,SanityTest)1080 TEST_F(BroadcasterTest, SanityTest) {
1081   ASSERT_EQ(broadcaster::lc3_mono_16_2_1, broadcaster::lc3_mono_16_2_1);
1082   ASSERT_EQ(vendor_stereo_16_2_1, vendor_stereo_16_2_1);
1083 }
1084 
TEST_F(BroadcasterTest,VendorCodecConfig)1085 TEST_F(BroadcasterTest, VendorCodecConfig) {
1086   ON_CALL(*mock_codec_manager_, GetBroadcastConfig)
1087       .WillByDefault(Invoke([](const bluetooth::le_audio::CodecManager::
1088                                    BroadcastConfigurationRequirements&) {
1089         return std::make_unique<broadcaster::BroadcastConfiguration>(
1090             vendor_stereo_16_2_1);
1091       }));
1092   ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA,
1093                                                  media_ccid);
1094 
1095   // iso_active_callback(false);
1096   auto broadcast_id = InstantiateBroadcast(media_metadata, default_code,
1097                                            {bluetooth::le_audio::QUALITY_HIGH});
1098   ASSERT_NE(LeAudioBroadcaster::kInstanceIdUndefined, broadcast_id);
1099 
1100   auto mock_state_machine = MockBroadcastStateMachine::GetLastInstance();
1101   ASSERT_NE(nullptr, mock_state_machine);
1102 
1103   // Verify the codec config
1104   ASSERT_EQ(vendor_stereo_16_2_1, mock_state_machine->cfg.config);
1105 
1106   // Verify the basic audio announcement
1107   ASSERT_NE(0lu, mock_state_machine->cfg.announcement.presentation_delay_us);
1108 
1109   // One subgroup
1110   ASSERT_EQ(1lu, mock_state_machine->cfg.announcement.subgroup_configs.size());
1111   auto const& subgroup =
1112       mock_state_machine->cfg.announcement.subgroup_configs.at(0);
1113 
1114   auto const& expected_subgroup_codec_conf =
1115       vendor_stereo_16_2_1.subgroups.at(0);
1116   ASSERT_EQ(expected_subgroup_codec_conf.GetNumBis(),
1117             subgroup.bis_configs.size());
1118 
1119   // Subgroup level codec configuration
1120   ASSERT_EQ(expected_subgroup_codec_conf.GetLeAudioCodecId().coding_format,
1121             subgroup.codec_config.codec_id);
1122   ASSERT_EQ(expected_subgroup_codec_conf.GetLeAudioCodecId().vendor_company_id,
1123             subgroup.codec_config.vendor_company_id);
1124   ASSERT_EQ(expected_subgroup_codec_conf.GetLeAudioCodecId().vendor_codec_id,
1125             subgroup.codec_config.vendor_codec_id);
1126 
1127   // There should be no common set of parameters in the LTV format if there is
1128   // a vendor specific configuration
1129   ASSERT_TRUE(subgroup.codec_config.codec_specific_params.empty());
1130   ASSERT_TRUE(subgroup.codec_config.vendor_codec_specific_params.has_value());
1131   ASSERT_EQ(
1132       0, memcmp(expected_subgroup_codec_conf.GetVendorCodecSpecData()->data(),
1133                 subgroup.codec_config.vendor_codec_specific_params->data(),
1134                 subgroup.codec_config.vendor_codec_specific_params->size()));
1135 
1136   // Subgroup metadata
1137   ASSERT_NE(0lu, subgroup.metadata.size());
1138 
1139   // Verify the BISes
1140   ASSERT_EQ(expected_subgroup_codec_conf.GetNumBis(),
1141             subgroup.bis_configs.size());
1142 
1143   // Verify BIS 1
1144   uint8_t bis_idx = 1;
1145   ASSERT_EQ(bis_idx, subgroup.bis_configs.at(0).bis_index);
1146   // Expect only the vendor specific data
1147   ASSERT_TRUE(subgroup.bis_configs.at(0).codec_specific_params.empty());
1148   ASSERT_TRUE(subgroup.bis_configs.at(0)
1149                   .vendor_codec_specific_params
1150                   .has_value());  // BIS vendor specific parameters
1151   ASSERT_NE(0lu,
1152             subgroup.bis_configs.at(0).vendor_codec_specific_params->size());
1153   ASSERT_EQ(expected_subgroup_codec_conf.GetBisVendorCodecSpecData(0)->size(),
1154             subgroup.bis_configs.at(0).vendor_codec_specific_params->size());
1155   ASSERT_EQ(
1156       0,
1157       memcmp(expected_subgroup_codec_conf.GetBisVendorCodecSpecData(0)->data(),
1158              subgroup.bis_configs.at(0).vendor_codec_specific_params->data(),
1159              subgroup.bis_configs.at(0).vendor_codec_specific_params->size()));
1160 
1161   // Verify BIS 2
1162   bis_idx = 2;
1163   ASSERT_EQ(bis_idx, subgroup.bis_configs.at(1).bis_index);
1164   // Expect only the vendor specific data
1165   ASSERT_TRUE(subgroup.bis_configs.at(1).codec_specific_params.empty());
1166   ASSERT_TRUE(subgroup.bis_configs.at(1)
1167                   .vendor_codec_specific_params
1168                   .has_value());  // BIS vendor specific parameters
1169   ASSERT_NE(0lu,
1170             subgroup.bis_configs.at(1).vendor_codec_specific_params->size());
1171   ASSERT_EQ(expected_subgroup_codec_conf.GetBisVendorCodecSpecData(1)->size(),
1172             subgroup.bis_configs.at(1).vendor_codec_specific_params->size());
1173   ASSERT_EQ(
1174       0,
1175       memcmp(expected_subgroup_codec_conf.GetBisVendorCodecSpecData(1)->data(),
1176              subgroup.bis_configs.at(1).vendor_codec_specific_params->data(),
1177              subgroup.bis_configs.at(1).vendor_codec_specific_params->size()));
1178 }
1179 
1180 // TODO: Add tests for:
1181 // ToRawPacket(BasicAudioAnnouncementData const& in, std::vector<uint8_t>& data)
1182 
1183 }  // namespace bluetooth::le_audio
1184