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 = &caps;
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