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