• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "devices.h"
19 
20 #include <bluetooth/log.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24 
25 #include "btif_storage_mock.h"
26 #include "btm_api_mock.h"
27 #include "device_groups.h"
28 #include "hardware/bt_le_audio.h"
29 #include "hci/controller_interface_mock.h"
30 #include "le_audio/le_audio_utils.h"
31 #include "le_audio_set_configuration_provider.h"
32 #include "le_audio_types.h"
33 #include "mock_codec_manager.h"
34 #include "mock_csis_client.h"
35 #include "stack/btm/btm_int_types.h"
36 #include "test/mock/mock_main_shim_entry.h"
37 
BTM_Sec_GetAddressWithType(const RawAddress & bd_addr)38 const tBLE_BD_ADDR BTM_Sec_GetAddressWithType(const RawAddress& bd_addr) {
39   return tBLE_BD_ADDR{.type = BLE_ADDR_PUBLIC, .bda = bd_addr};
40 }
41 
42 namespace bluetooth {
43 namespace le_audio {
44 namespace internal {
45 namespace {
46 
47 using ::bluetooth::le_audio::DeviceConnectState;
48 using ::bluetooth::le_audio::LeAudioDevice;
49 using ::bluetooth::le_audio::LeAudioDeviceGroup;
50 using ::bluetooth::le_audio::LeAudioDevices;
51 using ::bluetooth::le_audio::types::AseState;
52 using ::bluetooth::le_audio::types::AudioContexts;
53 using ::bluetooth::le_audio::types::AudioLocations;
54 using ::bluetooth::le_audio::types::BidirectionalPair;
55 using ::bluetooth::le_audio::types::CisType;
56 using ::bluetooth::le_audio::types::LeAudioContextType;
57 using testing::_;
58 using testing::Invoke;
59 using testing::NiceMock;
60 using testing::Return;
61 using testing::Test;
62 
63 auto constexpr kVendorCodecIdOne = bluetooth::le_audio::types::LeAudioCodecId(
64         {.coding_format = types::kLeAudioCodingFormatVendorSpecific,
65          .vendor_company_id = 0xF00D,
66          .vendor_codec_id = 0x0001});
67 
68 types::CodecConfigSetting kVendorCodecOne = {
69         .id = kVendorCodecIdOne,
70         .params = types::LeAudioLtvMap({
71                 // Add the Sampling Freq and AudioChannelAllocation which are
72                 // mandatory even for the Vendor codec provider (multicodec AIDL)
73                 {codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
74                  UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq16000Hz)},
75         }),
76         // Some opaque data buffer
77         .vendor_params = std::vector<uint8_t>({0x01, 0xC0, 0xDE, 0xF0, 0x0D}),
78         .channel_count_per_iso_stream = 1,
79 };
80 
81 types::CodecConfigSetting kVendorCodecOneSwb = {
82         .id = kVendorCodecIdOne,
83         .params = types::LeAudioLtvMap({
84                 // Add the Sampling Freq and AudioChannelAllocation which are
85                 // mandatory even for the Vendor codec provider (multicodec AIDL)
86                 {codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
87                  UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq32000Hz)},
88         }),
89         // Some opaque data buffer
90         .vendor_params = std::vector<uint8_t>({0x01, 0xC0, 0xDE, 0xF0, 0x0F}),
91         .channel_count_per_iso_stream = 1,
92 };
93 
GetTestAddress(int index)94 RawAddress GetTestAddress(int index) {
95   EXPECT_LT(index, UINT8_MAX);
96   RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
97   return result;
98 }
99 
100 class LeAudioDevicesTest : public Test {
101 protected:
SetUp()102   void SetUp() override {
103     __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
104     com::android::bluetooth::flags::provider_->reset_flags();
105     devices_ = new LeAudioDevices();
106     bluetooth::manager::SetMockBtmInterface(&btm_interface);
107     bluetooth::storage::SetMockBtifStorageInterface(&mock_btif_storage_);
108   }
109 
TearDown()110   void TearDown() override {
111     bluetooth::manager::SetMockBtmInterface(nullptr);
112     bluetooth::storage::SetMockBtifStorageInterface(nullptr);
113     delete devices_;
114   }
115 
116   LeAudioDevices* devices_ = nullptr;
117   bluetooth::manager::MockBtmInterface btm_interface;
118   bluetooth::storage::MockBtifStorageInterface mock_btif_storage_;
119 };
120 
TEST_F(LeAudioDevicesTest,test_add)121 TEST_F(LeAudioDevicesTest, test_add) {
122   RawAddress test_address_0 = GetTestAddress(0);
123   ASSERT_EQ((size_t)0, devices_->Size());
124   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
125   ASSERT_EQ((size_t)1, devices_->Size());
126   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 1);
127   ASSERT_EQ((size_t)2, devices_->Size());
128   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
129   ASSERT_EQ((size_t)2, devices_->Size());
130   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 2);
131   ASSERT_EQ((size_t)2, devices_->Size());
132 }
133 
TEST_F(LeAudioDevicesTest,test_remove)134 TEST_F(LeAudioDevicesTest, test_remove) {
135   RawAddress test_address_0 = GetTestAddress(0);
136   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
137   RawAddress test_address_1 = GetTestAddress(1);
138   devices_->Add(test_address_1, DeviceConnectState::CONNECTING_BY_USER);
139   RawAddress test_address_2 = GetTestAddress(2);
140   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
141   ASSERT_EQ((size_t)3, devices_->Size());
142   devices_->Remove(test_address_0);
143   ASSERT_EQ((size_t)2, devices_->Size());
144   devices_->Remove(GetTestAddress(3));
145   ASSERT_EQ((size_t)2, devices_->Size());
146   devices_->Remove(test_address_0);
147   ASSERT_EQ((size_t)2, devices_->Size());
148 }
149 
TEST_F(LeAudioDevicesTest,test_find_by_address_success)150 TEST_F(LeAudioDevicesTest, test_find_by_address_success) {
151   RawAddress test_address_0 = GetTestAddress(0);
152   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
153   RawAddress test_address_1 = GetTestAddress(1);
154   devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
155   RawAddress test_address_2 = GetTestAddress(2);
156   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
157   LeAudioDevice* device = devices_->FindByAddress(test_address_1);
158   ASSERT_NE(nullptr, device);
159   ASSERT_EQ(test_address_1, device->address_);
160 }
161 
TEST_F(LeAudioDevicesTest,test_find_by_address_failed)162 TEST_F(LeAudioDevicesTest, test_find_by_address_failed) {
163   RawAddress test_address_0 = GetTestAddress(0);
164   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
165   RawAddress test_address_2 = GetTestAddress(2);
166   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
167   LeAudioDevice* device = devices_->FindByAddress(GetTestAddress(1));
168   ASSERT_EQ(nullptr, device);
169 }
170 
TEST_F(LeAudioDevicesTest,test_get_by_address_success)171 TEST_F(LeAudioDevicesTest, test_get_by_address_success) {
172   RawAddress test_address_0 = GetTestAddress(0);
173   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
174   RawAddress test_address_1 = GetTestAddress(1);
175   devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
176   RawAddress test_address_2 = GetTestAddress(2);
177   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
178   std::shared_ptr<LeAudioDevice> device = devices_->GetByAddress(test_address_1);
179   ASSERT_NE(nullptr, device);
180   ASSERT_EQ(test_address_1, device->address_);
181 }
182 
TEST_F(LeAudioDevicesTest,test_get_by_address_failed)183 TEST_F(LeAudioDevicesTest, test_get_by_address_failed) {
184   RawAddress test_address_0 = GetTestAddress(0);
185   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
186   RawAddress test_address_2 = GetTestAddress(2);
187   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
188   std::shared_ptr<LeAudioDevice> device = devices_->GetByAddress(GetTestAddress(1));
189   ASSERT_EQ(nullptr, device);
190 }
191 
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_success)192 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_success) {
193   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
194   RawAddress test_address_0 = GetTestAddress(0);
195   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
196   devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
197   LeAudioDevice* device = devices_->FindByAddress(test_address_0);
198   device->conn_id_ = 0x0005;
199   ASSERT_EQ(device, devices_->FindByConnId(0x0005));
200 }
201 
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_failed)202 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_failed) {
203   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
204   devices_->Add(GetTestAddress(0), DeviceConnectState::CONNECTING_BY_USER);
205   devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
206   ASSERT_EQ(nullptr, devices_->FindByConnId(0x0006));
207 }
208 
TEST_F(LeAudioDevicesTest,test_get_device_model_name_success)209 TEST_F(LeAudioDevicesTest, test_get_device_model_name_success) {
210   RawAddress test_address_0 = GetTestAddress(0);
211   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
212   std::shared_ptr<LeAudioDevice> device = devices_->GetByAddress(test_address_0);
213   ASSERT_NE(nullptr, device);
214   device->model_name_ = "Test";
215   ON_CALL(mock_btif_storage_, GetRemoteDeviceProperty(_, _))
216           .WillByDefault(Return(BT_STATUS_SUCCESS));
217   device->GetDeviceModelName();
218   ASSERT_EQ("", device->model_name_);
219 }
220 
TEST_F(LeAudioDevicesTest,test_get_device_model_name_failed)221 TEST_F(LeAudioDevicesTest, test_get_device_model_name_failed) {
222   RawAddress test_address_0 = GetTestAddress(0);
223   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
224   std::shared_ptr<LeAudioDevice> device = devices_->GetByAddress(test_address_0);
225   ASSERT_NE(nullptr, device);
226   device->model_name_ = "Test";
227   ON_CALL(mock_btif_storage_, GetRemoteDeviceProperty(_, _)).WillByDefault(Return(BT_STATUS_FAIL));
228   device->GetDeviceModelName();
229   ASSERT_EQ("Test", device->model_name_);
230 }
231 
232 /* TODO: Add FindByCisConnHdl test cases (ASE) */
233 
234 }  // namespace
235 
236 namespace {
237 using namespace ::bluetooth::le_audio::codec_spec_caps;
238 using namespace ::bluetooth::le_audio::types;
239 
240 static const hdl_pair hdl_pair_nil = hdl_pair(0x0000, 0x0000);
241 
242 enum class Lc3SettingId {
243   _BEGIN,
244   LC3_8_1 = _BEGIN,
245   LC3_8_2,
246   LC3_16_1,
247   LC3_16_2,
248   LC3_24_1,
249   LC3_24_2,
250   LC3_32_1,
251   LC3_32_2,
252   LC3_441_1,
253   LC3_441_2,
254   LC3_48_1,
255   LC3_48_2,
256   LC3_48_3,
257   LC3_48_4,
258   LC3_48_5,
259   LC3_48_6,
260   LC3_VND_1,
261   _END,
262   UNSUPPORTED = _END,
263 };
264 static constexpr int Lc3SettingIdBegin = static_cast<int>(Lc3SettingId::_BEGIN);
265 static constexpr int Lc3SettingIdEnd = static_cast<int>(Lc3SettingId::_END);
266 
IsLc3SettingSupported(LeAudioContextType context_type,Lc3SettingId id)267 bool IsLc3SettingSupported(LeAudioContextType context_type, Lc3SettingId id) {
268   /* Update those values, on any change of codec linked with content type */
269   switch (context_type) {
270     case LeAudioContextType::RINGTONE:
271     case LeAudioContextType::CONVERSATIONAL:
272       if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
273           id == Lc3SettingId::LC3_24_1 || id == Lc3SettingId::LC3_24_2 ||
274           id == Lc3SettingId::LC3_32_1 || id == Lc3SettingId::LC3_32_2 ||
275           id == Lc3SettingId::LC3_48_1 || id == Lc3SettingId::LC3_48_2 ||
276           id == Lc3SettingId::LC3_48_3 || id == Lc3SettingId::LC3_48_4 ||
277           id == Lc3SettingId::LC3_VND_1) {
278         return true;
279       }
280 
281       break;
282 
283     case LeAudioContextType::MEDIA:
284     case LeAudioContextType::ALERTS:
285     case LeAudioContextType::INSTRUCTIONAL:
286     case LeAudioContextType::NOTIFICATIONS:
287     case LeAudioContextType::EMERGENCYALARM:
288     case LeAudioContextType::UNSPECIFIED:
289       if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
290           id == Lc3SettingId::LC3_48_4 || id == Lc3SettingId::LC3_48_1 ||
291           id == Lc3SettingId::LC3_48_2 || id == Lc3SettingId::LC3_VND_1 ||
292           id == Lc3SettingId::LC3_24_2) {
293         return true;
294       }
295 
296       break;
297 
298     default:
299       if (id == Lc3SettingId::LC3_16_2) {
300         return true;
301       }
302 
303       break;
304   };
305 
306   return false;
307 }
308 
309 static constexpr uint8_t kLeAudioSamplingFreqRfu = 0x0E;
GetSamplingFrequency(Lc3SettingId id)310 uint8_t GetSamplingFrequency(Lc3SettingId id) {
311   switch (id) {
312     case Lc3SettingId::LC3_8_1:
313     case Lc3SettingId::LC3_8_2:
314       return codec_spec_conf::kLeAudioSamplingFreq8000Hz;
315     case Lc3SettingId::LC3_16_1:
316     case Lc3SettingId::LC3_16_2:
317       return codec_spec_conf::kLeAudioSamplingFreq16000Hz;
318     case Lc3SettingId::LC3_24_1:
319     case Lc3SettingId::LC3_24_2:
320       return codec_spec_conf::kLeAudioSamplingFreq24000Hz;
321     case Lc3SettingId::LC3_32_1:
322     case Lc3SettingId::LC3_32_2:
323       return codec_spec_conf::kLeAudioSamplingFreq32000Hz;
324     case Lc3SettingId::LC3_441_1:
325     case Lc3SettingId::LC3_441_2:
326       return codec_spec_conf::kLeAudioSamplingFreq44100Hz;
327     case Lc3SettingId::LC3_48_1:
328     case Lc3SettingId::LC3_48_2:
329     case Lc3SettingId::LC3_48_3:
330     case Lc3SettingId::LC3_48_4:
331     case Lc3SettingId::LC3_48_5:
332     case Lc3SettingId::LC3_48_6:
333     case Lc3SettingId::LC3_VND_1:
334       return codec_spec_conf::kLeAudioSamplingFreq48000Hz;
335     case Lc3SettingId::UNSUPPORTED:
336       return kLeAudioSamplingFreqRfu;
337   }
338 }
339 
340 static constexpr uint8_t kLeAudioCodecFrameDurRfu = 0x02;
GetFrameDuration(Lc3SettingId id)341 uint8_t GetFrameDuration(Lc3SettingId id) {
342   switch (id) {
343     case Lc3SettingId::LC3_8_1:
344     case Lc3SettingId::LC3_16_1:
345     case Lc3SettingId::LC3_24_1:
346     case Lc3SettingId::LC3_32_1:
347     case Lc3SettingId::LC3_441_1:
348     case Lc3SettingId::LC3_48_1:
349     case Lc3SettingId::LC3_48_3:
350     case Lc3SettingId::LC3_48_5:
351       return codec_spec_conf::kLeAudioCodecFrameDur7500us;
352     case Lc3SettingId::LC3_8_2:
353     case Lc3SettingId::LC3_16_2:
354     case Lc3SettingId::LC3_24_2:
355     case Lc3SettingId::LC3_32_2:
356     case Lc3SettingId::LC3_441_2:
357     case Lc3SettingId::LC3_48_2:
358     case Lc3SettingId::LC3_48_4:
359     case Lc3SettingId::LC3_48_6:
360     case Lc3SettingId::LC3_VND_1:
361       return codec_spec_conf::kLeAudioCodecFrameDur10000us;
362     case Lc3SettingId::UNSUPPORTED:
363       return kLeAudioCodecFrameDurRfu;
364   }
365 }
366 
367 static constexpr uint8_t kLeAudioCodecLC3OctetsPerCodecFrameInvalid = 0;
GetOctetsPerCodecFrame(Lc3SettingId id)368 uint16_t GetOctetsPerCodecFrame(Lc3SettingId id) {
369   switch (id) {
370     case Lc3SettingId::LC3_8_1:
371       return 26;
372     case Lc3SettingId::LC3_8_2:
373     case Lc3SettingId::LC3_16_1:
374       return 30;
375     case Lc3SettingId::LC3_16_2:
376       return 40;
377     case Lc3SettingId::LC3_24_1:
378       return 45;
379     case Lc3SettingId::LC3_24_2:
380     case Lc3SettingId::LC3_32_1:
381       return 60;
382     case Lc3SettingId::LC3_32_2:
383       return 80;
384     case Lc3SettingId::LC3_441_1:
385       return 97;
386     case Lc3SettingId::LC3_441_2:
387       return 130;
388     case Lc3SettingId::LC3_48_1:
389       return 75;
390     case Lc3SettingId::LC3_48_2:
391     case Lc3SettingId::LC3_VND_1:
392       return 100;
393     case Lc3SettingId::LC3_48_3:
394       return 90;
395     case Lc3SettingId::LC3_48_4:
396       return 120;
397     case Lc3SettingId::LC3_48_5:
398       return 116;
399     case Lc3SettingId::LC3_48_6:
400       return 155;
401     case Lc3SettingId::UNSUPPORTED:
402       return kLeAudioCodecLC3OctetsPerCodecFrameInvalid;
403   }
404 }
405 
406 class PublishedAudioCapabilitiesBuilder {
407 public:
PublishedAudioCapabilitiesBuilder()408   PublishedAudioCapabilitiesBuilder() {}
409 
Add(LeAudioCodecId codec_id,uint8_t conf_sampling_frequency,uint8_t conf_frame_duration,uint8_t audio_channel_counts,uint16_t octets_per_frame,uint8_t codec_frames_per_sdu=0)410   void Add(LeAudioCodecId codec_id, uint8_t conf_sampling_frequency, uint8_t conf_frame_duration,
411            uint8_t audio_channel_counts, uint16_t octets_per_frame,
412            uint8_t codec_frames_per_sdu = 0) {
413     uint16_t sampling_frequencies = SamplingFreqConfig2Capability(conf_sampling_frequency);
414     uint8_t frame_durations = FrameDurationConfig2Capability(conf_frame_duration);
415     uint8_t max_codec_frames_per_sdu = codec_frames_per_sdu;
416     uint32_t octets_per_frame_range = octets_per_frame | (octets_per_frame << 16);
417 
418     auto ltv_map = LeAudioLtvMap();
419     ltv_map.Add(kLeAudioLtvTypeSupportedSamplingFrequencies, (uint16_t)sampling_frequencies)
420             .Add(kLeAudioLtvTypeSupportedFrameDurations, (uint8_t)frame_durations)
421             .Add(kLeAudioLtvTypeSupportedAudioChannelCounts, (uint8_t)audio_channel_counts)
422             .Add(kLeAudioLtvTypeSupportedOctetsPerCodecFrame, (uint32_t)octets_per_frame_range)
423             .Add(kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu, (uint8_t)max_codec_frames_per_sdu);
424 
425     auto record = acs_ac_record(
426             {.codec_id = codec_id,
427              .codec_spec_caps = (codec_id.coding_format != kLeAudioCodingFormatVendorSpecific
428                                          ? ltv_map
429                                          : LeAudioLtvMap()),
430              .codec_spec_caps_raw = ltv_map.RawPacket(),
431              .metadata = LeAudioLtvMap()});
432     pac_records_.push_back(record);
433   }
434 
Add(LeAudioCodecId codec_id,uint16_t capa_sampling_frequency,uint8_t capa_frame_duration,uint8_t audio_channel_counts,uint16_t octets_per_frame_min,uint16_t ocets_per_frame_max,uint8_t codec_frames_per_sdu=1)435   void Add(LeAudioCodecId codec_id, uint16_t capa_sampling_frequency, uint8_t capa_frame_duration,
436            uint8_t audio_channel_counts, uint16_t octets_per_frame_min,
437            uint16_t ocets_per_frame_max, uint8_t codec_frames_per_sdu = 1) {
438     uint32_t octets_per_frame_range = octets_per_frame_min | (ocets_per_frame_max << 16);
439 
440     auto ltv_map = LeAudioLtvMap({
441             {kLeAudioLtvTypeSupportedSamplingFrequencies,
442              UINT16_TO_VEC_UINT8(capa_sampling_frequency)},
443             {kLeAudioLtvTypeSupportedFrameDurations, UINT8_TO_VEC_UINT8(capa_frame_duration)},
444             {kLeAudioLtvTypeSupportedAudioChannelCounts, UINT8_TO_VEC_UINT8(audio_channel_counts)},
445             {kLeAudioLtvTypeSupportedOctetsPerCodecFrame,
446              UINT32_TO_VEC_UINT8(octets_per_frame_range)},
447             {kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu,
448              UINT8_TO_VEC_UINT8(codec_frames_per_sdu)},
449     });
450     pac_records_.push_back(
451             acs_ac_record({.codec_id = codec_id,
452                            // Transparent LTV map capabilities only for the LC3 codec
453                            .codec_spec_caps = (codec_id.coding_format == kLeAudioCodingFormatLC3)
454                                                       ? ltv_map
455                                                       : LeAudioLtvMap(),
456                            .codec_spec_caps_raw = ltv_map.RawPacket(),
457                            .metadata = LeAudioLtvMap()}));
458   }
459 
Add(LeAudioCodecId codec_id,const std::vector<uint8_t> & vendor_data,uint8_t audio_channel_counts)460   void Add(LeAudioCodecId codec_id, const std::vector<uint8_t>& vendor_data,
461            uint8_t audio_channel_counts) {
462     pac_records_.push_back(
463             acs_ac_record({.codec_id = codec_id,
464                            .codec_spec_caps = LeAudioLtvMap({
465                                    {kLeAudioLtvTypeSupportedAudioChannelCounts,
466                                     UINT8_TO_VEC_UINT8(audio_channel_counts)},
467                            }),
468                            // For now assume that vendor representation of codec capabilities
469                            // equals the representation of codec settings
470                            .codec_spec_caps_raw = vendor_data,
471                            .metadata = LeAudioLtvMap()}));
472   }
473 
Add(const CodecConfigSetting & setting,uint8_t audio_channel_counts)474   void Add(const CodecConfigSetting& setting, uint8_t audio_channel_counts) {
475     if (setting.id != LeAudioCodecIdLc3) {
476       Add(setting.id, setting.vendor_params, audio_channel_counts);
477       return;
478     }
479 
480     const LeAudioCoreCodecConfig core_config = setting.params.GetAsCoreCodecConfig();
481     Add(setting.id, *core_config.sampling_frequency, *core_config.frame_duration,
482         audio_channel_counts, *core_config.octets_per_codec_frame);
483   }
484 
Reset()485   void Reset() { pac_records_.clear(); }
486 
Get()487   PublishedAudioCapabilities Get() {
488     return PublishedAudioCapabilities({{hdl_pair_nil, pac_records_}});
489   }
490 
491 private:
492   std::vector<acs_ac_record> pac_records_;
493 };
494 
495 struct TestGroupAseConfigurationData {
496   LeAudioDevice* device;
497   uint8_t audio_channel_counts_snk;
498   uint8_t audio_channel_counts_src;
499 
500   /* Note, do not confuse ASEs with channels num. */
501   uint8_t expected_active_channel_num_snk;
502   uint8_t expected_active_channel_num_src;
503 };
504 
505 class LeAudioAseConfigurationTest : public Test, public ::testing::WithParamInterface<uint16_t> {
506 protected:
507   uint16_t codec_coding_format_ = 0x0000;
508 
SetUp()509   void SetUp() override {
510     __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
511     codec_coding_format_ = GetParam();
512 
513     group_ = new LeAudioDeviceGroup(group_id_);
514     desired_group_size_ = -1;
515 
516     bluetooth::manager::SetMockBtmInterface(&btm_interface_);
517 
518     bluetooth::hci::testing::mock_controller_ =
519             std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
520 
521     auto codec_location = ::bluetooth::le_audio::types::CodecLocation::HOST;
522     bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(codec_location);
523     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
524     ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_));
525     ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
526     ON_CALL(mock_csis_client_module_, GetDeviceList(_))
527             .WillByDefault(Invoke([this](int /*group_id*/) { return addresses_; }));
528     ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
529             .WillByDefault(Invoke([this](int /*group_id*/) {
530               return desired_group_size_ > 0 ? desired_group_size_ : (int)(addresses_.size());
531             }));
532     SetUpMockCodecManager(codec_location);
533   }
534 
GetVendorAseConfigurationsForRequirements(const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements & requirements,const CodecConfigSetting & codec,uint8_t direction)535   static std::vector<AseConfiguration> GetVendorAseConfigurationsForRequirements(
536           const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements& requirements,
537           const CodecConfigSetting& codec, uint8_t direction) {
538     std::vector<AseConfiguration> ase_confs;
539 
540     auto const& required_pacs = (direction == kLeAudioDirectionSink) ? requirements.sink_pacs
541                                                                      : requirements.source_pacs;
542     auto direction_requirements = (direction == kLeAudioDirectionSink)
543                                           ? requirements.sink_requirements
544                                           : requirements.source_requirements;
545 
546     if (std::count_if(required_pacs->begin(), required_pacs->end(),
547                       [](auto const& pac) { return pac.codec_spec_caps_raw.empty(); })) {
548       return ase_confs;
549     }
550 
551     if (!required_pacs.has_value() || (required_pacs->size() == 0)) {
552       return ase_confs;
553     }
554 
555     AseConfiguration endpoint_cfg(codec, {.target_latency = kTargetLatencyLower,
556                                           .retransmission_number = 3,
557                                           .max_transport_latency = kMaxTransportLatencyMin});
558 
559     // Finding the max channel count
560     uint32_t target_max_channel_counts_per_ase_bitmap = 0b1;  // bit 0 - one channel
561     for (auto const& pac : *required_pacs) {
562       auto caps = pac.codec_spec_caps.GetAsCoreCodecCapabilities();
563       if (caps.HasSupportedAudioChannelCounts()) {
564         auto new_counts = caps.supported_audio_channel_counts.value();
565         if (new_counts > target_max_channel_counts_per_ase_bitmap) {
566           target_max_channel_counts_per_ase_bitmap = new_counts;
567         }
568       }
569     }
570 
571     uint8_t target_max_channel_counts_per_ase = 0;
572     while (target_max_channel_counts_per_ase_bitmap) {
573       ++target_max_channel_counts_per_ase;
574       target_max_channel_counts_per_ase_bitmap = target_max_channel_counts_per_ase_bitmap >> 1;
575     }
576 
577     // For sink we always put a requirement here, but for source there are
578     // some conditions
579     auto sourceAsesNeeded =
580             (!kLeAudioContextAllRemoteSinkOnly.test(requirements.audio_context_type) ||
581              (requirements.audio_context_type == LeAudioContextType::RINGTONE)) &&
582             (requirements.audio_context_type != types::LeAudioContextType::UNSPECIFIED);
583     if ((direction == kLeAudioDirectionSink) || sourceAsesNeeded) {
584       // Create ASE configurations with the proper audio channel allocation
585       uint8_t count = 0;
586       uint32_t allocations = 0;
587       for (auto const& req : *direction_requirements) {
588         auto req_allocations = VEC_UINT8_TO_UINT32(
589                 req.params.At(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation));
590 
591         // Create the list of requested audio allocations
592         std::list<uint32_t> split_allocations;
593         uint8_t bit_pos = 0;
594         while (req_allocations) {
595           if (req_allocations & 0b1) {
596             split_allocations.push_back(1 << bit_pos);
597           }
598           req_allocations = req_allocations >> 1;
599           bit_pos++;
600         }
601 
602         if (split_allocations.empty()) {
603           // Add a single ASE mono configuration
604           endpoint_cfg.codec.params.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
605                                         (uint32_t)codec_spec_conf::kLeAudioLocationMonoAudio);
606           ase_confs.push_back(endpoint_cfg);
607           continue;
608         }
609 
610         // Pick a number of allocations from the list (depending on supported
611         // channel counts per ASE) and create an ASE configuration.
612         while (split_allocations.size()) {
613           auto num_of_allocations_per_ase =
614                   std::min(target_max_channel_counts_per_ase, (uint8_t)split_allocations.size());
615           // Note: This is very important to set for the unit test
616           // Configuration provider
617           endpoint_cfg.codec.channel_count_per_iso_stream = num_of_allocations_per_ase;
618 
619           // Consume the `num_of_allocations_per_ase` amount of allocations for
620           // this particular ASE
621           uint32_t ase_allocations = 0;
622           while (num_of_allocations_per_ase) {
623             ase_allocations |= split_allocations.front();
624             split_allocations.pop_front();
625             --num_of_allocations_per_ase;
626           }
627           endpoint_cfg.codec.params.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
628                                         ase_allocations);
629 
630           // Add the ASE configuration
631           ase_confs.push_back(endpoint_cfg);
632         }
633       }
634     }
635 
636     return ase_confs;
637   }
638 
MockVendorCodecProvider(const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements & requirements)639   static auto MockVendorCodecProvider(
640           const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements& requirements) {
641     AudioSetConfiguration cfg = {
642             .name = "Example Vendor Codec Configuration",
643             .packing = bluetooth::hci::kIsoCigPackingSequential,
644             .confs = {.sink = {}, .source = {}},
645     };
646 
647     CodecConfigSetting codec =
648             bluetooth::le_audio::CodecManager::GetInstance()->IsDualBiDirSwbSupported()
649                     ? kVendorCodecOneSwb
650                     : kVendorCodecOne;
651     if (requirements.sink_requirements) {
652       cfg.confs.sink =
653               GetVendorAseConfigurationsForRequirements(requirements, codec, kLeAudioDirectionSink);
654     }
655 
656     if (requirements.source_requirements) {
657       cfg.confs.source = GetVendorAseConfigurationsForRequirements(requirements, codec,
658                                                                    kLeAudioDirectionSource);
659     }
660 
661     log::debug("{}: snk confs size: {}", cfg.name, cfg.confs.sink.size());
662     log::debug("{}: src confs size: {}", cfg.name, cfg.confs.source.size());
663     return (!cfg.confs.sink.empty() || !cfg.confs.source.empty())
664                    ? std::make_unique<AudioSetConfiguration>(cfg)
665                    : nullptr;
666   }
667 
SetUpMockCodecManager(bluetooth::le_audio::types::CodecLocation location)668   void SetUpMockCodecManager(bluetooth::le_audio::types::CodecLocation location) {
669     codec_manager_ = bluetooth::le_audio::CodecManager::GetInstance();
670     ASSERT_NE(codec_manager_, nullptr);
671     std::vector<bluetooth::le_audio::btle_audio_codec_config_t> mock_offloading_preference(0);
672     codec_manager_->Start(mock_offloading_preference);
673     mock_codec_manager_ = MockCodecManager::GetInstance();
674     ASSERT_NE((void*)mock_codec_manager_, (void*)codec_manager_);
675     ASSERT_NE(mock_codec_manager_, nullptr);
676     ON_CALL(*mock_codec_manager_, GetCodecLocation()).WillByDefault(Return(location));
677 
678     // Set up the config provider for the Lc3 codec
679     if (codec_coding_format_ == kLeAudioCodingFormatLC3) {
680       // Regardless of the codec location, return all the possible
681       // configurations
682       ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
683     }
684 
685     ON_CALL(*mock_codec_manager_, GetCodecConfig)
686             .WillByDefault(Invoke(
687                     [&](const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&
688                                 requirements,
689                         bluetooth::le_audio::CodecManager::UnicastConfigurationProvider provider) {
690                       if (codec_coding_format_ == kLeAudioCodingFormatLC3) {
691                         auto filtered =
692                                 *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
693                                          ->GetConfigurations(requirements.audio_context_type);
694                         // Filter out the dual bidir SWB configurations
695                         if (!bluetooth::le_audio::CodecManager::GetInstance()
696                                      ->IsDualBiDirSwbSupported()) {
697                           filtered.erase(
698                                   std::remove_if(filtered.begin(), filtered.end(),
699                                                  [](auto const& el) {
700                                                    if (el->confs.source.empty()) {
701                                                      return false;
702                                                    }
703                                                    return AudioSetConfigurationProvider::Get()
704                                                            ->CheckConfigurationIsDualBiDirSwb(*el);
705                                                  }),
706                                   filtered.end());
707                         }
708                         auto cfg = provider(requirements, &filtered);
709                         if (cfg == nullptr) {
710                           return std::unique_ptr<AudioSetConfiguration>(nullptr);
711                         }
712                         return std::make_unique<AudioSetConfiguration>(*cfg);
713                       } else {
714                         return MockVendorCodecProvider(requirements);
715                       }
716                     }));
717 
718     ON_CALL(*mock_codec_manager_, CheckCodecConfigIsBiDirSwb)
719             .WillByDefault(
720                     Invoke([](const bluetooth::le_audio::types::AudioSetConfiguration& config) {
721                       return AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb(
722                               config);
723                     }));
724     ON_CALL(*mock_codec_manager_, CheckCodecConfigIsDualBiDirSwb)
725             .WillByDefault(
726                     Invoke([](const bluetooth::le_audio::types::AudioSetConfiguration& config) {
727                       return AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb(
728                               config);
729                     }));
730   }
731 
TearDown()732   void TearDown() override {
733     bluetooth::manager::SetMockBtmInterface(nullptr);
734     devices_.clear();
735     addresses_.clear();
736     delete group_;
737     ::bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
738 
739     if (mock_codec_manager_) {
740       testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
741     }
742     if (codec_manager_) {
743       codec_manager_->Stop();
744     }
745 
746     bluetooth::hci::testing::mock_controller_.reset();
747   }
748 
AddTestDevice(int snk_ase_num,int src_ase_num,int snk_ase_num_cached=0,int src_ase_num_cached=0,bool invert_ases_emplacement=false,bool out_of_range_device=false,std::optional<uint32_t> snk_allocation=kChannelAllocationStereo,std::optional<uint32_t> src_allocation=kChannelAllocationStereo)749   LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num, int snk_ase_num_cached = 0,
750                                int src_ase_num_cached = 0, bool invert_ases_emplacement = false,
751                                bool out_of_range_device = false,
752                                std::optional<uint32_t> snk_allocation = kChannelAllocationStereo,
753                                std::optional<uint32_t> src_allocation = kChannelAllocationStereo) {
754     int index = group_->Size() + 1;
755     auto device = (std::make_shared<LeAudioDevice>(GetTestAddress(index),
756                                                    DeviceConnectState::DISCONNECTED));
757     devices_.push_back(device);
758     addresses_.push_back(device->address_);
759     log::info("Number of devices {}", (int)(addresses_.size()));
760 
761     if (out_of_range_device == false) {
762       group_->AddNode(device);
763     }
764 
765     int ase_id = 1;
766     for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num : src_ase_num); i++) {
767       device->ases_.emplace_back(
768               0x0000, 0x0000,
769               invert_ases_emplacement ? kLeAudioDirectionSink : kLeAudioDirectionSource, ase_id++);
770     }
771 
772     for (int i = 0; i < (invert_ases_emplacement ? src_ase_num : snk_ase_num); i++) {
773       device->ases_.emplace_back(
774               0x0000, 0x0000,
775               invert_ases_emplacement ? kLeAudioDirectionSource : kLeAudioDirectionSink, ase_id++);
776     }
777 
778     for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num_cached : src_ase_num_cached); i++) {
779       struct ase ase(0x0000, 0x0000,
780                      invert_ases_emplacement ? kLeAudioDirectionSink : kLeAudioDirectionSource,
781                      ase_id++);
782       ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
783       device->ases_.push_back(ase);
784     }
785 
786     for (int i = 0; i < (invert_ases_emplacement ? src_ase_num_cached : snk_ase_num_cached); i++) {
787       struct ase ase(0x0000, 0x0000,
788                      invert_ases_emplacement ? kLeAudioDirectionSource : kLeAudioDirectionSink,
789                      ase_id++);
790       ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
791       device->ases_.push_back(ase);
792     }
793 
794     device->SetSupportedContexts({.sink = AudioContexts(kLeAudioContextAllTypes),
795                                   .source = AudioContexts(kLeAudioContextAllTypes)});
796     device->SetAvailableContexts({.sink = AudioContexts(kLeAudioContextAllTypes),
797                                   .source = AudioContexts(kLeAudioContextAllTypes)});
798 
799     if (snk_allocation) {
800       device->audio_locations_.sink.emplace(hdl_pair(0x00ea, 0x0eb),
801                                             types::AudioLocations(snk_allocation.value()));
802     }
803 
804     if (src_allocation) {
805       device->audio_locations_.source.emplace(hdl_pair(0x00fa, 0x00fb),
806                                               types::AudioLocations(src_allocation.value()));
807     }
808 
809     device->conn_id_ = index;
810     device->SetConnectionState(out_of_range_device ? DeviceConnectState::DISCONNECTED
811                                                    : DeviceConnectState::CONNECTED);
812     group_->ReloadAudioDirections();
813     group_->ReloadAudioLocations();
814     return device.get();
815   }
816 
AddTestDevice(std::optional<std::pair<int,uint32_t>> sink,std::optional<std::pair<int,uint32_t>> source=std::nullopt)817   LeAudioDevice* AddTestDevice(std::optional<std::pair<int, uint32_t>> sink,
818                                std::optional<std::pair<int, uint32_t>> source = std::nullopt) {
819     return AddTestDevice(sink ? sink->first : 0, source ? source->first : 0, 0, 0, false, false,
820                          sink ? sink->second : 0, source ? source->second : 0);
821   }
822 
TestGroupAseConfigurationVerdict(const TestGroupAseConfigurationData & data,uint8_t directions_to_verify)823   bool TestGroupAseConfigurationVerdict(const TestGroupAseConfigurationData& data,
824                                         uint8_t directions_to_verify) {
825     BidirectionalPair<uint8_t> active_channel_num = {0, 0};
826 
827     if (directions_to_verify == 0) {
828       return false;
829     }
830     if (data.device->HaveActiveAse() == 0) {
831       return false;
832     }
833 
834     for (ase* ase = data.device->GetFirstActiveAse(); ase;
835          ase = data.device->GetNextActiveAse(ase)) {
836       active_channel_num.get(ase->direction) += ase->codec_config.channel_count_per_iso_stream;
837     }
838 
839     bool result = true;
840     if (directions_to_verify & kLeAudioDirectionSink) {
841       result &= (data.expected_active_channel_num_snk ==
842                  active_channel_num.get(kLeAudioDirectionSink));
843     }
844     if (directions_to_verify & kLeAudioDirectionSource) {
845       result &= (data.expected_active_channel_num_src ==
846                  active_channel_num.get(kLeAudioDirectionSource));
847     }
848     return result;
849   }
850 
SetCisInformationToActiveAse(void)851   void SetCisInformationToActiveAse(void) {
852     uint8_t cis_id = 1;
853     uint16_t cis_conn_hdl = 0x0060;
854 
855     for (auto& device : devices_) {
856       for (auto& ase : device->ases_) {
857         if (ase.active) {
858           ase.cis_id = cis_id++;
859           ase.cis_conn_hdl = cis_conn_hdl++;
860         }
861       }
862     }
863   }
864 
PreparePreferredCodecConfig(const CodecConfigSetting & audio_set_codec_conf,const btle_audio_codec_config_t & preferred_config)865   const CodecConfigSetting PreparePreferredCodecConfig(
866           const CodecConfigSetting& audio_set_codec_conf,
867           const btle_audio_codec_config_t& preferred_config) {
868     constexpr uint8_t supported_codec_frames_per_sdu = 1;
869     return {.id = LeAudioCodecIdLc3,
870             .params = LeAudioLtvMap({
871                     {codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
872                      UINT8_TO_VEC_UINT8(codec_spec_conf::SingleSamplingFreqCapability2Config(
873                              preferred_config.sample_rate))},
874                     {codec_spec_conf::kLeAudioLtvTypeFrameDuration,
875                      UINT8_TO_VEC_UINT8(codec_spec_conf::SingleFrameDurationCapability2Config(
876                              preferred_config.frame_duration))},
877                     {codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
878                      UINT16_TO_VEC_UINT8(preferred_config.octets_per_frame)},
879                     {codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
880                      UINT8_TO_VEC_UINT8(supported_codec_frames_per_sdu)},
881             }),
882             .channel_count_per_iso_stream = audio_set_codec_conf.GetChannelCountPerIsoStream()};
883   }
884 
TestSingleAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,const AudioSetConfiguration * audio_set_conf,uint8_t directions_to_verify)885   void TestSingleAseConfiguration(LeAudioContextType context_type,
886                                   TestGroupAseConfigurationData* data, uint8_t data_size,
887                                   const AudioSetConfiguration* audio_set_conf,
888                                   uint8_t directions_to_verify) {
889     // the configuration should fail if there are no active ases expected
890     bool success_expected = data_size > 0;
891     uint8_t configuration_directions = 0;
892 
893     for (int i = 0; i < data_size; i++) {
894       success_expected &= (data[i].expected_active_channel_num_snk +
895                            data[i].expected_active_channel_num_src) > 0;
896 
897       /* Prepare PAC's */
898       PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
899       for (const auto& entry : (*audio_set_conf).confs.sink) {
900         configuration_directions |= kLeAudioDirectionSink;
901         snk_pac_builder.Add(entry.codec, data[i].audio_channel_counts_snk);
902       }
903       for (const auto& entry : (*audio_set_conf).confs.source) {
904         configuration_directions |= kLeAudioDirectionSource;
905         src_pac_builder.Add(entry.codec, data[i].audio_channel_counts_src);
906       }
907 
908       data[i].device->snk_pacs_ = snk_pac_builder.Get();
909       data[i].device->src_pacs_ = src_pac_builder.Get();
910     }
911 
912     BidirectionalPair<AudioContexts> group_audio_locations = {
913             .sink = AudioContexts(context_type), .source = AudioContexts(context_type)};
914 
915     ASSERT_EQ(success_expected, group_->Configure(context_type, group_audio_locations));
916 
917     bool result = true;
918     for (int i = 0; i < data_size; i++) {
919       result &= TestGroupAseConfigurationVerdict(data[i],
920                                                  directions_to_verify & configuration_directions);
921     }
922     ASSERT_TRUE(result);
923   }
924 
getNumOfAses(LeAudioDevice * device,uint8_t direction)925   int getNumOfAses(LeAudioDevice* device, uint8_t direction) {
926     return std::count_if(device->ases_.begin(), device->ases_.end(),
927                          [direction](auto& a) { return a.direction == direction; });
928   }
929 
TestGroupAseVendorConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,uint8_t directions_to_verify=kLeAudioDirectionSink|kLeAudioDirectionSource)930   void TestGroupAseVendorConfiguration(LeAudioContextType context_type,
931                                        TestGroupAseConfigurationData* data, uint8_t data_size,
932                                        uint8_t directions_to_verify = kLeAudioDirectionSink |
933                                                                       kLeAudioDirectionSource) {
934     for (int i = 0; i < data_size; i++) {
935       /* Add PACs and check if each of the devices has activated ASEs as
936        * expected */
937       PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
938 
939       // Prepare the PACs
940       for (auto direction : {kLeAudioDirectionSink, kLeAudioDirectionSource}) {
941         auto const& data_channel_counts = (direction == kLeAudioDirectionSink)
942                                                   ? data[i].audio_channel_counts_snk
943                                                   : data[i].audio_channel_counts_src;
944 
945         PublishedAudioCapabilitiesBuilder pac_builder;
946         for (auto codec : {kVendorCodecOne, kVendorCodecOneSwb}) {
947           codec.channel_count_per_iso_stream = data_channel_counts;
948           pac_builder.Add(codec, data_channel_counts);
949         }
950 
951         // Set the PACs
952         auto& dest_pacs = (direction == kLeAudioDirectionSink) ? data[i].device->snk_pacs_
953                                                                : data[i].device->src_pacs_;
954         dest_pacs = pac_builder.Get();
955       }
956     }
957 
958     // Verify if ASEs are configured
959     BidirectionalPair<AudioContexts> metadata = {.sink = AudioContexts(context_type),
960                                                  .source = AudioContexts(context_type)};
961     ASSERT_EQ(true, group_->Configure(context_type, metadata));
962 
963     for (int i = 0; i < data_size; i++) {
964       ASSERT_TRUE(TestGroupAseConfigurationVerdict(data[i], directions_to_verify));
965     }
966 
967     group_->Deactivate();
968     TestAsesInactive();
969   }
970 
TestGroupAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,uint8_t directions_to_verify=kLeAudioDirectionSink|kLeAudioDirectionSource,btle_audio_codec_config_t * preferred_codec_config=nullptr,bool should_use_preferred_codec=false)971   void TestGroupAseConfiguration(LeAudioContextType context_type,
972                                  TestGroupAseConfigurationData* data, uint8_t data_size,
973                                  uint8_t directions_to_verify = kLeAudioDirectionSink |
974                                                                 kLeAudioDirectionSource,
975                                  btle_audio_codec_config_t* preferred_codec_config = nullptr,
976                                  bool should_use_preferred_codec = false) {
977     if (codec_coding_format_ != kLeAudioCodingFormatLC3) {
978       return TestGroupAseVendorConfiguration(context_type, data, data_size, directions_to_verify);
979     }
980 
981     const auto* configurations =
982             ::bluetooth::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
983                     context_type);
984 
985     bool is_expected_to_match_config = directions_to_verify != 0;
986     int num_of_matching_configurations = 0;
987     for (const auto& audio_set_conf : *configurations) {
988       bool interesting_configuration = true;
989       uint8_t expected_configuration_directions = 0;
990 
991       /* Let's go thru devices in the group and configure them*/
992       for (int i = 0; i < data_size; i++) {
993         BidirectionalPair<int> num_of_ase{0, 0};
994 
995         /* Prepare PAC's for each device. Also make sure configuration is in our
996          * interest to test */
997         for (auto direction : {kLeAudioDirectionSink, kLeAudioDirectionSource}) {
998           auto const& ase_confs = audio_set_conf->confs;
999           if (ase_confs.get(direction).size() == 0) {
1000             // Skip the direction if not available
1001             continue;
1002           }
1003 
1004           /* Make sure the strategy is the expected one */
1005           auto ase_config_strategy = bluetooth::le_audio::utils::GetStrategyForAseConfig(
1006                   ase_confs.get(direction), data_size);
1007           if (group_->GetGroupSinkStrategy() != ase_config_strategy) {
1008             log::debug("Sink strategy mismatch group!=cfg.entry ({}!={})",
1009                        static_cast<int>(group_->GetGroupSinkStrategy()),
1010                        static_cast<int>(ase_config_strategy));
1011             interesting_configuration = false;
1012           }
1013 
1014           auto& dest_pacs = (direction == kLeAudioDirectionSink) ? data[i].device->snk_pacs_
1015                                                                  : data[i].device->src_pacs_;
1016           auto const& pacs_data_channel_counts = (direction == kLeAudioDirectionSink)
1017                                                          ? data[i].audio_channel_counts_snk
1018                                                          : data[i].audio_channel_counts_src;
1019 
1020           if (((direction == kLeAudioDirectionSink)
1021                        ? data[i].expected_active_channel_num_snk
1022                        : data[i].expected_active_channel_num_src) > 0) {
1023             expected_configuration_directions |= direction;
1024           }
1025 
1026           /* Add PAC records */
1027           PublishedAudioCapabilitiesBuilder pac_builder;
1028           for (const auto& entry : ase_confs.get(direction)) {
1029             pac_builder.Add(entry.codec, pacs_data_channel_counts);
1030             if (preferred_codec_config && should_use_preferred_codec) {
1031               const auto customized_codec_config =
1032                       PreparePreferredCodecConfig(entry.codec, *preferred_codec_config);
1033               pac_builder.Add(customized_codec_config, pacs_data_channel_counts);
1034             }
1035             dest_pacs = pac_builder.Get();
1036           }
1037           num_of_ase.get(direction) += ase_confs.get(direction).size();
1038           num_of_ase.get(direction) /= data_size;
1039         }
1040 
1041         /* Make sure configuration can satisfy number of expected active ASEs*/
1042         if (num_of_ase.sink > data[i].device->GetAseCount(kLeAudioDirectionSink)) {
1043           interesting_configuration = false;
1044         }
1045 
1046         if (num_of_ase.source > data[i].device->GetAseCount(kLeAudioDirectionSource)) {
1047           interesting_configuration = false;
1048         }
1049       }
1050 
1051       /* Set preferred codec*/
1052       if (preferred_codec_config) {
1053         group_->SetPreferredAudioSetConfiguration(*preferred_codec_config, *preferred_codec_config);
1054       }
1055 
1056       group_->UpdateAudioSetConfigurationCache(context_type);
1057 
1058       BidirectionalPair<AudioContexts> group_audio_locations = {
1059               .sink = AudioContexts(context_type), .source = AudioContexts(context_type)};
1060       auto configuration_result = group_->Configure(context_type, group_audio_locations);
1061 
1062       /* In case of configuration #ase is same as the one we expected to be
1063        * activated verify, ASEs are actually active */
1064       uint8_t configuration_directions =
1065               (audio_set_conf->confs.sink.size() ? kLeAudioDirectionSink : 0) |
1066               (audio_set_conf->confs.source.size() ? kLeAudioDirectionSource : 0);
1067 
1068       if (interesting_configuration &&
1069           (expected_configuration_directions == configuration_directions)) {
1070         ASSERT_TRUE(configuration_result);
1071         ASSERT_EQ(group_->GetPreferredConfiguration(context_type) != nullptr,
1072                   should_use_preferred_codec);
1073         ASSERT_EQ(group_->IsUsingPreferredAudioSetConfiguration(context_type),
1074                   should_use_preferred_codec);
1075         bool matching_conf = true;
1076         /* Check if each of the devices has activated ASEs as expected */
1077         for (int i = 0; i < data_size; i++) {
1078           matching_conf &= TestGroupAseConfigurationVerdict(data[i], configuration_directions);
1079         }
1080 
1081         if (matching_conf) {
1082           num_of_matching_configurations++;
1083         }
1084       }
1085       group_->Deactivate();
1086 
1087       TestAsesInactive();
1088     }
1089 
1090     if (is_expected_to_match_config) {
1091       ASSERT_GT(num_of_matching_configurations, 0);
1092     } else {
1093       ASSERT_EQ(0, num_of_matching_configurations);
1094     }
1095   }
1096 
TestGroupAseConfiguration(LeAudioContextType context_type,std::vector<TestGroupAseConfigurationData> data,uint8_t directions_to_verify=kLeAudioDirectionSink|kLeAudioDirectionSource,btle_audio_codec_config_t * preferred_codec_config=nullptr,bool should_use_preferred_codec=false)1097   auto TestGroupAseConfiguration(LeAudioContextType context_type,
1098                                  std::vector<TestGroupAseConfigurationData> data,
1099                                  uint8_t directions_to_verify = kLeAudioDirectionSink |
1100                                                                 kLeAudioDirectionSource,
1101                                  btle_audio_codec_config_t* preferred_codec_config = nullptr,
1102                                  bool should_use_preferred_codec = false) {
1103     return TestGroupAseConfiguration(context_type, data.data(), data.size(), directions_to_verify,
1104                                      preferred_codec_config, should_use_preferred_codec);
1105   }
1106 
TestAsesActive(LeAudioCodecId codec_id,uint8_t sampling_frequency,uint8_t frame_duration,uint16_t octets_per_frame,uint8_t codec_frame_blocks_per_sdu=1)1107   void TestAsesActive(LeAudioCodecId codec_id, uint8_t sampling_frequency, uint8_t frame_duration,
1108                       uint16_t octets_per_frame, uint8_t codec_frame_blocks_per_sdu = 1) {
1109     bool active_ase = false;
1110 
1111     for (const auto& device : devices_) {
1112       for (const auto& ase : device->ases_) {
1113         if (!ase.active) {
1114           continue;
1115         }
1116 
1117         /* Configure may request only partial ases to be activated */
1118         if (!active_ase && ase.active) {
1119           active_ase = true;
1120         }
1121 
1122         ASSERT_EQ(ase.codec_config.id, codec_id);
1123 
1124         /* FIXME: Validate other codec parameters than LC3 if any */
1125         ASSERT_EQ(ase.codec_config.id, LeAudioCodecIdLc3);
1126         if (ase.codec_config.id == LeAudioCodecIdLc3) {
1127           auto core_config = ase.codec_config.params.GetAsCoreCodecConfig();
1128           ASSERT_EQ(core_config.sampling_frequency, sampling_frequency);
1129           ASSERT_EQ(core_config.frame_duration, frame_duration);
1130           ASSERT_EQ(core_config.octets_per_codec_frame, octets_per_frame);
1131           ASSERT_EQ(core_config.codec_frames_blocks_per_sdu.value_or(0),
1132                     codec_frame_blocks_per_sdu);
1133         }
1134       }
1135     }
1136 
1137     ASSERT_TRUE(active_ase);
1138   }
1139 
TestActiveAses(void)1140   void TestActiveAses(void) {
1141     for (auto& device : devices_) {
1142       for (const auto& ase : device->ases_) {
1143         if (ase.active) {
1144           ASSERT_FALSE(ase.cis_id == ::bluetooth::le_audio::kInvalidCisId);
1145         }
1146       }
1147     }
1148   }
1149 
TestAsesInactivated(const LeAudioDevice * device)1150   void TestAsesInactivated(const LeAudioDevice* device) {
1151     for (const auto& ase : device->ases_) {
1152       ASSERT_FALSE(ase.active);
1153       ASSERT_TRUE(ase.cis_id == ::bluetooth::le_audio::kInvalidCisId);
1154       ASSERT_TRUE(ase.cis_conn_hdl == ::bluetooth::le_audio::kInvalidCisConnHandle);
1155     }
1156   }
1157 
TestAsesInactive()1158   void TestAsesInactive() {
1159     for (const auto& device : devices_) {
1160       for (const auto& ase : device->ases_) {
1161         ASSERT_FALSE(ase.active);
1162       }
1163     }
1164   }
1165 
TestLc3CodecConfig(LeAudioContextType context_type,uint8_t max_codec_frames_per_sdu=1)1166   void TestLc3CodecConfig(LeAudioContextType context_type, uint8_t max_codec_frames_per_sdu = 1) {
1167     for (int i = Lc3SettingIdBegin; i < Lc3SettingIdEnd; i++) {
1168       // test each configuration parameter against valid and invalid value
1169       std::array<Lc3SettingId, 2> test_variants = {static_cast<Lc3SettingId>(i),
1170                                                    Lc3SettingId::UNSUPPORTED};
1171 
1172       const bool is_lc3_setting_supported =
1173               IsLc3SettingSupported(context_type, static_cast<Lc3SettingId>(i));
1174 
1175       for (const auto sf_variant : test_variants) {
1176         uint8_t sampling_frequency = GetSamplingFrequency(sf_variant);
1177         for (const auto fd_variant : test_variants) {
1178           uint8_t frame_duration = GetFrameDuration(fd_variant);
1179           for (const auto opcf_variant : test_variants) {
1180             uint16_t octets_per_frame = GetOctetsPerCodecFrame(opcf_variant);
1181 
1182             PublishedAudioCapabilitiesBuilder pac_builder;
1183             pac_builder.Add(
1184                     LeAudioCodecIdLc3, sampling_frequency, frame_duration,
1185                     kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1186                     octets_per_frame, max_codec_frames_per_sdu);
1187             for (auto& device : devices_) {
1188               /* For simplicity configure both PACs with the same
1189               parameters*/
1190               device->snk_pacs_ = pac_builder.Get();
1191               device->src_pacs_ = pac_builder.Get();
1192             }
1193 
1194             bool success_expected = is_lc3_setting_supported;
1195             if (is_lc3_setting_supported && (sf_variant == Lc3SettingId::UNSUPPORTED ||
1196                                              fd_variant == Lc3SettingId::UNSUPPORTED ||
1197                                              opcf_variant == Lc3SettingId::UNSUPPORTED)) {
1198               success_expected = false;
1199             }
1200 
1201             group_->UpdateAudioSetConfigurationCache(context_type);
1202             BidirectionalPair<AudioContexts> group_audio_locations = {
1203                     .sink = AudioContexts(context_type), .source = AudioContexts(context_type)};
1204             ASSERT_EQ(success_expected, group_->Configure(context_type, group_audio_locations));
1205             if (success_expected) {
1206               TestAsesActive(LeAudioCodecIdLc3, sampling_frequency, frame_duration,
1207                              octets_per_frame, max_codec_frames_per_sdu);
1208               group_->Deactivate();
1209             }
1210 
1211             TestAsesInactive();
1212           }
1213         }
1214       }
1215     }
1216   }
1217 
TestSingleDevDualBidir(LeAudioDevice * device,LeAudioContextType context_type)1218   void TestSingleDevDualBidir(LeAudioDevice* device, LeAudioContextType context_type) {
1219     // Build PACs for device
1220     PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
1221     snk_pac_builder.Reset();
1222     src_pac_builder.Reset();
1223 
1224     const uint32_t supported_octets_per_codec_frame_80 = 80;
1225     const uint32_t supported_octets_per_codec_frame_40 = 40;
1226     const uint32_t supported_codec_frames_per_sdu = 1;
1227     CodecConfigSetting swb = {
1228             .id = LeAudioCodecIdLc3,
1229             .params = LeAudioLtvMap({
1230                     {codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
1231                      UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq32000Hz)},
1232                     {codec_spec_conf::kLeAudioLtvTypeFrameDuration,
1233                      UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioCodecFrameDur10000us)},
1234                     {codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
1235                      UINT16_TO_VEC_UINT8(supported_octets_per_codec_frame_80)},
1236                     {codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
1237                      UINT8_TO_VEC_UINT8(supported_codec_frames_per_sdu)},
1238             }),
1239             .channel_count_per_iso_stream = 1};
1240 
1241     auto swb_config = AudioSetConfiguration({
1242             .name = "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_SWB",
1243             .confs = {.sink = {AseConfiguration(swb), AseConfiguration(swb)},
1244                       .source = {AseConfiguration(swb), AseConfiguration(swb)}},
1245     });
1246 
1247     auto swb_config_single = AudioSetConfiguration({
1248             .name = "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_SWB",
1249             .confs = {.sink =
1250                               {
1251                                       AseConfiguration(swb),
1252                               },
1253                       .source =
1254                               {
1255                                       AseConfiguration(swb),
1256                               }},
1257     });
1258 
1259     ASSERT_FALSE(swb.params.IsEmpty());
1260     ASSERT_TRUE(swb.params.Find(codec_spec_conf::kLeAudioLtvTypeSamplingFreq).has_value());
1261 
1262     CodecConfigSetting non_swb = {
1263             .id = LeAudioCodecIdLc3,
1264             .params = LeAudioLtvMap({
1265                     {codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
1266                      UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioSamplingFreq16000Hz)},
1267                     {codec_spec_conf::kLeAudioLtvTypeFrameDuration,
1268                      UINT8_TO_VEC_UINT8(codec_spec_conf::kLeAudioCodecFrameDur10000us)},
1269                     {codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
1270                      UINT16_TO_VEC_UINT8(supported_octets_per_codec_frame_40)},
1271                     {codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
1272                      UINT8_TO_VEC_UINT8(supported_codec_frames_per_sdu)},
1273             }),
1274             .channel_count_per_iso_stream = 1};
1275     auto non_swb_config = AudioSetConfiguration({
1276             .name = "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_NON_SWB",
1277             .confs = {.sink = {AseConfiguration(non_swb), AseConfiguration(non_swb)},
1278                       .source = {AseConfiguration(non_swb), AseConfiguration(non_swb)}},
1279     });
1280     auto non_swb_config_single = AudioSetConfiguration({
1281             .name = "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_NON_SWB",
1282             .confs = {.sink = {AseConfiguration(non_swb)}, .source = {AseConfiguration(non_swb)}},
1283     });
1284     AudioSetConfigurations configs = {
1285             {&swb_config, &swb_config_single, &non_swb_config, &non_swb_config_single}};
1286 
1287     // Support single channel per ASE to activate two ASES on both direction
1288     for (auto config : configs) {
1289       for (const auto& entry : config->confs.sink) {
1290         snk_pac_builder.Add(entry.codec, kLeAudioCodecChannelCountSingleChannel);
1291       }
1292       for (const auto& entry : config->confs.source) {
1293         src_pac_builder.Add(entry.codec, kLeAudioCodecChannelCountSingleChannel);
1294       }
1295     }
1296 
1297     // Inject `configs` as there's no such config in the json file
1298     ON_CALL(*mock_codec_manager_, GetCodecConfig)
1299             .WillByDefault(Invoke([&configs](const bluetooth::le_audio::CodecManager::
1300                                                      UnicastConfigurationRequirements& requirements,
1301                                              bluetooth::le_audio::CodecManager::
1302                                                      UnicastConfigurationProvider provider) {
1303               auto filtered = configs;
1304               // Filter out the dual bidir SWB configurations
1305               if (!bluetooth::le_audio::CodecManager::GetInstance()->IsDualBiDirSwbSupported()) {
1306                 filtered.erase(std::remove_if(filtered.begin(), filtered.end(),
1307                                               [](auto const& el) {
1308                                                 if (el->confs.source.empty()) {
1309                                                   return false;
1310                                                 }
1311                                                 return AudioSetConfigurationProvider::Get()
1312                                                         ->CheckConfigurationIsDualBiDirSwb(*el);
1313                                               }),
1314                                filtered.end());
1315               }
1316               auto cfg = provider(requirements, &filtered);
1317               if (cfg == nullptr) {
1318                 return std::unique_ptr<AudioSetConfiguration>(nullptr);
1319               }
1320               return std::make_unique<AudioSetConfiguration>(*cfg);
1321             }));
1322 
1323     // Make two ASES available in both directions with equal capabilities
1324     device->snk_pacs_ = snk_pac_builder.Get();
1325     device->src_pacs_ = src_pac_builder.Get();
1326 
1327     ASSERT_TRUE(group_->Configure(context_type, {.sink = AudioContexts(context_type),
1328                                                  .source = AudioContexts(context_type)}));
1329 
1330     // Verify Dual-Bidir - the amount of ASES configured
1331     TestGroupAseConfigurationData data[] = {{device, kLeAudioCodecChannelCountSingleChannel,
1332                                              kLeAudioCodecChannelCountSingleChannel, 2, 2}};
1333     TestGroupAseConfigurationVerdict(data[0], kLeAudioDirectionSink | kLeAudioDirectionSource);
1334   }
1335 
1336   /* Helper */
getSpecificConfiguration(const char * config_name,LeAudioContextType context)1337   static const AudioSetConfiguration* getSpecificConfiguration(const char* config_name,
1338                                                                LeAudioContextType context) {
1339     auto all_configurations =
1340             ::bluetooth::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(context);
1341 
1342     if (all_configurations == nullptr) {
1343       return nullptr;
1344     }
1345     if (all_configurations->end() == all_configurations->begin()) {
1346       return nullptr;
1347     }
1348 
1349     auto iter = std::find_if(
1350             all_configurations->begin(), all_configurations->end(),
1351             [config_name](auto& configuration) { return configuration->name == config_name; });
1352     if (iter == all_configurations->end()) {
1353       return nullptr;
1354     }
1355     return *iter;
1356   }
1357 
TestDualDevDualBidir(LeAudioDevice * left,LeAudioDevice * right,LeAudioContextType context_type)1358   void TestDualDevDualBidir(LeAudioDevice* left, LeAudioDevice* right,
1359                             LeAudioContextType context_type) {
1360     // Build PACs for device
1361     PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
1362     snk_pac_builder.Reset();
1363     src_pac_builder.Reset();
1364 
1365     /* Create PACs for conversational scenario, SWB and non SWB */
1366     for (auto config :
1367          {getSpecificConfiguration("Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
1368                                    context_type),
1369           getSpecificConfiguration("Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
1370                                    context_type)}) {
1371       ASSERT_NE(nullptr, config);
1372       for (const auto& entry : (*config).confs.sink) {
1373         snk_pac_builder.Add(entry.codec, kLeAudioCodecChannelCountSingleChannel);
1374       }
1375       for (const auto& entry : (*config).confs.source) {
1376         src_pac_builder.Add(entry.codec, kLeAudioCodecChannelCountSingleChannel);
1377       }
1378     }
1379 
1380     // Add pacs for remote to support the configs above
1381     for (auto& dev : {left, right}) {
1382       dev->snk_pacs_ = snk_pac_builder.Get();
1383       dev->src_pacs_ = src_pac_builder.Get();
1384     }
1385 
1386     /* Change location as by default it is stereo */
1387     left->audio_locations_.sink->value = codec_spec_conf::kLeAudioLocationFrontLeft;
1388     left->audio_locations_.source->value = codec_spec_conf::kLeAudioLocationFrontLeft;
1389     right->audio_locations_.sink->value = codec_spec_conf::kLeAudioLocationFrontRight;
1390     right->audio_locations_.source->value = codec_spec_conf::kLeAudioLocationFrontRight;
1391     group_->ReloadAudioLocations();
1392 
1393     ASSERT_TRUE(group_->Configure(context_type, {.sink = AudioContexts(context_type),
1394                                                  .source = AudioContexts(context_type)}));
1395 
1396     // Verify the amount of ASES configured
1397     TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1398                                              kLeAudioCodecChannelCountSingleChannel, 1, 1},
1399                                             {right, kLeAudioCodecChannelCountSingleChannel,
1400                                              kLeAudioCodecChannelCountSingleChannel, 1, 1}};
1401     TestGroupAseConfigurationVerdict(data[0], kLeAudioDirectionSink | kLeAudioDirectionSource);
1402     TestGroupAseConfigurationVerdict(data[1], kLeAudioDirectionSink | kLeAudioDirectionSource);
1403   }
1404 
SetAsesToCachedConfiguration(LeAudioDevice * device,LeAudioContextType context_type,uint8_t directions)1405   void SetAsesToCachedConfiguration(LeAudioDevice* device, LeAudioContextType context_type,
1406                                     uint8_t directions) {
1407     for (struct ase& ase : device->ases_) {
1408       if (ase.direction & directions) {
1409         ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
1410         ase.active = false;
1411         ase.configured_for_context_type = context_type;
1412       }
1413     }
1414   }
1415 
1416   const int group_id_ = 6;
1417   int desired_group_size_ = -1;
1418 
1419   std::vector<std::shared_ptr<LeAudioDevice>> devices_;
1420   std::vector<RawAddress> addresses_;
1421   LeAudioDeviceGroup* group_ = nullptr;
1422   bluetooth::manager::MockBtmInterface btm_interface_;
1423   MockCsisClient mock_csis_client_module_;
1424 
1425   bluetooth::le_audio::CodecManager* codec_manager_;
1426   MockCodecManager* mock_codec_manager_;
1427 };
1428 
TEST_P(LeAudioAseConfigurationTest,test_context_update)1429 TEST_P(LeAudioAseConfigurationTest, test_context_update) {
1430   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1431                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1432   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1433                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1434 
1435   ASSERT_EQ(2, group_->Size());
1436 
1437   /* Put the PACS */
1438   auto conversational_configuration = getSpecificConfiguration(
1439           "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
1440           LeAudioContextType::CONVERSATIONAL);
1441   auto media_configuration = getSpecificConfiguration(
1442           "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", LeAudioContextType::MEDIA);
1443   ASSERT_NE(nullptr, conversational_configuration);
1444   ASSERT_NE(nullptr, media_configuration);
1445 
1446   /* Create PACs for conversational and media scenarios */
1447   PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
1448   for (auto const& cfg : {conversational_configuration, media_configuration}) {
1449     for (const auto& entry : cfg->confs.sink) {
1450       snk_pac_builder.Add(entry.codec, 1);
1451     }
1452     for (const auto& entry : cfg->confs.source) {
1453       src_pac_builder.Add(entry.codec, 1);
1454     }
1455   }
1456   left->snk_pacs_ = snk_pac_builder.Get();
1457   left->src_pacs_ = src_pac_builder.Get();
1458   right->snk_pacs_ = snk_pac_builder.Get();
1459   right->src_pacs_ = src_pac_builder.Get();
1460 
1461   /* UNSPECIFIED must be supported, MEDIA is on the remote sink only... */
1462   auto remote_snk_supp_contexts =
1463           AudioContexts(LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL |
1464                         LeAudioContextType::SOUNDEFFECTS | LeAudioContextType::UNSPECIFIED);
1465   auto remote_src_supp_contexts =
1466           AudioContexts(LeAudioContextType::CONVERSATIONAL | LeAudioContextType::UNSPECIFIED);
1467 
1468   left->SetSupportedContexts(
1469           {.sink = remote_snk_supp_contexts, .source = remote_src_supp_contexts});
1470 
1471   auto right_bud_only_context = LeAudioContextType::ALERTS;
1472   right->SetSupportedContexts({.sink = remote_snk_supp_contexts | right_bud_only_context,
1473                                .source = remote_src_supp_contexts | right_bud_only_context});
1474 
1475   /* ...but UNSPECIFIED and SOUNDEFFECTS are unavailable */
1476   auto remote_snk_avail_contexts =
1477           AudioContexts(LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL);
1478   auto remote_src_avail_contexts = AudioContexts(LeAudioContextType::CONVERSATIONAL);
1479 
1480   left->SetAvailableContexts(
1481           {.sink = remote_snk_avail_contexts, .source = remote_src_avail_contexts});
1482   ASSERT_EQ(left->GetAvailableContexts(), remote_snk_avail_contexts | remote_src_avail_contexts);
1483 
1484   // Make an additional context available on the right earbud sink
1485   right->SetAvailableContexts({.sink = remote_snk_avail_contexts | right_bud_only_context,
1486                                .source = remote_src_avail_contexts});
1487   ASSERT_EQ(right->GetAvailableContexts(),
1488             remote_snk_avail_contexts | remote_src_avail_contexts | right_bud_only_context);
1489 
1490   /* Now add the right earbud contexts - mind the extra context on that bud */
1491   ASSERT_NE(group_->GetAvailableContexts(), left->GetAvailableContexts());
1492   ASSERT_EQ(group_->GetAvailableContexts(),
1493             left->GetAvailableContexts() | right->GetAvailableContexts());
1494 
1495   /* Since no device is being added or removed from the group this should not
1496    * change the configuration set.
1497    */
1498   ASSERT_EQ(group_->GetAvailableContexts(),
1499             left->GetAvailableContexts() | right->GetAvailableContexts());
1500 
1501   /* MEDIA Available on remote sink direction only */
1502   auto config = group_->GetConfiguration(LeAudioContextType::MEDIA);
1503   ASSERT_NE(nullptr, config);
1504   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1505   ASSERT_FALSE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1506   ASSERT_EQ(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink)
1507                     .at(0)
1508                     .codec.GetChannelCountPerIsoStream(),
1509             ::bluetooth::le_audio::LeAudioCodecConfiguration::kChannelNumberMono);
1510 
1511   /* CONVERSATIONAL Available on both directions */
1512   config = group_->GetConfiguration(LeAudioContextType::CONVERSATIONAL);
1513   ASSERT_NE(nullptr, config);
1514   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1515   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1516 
1517   /* UNSPECIFIED Unavailable yet supported */
1518   config = group_->GetConfiguration(LeAudioContextType::UNSPECIFIED);
1519   ASSERT_NE(nullptr, config);
1520   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1521   ASSERT_FALSE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1522 
1523   /* SOUNDEFFECTS Unavailable yet supported on sink only */
1524   config = group_->GetConfiguration(LeAudioContextType::SOUNDEFFECTS);
1525   ASSERT_NE(nullptr, config);
1526   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1527   ASSERT_FALSE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1528 
1529   /* INSTRUCTIONAL Unavailable and not supported, while UNSPECIFIED not
1530    * available */
1531   config = group_->GetConfiguration(LeAudioContextType::INSTRUCTIONAL);
1532   ASSERT_NE(nullptr, config);
1533   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1534   ASSERT_FALSE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1535 
1536   /* ALERTS on sink only */
1537   config = group_->GetConfiguration(LeAudioContextType::ALERTS);
1538   ASSERT_NE(nullptr, config);
1539   ASSERT_TRUE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink).size());
1540   ASSERT_FALSE(config->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSource).size());
1541 
1542   /* We should get the config for ALERTS for both channels as the other has
1543    * UNSPECIFIED context supported.
1544    */
1545   auto sink_configs = group_->GetConfiguration(LeAudioContextType::ALERTS)
1546                               ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink);
1547   ASSERT_EQ(2lu, sink_configs.size());
1548   ASSERT_TRUE(group_->IsAudioSetConfigurationAvailable(LeAudioContextType::ALERTS));
1549 
1550   /* Turn off the ALERTS context */
1551   right->SetAvailableContexts(
1552           {.sink = right->GetAvailableContexts(
1553                            ::bluetooth::le_audio::types::kLeAudioDirectionSink) &
1554                    ~AudioContexts(LeAudioContextType::ALERTS),
1555            .source = right->GetAvailableContexts(
1556                    ::bluetooth::le_audio::types::kLeAudioDirectionSource)});
1557 
1558   /* Right one was changed but the config exist, just not available */
1559   ASSERT_EQ(group_->GetAvailableContexts(),
1560             left->GetAvailableContexts() | right->GetAvailableContexts());
1561   ASSERT_FALSE(group_->GetAvailableContexts().test(LeAudioContextType::ALERTS));
1562   ASSERT_TRUE(group_->GetConfiguration(LeAudioContextType::ALERTS)
1563                       ->confs.get(bluetooth::le_audio::types::kLeAudioDirectionSink)
1564                       .size());
1565   ASSERT_TRUE(group_->IsAudioSetConfigurationAvailable(LeAudioContextType::ALERTS));
1566 }
1567 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_ringtone_loc0)1568 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_ringtone_loc0) {
1569   /* mono location */
1570   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationMonoAudio}});
1571   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1572                                       kLeAudioCodecChannelCountSingleChannel, 1, 0});
1573 
1574   uint8_t direction_to_verify = kLeAudioDirectionSink;
1575 
1576   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1, direction_to_verify);
1577 }
1578 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_ringtone)1579 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_ringtone) {
1580   /* left only location */
1581   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1582   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1583                                       kLeAudioCodecChannelCountSingleChannel, 1, 0});
1584 
1585   uint8_t direction_to_verify = kLeAudioDirectionSink;
1586 
1587   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1, direction_to_verify);
1588 }
1589 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_conversational_loc0)1590 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_conversational_loc0) {
1591   /* mono location */
1592   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationMonoAudio}});
1593   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1594                                       kLeAudioCodecChannelCountNone, 1, 0});
1595 
1596   /* Microphone should be used on the phone */
1597   uint8_t direction_to_verify = kLeAudioDirectionSink;
1598   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1, direction_to_verify);
1599 }
1600 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_conversational)1601 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_conversational) {
1602   /* left only location */
1603   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1604   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1605                                       kLeAudioCodecChannelCountNone, 1, 0});
1606 
1607   /* Microphone should be used on the phone */
1608   uint8_t direction_to_verify = kLeAudioDirectionSink;
1609   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1, direction_to_verify);
1610 }
1611 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_media_loc0)1612 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_media_loc0) {
1613   /* mono location */
1614   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationMonoAudio}});
1615   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1616                                       kLeAudioCodecChannelCountNone, 1, 0});
1617 
1618   uint8_t direction_to_verify = kLeAudioDirectionSink;
1619   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1, direction_to_verify);
1620 }
1621 
TEST_P(LeAudioAseConfigurationTest,test_mono_speaker_media)1622 TEST_P(LeAudioAseConfigurationTest, test_mono_speaker_media) {
1623   /* left only location */
1624   LeAudioDevice* mono_speaker = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1625   TestGroupAseConfigurationData data({mono_speaker, kLeAudioCodecChannelCountSingleChannel,
1626                                       kLeAudioCodecChannelCountNone, 1, 0});
1627 
1628   uint8_t direction_to_verify = kLeAudioDirectionSink;
1629   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1, direction_to_verify);
1630 }
1631 
TEST_P(LeAudioAseConfigurationTest,test_banded_headphones_ringtone)1632 TEST_P(LeAudioAseConfigurationTest, test_banded_headphones_ringtone) {
1633   LeAudioDevice* banded_headphones = AddTestDevice(2, 0);
1634   TestGroupAseConfigurationData data({banded_headphones, kLeAudioCodecChannelCountTwoChannel,
1635                                       kLeAudioCodecChannelCountSingleChannel, 2, 0});
1636 
1637   uint8_t direction_to_verify = kLeAudioDirectionSink;
1638   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1, direction_to_verify);
1639 }
1640 
TEST_P(LeAudioAseConfigurationTest,test_banded_headphones_conversational)1641 TEST_P(LeAudioAseConfigurationTest, test_banded_headphones_conversational) {
1642   LeAudioDevice* banded_headphones = AddTestDevice(2, 0);
1643   TestGroupAseConfigurationData data({banded_headphones, kLeAudioCodecChannelCountTwoChannel,
1644                                       kLeAudioCodecChannelCountNone, 2, 0});
1645 
1646   uint8_t direction_to_verify = kLeAudioDirectionSink;
1647   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1, direction_to_verify);
1648 }
1649 
TEST_P(LeAudioAseConfigurationTest,test_banded_headphones_media)1650 TEST_P(LeAudioAseConfigurationTest, test_banded_headphones_media) {
1651   LeAudioDevice* banded_headphones = AddTestDevice(2, 0);
1652   TestGroupAseConfigurationData data({banded_headphones, kLeAudioCodecChannelCountTwoChannel,
1653                                       kLeAudioCodecChannelCountNone, 2, 0});
1654 
1655   uint8_t direction_to_verify = kLeAudioDirectionSink;
1656   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1, direction_to_verify);
1657 }
1658 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_ringtone_mono_microphone)1659 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_ringtone_mono_microphone) {
1660   /* mono source */
1661   LeAudioDevice* banded_headset = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationStereo}},
1662                                                 {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1663   TestGroupAseConfigurationData data({banded_headset, kLeAudioCodecChannelCountTwoChannel,
1664                                       kLeAudioCodecChannelCountSingleChannel, 2, 1});
1665 
1666   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1667 }
1668 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_ringtone_mono_microphone_loc0)1669 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_ringtone_mono_microphone_loc0) {
1670   /* mono source */
1671   LeAudioDevice* banded_headset = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationStereo}},
1672                                                 {{1, codec_spec_conf::kLeAudioLocationMonoAudio}});
1673   TestGroupAseConfigurationData data({banded_headset, kLeAudioCodecChannelCountTwoChannel,
1674                                       kLeAudioCodecChannelCountSingleChannel, 2, 1});
1675 
1676   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1677 }
1678 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_ringtone_stereo_microphone)1679 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_ringtone_stereo_microphone) {
1680   LeAudioDevice* banded_headset = AddTestDevice(2, 2);
1681   TestGroupAseConfigurationData data(
1682           {banded_headset,
1683            kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1684            kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel, 2, 2});
1685 
1686   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1687 }
1688 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_conversational_stereo_microphone_no_swb)1689 TEST_P(LeAudioAseConfigurationTest, test_earbuds_conversational_stereo_microphone_no_swb) {
1690   // Turn off the dual bidir SWB support
1691   ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(false));
1692   ASSERT_FALSE(CodecManager::GetInstance()->IsDualBiDirSwbSupported());
1693 
1694   const auto context_type = LeAudioContextType::CONVERSATIONAL;
1695   TestDualDevDualBidir(AddTestDevice(1, 1), AddTestDevice(1, 1), context_type);
1696 
1697   // Verify non-SWB config was selected
1698   auto config = group_->GetCachedConfiguration(context_type).get();
1699   ASSERT_NE(nullptr, config);
1700   ASSERT_FALSE(CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config));
1701 }
1702 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_conversational_stereo_microphone_no_swb_one_bonded)1703 TEST_P(LeAudioAseConfigurationTest,
1704        test_earbuds_conversational_stereo_microphone_no_swb_one_bonded) {
1705   /* There will be 2 eabuds eventually but for the moment only 1 is bonded
1706    * Turn off the dual bidir SWB support
1707    */
1708   desired_group_size_ = 2;
1709   ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(false));
1710   ASSERT_FALSE(CodecManager::GetInstance()->IsDualBiDirSwbSupported());
1711 
1712   const auto context_type = LeAudioContextType::CONVERSATIONAL;
1713   TestSingleDevDualBidir(
1714           AddTestDevice(1, 1, 0, 0, false, false, codec_spec_conf::kLeAudioLocationFrontLeft,
1715                         codec_spec_conf::kLeAudioLocationFrontLeft),
1716           context_type);
1717 
1718   // Verify non-SWB config was selected
1719   auto config = group_->GetCachedConfiguration(context_type).get();
1720   ASSERT_NE(nullptr, config);
1721   ASSERT_FALSE(CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config));
1722   ASSERT_FALSE(CodecManager::GetInstance()->CheckCodecConfigIsBiDirSwb(*config));
1723 }
1724 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_conversational_stereo_microphone_swb)1725 TEST_P(LeAudioAseConfigurationTest, test_earbuds_conversational_stereo_microphone_swb) {
1726   // Turn on the dual bidir SWB support
1727   ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
1728   ASSERT_TRUE(CodecManager::GetInstance()->IsDualBiDirSwbSupported());
1729 
1730   const auto context_type = LeAudioContextType::CONVERSATIONAL;
1731   TestDualDevDualBidir(AddTestDevice(1, 1), AddTestDevice(1, 1), context_type);
1732 
1733   // Verify SWB config was selected
1734   auto config = group_->GetCachedConfiguration(context_type).get();
1735   ASSERT_NE(nullptr, config);
1736   ASSERT_TRUE(CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config));
1737 }
1738 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_ringtone_stereo_microphone_no_swb)1739 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_ringtone_stereo_microphone_no_swb) {
1740   // Turn off the dual bidir SWB support
1741   ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(false));
1742   ASSERT_FALSE(CodecManager::GetInstance()->IsDualBiDirSwbSupported());
1743 
1744   // Verify non-SWB config was selected
1745   auto context_type = LeAudioContextType::CONVERSATIONAL;
1746   TestSingleDevDualBidir(AddTestDevice(2, 2), context_type);
1747   auto config = group_->GetCachedConfiguration(context_type).get();
1748   ASSERT_NE(nullptr, config);
1749   ASSERT_FALSE(CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config));
1750 }
1751 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_ringtone_stereo_microphone_swb)1752 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_ringtone_stereo_microphone_swb) {
1753   // Turn on the dual bidir SWB support
1754   ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
1755   ASSERT_TRUE(CodecManager::GetInstance()->IsDualBiDirSwbSupported());
1756 
1757   // Verify SWB config was selected
1758   auto context_type = LeAudioContextType::CONVERSATIONAL;
1759   TestSingleDevDualBidir(AddTestDevice(2, 2), context_type);
1760   auto config = group_->GetCachedConfiguration(context_type).get();
1761   ASSERT_NE(nullptr, config);
1762   ASSERT_TRUE(CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*config));
1763 }
1764 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_conversational)1765 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_conversational) {
1766   LeAudioDevice* banded_headset = AddTestDevice(2, 1);
1767   TestGroupAseConfigurationData data({banded_headset, kLeAudioCodecChannelCountTwoChannel,
1768                                       kLeAudioCodecChannelCountSingleChannel, 2, 1});
1769 
1770   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1771 }
1772 
TEST_P(LeAudioAseConfigurationTest,test_banded_headset_media)1773 TEST_P(LeAudioAseConfigurationTest, test_banded_headset_media) {
1774   LeAudioDevice* banded_headset = AddTestDevice(2, 1);
1775   TestGroupAseConfigurationData data({banded_headset, kLeAudioCodecChannelCountTwoChannel,
1776                                       kLeAudioCodecChannelCountSingleChannel, 2, 0});
1777 
1778   uint8_t directions_to_verify = kLeAudioDirectionSink;
1779   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1, directions_to_verify);
1780 }
1781 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_ringtone)1782 TEST_P(LeAudioAseConfigurationTest, test_earbuds_ringtone) {
1783   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1784                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1785   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1786                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1787   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1788                                            kLeAudioCodecChannelCountSingleChannel, 1, 1},
1789                                           {right, kLeAudioCodecChannelCountSingleChannel,
1790                                            kLeAudioCodecChannelCountSingleChannel, 1, 1}};
1791 
1792   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, data, 2);
1793 }
1794 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_conversational)1795 TEST_P(LeAudioAseConfigurationTest, test_earbuds_conversational) {
1796   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1797                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1798   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1799                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1800   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1801                                            kLeAudioCodecChannelCountSingleChannel, 1, 1},
1802                                           {right, kLeAudioCodecChannelCountSingleChannel,
1803                                            kLeAudioCodecChannelCountSingleChannel, 1, 1}};
1804 
1805   group_->ReloadAudioLocations();
1806 
1807   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, data, 2);
1808 }
1809 
TEST_P(LeAudioAseConfigurationTest,test_earbuds_media)1810 TEST_P(LeAudioAseConfigurationTest, test_earbuds_media) {
1811   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1812                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1813   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1814                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1815   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1816                                            kLeAudioCodecChannelCountSingleChannel, 1, 0},
1817                                           {right, kLeAudioCodecChannelCountSingleChannel,
1818                                            kLeAudioCodecChannelCountSingleChannel, 1, 0}};
1819 
1820   uint8_t directions_to_verify = kLeAudioDirectionSink;
1821   TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, 2, directions_to_verify);
1822 }
1823 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_mono_ringtone)1824 TEST_P(LeAudioAseConfigurationTest, test_handsfree_mono_ringtone) {
1825   LeAudioDevice* handsfree = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1826                                            {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1827   TestGroupAseConfigurationData data({handsfree, kLeAudioCodecChannelCountSingleChannel,
1828                                       kLeAudioCodecChannelCountSingleChannel, 1, 1});
1829 
1830   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1831 }
1832 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_stereo_ringtone)1833 TEST_P(LeAudioAseConfigurationTest, test_handsfree_stereo_ringtone) {
1834   LeAudioDevice* handsfree = AddTestDevice({{1, kChannelAllocationStereo}},
1835                                            {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1836   TestGroupAseConfigurationData data(
1837           {handsfree, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1838            kLeAudioCodecChannelCountSingleChannel, 2, 1});
1839 
1840   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1841 }
1842 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_mono_conversational)1843 TEST_P(LeAudioAseConfigurationTest, test_handsfree_mono_conversational) {
1844   LeAudioDevice* handsfree = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1845                                            {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1846   TestGroupAseConfigurationData data({handsfree, kLeAudioCodecChannelCountSingleChannel,
1847                                       kLeAudioCodecChannelCountSingleChannel, 1, 1});
1848 
1849   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1850 }
1851 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_stereo_conversational)1852 TEST_P(LeAudioAseConfigurationTest, test_handsfree_stereo_conversational) {
1853   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1854   TestGroupAseConfigurationData data(
1855           {handsfree, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1856            kLeAudioCodecChannelCountSingleChannel, 2, 1});
1857 
1858   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1859 }
1860 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_full_cached_conversational)1861 TEST_P(LeAudioAseConfigurationTest, test_handsfree_full_cached_conversational) {
1862   LeAudioDevice* handsfree = AddTestDevice(0, 0, 1, 1);
1863   TestGroupAseConfigurationData data(
1864           {handsfree, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1865            kLeAudioCodecChannelCountSingleChannel, 2, 1});
1866 
1867   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1868 }
1869 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_partial_cached_conversational)1870 TEST_P(LeAudioAseConfigurationTest, test_handsfree_partial_cached_conversational) {
1871   LeAudioDevice* handsfree = AddTestDevice(1, 0, 0, 1);
1872   TestGroupAseConfigurationData data(
1873           {handsfree, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1874            kLeAudioCodecChannelCountSingleChannel, 2, 1});
1875 
1876   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1877 }
1878 
TEST_P(LeAudioAseConfigurationTest,test_handsfree_media_two_channels_allocation_stereo)1879 TEST_P(LeAudioAseConfigurationTest, test_handsfree_media_two_channels_allocation_stereo) {
1880   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1881   TestGroupAseConfigurationData data(
1882           {handsfree, kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel,
1883            kLeAudioCodecChannelCountSingleChannel, 2, 0});
1884 
1885   uint8_t directions_to_verify = kLeAudioDirectionSink;
1886   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1, directions_to_verify);
1887 }
1888 
TEST_P(LeAudioAseConfigurationTest,test_lc3_config_ringtone)1889 TEST_P(LeAudioAseConfigurationTest, test_lc3_config_ringtone) {
1890   if (codec_coding_format_ != kLeAudioCodingFormatLC3) {
1891     GTEST_SKIP();
1892   }
1893 
1894   AddTestDevice(1, 1);
1895 
1896   TestLc3CodecConfig(LeAudioContextType::RINGTONE);
1897 }
1898 
TEST_P(LeAudioAseConfigurationTest,test_lc3_config_conversational)1899 TEST_P(LeAudioAseConfigurationTest, test_lc3_config_conversational) {
1900   if (codec_coding_format_ != kLeAudioCodingFormatLC3) {
1901     GTEST_SKIP();
1902   }
1903 
1904   AddTestDevice(1, 1);
1905 
1906   TestLc3CodecConfig(LeAudioContextType::CONVERSATIONAL);
1907 }
1908 
TEST_P(LeAudioAseConfigurationTest,test_lc3_config_media)1909 TEST_P(LeAudioAseConfigurationTest, test_lc3_config_media) {
1910   if (codec_coding_format_ != kLeAudioCodingFormatLC3) {
1911     GTEST_SKIP();
1912   }
1913 
1914   AddTestDevice(1, 1);
1915 
1916   TestLc3CodecConfig(LeAudioContextType::MEDIA);
1917 }
1918 
TEST_P(LeAudioAseConfigurationTest,test_use_codec_preference_earbuds_media)1919 TEST_P(LeAudioAseConfigurationTest, test_use_codec_preference_earbuds_media) {
1920   com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
1921 
1922   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1923                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1924   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1925                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1926   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1927                                            kLeAudioCodecChannelCountSingleChannel, 1, 0},
1928                                           {right, kLeAudioCodecChannelCountSingleChannel,
1929                                            kLeAudioCodecChannelCountSingleChannel, 1, 0}};
1930 
1931   // this would be also built into pac record
1932   btle_audio_codec_config_t preferred_codec_config = {
1933           .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
1934           .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
1935           .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
1936           .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
1937           .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
1938           .octets_per_frame = 40};
1939 
1940   uint8_t directions_to_verify = kLeAudioDirectionSink;
1941   bool should_use_preferred_codec = true;
1942 
1943   TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, 2, directions_to_verify,
1944                             &preferred_codec_config, should_use_preferred_codec);
1945 }
1946 
TEST_P(LeAudioAseConfigurationTest,test_not_use_codec_preference_earbuds_media)1947 TEST_P(LeAudioAseConfigurationTest, test_not_use_codec_preference_earbuds_media) {
1948   com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
1949 
1950   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1951                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1952   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1953                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1954   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1955                                            kLeAudioCodecChannelCountSingleChannel, 1, 0},
1956                                           {right, kLeAudioCodecChannelCountSingleChannel,
1957                                            kLeAudioCodecChannelCountSingleChannel, 1, 0}};
1958 
1959   // this would be also built into pac record
1960   btle_audio_codec_config_t preferred_codec_config = {
1961           .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
1962           .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
1963           .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
1964           .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
1965           .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
1966           .octets_per_frame = 70};
1967 
1968   uint8_t directions_to_verify = kLeAudioDirectionSink;
1969   bool should_use_preferred_codec = false;
1970 
1971   TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, 2, directions_to_verify,
1972                             &preferred_codec_config, should_use_preferred_codec);
1973 }
1974 
TEST_P(LeAudioAseConfigurationTest,test_use_codec_preference_earbuds_conv)1975 TEST_P(LeAudioAseConfigurationTest, test_use_codec_preference_earbuds_conv) {
1976   com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
1977 
1978   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
1979                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
1980   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
1981                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
1982   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
1983                                            kLeAudioCodecChannelCountSingleChannel, 1, 1},
1984                                           {right, kLeAudioCodecChannelCountSingleChannel,
1985                                            kLeAudioCodecChannelCountSingleChannel, 1, 1}};
1986 
1987   // this would be also built into pac record
1988   btle_audio_codec_config_t preferred_codec_config = {
1989           .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
1990           .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
1991           .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
1992           .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
1993           .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
1994           .octets_per_frame = 80};
1995 
1996   uint8_t directions_to_verify = kLeAudioDirectionBoth;
1997   bool should_use_preferred_codec = true;
1998 
1999   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, data, 2, directions_to_verify,
2000                             &preferred_codec_config, should_use_preferred_codec);
2001 }
2002 
TEST_P(LeAudioAseConfigurationTest,test_not_use_codec_preference_earbuds_conv)2003 TEST_P(LeAudioAseConfigurationTest, test_not_use_codec_preference_earbuds_conv) {
2004   com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
2005 
2006   LeAudioDevice* left = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontLeft}},
2007                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
2008   LeAudioDevice* right = AddTestDevice({{1, codec_spec_conf::kLeAudioLocationFrontRight}},
2009                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
2010   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
2011                                            kLeAudioCodecChannelCountSingleChannel, 1, 1},
2012                                           {right, kLeAudioCodecChannelCountSingleChannel,
2013                                            kLeAudioCodecChannelCountSingleChannel, 1, 1}};
2014 
2015   // this would be also built into pac record
2016   btle_audio_codec_config_t preferred_codec_config = {
2017           .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
2018           .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
2019           .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
2020           .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
2021           .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
2022           .octets_per_frame = 10};
2023 
2024   uint8_t directions_to_verify = kLeAudioDirectionBoth;
2025   bool should_use_preferred_codec = false;
2026 
2027   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, data, 2, directions_to_verify,
2028                             &preferred_codec_config, should_use_preferred_codec);
2029 }
2030 
TEST_P(LeAudioAseConfigurationTest,test_lc3_config_media_codec_extensibility_fb2)2031 TEST_P(LeAudioAseConfigurationTest, test_lc3_config_media_codec_extensibility_fb2) {
2032   if (codec_coding_format_ != kLeAudioCodingFormatLC3) {
2033     GTEST_SKIP();
2034   }
2035 
2036   bool is_fb2_passed_as_requirement = false;
2037   auto max_codec_frames_per_sdu = 2;
2038 
2039   // Mock the configuration provider to give us config with 2 frame blocks per
2040   // SDU if it receives the proper PAC entry in the requirements
2041   // ON_CALL(*mock_codec_manager_, IsUsingCodecExtensibility)
2042   //       .WillByDefault(Return(true));
2043   ON_CALL(*mock_codec_manager_, GetCodecConfig)
2044           .WillByDefault(Invoke(
2045                   [&](const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&
2046                               requirements,
2047                       bluetooth::le_audio::CodecManager::UnicastConfigurationProvider provider) {
2048                     auto filtered = *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
2049                                              ->GetConfigurations(requirements.audio_context_type);
2050                     // Filter out the dual bidir SWB configurations
2051                     if (!bluetooth::le_audio::CodecManager::GetInstance()
2052                                  ->IsDualBiDirSwbSupported()) {
2053                       filtered.erase(
2054                               std::remove_if(filtered.begin(), filtered.end(),
2055                                              [](auto const& el) {
2056                                                if (el->confs.source.empty()) {
2057                                                  return false;
2058                                                }
2059                                                return AudioSetConfigurationProvider::Get()
2060                                                        ->CheckConfigurationIsDualBiDirSwb(*el);
2061                                              }),
2062                               filtered.end());
2063                     }
2064                     auto cfg = provider(requirements, &filtered);
2065                     if (cfg == nullptr) {
2066                       return std::unique_ptr<AudioSetConfiguration>(nullptr);
2067                     }
2068 
2069                     auto config = *cfg;
2070 
2071                     if (requirements.sink_pacs.has_value()) {
2072                       for (auto const& rec : requirements.sink_pacs.value()) {
2073                         auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
2074                         if (caps.HasSupportedMaxCodecFramesPerSdu()) {
2075                           if (caps.supported_max_codec_frames_per_sdu.value() ==
2076                               max_codec_frames_per_sdu) {
2077                             // Inject the proper Codec Frames Per SDU as the json
2078                             // configs are conservative and will always give us 1
2079                             for (auto& entry : config.confs.sink) {
2080                               entry.codec.params.Add(
2081                                       codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
2082                                       (uint8_t)max_codec_frames_per_sdu);
2083                             }
2084                             is_fb2_passed_as_requirement = true;
2085                           }
2086                         }
2087                       }
2088                     }
2089                     return std::make_unique<AudioSetConfiguration>(config);
2090                   }));
2091 
2092   AddTestDevice(1, 1);
2093 
2094   TestLc3CodecConfig(LeAudioContextType::MEDIA, max_codec_frames_per_sdu);
2095 
2096   // Make sure the CodecManager mock gets the proper PAC record
2097   ASSERT_TRUE(is_fb2_passed_as_requirement);
2098 }
2099 
TEST_P(LeAudioAseConfigurationTest,test_unsupported_codec)2100 TEST_P(LeAudioAseConfigurationTest, test_unsupported_codec) {
2101   if (codec_coding_format_ == kLeAudioCodingFormatVendorSpecific) {
2102     GTEST_SKIP();
2103   }
2104 
2105   const LeAudioCodecId UnsupportedCodecId = {
2106           .coding_format = kLeAudioCodingFormatVendorSpecific,
2107           .vendor_company_id = 0xBAD,
2108           .vendor_codec_id = 0xC0DE,
2109   };
2110 
2111   LeAudioDevice* device = AddTestDevice(1, 0);
2112 
2113   PublishedAudioCapabilitiesBuilder pac_builder;
2114   pac_builder.Add(UnsupportedCodecId, GetSamplingFrequency(Lc3SettingId::LC3_16_2),
2115                   GetFrameDuration(Lc3SettingId::LC3_16_2), kLeAudioCodecChannelCountSingleChannel,
2116                   GetOctetsPerCodecFrame(Lc3SettingId::LC3_16_2));
2117   device->snk_pacs_ = pac_builder.Get();
2118   device->src_pacs_ = pac_builder.Get();
2119 
2120   ASSERT_FALSE(group_->Configure(LeAudioContextType::RINGTONE,
2121                                  {AudioContexts(LeAudioContextType::RINGTONE),
2122                                   AudioContexts(LeAudioContextType::RINGTONE)}));
2123   TestAsesInactive();
2124 }
2125 
PrepareStackMetadataLtvBase()2126 static auto PrepareStackMetadataLtvBase() {
2127   ::bluetooth::le_audio::types::LeAudioLtvMap metadata_ltvs;
2128   // Prepare the metadata LTVs
2129   metadata_ltvs
2130           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfo,
2131                std::string{"ProgramInfo"})
2132           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeLanguage, std::string{"ice"})
2133           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeparentalRating, (uint8_t)0x01)
2134           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfoUri,
2135                std::string{"ProgramInfoUri"})
2136           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, false)
2137           .Add(::bluetooth::le_audio::types::
2138                        kLeAudioMetadataTypeBroadcastAudioImmediateRenderingFlag,
2139                true)
2140           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeExtendedMetadata,
2141                std::vector<uint8_t>{1, 2, 3})
2142           .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeVendorSpecific,
2143                std::vector<uint8_t>{1, 2, 3});
2144   return metadata_ltvs;
2145 }
2146 
TEST_P(LeAudioAseConfigurationTest,test_reconnection_media)2147 TEST_P(LeAudioAseConfigurationTest, test_reconnection_media) {
2148   LeAudioDevice* left = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationFrontLeft}},
2149                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
2150   LeAudioDevice* right = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationFrontRight}},
2151                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
2152   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
2153                                            kLeAudioCodecChannelCountSingleChannel, 1, 0},
2154                                           {right, kLeAudioCodecChannelCountSingleChannel,
2155                                            kLeAudioCodecChannelCountSingleChannel, 1, 0}};
2156 
2157   auto all_configurations =
2158           ::bluetooth::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
2159                   LeAudioContextType::MEDIA);
2160   ASSERT_NE(nullptr, all_configurations);
2161   ASSERT_NE(all_configurations->end(), all_configurations->begin());
2162   auto configuration = *all_configurations->begin();
2163 
2164   uint8_t direction_to_verify = kLeAudioDirectionSink;
2165   TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, configuration,
2166                              direction_to_verify);
2167 
2168   // Get the proper configuration for the group
2169   configuration = group_->GetConfiguration(LeAudioContextType::MEDIA).get();
2170 
2171   /* Generate CISes, symulate CIG creation and assign cis handles to ASEs.*/
2172   group_->cig.GenerateCisIds(LeAudioContextType::MEDIA);
2173   std::vector<uint16_t> handles = {0x0012, 0x0013};
2174   group_->cig.AssignCisConnHandles(handles);
2175   group_->cig.AssignCisIds(left);
2176   group_->cig.AssignCisIds(right);
2177 
2178   TestActiveAses();
2179   /* Left got disconnected */
2180   left->DeactivateAllAses();
2181 
2182   /* Unassign from the group*/
2183   group_->cig.UnassignCis(left, 0x0012);
2184   group_->cig.UnassignCis(left, 0x0013);
2185 
2186   TestAsesInactivated(left);
2187 
2188   /* Prepare reconfiguration */
2189   uint8_t number_of_active_ases = 1;  // Right one
2190   auto* ase = right->GetFirstActiveAseByDirection(kLeAudioDirectionSink);
2191   ASSERT_NE(nullptr, ase);
2192 
2193   auto core_config = ase->codec_config.params.GetAsCoreCodecConfig();
2194   BidirectionalPair<AudioLocations> group_audio_locations = {
2195           .sink = *core_config.audio_channel_allocation,
2196           .source = *core_config.audio_channel_allocation};
2197 
2198   /* Get entry for the sink direction and use it to set configuration */
2199   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
2200   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(), AudioContexts()};
2201   if (!configuration->confs.sink.empty()) {
2202     left->ConfigureAses(configuration, group_->Size(), kLeAudioDirectionSink,
2203                         group_->GetConfigurationContextType(), &number_of_active_ases,
2204                         group_audio_locations.get(kLeAudioDirectionSink),
2205                         audio_contexts.get(kLeAudioDirectionSink),
2206                         ccid_lists.get(kLeAudioDirectionSink), false);
2207   }
2208   if (!configuration->confs.source.empty()) {
2209     left->ConfigureAses(configuration, group_->Size(), kLeAudioDirectionSource,
2210                         group_->GetConfigurationContextType(), &number_of_active_ases,
2211                         group_audio_locations.get(kLeAudioDirectionSource),
2212                         audio_contexts.get(kLeAudioDirectionSource),
2213                         ccid_lists.get(kLeAudioDirectionSource), false);
2214   }
2215 
2216   ASSERT_EQ(number_of_active_ases, 2);
2217   ASSERT_EQ(group_audio_locations.sink, kChannelAllocationStereo);
2218 
2219   uint8_t directions_to_verify = ::bluetooth::le_audio::types::kLeAudioDirectionSink;
2220   for (int i = 0; i < 2; i++) {
2221     TestGroupAseConfigurationVerdict(data[i], directions_to_verify);
2222   }
2223 
2224   /* Before device is rejoining, and group already exist, cis handles are
2225    * assigned before sending codec config
2226    */
2227   group_->cig.AssignCisIds(left);
2228   group_->AssignCisConnHandlesToAses(left);
2229 
2230   TestActiveAses();
2231 }
2232 
TEST_P(LeAudioAseConfigurationTest,test_ase_metadata)2233 TEST_P(LeAudioAseConfigurationTest, test_ase_metadata) {
2234   /* Set desired size to 1 */
2235   desired_group_size_ = 1;
2236 
2237   LeAudioDevice* headphones = AddTestDevice(2, 1);
2238 
2239   AudioSetConfiguration media_configuration = *getSpecificConfiguration(
2240           "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", LeAudioContextType::MEDIA);
2241 
2242   // Build PACs for device
2243   PublishedAudioCapabilitiesBuilder snk_pac_builder;
2244   snk_pac_builder.Reset();
2245 
2246   /* Create PACs for media. Single PAC for each direction is enough.
2247    */
2248   if (media_configuration.confs.sink.size()) {
2249     snk_pac_builder.Add(LeAudioCodecIdLc3, 0x00b5, 0x03, 0x03, 0x001a, 0x00f0, 2);
2250   }
2251 
2252   headphones->snk_pacs_ = snk_pac_builder.Get();
2253 
2254   ::bluetooth::le_audio::types::AudioLocations group_snk_audio_locations = 3;
2255   ::bluetooth::le_audio::types::AudioLocations group_src_audio_locations = 0;
2256   BidirectionalPair<AudioLocations> group_audio_locations = {.sink = group_snk_audio_locations,
2257                                                              .source = group_src_audio_locations};
2258 
2259   /* Get entry for the sink direction and use it to set configuration */
2260   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {.sink = {0xC0}, .source = {}};
2261   BidirectionalPair<AudioContexts> audio_contexts = {
2262           .sink = AudioContexts(LeAudioContextType::MEDIA), .source = AudioContexts()};
2263 
2264   /* Get entry for the sink direction and use it to set configuration */
2265   ASSERT_FALSE(media_configuration.confs.sink.empty());
2266   if (!media_configuration.confs.sink.empty()) {
2267     // Prepare a base metadata - as if it was received from the configuration provider
2268     for (auto& cfg : media_configuration.confs.sink) {
2269       cfg.metadata = PrepareStackMetadataLtvBase();
2270     }
2271     uint8_t number_of_already_active_ases = 0;
2272     headphones->ConfigureAses(&media_configuration, group_->Size(), kLeAudioDirectionSink,
2273                               group_->GetConfigurationContextType(), &number_of_already_active_ases,
2274                               group_audio_locations.get(kLeAudioDirectionSink),
2275                               audio_contexts.get(kLeAudioDirectionSink),
2276                               ccid_lists.get(kLeAudioDirectionSink), false);
2277   }
2278 
2279   /* Generate CIS, simulate CIG creation and assign cis handles to ASEs.*/
2280   std::vector<uint16_t> handles = {0x0012};
2281   group_->cig.GenerateCisIds(LeAudioContextType::MEDIA);
2282 
2283   /* Verify the metadata content */
2284   for (auto* ase = headphones->GetFirstActiveAse(); ase; ase = headphones->GetNextActiveAse(ase)) {
2285     /* The base metadata as if received from the audio set configuration provider */
2286     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().program_info, std::string("ProgramInfo"));
2287     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().language, std::string("ice"));
2288     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().parental_rating, 0x01);
2289     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().program_info_uri, std::string("ProgramInfoUri"));
2290     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().audio_active_state, false);
2291     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().broadcast_audio_immediate_rendering, true);
2292     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().extended_metadata,
2293               (std::vector<uint8_t>{1, 2, 3}));
2294     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().vendor_specific,
2295               (std::vector<uint8_t>{1, 2, 3}));
2296 
2297     /* The adidtional metadata appended by the host stack */
2298     uint16_t streaming_context =
2299             ase->metadata.GetAsLeAudioMetadata().streaming_audio_context.value().value();
2300     ASSERT_EQ(streaming_context, (uint16_t)LeAudioContextType::MEDIA);
2301     ASSERT_EQ(ase->metadata.GetAsLeAudioMetadata().ccid_list, (std::vector<uint8_t>{0xC0}));
2302   }
2303 }
2304 
2305 /*
2306  * Failure happens when restarting conversational scenario and when
2307  * remote device uses caching.
2308  *
2309  * Failing scenario.
2310  * 1. Conversational scenario set up with
2311  *  - ASE 1 and ASE 5 using bidirectional CIS 0
2312  *  - ASE 2  being unidirectional on CIS 1
2313  * 2. Stop stream and go to CONFIGURED STATE.
2314  * 3. Trying to configure ASES again would end up in incorrectly assigned
2315  *    CISes
2316  *  - ASE 1 and ASE 5 set to CIS 0
2317  *  - ASE 2 stay on CIS 1 but ASE 5 got reassigned to CIS 1 (error)
2318  *
2319  * The problem is finding matching_bidir_ase which shall not be just next
2320  * active ase with different direction, but it shall be also available (Cis
2321  * not assigned) or assigned to the same CIS ID as the opposite direction.
2322  */
TEST_P(LeAudioAseConfigurationTest,test_reactivation_conversational)2323 TEST_P(LeAudioAseConfigurationTest, test_reactivation_conversational) {
2324   LeAudioDevice* tws_headset = AddTestDevice(0, 0, 2, 1, true, false, kChannelAllocationStereo,
2325                                              codec_spec_conf::kLeAudioLocationFrontLeft);
2326 
2327   auto conversational_configuration = getSpecificConfiguration(
2328           "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
2329           LeAudioContextType::CONVERSATIONAL);
2330   ASSERT_NE(nullptr, conversational_configuration);
2331 
2332   // Build PACs for device
2333   PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
2334   snk_pac_builder.Reset();
2335   src_pac_builder.Reset();
2336 
2337   /* Create PACs for conversational scenario which covers also media. Single
2338    * PAC for each direction is enough.
2339    */
2340   for (const auto& entry : (*conversational_configuration).confs.sink) {
2341     snk_pac_builder.Add(entry.codec, 1);
2342   }
2343   for (const auto& entry : (*conversational_configuration).confs.source) {
2344     src_pac_builder.Add(entry.codec, 1);
2345   }
2346 
2347   tws_headset->snk_pacs_ = snk_pac_builder.Get();
2348   tws_headset->src_pacs_ = src_pac_builder.Get();
2349 
2350   ::bluetooth::le_audio::types::AudioLocations group_snk_audio_locations = 0;
2351   ::bluetooth::le_audio::types::AudioLocations group_src_audio_locations = 0;
2352   BidirectionalPair<uint8_t> number_of_already_active_ases = {0, 0};
2353 
2354   BidirectionalPair<AudioLocations> group_audio_locations = {.sink = group_snk_audio_locations,
2355                                                              .source = group_src_audio_locations};
2356 
2357   /* Get entry for the sink direction and use it to set configuration */
2358   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
2359   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(), AudioContexts()};
2360 
2361   /* Get entry for the sink direction and use it to set configuration */
2362   if (!conversational_configuration->confs.sink.empty()) {
2363     tws_headset->ConfigureAses(conversational_configuration, group_->Size(), kLeAudioDirectionSink,
2364                                group_->GetConfigurationContextType(),
2365                                &number_of_already_active_ases.get(kLeAudioDirectionSink),
2366                                group_audio_locations.get(kLeAudioDirectionSink),
2367                                audio_contexts.get(kLeAudioDirectionSink),
2368                                ccid_lists.get(kLeAudioDirectionSink), false);
2369   }
2370   if (!conversational_configuration->confs.source.empty()) {
2371     tws_headset->ConfigureAses(conversational_configuration, group_->Size(),
2372                                kLeAudioDirectionSource, group_->GetConfigurationContextType(),
2373                                &number_of_already_active_ases.get(kLeAudioDirectionSource),
2374                                group_audio_locations.get(kLeAudioDirectionSource),
2375                                audio_contexts.get(kLeAudioDirectionSource),
2376                                ccid_lists.get(kLeAudioDirectionSource), false);
2377   }
2378 
2379   /* Generate CISes, simulate CIG creation and assign cis handles to ASEs.*/
2380   std::vector<uint16_t> handles = {0x0012, 0x0013};
2381   group_->cig.GenerateCisIds(LeAudioContextType::CONVERSATIONAL);
2382   group_->cig.AssignCisConnHandles(handles);
2383   group_->cig.AssignCisIds(tws_headset);
2384 
2385   TestActiveAses();
2386 
2387   /* Simulate stopping stream with caching codec configuration in ASEs */
2388   group_->cig.UnassignCis(tws_headset, 0x0012);
2389   group_->cig.UnassignCis(tws_headset, 0x0013);
2390   SetAsesToCachedConfiguration(tws_headset, LeAudioContextType::CONVERSATIONAL,
2391                                kLeAudioDirectionSink | kLeAudioDirectionSource);
2392 
2393   /* As context type is the same as previous and no changes were made in PACs
2394    * the same CIS ID can be used. This would lead to only activating group
2395    * without reconfiguring CIG.
2396    */
2397   group_->Activate(LeAudioContextType::CONVERSATIONAL, audio_contexts, ccid_lists);
2398 
2399   TestActiveAses();
2400   ASSERT_NE(this->group_->cig.cises.size(), 0lu);
2401 
2402   /* Verify ASEs assigned CISes by counting assigned to bi-directional CISes */
2403   int bi_dir_ases_count =
2404           std::count_if(tws_headset->ases_.begin(), tws_headset->ases_.end(), [this](auto& ase) {
2405             if (ase.cis_id == kInvalidCisId) {
2406               return false;
2407             }
2408             return this->group_->cig.cises[ase.cis_id].type == CisType::CIS_TYPE_BIDIRECTIONAL;
2409           });
2410 
2411   /* Only two ASEs can be bonded to one bi-directional CIS */
2412   ASSERT_EQ(bi_dir_ases_count, 2);
2413 }
2414 
TEST_P(LeAudioAseConfigurationTest,test_num_of_connected)2415 TEST_P(LeAudioAseConfigurationTest, test_num_of_connected) {
2416   auto device1 = AddTestDevice(2, 1);
2417   auto device2 = AddTestDevice(2, 1);
2418   ASSERT_EQ(2, group_->NumOfConnected());
2419 
2420   // Drop the ACL connection
2421   device1->conn_id_ = GATT_INVALID_CONN_ID;
2422   ASSERT_EQ(1, group_->NumOfConnected());
2423 
2424   // Fully disconnect the other device
2425   device2->SetConnectionState(DeviceConnectState::DISCONNECTING);
2426   ASSERT_EQ(0, group_->NumOfConnected());
2427 }
2428 
2429 /*
2430  * Failure happens when there is no matching single device scenario for dual
2431  * device scanario. Stereo location for single earbud seems to be invalid but
2432  * possible and stack should handle it.
2433  *
2434  * Failing scenario:
2435  * 1. Connect two - stereo location earbuds
2436  * 2. Disconnect one of earbud
2437  * 3. CIS generator will look for dual device scenario with matching strategy
2438  * 4. There is no dual device scenario with strategy stereo channels per device
2439  */
TEST_P(LeAudioAseConfigurationTest,test_getting_cis_count)2440 TEST_P(LeAudioAseConfigurationTest, test_getting_cis_count) {
2441   /* Set desired size to 2 */
2442   desired_group_size_ = 2;
2443 
2444   LeAudioDevice* left =
2445           AddTestDevice({{2, kChannelAllocationStereo}}, {{1, kChannelAllocationStereo}});
2446   LeAudioDevice* right = AddTestDevice(0, 0, 0, 0, false, true);
2447 
2448   auto media_configuration = getSpecificConfiguration(
2449           "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability", LeAudioContextType::MEDIA);
2450   ASSERT_NE(nullptr, media_configuration);
2451 
2452   // Build PACs for device
2453   PublishedAudioCapabilitiesBuilder snk_pac_builder;
2454   snk_pac_builder.Reset();
2455 
2456   /* Create PACs for media. Single PAC for each direction is enough.
2457    */
2458   if (media_configuration->confs.sink.size()) {
2459     snk_pac_builder.Add(LeAudioCodecIdLc3, 0x00b5, 0x03, 0x03, 0x001a, 0x00f0, 2);
2460   }
2461 
2462   left->snk_pacs_ = snk_pac_builder.Get();
2463   right->snk_pacs_ = snk_pac_builder.Get();
2464 
2465   ::bluetooth::le_audio::types::AudioLocations group_snk_audio_locations = 3;
2466   ::bluetooth::le_audio::types::AudioLocations group_src_audio_locations = 0;
2467   uint8_t number_of_already_active_ases = 0;
2468 
2469   BidirectionalPair<AudioLocations> group_audio_locations = {.sink = group_snk_audio_locations,
2470                                                              .source = group_src_audio_locations};
2471 
2472   /* Get entry for the sink direction and use it to set configuration */
2473   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
2474   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(), AudioContexts()};
2475 
2476   /* Get entry for the sink direction and use it to set configuration */
2477   if (!media_configuration->confs.sink.empty()) {
2478     left->ConfigureAses(media_configuration, group_->Size(), kLeAudioDirectionSink,
2479                         group_->GetConfigurationContextType(), &number_of_already_active_ases,
2480                         group_audio_locations.get(kLeAudioDirectionSink),
2481                         audio_contexts.get(kLeAudioDirectionSink),
2482                         ccid_lists.get(kLeAudioDirectionSink), false);
2483   }
2484 
2485   /* Generate CIS, simulate CIG creation and assign cis handles to ASEs.*/
2486   std::vector<uint16_t> handles = {0x0012};
2487   group_->cig.GenerateCisIds(LeAudioContextType::MEDIA);
2488 
2489   /* Verify prepared CISes by counting generated entries */
2490   int snk_cis_count = std::count_if(
2491           this->group_->cig.cises.begin(), this->group_->cig.cises.end(),
2492           [](auto& cis) { return cis.type == CisType::CIS_TYPE_UNIDIRECTIONAL_SINK; });
2493 
2494   /* Two CIS should be prepared for dual dev expected set */
2495   ASSERT_EQ(snk_cis_count, 2);
2496 }
2497 
TEST_P(LeAudioAseConfigurationTest,test_config_support)2498 TEST_P(LeAudioAseConfigurationTest, test_config_support) {
2499   LeAudioDevice* left =
2500           AddTestDevice({{2, kChannelAllocationStereo}}, {{1, kChannelAllocationStereo}});
2501   LeAudioDevice* right = AddTestDevice(0, 0, 0, 0, false, true);
2502 
2503   auto test_config = getSpecificConfiguration(
2504           "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
2505           LeAudioContextType::VOICEASSISTANTS);
2506   ASSERT_NE(nullptr, test_config);
2507 
2508   /* Create PACs for sink */
2509   PublishedAudioCapabilitiesBuilder snk_pac_builder;
2510   snk_pac_builder.Reset();
2511   for (const auto& entry : (*test_config).confs.sink) {
2512     snk_pac_builder.Add(entry.codec, 1);
2513   }
2514   left->snk_pacs_ = snk_pac_builder.Get();
2515   right->snk_pacs_ = snk_pac_builder.Get();
2516 
2517   ASSERT_FALSE(left->IsAudioSetConfigurationSupported(test_config));
2518   ASSERT_FALSE(right->IsAudioSetConfigurationSupported(test_config));
2519 
2520   /* Create PACs for source */
2521   PublishedAudioCapabilitiesBuilder src_pac_builder;
2522   src_pac_builder.Reset();
2523   for (const auto& entry : (*test_config).confs.source) {
2524     src_pac_builder.Add(entry.codec, 1);
2525   }
2526   left->src_pacs_ = src_pac_builder.Get();
2527   right->src_pacs_ = src_pac_builder.Get();
2528 
2529   ASSERT_TRUE(left->IsAudioSetConfigurationSupported(test_config));
2530   ASSERT_TRUE(right->IsAudioSetConfigurationSupported(test_config));
2531 }
2532 
TEST_P(LeAudioAseConfigurationTest,test_vendor_codec_configure_incomplete_group)2533 TEST_P(LeAudioAseConfigurationTest, test_vendor_codec_configure_incomplete_group) {
2534   // A group of two earbuds
2535   LeAudioDevice* left = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationFrontLeft}},
2536                                       {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
2537   LeAudioDevice* right = AddTestDevice({{2, codec_spec_conf::kLeAudioLocationFrontRight}},
2538                                        {{1, codec_spec_conf::kLeAudioLocationFrontRight}});
2539 
2540   // The Right earbud is currently disconnected
2541   right->SetConnectionState(DeviceConnectState::DISCONNECTED);
2542 
2543   uint8_t direction_to_verify = kLeAudioDirectionSink;
2544   uint8_t devices_to_verify = 1;
2545   TestGroupAseConfigurationData data[] = {{left, kLeAudioCodecChannelCountSingleChannel,
2546                                            kLeAudioCodecChannelCountSingleChannel, 1, 0},
2547                                           {right, kLeAudioCodecChannelCountSingleChannel,
2548                                            kLeAudioCodecChannelCountSingleChannel, 0, 0}};
2549 
2550   TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, devices_to_verify,
2551                             direction_to_verify);
2552 }
2553 
TEST_P(LeAudioAseConfigurationTest,test_mono_microphone_conversational_loc0)2554 TEST_P(LeAudioAseConfigurationTest, test_mono_microphone_conversational_loc0) {
2555   /* Mono microphone - Speaker should be used on the phone */
2556   auto mono_microphone =
2557           AddTestDevice(std::nullopt, {{1, codec_spec_conf::kLeAudioLocationMonoAudio}});
2558   TestGroupAseConfigurationData data(
2559           {.device = mono_microphone,
2560            .audio_channel_counts_snk = kLeAudioCodecChannelCountNone,
2561            .audio_channel_counts_src = kLeAudioCodecChannelCountSingleChannel,
2562            .expected_active_channel_num_snk = 0,
2563            .expected_active_channel_num_src = 1});
2564   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, {data});
2565 }
2566 
TEST_P(LeAudioAseConfigurationTest,test_mono_microphone_conversational)2567 TEST_P(LeAudioAseConfigurationTest, test_mono_microphone_conversational) {
2568   /* Mono microphone - Speaker should be used on the phone */
2569   auto mono_microphone =
2570           AddTestDevice(std::nullopt, {{1, codec_spec_conf::kLeAudioLocationFrontLeft}});
2571   TestGroupAseConfigurationData data(
2572           {.device = mono_microphone,
2573            .audio_channel_counts_snk = kLeAudioCodecChannelCountNone,
2574            .audio_channel_counts_src = kLeAudioCodecChannelCountSingleChannel,
2575            .expected_active_channel_num_snk = 0,
2576            .expected_active_channel_num_src = 1});
2577   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, {data});
2578 }
2579 
TEST_P(LeAudioAseConfigurationTest,test_get_metadata_no_ccid)2580 TEST_P(LeAudioAseConfigurationTest, test_get_metadata_no_ccid) {
2581   auto mono_microphone = AddTestDevice(1, 0);
2582   auto metadata = mono_microphone->GetMetadata(
2583           bluetooth::le_audio::types::AudioContexts(
2584                   bluetooth::le_audio::types::LeAudioContextType::MEDIA),
2585           std::vector<uint8_t>());
2586   ASSERT_EQ(metadata.Find(types::kLeAudioMetadataTypeCcidList), std::nullopt);
2587   ASSERT_TRUE(metadata.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext)
2588                       .has_value());
2589   ASSERT_EQ(metadata.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext)
2590                     .value()[0],
2591             uint8_t(LeAudioContextType::MEDIA));
2592   ASSERT_EQ(metadata.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext)
2593                     .value()[1],
2594             uint8_t((uint16_t)LeAudioContextType::MEDIA >> 8));
2595 }
2596 
2597 INSTANTIATE_TEST_CASE_P(Test, LeAudioAseConfigurationTest,
2598                         ::testing::Values(kLeAudioCodingFormatLC3,
2599                                           kLeAudioCodingFormatVendorSpecific));
2600 
2601 }  // namespace
2602 }  // namespace internal
2603 }  // namespace le_audio
2604 }  // namespace bluetooth
2605