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