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