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