1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "codec_manager.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <log/log.h>
22
23 #include "audio_hal_client/audio_hal_client.h"
24 #include "audio_hal_interface/le_audio_software.h"
25 #include "common/init_flags.h"
26 #include "hci/controller_interface_mock.h"
27 #include "hci/hci_packets.h"
28 #include "internal_include/stack_config.h"
29 #include "le_audio/le_audio_types.h"
30 #include "le_audio_set_configuration_provider.h"
31 #include "test/mock/mock_legacy_hci_interface.h"
32 #include "test/mock/mock_main_shim_entry.h"
33
34 using ::testing::_;
35 using ::testing::Mock;
36 using ::testing::NiceMock;
37 using ::testing::Return;
38 using ::testing::Test;
39
40 using bluetooth::hci::OpCode;
41 using bluetooth::hci::iso_manager::kIsoDataPathHci;
42 using bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
43 using bluetooth::le_audio::set_configurations::AudioSetConfiguration;
44 using bluetooth::le_audio::types::CodecLocation;
45 using bluetooth::le_audio::types::kLeAudioDirectionSink;
46 using bluetooth::le_audio::types::kLeAudioDirectionSource;
47
48 void osi_property_set_bool(const char* key, bool value);
49
50 template <typename T>
get(uint8_t direction)51 T& bluetooth::le_audio::types::BidirectionalPair<T>::get(uint8_t direction) {
52 return (direction == bluetooth::le_audio::types::kLeAudioDirectionSink)
53 ? sink
54 : source;
55 }
56
57 static const std::vector<AudioSetConfiguration> offload_capabilities_none(0);
58
59 const std::vector<AudioSetConfiguration>* offload_capabilities =
60 &offload_capabilities_none;
61
62 static const char* test_flags[] = {
63 "INIT_default_log_level_str=LOG_VERBOSE",
64 nullptr,
65 };
66
67 const std::string kSmpOptions("mock smp options");
get_pts_avrcp_test(void)68 bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)69 bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)70 bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)71 bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)72 const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)73 int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)74 bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)75 bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)76 bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)77 bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)78 bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)79 bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)80 bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)81 config_t* get_all(void) { return nullptr; }
82
83 stack_config_t mock_stack_config{
84 .get_pts_avrcp_test = get_pts_avrcp_test,
85 .get_pts_secure_only_mode = get_pts_secure_only_mode,
86 .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
87 .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
88 .get_pts_smp_options = get_pts_smp_options,
89 .get_pts_smp_failure_case = get_pts_smp_failure_case,
90 .get_pts_force_eatt_for_notifications =
91 get_pts_force_eatt_for_notifications,
92 .get_pts_connect_eatt_unconditionally =
93 get_pts_connect_eatt_unconditionally,
94 .get_pts_connect_eatt_before_encryption =
95 get_pts_connect_eatt_before_encryption,
96 .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
97 .get_pts_eatt_peripheral_collision_support =
98 get_pts_eatt_peripheral_collision_support,
99 .get_pts_force_le_audio_multiple_contexts_metadata =
100 get_pts_force_le_audio_multiple_contexts_metadata,
101 .get_pts_le_audio_disable_ases_before_stopping =
102 get_pts_le_audio_disable_ases_before_stopping,
103 .get_all = get_all,
104 };
105
stack_config_get_interface(void)106 const stack_config_t* stack_config_get_interface(void) {
107 return &mock_stack_config;
108 }
109
110 namespace server_configurable_flags {
GetServerConfigurableFlag(const std::string & experiment_category_name,const std::string & experiment_flag_name,const std::string & default_value)111 std::string GetServerConfigurableFlag(
112 const std::string& experiment_category_name,
113 const std::string& experiment_flag_name, const std::string& default_value) {
114 return "";
115 }
116 } // namespace server_configurable_flags
117
118 namespace bluetooth {
119 namespace audio {
120 namespace le_audio {
get_offload_capabilities()121 OffloadCapabilities get_offload_capabilities() {
122 return {*offload_capabilities, *offload_capabilities};
123 }
124 } // namespace le_audio
125 } // namespace audio
126 } // namespace bluetooth
127
128 namespace bluetooth::le_audio {
129
130 class MockLeAudioSourceHalClient;
131 MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_;
132 std::unique_ptr<LeAudioSourceAudioHalClient>
133 owned_mock_le_audio_source_hal_client_;
134 bool is_audio_unicast_source_acquired;
135 bool is_audio_broadcast_source_acquired;
136
137 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireUnicast()138 LeAudioSourceAudioHalClient::AcquireUnicast() {
139 if (is_audio_unicast_source_acquired) return nullptr;
140 is_audio_unicast_source_acquired = true;
141 return std::move(owned_mock_le_audio_source_hal_client_);
142 }
143
144 MockLeAudioSourceHalClient* mock_broadcast_le_audio_source_hal_client_;
145 std::unique_ptr<LeAudioSourceAudioHalClient>
146 owned_mock_broadcast_le_audio_source_hal_client_;
147
148 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireBroadcast()149 LeAudioSourceAudioHalClient::AcquireBroadcast() {
150 if (is_audio_broadcast_source_acquired) return nullptr;
151 is_audio_broadcast_source_acquired = true;
152 return std::move(owned_mock_broadcast_le_audio_source_hal_client_);
153 }
154
DebugDump(int fd)155 void LeAudioSourceAudioHalClient::DebugDump(int fd) {}
156
157 class MockLeAudioSinkHalClient;
158 MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_;
159 std::unique_ptr<LeAudioSinkAudioHalClient> owned_mock_le_audio_sink_hal_client_;
160 bool is_audio_unicast_sink_acquired;
161
162 std::unique_ptr<LeAudioSinkAudioHalClient>
AcquireUnicast()163 LeAudioSinkAudioHalClient::AcquireUnicast() {
164 if (is_audio_unicast_sink_acquired) return nullptr;
165 is_audio_unicast_sink_acquired = true;
166 return std::move(owned_mock_le_audio_sink_hal_client_);
167 }
168
169 class MockLeAudioSinkHalClient : public LeAudioSinkAudioHalClient {
170 public:
171 MockLeAudioSinkHalClient() = default;
172 MOCK_METHOD((bool), Start,
173 (const LeAudioCodecConfiguration& codecConfiguration,
174 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
175 DsaModes dsa_modes),
176 (override));
177 MOCK_METHOD((void), Stop, (), (override));
178 MOCK_METHOD((size_t), SendData, (uint8_t * data, uint16_t size), (override));
179 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
180 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
181 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
182 MOCK_METHOD((void), UpdateAudioConfigToHal,
183 (const ::bluetooth::le_audio::offload_config&), (override));
184 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
185 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
186
187 MOCK_METHOD(
188 (std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
189 ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
190 (const std::optional<
191 std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
192 (const override));
193
194 MOCK_METHOD(
195 (std::optional<
196 ::bluetooth::le_audio::set_configurations::AudioSetConfiguration>),
197 GetUnicastConfig,
198 (types::LeAudioContextType,
199 std::optional<
200 const ::bluetooth::le_audio::types::PublishedAudioCapabilities*>,
201 std::optional<
202 const ::bluetooth::le_audio::types::PublishedAudioCapabilities*>),
203 (const override));
204
205 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSinkHalClient()206 virtual ~MockLeAudioSinkHalClient() override { OnDestroyed(); }
207 };
208
209 class MockLeAudioSourceHalClient : public LeAudioSourceAudioHalClient {
210 public:
211 MockLeAudioSourceHalClient() = default;
212 MOCK_METHOD((bool), Start,
213 (const LeAudioCodecConfiguration& codecConfiguration,
214 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
215 DsaModes dsa_modes),
216 (override));
217 MOCK_METHOD((void), Stop, (), (override));
218 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
219 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
220 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
221 MOCK_METHOD((void), UpdateAudioConfigToHal,
222 (const ::bluetooth::le_audio::offload_config&), (override));
223 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
224 (const ::bluetooth::le_audio::broadcast_offload_config&),
225 (override));
226 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
227 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
228
229 MOCK_METHOD(
230 (std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
231 ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
232 (const std::optional<
233 std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
234 (const override));
235
236 MOCK_METHOD(
237 (std::optional<
238 ::bluetooth::le_audio::set_configurations::AudioSetConfiguration>),
239 GetUnicastConfig, (const CodecManager::UnicastConfigurationRequirements&),
240 (const override));
241
242 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSourceHalClient()243 virtual ~MockLeAudioSourceHalClient() override { OnDestroyed(); }
244 };
245
246 static const types::LeAudioCodecId kLeAudioCodecIdLc3 = {
247 .coding_format = types::kLeAudioCodingFormatLC3,
248 .vendor_company_id = types::kLeAudioVendorCompanyIdUndefined,
249 .vendor_codec_id = types::kLeAudioVendorCodecIdUndefined};
250
251 static const set_configurations::CodecConfigSetting lc3_16_2 = {
252 .id = kLeAudioCodecIdLc3,
253 .params = types::LeAudioLtvMap({
254 LTV_ENTRY_SAMPLING_FREQUENCY(
255 codec_spec_conf::kLeAudioSamplingFreq16000Hz),
256 LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
257 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
258 codec_spec_conf::kLeAudioLocationStereo),
259 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
260 }),
261 .channel_count_per_iso_stream = 1,
262 };
263
264 static const set_configurations::CodecConfigSetting lc3_24_2 = {
265 .id = kLeAudioCodecIdLc3,
266 .params = types::LeAudioLtvMap({
267 LTV_ENTRY_SAMPLING_FREQUENCY(
268 codec_spec_conf::kLeAudioSamplingFreq24000Hz),
269 LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
270 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
271 codec_spec_conf::kLeAudioLocationStereo),
272 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(60),
273 }),
274 .channel_count_per_iso_stream = 1,
275 };
276
277 static const set_configurations::CodecConfigSetting lc3_32_2 = {
278 .id = kLeAudioCodecIdLc3,
279 .params = types::LeAudioLtvMap({
280 LTV_ENTRY_SAMPLING_FREQUENCY(
281 codec_spec_conf::kLeAudioSamplingFreq32000Hz),
282 LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
283 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
284 codec_spec_conf::kLeAudioLocationStereo),
285 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(80),
286 }),
287 .channel_count_per_iso_stream = 1,
288 };
289
290 static const set_configurations::CodecConfigSetting lc3_48_2 = {
291 .id = kLeAudioCodecIdLc3,
292 .params = types::LeAudioLtvMap({
293 LTV_ENTRY_SAMPLING_FREQUENCY(
294 codec_spec_conf::kLeAudioSamplingFreq48000Hz),
295 LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
296 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
297 codec_spec_conf::kLeAudioLocationStereo),
298 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100),
299 }),
300 .channel_count_per_iso_stream = 1,
301 };
302
set_mock_offload_capabilities(const std::vector<AudioSetConfiguration> & caps)303 void set_mock_offload_capabilities(
304 const std::vector<AudioSetConfiguration>& caps) {
305 offload_capabilities = ∩︀
306 }
307
308 static constexpr char kPropLeAudioOffloadSupported[] =
309 "ro.bluetooth.leaudio_offload.supported";
310 static constexpr char kPropLeAudioOffloadDisabled[] =
311 "persist.bluetooth.leaudio_offload.disabled";
312 static constexpr char kPropLeAudioBidirSwbSupported[] =
313 "bluetooth.leaudio.dual_bidirection_swb.supported";
314
315 class CodecManagerTestBase : public Test {
316 public:
SetUp()317 virtual void SetUp() override {
318 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
319 bluetooth::common::InitFlags::Load(test_flags);
320 set_mock_offload_capabilities(offload_capabilities_none);
321
322 bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_);
323
324 ON_CALL(controller_interface, SupportsBleIsochronousBroadcaster)
325 .WillByDefault(Return(true));
326 ON_CALL(controller_interface, IsSupported(OpCode::CONFIGURE_DATA_PATH))
327 .WillByDefault(Return(true));
328 bluetooth::hci::testing::mock_controller_ = &controller_interface;
329
330 codec_manager = CodecManager::GetInstance();
331
332 RegisterSourceHalClientMock();
333 RegisterSinkHalClientMock();
334 }
335
TearDown()336 virtual void TearDown() override { codec_manager->Stop(); }
337
338 NiceMock<bluetooth::hci::testing::MockControllerInterface>
339 controller_interface;
340 CodecManager* codec_manager;
341 bluetooth::legacy::hci::testing::MockInterface legacy_hci_mock_;
342
343 protected:
RegisterSourceHalClientMock()344 void RegisterSourceHalClientMock() {
345 owned_mock_le_audio_source_hal_client_.reset(
346 new NiceMock<MockLeAudioSourceHalClient>());
347 mock_le_audio_source_hal_client_ =
348 (MockLeAudioSourceHalClient*)
349 owned_mock_le_audio_source_hal_client_.get();
350
351 is_audio_unicast_source_acquired = false;
352
353 owned_mock_broadcast_le_audio_source_hal_client_.reset(
354 new NiceMock<MockLeAudioSourceHalClient>());
355 mock_broadcast_le_audio_source_hal_client_ =
356 (MockLeAudioSourceHalClient*)
357 owned_mock_broadcast_le_audio_source_hal_client_.get();
358 is_audio_broadcast_source_acquired = false;
359
360 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
361 mock_le_audio_source_hal_client_ = nullptr;
362 is_audio_unicast_source_acquired = false;
363 });
364 }
365
RegisterSinkHalClientMock()366 void RegisterSinkHalClientMock() {
367 owned_mock_le_audio_sink_hal_client_.reset(
368 new NiceMock<MockLeAudioSinkHalClient>());
369 mock_le_audio_sink_hal_client_ =
370 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
371
372 is_audio_unicast_sink_acquired = false;
373
374 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
375 mock_le_audio_sink_hal_client_ = nullptr;
376 is_audio_unicast_sink_acquired = false;
377 });
378 }
379 };
380
381 /*----------------- ADSP codec manager tests ------------------*/
382 class CodecManagerTestAdsp : public CodecManagerTestBase {
383 public:
SetUp()384 virtual void SetUp() override {
385 // Enable the HW offloader
386 osi_property_set_bool(kPropLeAudioOffloadSupported, true);
387 osi_property_set_bool(kPropLeAudioOffloadDisabled, false);
388
389 // Allow for bidir SWB configurations
390 osi_property_set_bool(kPropLeAudioBidirSwbSupported, true);
391
392 CodecManagerTestBase::SetUp();
393 }
394 };
395
396 class CodecManagerTestAdspNoSwb : public CodecManagerTestBase {
397 public:
SetUp()398 virtual void SetUp() override {
399 // Enable the HW offloader
400 osi_property_set_bool(kPropLeAudioOffloadSupported, true);
401 osi_property_set_bool(kPropLeAudioOffloadDisabled, false);
402
403 // Allow for bidir SWB configurations
404 osi_property_set_bool(kPropLeAudioBidirSwbSupported, false);
405
406 CodecManagerTestBase::SetUp();
407 }
408 };
409
TEST_F(CodecManagerTestAdsp,test_init)410 TEST_F(CodecManagerTestAdsp, test_init) {
411 ASSERT_EQ(codec_manager, CodecManager::GetInstance());
412 }
413
TEST_F(CodecManagerTestAdsp,test_start)414 TEST_F(CodecManagerTestAdsp, test_start) {
415 EXPECT_CALL(legacy_hci_mock_,
416 ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
417 kIsoDataPathPlatformDefault, _))
418 .Times(1);
419 EXPECT_CALL(legacy_hci_mock_,
420 ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
421 kIsoDataPathPlatformDefault, _))
422 .Times(1);
423
424 // Verify data path is reset on Stop()
425 EXPECT_CALL(legacy_hci_mock_,
426 ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
427 kIsoDataPathHci, _))
428 .Times(1);
429 EXPECT_CALL(legacy_hci_mock_,
430 ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
431 kIsoDataPathHci, _))
432 .Times(1);
433
434 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
435 offloading_preference(0);
436 codec_manager->Start(offloading_preference);
437
438 ASSERT_EQ(codec_manager->GetCodecLocation(), CodecLocation::ADSP);
439 }
440
TEST_F(CodecManagerTestAdsp,testStreamConfigurationAdspDownMix)441 TEST_F(CodecManagerTestAdsp, testStreamConfigurationAdspDownMix) {
442 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
443 offloading_preference(0);
444 codec_manager->Start(offloading_preference);
445
446 // Current CIS configuration for two earbuds
447 std::vector<struct types::cis> cises{
448 {
449 .id = 0x00,
450 .type = types::CisType::CIS_TYPE_BIDIRECTIONAL,
451 .conn_handle = 96,
452 },
453 {
454 .id = 0x01,
455 .type = types::CisType::CIS_TYPE_BIDIRECTIONAL,
456 .conn_handle = 97,
457 },
458 };
459
460 // Stream parameters
461 types::BidirectionalPair<stream_parameters> stream_params{
462 .sink =
463 {
464 .sample_frequency_hz = 16000,
465 .frame_duration_us = 10000,
466 .octets_per_codec_frame = 40,
467 .audio_channel_allocation =
468 codec_spec_conf::kLeAudioLocationFrontLeft,
469 .codec_frames_blocks_per_sdu = 1,
470 .num_of_channels = 1,
471 .num_of_devices = 1,
472 .stream_locations =
473 {
474 std::pair<uint16_t, uint32_t>{
475 97 /*conn_handle*/,
476 codec_spec_conf::kLeAudioLocationFrontLeft},
477 },
478 },
479 .source =
480 {
481 .sample_frequency_hz = 16000,
482 .frame_duration_us = 10000,
483 .octets_per_codec_frame = 40,
484 .audio_channel_allocation =
485 codec_spec_conf::kLeAudioLocationFrontLeft,
486 .codec_frames_blocks_per_sdu = 1,
487 .num_of_channels = 1,
488 .num_of_devices = 1,
489 {
490 std::pair<uint16_t, uint32_t>{
491 97 /*conn_handle*/,
492 codec_spec_conf::kLeAudioLocationBackLeft},
493 },
494 },
495 };
496
497 codec_manager->UpdateCisConfiguration(cises, stream_params.sink,
498 kLeAudioDirectionSink);
499 codec_manager->UpdateCisConfiguration(cises, stream_params.source,
500 kLeAudioDirectionSource);
501
502 // Verify the offloader config content
503 types::BidirectionalPair<std::optional<offload_config>> out_offload_configs;
504 codec_manager->UpdateActiveAudioConfig(
505 stream_params, {.sink = 44, .source = 44},
506 [&out_offload_configs](const offload_config& config, uint8_t direction) {
507 out_offload_configs.get(direction) = config;
508 });
509
510 // Expect the same configuration for sink and source
511 ASSERT_TRUE(out_offload_configs.sink.has_value());
512 ASSERT_TRUE(out_offload_configs.source.has_value());
513 for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink,
514 bluetooth::le_audio::types::kLeAudioDirectionSource}) {
515 uint32_t allocation = 0;
516 auto& config = out_offload_configs.get(direction).value();
517 ASSERT_EQ(2lu, config.stream_map.size());
518 for (const auto& info : config.stream_map) {
519 if (info.stream_handle == 96) {
520 ASSERT_EQ(codec_spec_conf::kLeAudioLocationFrontRight,
521 info.audio_channel_allocation);
522 // The disconnected should be inactive
523 ASSERT_FALSE(info.is_stream_active);
524
525 } else if (info.stream_handle == 97) {
526 ASSERT_EQ(codec_spec_conf::kLeAudioLocationFrontLeft,
527 info.audio_channel_allocation);
528 // The connected should be active
529 ASSERT_TRUE(info.is_stream_active);
530
531 } else {
532 ASSERT_EQ(97, info.stream_handle);
533 }
534 allocation |= info.audio_channel_allocation;
535 }
536
537 ASSERT_EQ(16, config.bits_per_sample);
538 ASSERT_EQ(16000u, config.sampling_rate);
539 ASSERT_EQ(10000u, config.frame_duration);
540 ASSERT_EQ(40u, config.octets_per_frame);
541 ASSERT_EQ(1, config.blocks_per_sdu);
542 ASSERT_EQ(44, config.peer_delay_ms);
543 ASSERT_EQ(codec_spec_conf::kLeAudioLocationStereo, allocation);
544 }
545
546 // Clear the CIS configuration map (no active CISes).
547 codec_manager->ClearCisConfiguration(kLeAudioDirectionSink);
548 codec_manager->ClearCisConfiguration(kLeAudioDirectionSource);
549 out_offload_configs.sink = std::nullopt;
550 out_offload_configs.source = std::nullopt;
551 codec_manager->UpdateActiveAudioConfig(
552 stream_params, {.sink = 44, .source = 44},
553 [&out_offload_configs](const offload_config& config, uint8_t direction) {
554 out_offload_configs.get(direction) = config;
555 });
556
557 // Expect sink & source configurations with empty CIS channel allocation map.
558 ASSERT_TRUE(out_offload_configs.sink.has_value());
559 ASSERT_TRUE(out_offload_configs.source.has_value());
560 for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink,
561 bluetooth::le_audio::types::kLeAudioDirectionSource}) {
562 auto& config = out_offload_configs.get(direction).value();
563 ASSERT_EQ(0lu, config.stream_map.size());
564 ASSERT_EQ(16, config.bits_per_sample);
565 ASSERT_EQ(16000u, config.sampling_rate);
566 ASSERT_EQ(10000u, config.frame_duration);
567 ASSERT_EQ(40u, config.octets_per_frame);
568 ASSERT_EQ(1, config.blocks_per_sdu);
569 ASSERT_EQ(44, config.peer_delay_ms);
570 }
571 }
572
TEST_F(CodecManagerTestAdsp,test_capabilities_none)573 TEST_F(CodecManagerTestAdsp, test_capabilities_none) {
574 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
575 offloading_preference(0);
576 codec_manager->Start(offloading_preference);
577
578 bool has_null_config = false;
579 auto match_first_config =
580 [&](const CodecManager::UnicastConfigurationRequirements& requirements,
581 const set_configurations::AudioSetConfigurations* confs)
582 -> const set_configurations::AudioSetConfiguration* {
583 // Don't expect the matcher being called on nullptr
584 if (confs == nullptr) {
585 has_null_config = true;
586 }
587 if (confs && confs->size()) {
588 // For simplicity return the first element, the real matcher should
589 // check the group capabilities.
590 return confs->at(0);
591 }
592 return nullptr;
593 };
594
595 // Verify every context
596 for (::bluetooth::le_audio::types::LeAudioContextType ctx_type :
597 ::bluetooth::le_audio::types::kLeAudioContextAllTypesArray) {
598 has_null_config = false;
599 CodecManager::UnicastConfigurationRequirements requirements = {
600 .audio_context_type = ctx_type,
601 };
602 ASSERT_EQ(nullptr,
603 codec_manager->GetCodecConfig(requirements, match_first_config));
604 ASSERT_FALSE(has_null_config);
605 }
606 }
607
TEST_F(CodecManagerTestAdsp,test_capabilities)608 TEST_F(CodecManagerTestAdsp, test_capabilities) {
609 for (auto test_context :
610 ::bluetooth::le_audio::types::kLeAudioContextAllTypesArray) {
611 // Build the offloader capabilities vector using the configuration provider
612 // in HOST mode to get all the .json filce configuration entries.
613 std::vector<AudioSetConfiguration> offload_capabilities;
614 AudioSetConfigurationProvider::Initialize(
615 bluetooth::le_audio::types::CodecLocation::HOST);
616 for (auto& cap : *AudioSetConfigurationProvider::Get()->GetConfigurations(
617 test_context)) {
618 offload_capabilities.push_back(*cap);
619 }
620 ASSERT_NE(0u, offload_capabilities.size());
621 set_mock_offload_capabilities(offload_capabilities);
622 // Clean up before the codec manager starts it in ADSP mode.
623 AudioSetConfigurationProvider::Cleanup();
624
625 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
626 offloading_preference = {
627 {.codec_type =
628 bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
629 codec_manager->Start(offloading_preference);
630
631 size_t available_configs_size = 0;
632 auto match_first_config =
633 [&available_configs_size](
634 const CodecManager::UnicastConfigurationRequirements& requirements,
635 const set_configurations::AudioSetConfigurations* confs)
636 -> const set_configurations::AudioSetConfiguration* {
637 if (confs && confs->size()) {
638 available_configs_size = confs->size();
639 // For simplicity return the first element, the real matcher should
640 // check the group capabilities.
641 return confs->at(0);
642 }
643 return nullptr;
644 };
645
646 CodecManager::UnicastConfigurationRequirements requirements = {
647 .audio_context_type = test_context,
648 };
649 auto cfg = codec_manager->GetCodecConfig(requirements, match_first_config);
650 ASSERT_NE(nullptr, cfg);
651 ASSERT_EQ(offload_capabilities.size(), available_configs_size);
652
653 // Clean up the before testing any other offload capabilities.
654 codec_manager->Stop();
655 }
656 }
657
TEST_F(CodecManagerTestAdsp,test_broadcast_config)658 TEST_F(CodecManagerTestAdsp, test_broadcast_config) {
659 static const set_configurations::CodecConfigSetting bc_lc3_48_2 = {
660 .id = kLeAudioCodecIdLc3,
661 .params = types::LeAudioLtvMap({
662 LTV_ENTRY_SAMPLING_FREQUENCY(
663 codec_spec_conf::kLeAudioSamplingFreq48000Hz),
664 LTV_ENTRY_FRAME_DURATION(
665 codec_spec_conf::kLeAudioCodecFrameDur10000us),
666 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
667 codec_spec_conf::kLeAudioLocationStereo),
668 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100),
669 }),
670 .channel_count_per_iso_stream = 2,
671 };
672
673 std::vector<AudioSetConfiguration> offload_capabilities = {{
674 .name = "Test_Broadcast_Config_No_Dev_lc3_48_2",
675 .confs = {.sink = {set_configurations::AseConfiguration(bc_lc3_48_2),
676 set_configurations::AseConfiguration(bc_lc3_48_2)},
677 .source = {}},
678 }};
679 set_mock_offload_capabilities(offload_capabilities);
680
681 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
682 offloading_preference = {
683 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
684 codec_manager->Start(offloading_preference);
685
686 CodecManager::BroadcastConfigurationRequirements requirements = {
687 .subgroup_quality = {{types::LeAudioContextType::MEDIA, 1}}};
688 auto cfg = codec_manager->GetBroadcastConfig(requirements);
689 ASSERT_EQ(2, cfg->GetNumBisTotal());
690 ASSERT_EQ(2, cfg->GetNumChannelsMax());
691 ASSERT_EQ(48000u, cfg->GetSamplingFrequencyHzMax());
692 ASSERT_EQ(10000u, cfg->GetSduIntervalUs());
693 ASSERT_EQ(100u, cfg->GetMaxSduOctets());
694 ASSERT_EQ(1lu, cfg->subgroups.size());
695 ASSERT_EQ(2lu, cfg->subgroups.at(0).GetNumBis());
696 ASSERT_EQ(2lu, cfg->subgroups.at(0).GetNumChannelsTotal());
697
698 ASSERT_EQ(2lu, cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumBis());
699 ASSERT_EQ(2lu,
700 cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumChannels());
701 ASSERT_EQ(
702 1lu,
703 cfg->subgroups.at(0).GetBisCodecConfigs().at(0).GetNumChannelsPerBis());
704
705 // Clean up the before testing any other offload capabilities.
706 codec_manager->Stop();
707 }
708
TEST_F(CodecManagerTestAdsp,test_update_broadcast_offloader)709 TEST_F(CodecManagerTestAdsp, test_update_broadcast_offloader) {
710 static const set_configurations::CodecConfigSetting bc_lc3_48_2 = {
711 .id = kLeAudioCodecIdLc3,
712 .params = types::LeAudioLtvMap({
713 LTV_ENTRY_SAMPLING_FREQUENCY(
714 codec_spec_conf::kLeAudioSamplingFreq48000Hz),
715 LTV_ENTRY_FRAME_DURATION(
716 codec_spec_conf::kLeAudioCodecFrameDur10000us),
717 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(
718 codec_spec_conf::kLeAudioLocationStereo),
719 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100),
720 }),
721 .channel_count_per_iso_stream = 2,
722 };
723 std::vector<AudioSetConfiguration> offload_capabilities = {{
724 .name = "Test_Broadcast_Config_For_Offloader",
725 .confs = {.sink = {set_configurations::AseConfiguration(bc_lc3_48_2),
726 set_configurations::AseConfiguration(bc_lc3_48_2)},
727 .source = {}},
728 }};
729 set_mock_offload_capabilities(offload_capabilities);
730
731 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
732 offloading_preference = {
733 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
734 codec_manager->Start(offloading_preference);
735
736 CodecManager::BroadcastConfigurationRequirements requirements = {
737 .subgroup_quality = {{types::LeAudioContextType::MEDIA, 1}}};
738 codec_manager->GetBroadcastConfig(requirements);
739
740 bool was_called = false;
741 bluetooth::le_audio::broadcast_offload_config bcast_config;
742 codec_manager->UpdateBroadcastConnHandle(
743 {0x0001, 0x0002},
744 [&](const bluetooth::le_audio::broadcast_offload_config& config) {
745 was_called = true;
746 bcast_config = config;
747 });
748
749 // Expect a call for ADSP encoding
750 ASSERT_TRUE(was_called);
751 ASSERT_EQ(2lu, bcast_config.stream_map.size());
752 ASSERT_EQ(16, bcast_config.bits_per_sample);
753 ASSERT_EQ(48000lu, bcast_config.sampling_rate);
754 ASSERT_EQ(10000lu, bcast_config.frame_duration);
755 ASSERT_EQ(100u, bcast_config.octets_per_frame);
756 ASSERT_EQ(1u, bcast_config.blocks_per_sdu);
757 ASSERT_NE(0u, bcast_config.retransmission_number);
758 ASSERT_NE(0u, bcast_config.max_transport_latency);
759 }
760
761 /*----------------- HOST codec manager tests ------------------*/
762 class CodecManagerTestHost : public CodecManagerTestBase {
763 public:
SetUp()764 virtual void SetUp() override {
765 // Enable the HW offloader
766 osi_property_set_bool(kPropLeAudioOffloadSupported, false);
767 osi_property_set_bool(kPropLeAudioOffloadDisabled, false);
768
769 // Allow for bidir SWB configurations
770 osi_property_set_bool(kPropLeAudioBidirSwbSupported, true);
771
772 CodecManagerTestBase::SetUp();
773 }
774 };
775
776 class CodecManagerTestHostNoSwb : public CodecManagerTestBase {
777 public:
SetUp()778 virtual void SetUp() override {
779 // Enable the HW offloader
780 osi_property_set_bool(kPropLeAudioOffloadSupported, true);
781 osi_property_set_bool(kPropLeAudioOffloadDisabled, false);
782
783 // Do not allow for bidir SWB configurations
784 osi_property_set_bool(kPropLeAudioBidirSwbSupported, false);
785
786 CodecManagerTestBase::SetUp();
787 }
788 };
789
TEST_F(CodecManagerTestHost,test_init)790 TEST_F(CodecManagerTestHost, test_init) {
791 ASSERT_EQ(codec_manager, CodecManager::GetInstance());
792 }
793
TEST_F(CodecManagerTestHost,test_audio_session_update)794 TEST_F(CodecManagerTestHost, test_audio_session_update) {
795 ASSERT_EQ(codec_manager, CodecManager::GetInstance());
796
797 auto unicast_source = LeAudioSourceAudioHalClient::AcquireUnicast();
798 auto unicast_sink = LeAudioSinkAudioHalClient::AcquireUnicast();
799 auto broadcast_source = LeAudioSourceAudioHalClient::AcquireBroadcast();
800
801 // codec manager not started
802 ASSERT_FALSE(codec_manager->UpdateActiveUnicastAudioHalClient(
803 unicast_source.get(), unicast_sink.get(), true));
804 ASSERT_FALSE(codec_manager->UpdateActiveUnicastAudioHalClient(
805 unicast_source.get(), unicast_sink.get(), false));
806 ASSERT_FALSE(codec_manager->UpdateActiveBroadcastAudioHalClient(
807 broadcast_source.get(), true));
808 ASSERT_FALSE(codec_manager->UpdateActiveBroadcastAudioHalClient(
809 broadcast_source.get(), false));
810
811 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
812 offloading_preference(0);
813
814 // Start codec manager
815 codec_manager->Start(offloading_preference);
816
817 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
818 unicast_source.get(), unicast_sink.get(), true));
819 ASSERT_FALSE(codec_manager->UpdateActiveUnicastAudioHalClient(
820 unicast_source.get(), unicast_sink.get(), true));
821 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
822 unicast_source.get(), unicast_sink.get(), false));
823 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
824 unicast_source.get(), nullptr, true));
825 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
826 nullptr, unicast_sink.get(), true));
827 ASSERT_FALSE(codec_manager->UpdateActiveUnicastAudioHalClient(
828 nullptr, nullptr, false));
829 ASSERT_FALSE(
830 codec_manager->UpdateActiveUnicastAudioHalClient(nullptr, nullptr, true));
831 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
832 nullptr, unicast_sink.get(), false));
833 ASSERT_TRUE(codec_manager->UpdateActiveUnicastAudioHalClient(
834 unicast_source.get(), nullptr, false));
835
836 ASSERT_TRUE(codec_manager->UpdateActiveBroadcastAudioHalClient(
837 broadcast_source.get(), true));
838 ASSERT_TRUE(codec_manager->UpdateActiveBroadcastAudioHalClient(
839 broadcast_source.get(), false));
840 ASSERT_TRUE(codec_manager->UpdateActiveBroadcastAudioHalClient(
841 broadcast_source.get(), true));
842 ASSERT_FALSE(codec_manager->UpdateActiveBroadcastAudioHalClient(
843 broadcast_source.get(), true));
844 ASSERT_FALSE(codec_manager->UpdateActiveBroadcastAudioHalClient(
845 unicast_source.get(), true));
846 ASSERT_FALSE(codec_manager->UpdateActiveBroadcastAudioHalClient(
847 unicast_source.get(), false));
848 ASSERT_FALSE(
849 codec_manager->UpdateActiveBroadcastAudioHalClient(nullptr, false));
850 ASSERT_FALSE(
851 codec_manager->UpdateActiveBroadcastAudioHalClient(nullptr, true));
852 }
853
TEST_F(CodecManagerTestHost,test_start)854 TEST_F(CodecManagerTestHost, test_start) {
855 EXPECT_CALL(legacy_hci_mock_,
856 ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
857 kIsoDataPathPlatformDefault, _))
858 .Times(0);
859 EXPECT_CALL(legacy_hci_mock_,
860 ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
861 kIsoDataPathPlatformDefault, _))
862 .Times(0);
863
864 // Verify data path is NOT reset on Stop() for the Host encoding session
865 EXPECT_CALL(legacy_hci_mock_,
866 ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
867 kIsoDataPathHci, _))
868 .Times(0);
869 EXPECT_CALL(legacy_hci_mock_,
870 ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
871 kIsoDataPathHci, _))
872 .Times(0);
873
874 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
875 offloading_preference(0);
876 codec_manager->Start(offloading_preference);
877
878 ASSERT_EQ(codec_manager->GetCodecLocation(), CodecLocation::HOST);
879 }
880
TEST_F(CodecManagerTestHost,test_non_bidir_swb)881 TEST_F(CodecManagerTestHost, test_non_bidir_swb) {
882 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
883 offloading_preference = {
884 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
885 codec_manager->Start(offloading_preference);
886
887 // NON-SWB configs
888 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
889 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
890 set_configurations::AseConfiguration(lc3_16_2)},
891 .source = {set_configurations::AseConfiguration(lc3_16_2),
892 set_configurations::AseConfiguration(lc3_16_2)}},
893 }));
894 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
895 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
896 set_configurations::AseConfiguration(lc3_24_2)},
897 .source = {set_configurations::AseConfiguration(lc3_16_2),
898 set_configurations::AseConfiguration(lc3_16_2)}},
899 }));
900 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
901 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
902 set_configurations::AseConfiguration(lc3_16_2)},
903 .source = {set_configurations::AseConfiguration(lc3_24_2),
904 set_configurations::AseConfiguration(lc3_24_2)}},
905 }));
906
907 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
908 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
909 set_configurations::AseConfiguration(lc3_16_2)},
910 .source = {set_configurations::AseConfiguration(lc3_32_2),
911 set_configurations::AseConfiguration(lc3_32_2)}},
912 }));
913 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
914 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
915 set_configurations::AseConfiguration(lc3_32_2)},
916 .source = {set_configurations::AseConfiguration(lc3_16_2),
917 set_configurations::AseConfiguration(lc3_16_2)}},
918 }));
919
920 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
921 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
922 set_configurations::AseConfiguration(lc3_24_2)},
923 .source = {set_configurations::AseConfiguration(lc3_24_2),
924 set_configurations::AseConfiguration(lc3_24_2)}},
925 }));
926 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
927 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
928 set_configurations::AseConfiguration(lc3_24_2)},
929 .source = {set_configurations::AseConfiguration(lc3_32_2),
930 set_configurations::AseConfiguration(lc3_32_2)}},
931 }));
932 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
933 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
934 set_configurations::AseConfiguration(lc3_32_2)},
935 .source = {set_configurations::AseConfiguration(lc3_24_2),
936 set_configurations::AseConfiguration(lc3_24_2)}},
937 }));
938
939 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
940 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
941 set_configurations::AseConfiguration(lc3_16_2)}},
942 }));
943 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
944 .confs = {.source = {set_configurations::AseConfiguration(lc3_16_2),
945 set_configurations::AseConfiguration(lc3_16_2)}},
946 }));
947 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
948 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
949 set_configurations::AseConfiguration(lc3_24_2)}},
950 }));
951 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
952 .confs = {.source = {set_configurations::AseConfiguration(lc3_24_2),
953 set_configurations::AseConfiguration(lc3_24_2)}},
954 }));
955 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
956 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
957 set_configurations::AseConfiguration(lc3_32_2)}},
958 }));
959 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
960 .confs = {.source = {set_configurations::AseConfiguration(lc3_32_2),
961 set_configurations::AseConfiguration(lc3_32_2)}},
962 }));
963 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
964 .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2),
965 set_configurations::AseConfiguration(lc3_48_2)}},
966 }));
967 ASSERT_FALSE(codec_manager->CheckCodecConfigIsBiDirSwb({
968 .confs = {.source = {set_configurations::AseConfiguration(lc3_48_2),
969 set_configurations::AseConfiguration(lc3_48_2)}},
970 }));
971
972 // NON-DUAL-SWB configs
973 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
974 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
975 set_configurations::AseConfiguration(lc3_16_2)},
976 .source = {set_configurations::AseConfiguration(lc3_16_2),
977 set_configurations::AseConfiguration(lc3_16_2)}},
978 }));
979 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
980 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
981 set_configurations::AseConfiguration(lc3_24_2)},
982 .source = {set_configurations::AseConfiguration(lc3_16_2),
983 set_configurations::AseConfiguration(lc3_16_2)}},
984 }));
985 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
986 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
987 set_configurations::AseConfiguration(lc3_16_2)},
988 .source = {set_configurations::AseConfiguration(lc3_24_2),
989 set_configurations::AseConfiguration(lc3_24_2)}},
990 }));
991
992 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
993 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
994 set_configurations::AseConfiguration(lc3_16_2)},
995 .source = {set_configurations::AseConfiguration(lc3_32_2),
996 set_configurations::AseConfiguration(lc3_32_2)}},
997 }));
998 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
999 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1000 set_configurations::AseConfiguration(lc3_32_2)},
1001 .source = {set_configurations::AseConfiguration(lc3_16_2),
1002 set_configurations::AseConfiguration(lc3_16_2)}},
1003 }));
1004
1005 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1006 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
1007 set_configurations::AseConfiguration(lc3_24_2)},
1008 .source = {set_configurations::AseConfiguration(lc3_24_2),
1009 set_configurations::AseConfiguration(lc3_24_2)}},
1010 }));
1011 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1012 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
1013 set_configurations::AseConfiguration(lc3_24_2)},
1014 .source = {set_configurations::AseConfiguration(lc3_32_2),
1015 set_configurations::AseConfiguration(lc3_32_2)}},
1016 }));
1017 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1018 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1019 set_configurations::AseConfiguration(lc3_32_2)},
1020 .source = {set_configurations::AseConfiguration(lc3_24_2),
1021 set_configurations::AseConfiguration(lc3_24_2)}},
1022 }));
1023
1024 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1025 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
1026 set_configurations::AseConfiguration(lc3_16_2)}},
1027 }));
1028 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1029 .confs = {.source = {set_configurations::AseConfiguration(lc3_16_2),
1030 set_configurations::AseConfiguration(lc3_16_2)}},
1031 }));
1032 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1033 .confs = {.sink = {set_configurations::AseConfiguration(lc3_24_2),
1034 set_configurations::AseConfiguration(lc3_24_2)}},
1035 }));
1036 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1037 .confs = {.source = {set_configurations::AseConfiguration(lc3_24_2),
1038 set_configurations::AseConfiguration(lc3_24_2)}},
1039 }));
1040 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1041 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1042 set_configurations::AseConfiguration(lc3_32_2)}},
1043 }));
1044 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1045 .confs = {.source = {set_configurations::AseConfiguration(lc3_32_2),
1046 set_configurations::AseConfiguration(lc3_32_2)}},
1047 }));
1048 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1049 .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2),
1050 set_configurations::AseConfiguration(lc3_48_2)}},
1051 }));
1052 ASSERT_FALSE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1053 .confs = {.source = {set_configurations::AseConfiguration(lc3_48_2),
1054 set_configurations::AseConfiguration(lc3_48_2)}},
1055 }));
1056 }
1057
TEST_F(CodecManagerTestHost,test_dual_bidir_swb)1058 TEST_F(CodecManagerTestHost, test_dual_bidir_swb) {
1059 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1060 offloading_preference = {
1061 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1062 codec_manager->Start(offloading_preference);
1063
1064 // Single Dev BiDir SWB configs
1065 ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1066 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1067 set_configurations::AseConfiguration(lc3_32_2)},
1068 .source = {set_configurations::AseConfiguration(lc3_32_2),
1069 set_configurations::AseConfiguration(lc3_32_2)}},
1070 }));
1071 ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1072 .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2),
1073 set_configurations::AseConfiguration(lc3_48_2)},
1074 .source = {set_configurations::AseConfiguration(lc3_32_2),
1075 set_configurations::AseConfiguration(lc3_32_2)}},
1076 }));
1077 ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1078 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1079 set_configurations::AseConfiguration(lc3_32_2)},
1080 .source = {set_configurations::AseConfiguration(lc3_48_2),
1081 set_configurations::AseConfiguration(lc3_48_2)}},
1082 }));
1083 ASSERT_TRUE(codec_manager->CheckCodecConfigIsDualBiDirSwb({
1084 .confs = {.sink = {set_configurations::AseConfiguration(lc3_48_2),
1085 set_configurations::AseConfiguration(lc3_48_2)},
1086 .source = {set_configurations::AseConfiguration(lc3_48_2),
1087 set_configurations::AseConfiguration(lc3_48_2)}},
1088 }));
1089 }
1090
TEST_F(CodecManagerTestHost,test_dual_bidir_swb_supported)1091 TEST_F(CodecManagerTestHost, test_dual_bidir_swb_supported) {
1092 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1093 offloading_preference = {
1094 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1095 codec_manager->Start(offloading_preference);
1096
1097 int num_of_dual_bidir_swb_configs = 0;
1098 for (auto context : types::kLeAudioContextAllTypesArray) {
1099 bool got_null_cfgs_container = false;
1100 auto ptr = codec_manager->GetCodecConfig(
1101 {.audio_context_type = context},
1102 [&](const CodecManager::UnicastConfigurationRequirements& requirements,
1103 const set_configurations::AudioSetConfigurations* confs)
1104 -> const set_configurations::AudioSetConfiguration* {
1105 if (confs == nullptr) {
1106 got_null_cfgs_container = true;
1107 } else {
1108 num_of_dual_bidir_swb_configs += std::count_if(
1109 confs->begin(), confs->end(), [&](auto const& cfg) {
1110 bool is_bidir =
1111 codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1112 return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1113 });
1114 }
1115 // In this case the chosen configuration doesn't matter - select none
1116 return nullptr;
1117 });
1118 ASSERT_FALSE(got_null_cfgs_container);
1119 }
1120
1121 // Make sure some dual bidir SWB configs were returned
1122 ASSERT_NE(0, num_of_dual_bidir_swb_configs);
1123 }
1124
TEST_F(CodecManagerTestAdsp,test_dual_bidir_swb_supported)1125 TEST_F(CodecManagerTestAdsp, test_dual_bidir_swb_supported) {
1126 // Set the offloader capabilities
1127 std::vector<AudioSetConfiguration> offload_capabilities = {
1128 {
1129 .name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2",
1130 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1131 set_configurations::AseConfiguration(lc3_32_2)},
1132 .source = {set_configurations::AseConfiguration(lc3_32_2),
1133 set_configurations::AseConfiguration(lc3_32_2)}},
1134 },
1135 {
1136 .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2",
1137 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
1138 set_configurations::AseConfiguration(lc3_16_2)},
1139 .source = {set_configurations::AseConfiguration(lc3_16_2),
1140 set_configurations::AseConfiguration(lc3_16_2)}},
1141 }};
1142 set_mock_offload_capabilities(offload_capabilities);
1143
1144 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1145 offloading_preference = {
1146 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1147 codec_manager->Start(offloading_preference);
1148
1149 int num_of_dual_bidir_swb_configs = 0;
1150 for (auto context : types::kLeAudioContextAllTypesArray) {
1151 bool got_null_cfgs_container = false;
1152 auto ptr = codec_manager->GetCodecConfig(
1153 {.audio_context_type = context},
1154 [&](const CodecManager::UnicastConfigurationRequirements& requirements,
1155 const set_configurations::AudioSetConfigurations* confs)
1156 -> const set_configurations::AudioSetConfiguration* {
1157 if (confs == nullptr) {
1158 got_null_cfgs_container = true;
1159 } else {
1160 num_of_dual_bidir_swb_configs += std::count_if(
1161 confs->begin(), confs->end(), [&](auto const& cfg) {
1162 bool is_bidir =
1163 codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1164 return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1165 });
1166 }
1167 // In this case the chosen configuration doesn't matter - select none
1168 return nullptr;
1169 });
1170 ASSERT_FALSE(got_null_cfgs_container);
1171 }
1172
1173 // Make sure some dual bidir SWB configs were returned
1174 ASSERT_NE(0, num_of_dual_bidir_swb_configs);
1175 }
1176
TEST_F(CodecManagerTestHostNoSwb,test_dual_bidir_swb_not_supported)1177 TEST_F(CodecManagerTestHostNoSwb, test_dual_bidir_swb_not_supported) {
1178 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1179 offloading_preference = {
1180 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1181 codec_manager->Start(offloading_preference);
1182
1183 int num_of_dual_bidir_swb_configs = 0;
1184 for (auto context : types::kLeAudioContextAllTypesArray) {
1185 bool got_null_cfgs_container = false;
1186 auto ptr = codec_manager->GetCodecConfig(
1187 {.audio_context_type = context},
1188 [&](const CodecManager::UnicastConfigurationRequirements& requirements,
1189 const set_configurations::AudioSetConfigurations* confs)
1190 -> const set_configurations::AudioSetConfiguration* {
1191 if (confs == nullptr) {
1192 got_null_cfgs_container = true;
1193 } else {
1194 num_of_dual_bidir_swb_configs += std::count_if(
1195 confs->begin(), confs->end(), [&](auto const& cfg) {
1196 return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1197 });
1198 }
1199 // In this case the chosen configuration doesn't matter - select none
1200 return nullptr;
1201 });
1202 ASSERT_FALSE(got_null_cfgs_container);
1203 }
1204
1205 // Make sure no dual bidir SWB configs were returned
1206 ASSERT_EQ(0, num_of_dual_bidir_swb_configs);
1207 }
1208
TEST_F(CodecManagerTestAdspNoSwb,test_dual_bidir_swb_not_supported)1209 TEST_F(CodecManagerTestAdspNoSwb, test_dual_bidir_swb_not_supported) {
1210 // Set the offloader capabilities
1211 std::vector<AudioSetConfiguration> offload_capabilities = {
1212 {
1213 .name = "Test_Bidir_SWB_Config_No_Dev_lc3_32_2",
1214 .confs = {.sink = {set_configurations::AseConfiguration(lc3_32_2),
1215 set_configurations::AseConfiguration(lc3_32_2)},
1216 .source = {set_configurations::AseConfiguration(lc3_32_2),
1217 set_configurations::AseConfiguration(lc3_32_2)}},
1218 },
1219 {
1220 .name = "Test_Bidir_Non_SWB_Config_No_Dev_lc3_16_2",
1221 .confs = {.sink = {set_configurations::AseConfiguration(lc3_16_2),
1222 set_configurations::AseConfiguration(lc3_16_2)},
1223 .source = {set_configurations::AseConfiguration(lc3_16_2),
1224 set_configurations::AseConfiguration(lc3_16_2)}},
1225 }};
1226 set_mock_offload_capabilities(offload_capabilities);
1227
1228 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1229 offloading_preference = {
1230 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1231 codec_manager->Start(offloading_preference);
1232
1233 int num_of_dual_bidir_swb_configs = 0;
1234 for (auto context : types::kLeAudioContextAllTypesArray) {
1235 bool got_null_cfgs_container = false;
1236 auto ptr = codec_manager->GetCodecConfig(
1237 {.audio_context_type = context},
1238 [&](const CodecManager::UnicastConfigurationRequirements& requirements,
1239 const set_configurations::AudioSetConfigurations* confs)
1240 -> const set_configurations::AudioSetConfiguration* {
1241 if (confs == nullptr) {
1242 got_null_cfgs_container = true;
1243 } else {
1244 num_of_dual_bidir_swb_configs += std::count_if(
1245 confs->begin(), confs->end(), [&](auto const& cfg) {
1246 return codec_manager->CheckCodecConfigIsDualBiDirSwb(*cfg);
1247 });
1248 }
1249 // In this case the chosen configuration doesn't matter - select none
1250 return nullptr;
1251 });
1252 ASSERT_FALSE(got_null_cfgs_container);
1253 }
1254
1255 // Make sure no dual bidir SWB configs were returned
1256 ASSERT_EQ(0, num_of_dual_bidir_swb_configs);
1257 }
1258
TEST_F(CodecManagerTestHost,test_dont_update_broadcast_offloader)1259 TEST_F(CodecManagerTestHost, test_dont_update_broadcast_offloader) {
1260 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1261 offloading_preference = {
1262 {.codec_type = bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3}};
1263 codec_manager->Start(offloading_preference);
1264
1265 bool was_called = false;
1266 codec_manager->UpdateBroadcastConnHandle(
1267 {0x0001, 0x0002},
1268 [&](const bluetooth::le_audio::broadcast_offload_config& config) {
1269 was_called = true;
1270 });
1271
1272 // Expect no call for HOST encoding
1273 ASSERT_FALSE(was_called);
1274 }
1275
1276 } // namespace bluetooth::le_audio
1277