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