• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "devices.h"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include "btm_api_mock.h"
24 #include "le_audio_set_configuration_provider.h"
25 #include "le_audio_types.h"
26 #include "mock_controller.h"
27 #include "mock_csis_client.h"
28 #include "os/log.h"
29 #include "stack/btm/btm_int_types.h"
30 
btm_bda_to_acl(const RawAddress & bda,tBT_TRANSPORT transport)31 tACL_CONN* btm_bda_to_acl(const RawAddress& bda, tBT_TRANSPORT transport) {
32   return nullptr;
33 }
34 
35 namespace bluetooth {
36 namespace le_audio {
37 namespace internal {
38 namespace {
39 
40 using ::le_audio::DeviceConnectState;
41 using ::le_audio::LeAudioDevice;
42 using ::le_audio::LeAudioDeviceGroup;
43 using ::le_audio::LeAudioDevices;
44 using ::le_audio::types::AseState;
45 using ::le_audio::types::AudioContexts;
46 using ::le_audio::types::AudioLocations;
47 using ::le_audio::types::BidirectionalPair;
48 using ::le_audio::types::CisType;
49 using ::le_audio::types::LeAudioContextType;
50 using testing::_;
51 using testing::Invoke;
52 using testing::Return;
53 using testing::Test;
54 
GetTestAddress(int index)55 RawAddress GetTestAddress(int index) {
56   CHECK_LT(index, UINT8_MAX);
57   RawAddress result = {
58       {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
59   return result;
60 }
61 
62 class LeAudioDevicesTest : public Test {
63  protected:
SetUp()64   void SetUp() override {
65     devices_ = new LeAudioDevices();
66     bluetooth::manager::SetMockBtmInterface(&btm_interface);
67     controller::SetMockControllerInterface(&controller_interface_);
68   }
69 
TearDown()70   void TearDown() override {
71     controller::SetMockControllerInterface(nullptr);
72     bluetooth::manager::SetMockBtmInterface(nullptr);
73     delete devices_;
74   }
75 
76   LeAudioDevices* devices_ = nullptr;
77   bluetooth::manager::MockBtmInterface btm_interface;
78   controller::MockControllerInterface controller_interface_;
79 };
80 
TEST_F(LeAudioDevicesTest,test_add)81 TEST_F(LeAudioDevicesTest, test_add) {
82   RawAddress test_address_0 = GetTestAddress(0);
83   ASSERT_EQ((size_t)0, devices_->Size());
84   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
85   ASSERT_EQ((size_t)1, devices_->Size());
86   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 1);
87   ASSERT_EQ((size_t)2, devices_->Size());
88   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
89   ASSERT_EQ((size_t)2, devices_->Size());
90   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 2);
91   ASSERT_EQ((size_t)2, devices_->Size());
92 }
93 
TEST_F(LeAudioDevicesTest,test_remove)94 TEST_F(LeAudioDevicesTest, test_remove) {
95   RawAddress test_address_0 = GetTestAddress(0);
96   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
97   RawAddress test_address_1 = GetTestAddress(1);
98   devices_->Add(test_address_1, DeviceConnectState::CONNECTING_BY_USER);
99   RawAddress test_address_2 = GetTestAddress(2);
100   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
101   ASSERT_EQ((size_t)3, devices_->Size());
102   devices_->Remove(test_address_0);
103   ASSERT_EQ((size_t)2, devices_->Size());
104   devices_->Remove(GetTestAddress(3));
105   ASSERT_EQ((size_t)2, devices_->Size());
106   devices_->Remove(test_address_0);
107   ASSERT_EQ((size_t)2, devices_->Size());
108 }
109 
TEST_F(LeAudioDevicesTest,test_find_by_address_success)110 TEST_F(LeAudioDevicesTest, test_find_by_address_success) {
111   RawAddress test_address_0 = GetTestAddress(0);
112   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
113   RawAddress test_address_1 = GetTestAddress(1);
114   devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
115   RawAddress test_address_2 = GetTestAddress(2);
116   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
117   LeAudioDevice* device = devices_->FindByAddress(test_address_1);
118   ASSERT_NE(nullptr, device);
119   ASSERT_EQ(test_address_1, device->address_);
120 }
121 
TEST_F(LeAudioDevicesTest,test_find_by_address_failed)122 TEST_F(LeAudioDevicesTest, test_find_by_address_failed) {
123   RawAddress test_address_0 = GetTestAddress(0);
124   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
125   RawAddress test_address_2 = GetTestAddress(2);
126   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
127   LeAudioDevice* device = devices_->FindByAddress(GetTestAddress(1));
128   ASSERT_EQ(nullptr, device);
129 }
130 
TEST_F(LeAudioDevicesTest,test_get_by_address_success)131 TEST_F(LeAudioDevicesTest, test_get_by_address_success) {
132   RawAddress test_address_0 = GetTestAddress(0);
133   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
134   RawAddress test_address_1 = GetTestAddress(1);
135   devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
136   RawAddress test_address_2 = GetTestAddress(2);
137   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
138   std::shared_ptr<LeAudioDevice> device =
139       devices_->GetByAddress(test_address_1);
140   ASSERT_NE(nullptr, device);
141   ASSERT_EQ(test_address_1, device->address_);
142 }
143 
TEST_F(LeAudioDevicesTest,test_get_by_address_failed)144 TEST_F(LeAudioDevicesTest, test_get_by_address_failed) {
145   RawAddress test_address_0 = GetTestAddress(0);
146   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
147   RawAddress test_address_2 = GetTestAddress(2);
148   devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
149   std::shared_ptr<LeAudioDevice> device =
150       devices_->GetByAddress(GetTestAddress(1));
151   ASSERT_EQ(nullptr, device);
152 }
153 
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_success)154 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_success) {
155   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
156   RawAddress test_address_0 = GetTestAddress(0);
157   devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
158   devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
159   LeAudioDevice* device = devices_->FindByAddress(test_address_0);
160   device->conn_id_ = 0x0005;
161   ASSERT_EQ(device, devices_->FindByConnId(0x0005));
162 }
163 
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_failed)164 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_failed) {
165   devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
166   devices_->Add(GetTestAddress(0), DeviceConnectState::CONNECTING_BY_USER);
167   devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
168   ASSERT_EQ(nullptr, devices_->FindByConnId(0x0006));
169 }
170 
171 /* TODO: Add FindByCisConnHdl test cases (ASE) */
172 
173 }  // namespace
174 
175 namespace {
176 using namespace ::le_audio::codec_spec_caps;
177 using namespace ::le_audio::set_configurations;
178 using namespace ::le_audio::types;
179 
180 static const hdl_pair hdl_pair_nil = hdl_pair(0x0000, 0x0000);
181 
182 enum class Lc3SettingId {
183   _BEGIN,
184   LC3_8_1 = _BEGIN,
185   LC3_8_2,
186   LC3_16_1,
187   LC3_16_2,
188   LC3_24_1,
189   LC3_24_2,
190   LC3_32_1,
191   LC3_32_2,
192   LC3_441_1,
193   LC3_441_2,
194   LC3_48_1,
195   LC3_48_2,
196   LC3_48_3,
197   LC3_48_4,
198   LC3_48_5,
199   LC3_48_6,
200   LC3_VND_1,
201   _END,
202   UNSUPPORTED = _END,
203 };
204 static constexpr int Lc3SettingIdBegin = static_cast<int>(Lc3SettingId::_BEGIN);
205 static constexpr int Lc3SettingIdEnd = static_cast<int>(Lc3SettingId::_END);
206 
IsLc3SettingSupported(LeAudioContextType context_type,Lc3SettingId id)207 bool IsLc3SettingSupported(LeAudioContextType context_type, Lc3SettingId id) {
208   /* Update those values, on any change of codec linked with content type */
209   switch (context_type) {
210     case LeAudioContextType::RINGTONE:
211     case LeAudioContextType::CONVERSATIONAL:
212       if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
213           id == Lc3SettingId::LC3_24_1 || id == Lc3SettingId::LC3_24_2 ||
214           id == Lc3SettingId::LC3_32_1 || id == Lc3SettingId::LC3_32_2 ||
215           id == Lc3SettingId::LC3_48_1 || id == Lc3SettingId::LC3_48_2 ||
216           id == Lc3SettingId::LC3_48_3 || id == Lc3SettingId::LC3_48_4 ||
217           id == Lc3SettingId::LC3_VND_1)
218         return true;
219 
220       break;
221 
222     case LeAudioContextType::MEDIA:
223     case LeAudioContextType::ALERTS:
224     case LeAudioContextType::INSTRUCTIONAL:
225     case LeAudioContextType::NOTIFICATIONS:
226     case LeAudioContextType::EMERGENCYALARM:
227     case LeAudioContextType::UNSPECIFIED:
228       if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
229           id == Lc3SettingId::LC3_48_4 || id == Lc3SettingId::LC3_48_1 ||
230           id == Lc3SettingId::LC3_48_2 || id == Lc3SettingId::LC3_VND_1 ||
231           id == Lc3SettingId::LC3_24_2)
232         return true;
233 
234       break;
235 
236     default:
237       if (id == Lc3SettingId::LC3_16_2) return true;
238 
239       break;
240   };
241 
242   return false;
243 }
244 
245 static constexpr uint8_t kLeAudioSamplingFreqRfu = 0x0E;
GetSamplingFrequency(Lc3SettingId id)246 uint8_t GetSamplingFrequency(Lc3SettingId id) {
247   switch (id) {
248     case Lc3SettingId::LC3_8_1:
249     case Lc3SettingId::LC3_8_2:
250       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq8000Hz;
251     case Lc3SettingId::LC3_16_1:
252     case Lc3SettingId::LC3_16_2:
253       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq16000Hz;
254     case Lc3SettingId::LC3_24_1:
255     case Lc3SettingId::LC3_24_2:
256       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq24000Hz;
257     case Lc3SettingId::LC3_32_1:
258     case Lc3SettingId::LC3_32_2:
259       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq32000Hz;
260     case Lc3SettingId::LC3_441_1:
261     case Lc3SettingId::LC3_441_2:
262       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq44100Hz;
263     case Lc3SettingId::LC3_48_1:
264     case Lc3SettingId::LC3_48_2:
265     case Lc3SettingId::LC3_48_3:
266     case Lc3SettingId::LC3_48_4:
267     case Lc3SettingId::LC3_48_5:
268     case Lc3SettingId::LC3_48_6:
269     case Lc3SettingId::LC3_VND_1:
270       return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq48000Hz;
271     case Lc3SettingId::UNSUPPORTED:
272       return kLeAudioSamplingFreqRfu;
273   }
274 }
275 
276 static constexpr uint8_t kLeAudioCodecLC3FrameDurRfu = 0x02;
GetFrameDuration(Lc3SettingId id)277 uint8_t GetFrameDuration(Lc3SettingId id) {
278   switch (id) {
279     case Lc3SettingId::LC3_8_1:
280     case Lc3SettingId::LC3_16_1:
281     case Lc3SettingId::LC3_24_1:
282     case Lc3SettingId::LC3_32_1:
283     case Lc3SettingId::LC3_441_1:
284     case Lc3SettingId::LC3_48_1:
285     case Lc3SettingId::LC3_48_3:
286     case Lc3SettingId::LC3_48_5:
287       return ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur7500us;
288     case Lc3SettingId::LC3_8_2:
289     case Lc3SettingId::LC3_16_2:
290     case Lc3SettingId::LC3_24_2:
291     case Lc3SettingId::LC3_32_2:
292     case Lc3SettingId::LC3_441_2:
293     case Lc3SettingId::LC3_48_2:
294     case Lc3SettingId::LC3_48_4:
295     case Lc3SettingId::LC3_48_6:
296     case Lc3SettingId::LC3_VND_1:
297       return ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur10000us;
298     case Lc3SettingId::UNSUPPORTED:
299       return kLeAudioCodecLC3FrameDurRfu;
300   }
301 }
302 
303 static constexpr uint8_t kLeAudioCodecLC3OctetsPerCodecFrameInvalid = 0;
GetOctetsPerCodecFrame(Lc3SettingId id)304 uint16_t GetOctetsPerCodecFrame(Lc3SettingId id) {
305   switch (id) {
306     case Lc3SettingId::LC3_8_1:
307       return 26;
308     case Lc3SettingId::LC3_8_2:
309     case Lc3SettingId::LC3_16_1:
310       return 30;
311     case Lc3SettingId::LC3_16_2:
312       return 40;
313     case Lc3SettingId::LC3_24_1:
314       return 45;
315     case Lc3SettingId::LC3_24_2:
316     case Lc3SettingId::LC3_32_1:
317       return 60;
318     case Lc3SettingId::LC3_32_2:
319       return 80;
320     case Lc3SettingId::LC3_441_1:
321       return 97;
322     case Lc3SettingId::LC3_441_2:
323       return 130;
324     case Lc3SettingId::LC3_48_1:
325       return 75;
326     case Lc3SettingId::LC3_48_2:
327     case Lc3SettingId::LC3_VND_1:
328       return 100;
329     case Lc3SettingId::LC3_48_3:
330       return 90;
331     case Lc3SettingId::LC3_48_4:
332       return 120;
333     case Lc3SettingId::LC3_48_5:
334       return 116;
335     case Lc3SettingId::LC3_48_6:
336       return 155;
337     case Lc3SettingId::UNSUPPORTED:
338       return kLeAudioCodecLC3OctetsPerCodecFrameInvalid;
339   }
340 }
341 
342 class PublishedAudioCapabilitiesBuilder {
343  public:
PublishedAudioCapabilitiesBuilder()344   PublishedAudioCapabilitiesBuilder() {}
345 
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)346   void Add(LeAudioCodecId codec_id, uint8_t conf_sampling_frequency,
347            uint8_t conf_frame_duration, uint8_t audio_channel_counts,
348            uint16_t octets_per_frame, uint8_t codec_frames_per_sdu = 0) {
349     uint16_t sampling_frequencies =
350         SamplingFreqConfig2Capability(conf_sampling_frequency);
351     uint8_t frame_durations =
352         FrameDurationConfig2Capability(conf_frame_duration);
353     uint8_t max_codec_frames_per_sdu = codec_frames_per_sdu;
354     uint32_t octets_per_frame_range =
355         octets_per_frame | (octets_per_frame << 16);
356 
357     pac_records_.push_back(
358         acs_ac_record({.codec_id = codec_id,
359                        .codec_spec_caps = LeAudioLtvMap({
360                            {kLeAudioCodecLC3TypeSamplingFreq,
361                             UINT16_TO_VEC_UINT8(sampling_frequencies)},
362                            {kLeAudioCodecLC3TypeFrameDuration,
363                             UINT8_TO_VEC_UINT8(frame_durations)},
364                            {kLeAudioCodecLC3TypeAudioChannelCounts,
365                             UINT8_TO_VEC_UINT8(audio_channel_counts)},
366                            {kLeAudioCodecLC3TypeOctetPerFrame,
367                             UINT32_TO_VEC_UINT8(octets_per_frame_range)},
368                            {kLeAudioCodecLC3TypeMaxCodecFramesPerSdu,
369                             UINT8_TO_VEC_UINT8(max_codec_frames_per_sdu)},
370                        }),
371                        .metadata = std::vector<uint8_t>(0)}));
372   }
373 
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)374   void Add(LeAudioCodecId codec_id, uint16_t capa_sampling_frequency,
375            uint8_t capa_frame_duration, uint8_t audio_channel_counts,
376            uint16_t octets_per_frame_min, uint16_t ocets_per_frame_max,
377            uint8_t codec_frames_per_sdu = 1) {
378     uint32_t octets_per_frame_range =
379         octets_per_frame_min | (ocets_per_frame_max << 16);
380 
381     pac_records_.push_back(
382         acs_ac_record({.codec_id = codec_id,
383                        .codec_spec_caps = LeAudioLtvMap({
384                            {kLeAudioCodecLC3TypeSamplingFreq,
385                             UINT16_TO_VEC_UINT8(capa_sampling_frequency)},
386                            {kLeAudioCodecLC3TypeFrameDuration,
387                             UINT8_TO_VEC_UINT8(capa_frame_duration)},
388                            {kLeAudioCodecLC3TypeAudioChannelCounts,
389                             UINT8_TO_VEC_UINT8(audio_channel_counts)},
390                            {kLeAudioCodecLC3TypeOctetPerFrame,
391                             UINT32_TO_VEC_UINT8(octets_per_frame_range)},
392                            {kLeAudioCodecLC3TypeMaxCodecFramesPerSdu,
393                             UINT8_TO_VEC_UINT8(codec_frames_per_sdu)},
394                        }),
395                        .metadata = std::vector<uint8_t>(0)}));
396   }
397 
Add(const CodecCapabilitySetting & setting,uint8_t audio_channel_counts)398   void Add(const CodecCapabilitySetting& setting,
399            uint8_t audio_channel_counts) {
400     if (setting.id != LeAudioCodecIdLc3) return;
401 
402     const LeAudioLc3Config config = std::get<LeAudioLc3Config>(setting.config);
403 
404     Add(setting.id, *config.sampling_frequency, *config.frame_duration,
405         audio_channel_counts, *config.octets_per_codec_frame);
406   }
407 
Reset()408   void Reset() { pac_records_.clear(); }
409 
Get()410   PublishedAudioCapabilities Get() {
411     return PublishedAudioCapabilities({{hdl_pair_nil, pac_records_}});
412   }
413 
414  private:
415   std::vector<acs_ac_record> pac_records_;
416 };
417 
418 struct TestGroupAseConfigurationData {
419   LeAudioDevice* device;
420   uint8_t audio_channel_counts_snk;
421   uint8_t audio_channel_counts_src;
422 
423   /* Note, do not confuse ASEs with channels num. */
424   uint8_t expected_active_channel_num_snk;
425   uint8_t expected_active_channel_num_src;
426 };
427 
428 class LeAudioAseConfigurationTest : public Test {
429  protected:
SetUp()430   void SetUp() override {
431     group_ = new LeAudioDeviceGroup(group_id_);
432     bluetooth::manager::SetMockBtmInterface(&btm_interface_);
433     controller::SetMockControllerInterface(&controller_interface_);
434     ::le_audio::AudioSetConfigurationProvider::Initialize();
435     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
436     ON_CALL(mock_csis_client_module_, Get())
437         .WillByDefault(Return(&mock_csis_client_module_));
438     ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
439         .WillByDefault(Return(true));
440     ON_CALL(mock_csis_client_module_, GetDeviceList(_))
441         .WillByDefault(Invoke([this](int group_id) { return addresses_; }));
442     ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
443         .WillByDefault(
444             Invoke([this](int group_id) { return (int)(addresses_.size()); }));
445   }
446 
TearDown()447   void TearDown() override {
448     controller::SetMockControllerInterface(nullptr);
449     bluetooth::manager::SetMockBtmInterface(nullptr);
450     devices_.clear();
451     addresses_.clear();
452     delete group_;
453     ::le_audio::AudioSetConfigurationProvider::Cleanup();
454   }
455 
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)456   LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num,
457                                int snk_ase_num_cached = 0,
458                                int src_ase_num_cached = 0,
459                                bool invert_ases_emplacement = false,
460                                bool out_of_range_device = false) {
461     int index = group_->Size() + 1;
462     auto device = (std::make_shared<LeAudioDevice>(
463         GetTestAddress(index), DeviceConnectState::DISCONNECTED));
464     devices_.push_back(device);
465     LOG_INFO(" addresses %d", (int)(addresses_.size()));
466     addresses_.push_back(device->address_);
467     LOG_INFO(" Addresses %d", (int)(addresses_.size()));
468 
469     if (out_of_range_device == false) {
470       group_->AddNode(device);
471     }
472 
473     int ase_id = 1;
474     for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num : src_ase_num);
475          i++) {
476       device->ases_.emplace_back(0x0000, 0x0000,
477                                  invert_ases_emplacement
478                                      ? kLeAudioDirectionSink
479                                      : kLeAudioDirectionSource,
480                                  ase_id++);
481     }
482 
483     for (int i = 0; i < (invert_ases_emplacement ? src_ase_num : snk_ase_num);
484          i++) {
485       device->ases_.emplace_back(0x0000, 0x0000,
486                                  invert_ases_emplacement
487                                      ? kLeAudioDirectionSource
488                                      : kLeAudioDirectionSink,
489                                  ase_id++);
490     }
491 
492     for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num_cached
493                                                  : src_ase_num_cached);
494          i++) {
495       struct ase ase(0x0000, 0x0000,
496                      invert_ases_emplacement ? kLeAudioDirectionSink
497                                              : kLeAudioDirectionSource,
498                      ase_id++);
499       ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
500       device->ases_.push_back(ase);
501     }
502 
503     for (int i = 0; i < (invert_ases_emplacement ? src_ase_num_cached
504                                                  : snk_ase_num_cached);
505          i++) {
506       struct ase ase(0x0000, 0x0000,
507                      invert_ases_emplacement ? kLeAudioDirectionSource
508                                              : kLeAudioDirectionSink,
509                      ase_id++);
510       ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
511       device->ases_.push_back(ase);
512     }
513 
514     device->SetSupportedContexts(AudioContexts(kLeAudioContextAllTypes),
515                                  AudioContexts(kLeAudioContextAllTypes));
516     device->SetAvailableContexts(AudioContexts(kLeAudioContextAllTypes),
517                                  AudioContexts(kLeAudioContextAllTypes));
518     device->snk_audio_locations_ =
519         ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
520         ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
521     device->src_audio_locations_ =
522         ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
523         ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
524 
525     device->conn_id_ = index;
526     device->SetConnectionState(out_of_range_device
527                                    ? DeviceConnectState::DISCONNECTED
528                                    : DeviceConnectState::CONNECTED);
529     group_->ReloadAudioDirections();
530     group_->ReloadAudioLocations();
531     return device.get();
532   }
533 
TestGroupAseConfigurationVerdict(const TestGroupAseConfigurationData & data,uint8_t directions_to_verify)534   bool TestGroupAseConfigurationVerdict(
535       const TestGroupAseConfigurationData& data, uint8_t directions_to_verify) {
536     uint8_t active_channel_num_snk = 0;
537     uint8_t active_channel_num_src = 0;
538 
539     if (directions_to_verify == 0) return false;
540     if (data.device->HaveActiveAse() == 0) return false;
541 
542     for (ase* ase = data.device->GetFirstActiveAse(); ase;
543          ase = data.device->GetNextActiveAse(ase)) {
544       if (ase->direction == kLeAudioDirectionSink)
545         active_channel_num_snk +=
546             GetAudioChannelCounts(*ase->codec_config.audio_channel_allocation);
547       else
548         active_channel_num_src +=
549             GetAudioChannelCounts(*ase->codec_config.audio_channel_allocation);
550     }
551 
552     bool result = true;
553     if (directions_to_verify & kLeAudioDirectionSink) {
554       result &=
555           (data.expected_active_channel_num_snk == active_channel_num_snk);
556     }
557     if (directions_to_verify & kLeAudioDirectionSource) {
558       result &=
559           (data.expected_active_channel_num_src == active_channel_num_src);
560     }
561 
562     return result;
563   }
564 
SetCisInformationToActiveAse(void)565   void SetCisInformationToActiveAse(void) {
566     uint8_t cis_id = 1;
567     uint16_t cis_conn_hdl = 0x0060;
568 
569     for (auto& device : devices_) {
570       for (auto& ase : device->ases_) {
571         if (ase.active) {
572           ase.cis_id = cis_id++;
573           ase.cis_conn_hdl = cis_conn_hdl++;
574         }
575       }
576     }
577   }
578 
TestSingleAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,const AudioSetConfiguration * audio_set_conf,uint8_t directions_to_verify)579   void TestSingleAseConfiguration(LeAudioContextType context_type,
580                                   TestGroupAseConfigurationData* data,
581                                   uint8_t data_size,
582                                   const AudioSetConfiguration* audio_set_conf,
583                                   uint8_t directions_to_verify) {
584     // the configuration should fail if there are no active ases expected
585     bool success_expected = data_size > 0;
586     uint8_t configuration_directions = 0;
587 
588     for (int i = 0; i < data_size; i++) {
589       success_expected &= (data[i].expected_active_channel_num_snk +
590                            data[i].expected_active_channel_num_src) > 0;
591 
592       /* Prepare PAC's */
593       PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
594       for (const auto& entry : (*audio_set_conf).confs) {
595         if (entry.direction == kLeAudioDirectionSink) {
596           configuration_directions |= kLeAudioDirectionSink;
597           snk_pac_builder.Add(entry.codec, data[i].audio_channel_counts_snk);
598         } else {
599           configuration_directions |= kLeAudioDirectionSource;
600           src_pac_builder.Add(entry.codec, data[i].audio_channel_counts_src);
601         }
602       }
603 
604       data[i].device->snk_pacs_ = snk_pac_builder.Get();
605       data[i].device->src_pacs_ = src_pac_builder.Get();
606     }
607 
608     BidirectionalPair<AudioContexts> group_audio_locations = {
609         .sink = AudioContexts(context_type),
610         .source = AudioContexts(context_type)};
611 
612     /* Stimulate update of available context map */
613     group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type));
614     ASSERT_EQ(success_expected,
615               group_->Configure(context_type, group_audio_locations));
616 
617     bool result = true;
618     for (int i = 0; i < data_size; i++) {
619       result &= TestGroupAseConfigurationVerdict(
620           data[i], directions_to_verify & configuration_directions);
621     }
622     ASSERT_TRUE(result);
623   }
624 
getNumOfAses(LeAudioDevice * device,uint8_t direction)625   int getNumOfAses(LeAudioDevice* device, uint8_t direction) {
626     return std::count_if(
627         device->ases_.begin(), device->ases_.end(),
628         [direction](auto& a) { return a.direction == direction; });
629   }
630 
TestGroupAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,uint8_t directions_to_verify=kLeAudioDirectionSink|kLeAudioDirectionSource)631   void TestGroupAseConfiguration(
632       LeAudioContextType context_type, TestGroupAseConfigurationData* data,
633       uint8_t data_size,
634       uint8_t directions_to_verify = kLeAudioDirectionSink |
635                                      kLeAudioDirectionSource) {
636     const auto* configurations =
637         ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
638             context_type);
639 
640     bool success_expected = directions_to_verify != 0;
641     int num_of_matching_configurations = 0;
642     for (const auto& audio_set_conf : *configurations) {
643       bool interesting_configuration = true;
644       uint8_t configuration_directions = 0;
645 
646       // the configuration should fail if there are no active ases expected
647       PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
648       snk_pac_builder.Reset();
649       src_pac_builder.Reset();
650 
651       /* Let's go thru devices in the group and configure them*/
652       for (int i = 0; i < data_size; i++) {
653         int num_of_ase_snk_per_dev = 0;
654         int num_of_ase_src_per_dev = 0;
655 
656         /* Prepare PAC's for each device. Also make sure configuration is in our
657          * interest to test */
658         for (const auto& entry : (*audio_set_conf).confs) {
659           /* We are interested in the configurations which contains exact number
660            * of devices and number of ases is same the number of expected ases
661            * to active
662            */
663           if (entry.device_cnt != data_size) {
664             interesting_configuration = false;
665           }
666 
667           /* Make sure the strategy is the expected one */
668           if (entry.direction == kLeAudioDirectionSink &&
669               group_->GetGroupStrategy(group_->Size()) != entry.strategy) {
670             interesting_configuration = false;
671           }
672 
673           if (entry.direction == kLeAudioDirectionSink) {
674             configuration_directions |= kLeAudioDirectionSink;
675             num_of_ase_snk_per_dev = entry.ase_cnt / data_size;
676             snk_pac_builder.Add(entry.codec, data[i].audio_channel_counts_snk);
677           } else {
678             configuration_directions |= kLeAudioDirectionSource;
679             num_of_ase_src_per_dev = entry.ase_cnt / data_size;
680             src_pac_builder.Add(entry.codec, data[i].audio_channel_counts_src);
681           }
682 
683           data[i].device->snk_pacs_ = snk_pac_builder.Get();
684           data[i].device->src_pacs_ = src_pac_builder.Get();
685         }
686 
687         /* Make sure configuration can satisfy number of expected active ASEs*/
688         if (num_of_ase_snk_per_dev >
689             data[i].device->GetAseCount(kLeAudioDirectionSink)) {
690           interesting_configuration = false;
691         }
692 
693         if (num_of_ase_src_per_dev >
694             data[i].device->GetAseCount(kLeAudioDirectionSource)) {
695           interesting_configuration = false;
696         }
697       }
698 
699       BidirectionalPair<AudioContexts> group_audio_locations = {
700           .sink = AudioContexts(context_type),
701           .source = AudioContexts(context_type)};
702 
703       /* Stimulate update of available context map */
704       group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type));
705       auto configuration_result =
706           group_->Configure(context_type, group_audio_locations);
707 
708       /* In case of configuration #ase is same as the one we expected to be
709        * activated verify, ASEs are actually active */
710       if (interesting_configuration &&
711           (directions_to_verify == configuration_directions)) {
712         ASSERT_TRUE(configuration_result);
713 
714         bool matching_conf = true;
715         /* Check if each of the devices has activated ASEs as expected */
716         for (int i = 0; i < data_size; i++) {
717           matching_conf &= TestGroupAseConfigurationVerdict(
718               data[i], configuration_directions);
719         }
720 
721         if (matching_conf) num_of_matching_configurations++;
722       }
723       group_->Deactivate();
724       TestAsesInactive();
725     }
726 
727     if (success_expected) {
728       ASSERT_TRUE((num_of_matching_configurations > 0));
729     } else {
730       ASSERT_TRUE(num_of_matching_configurations == 0);
731     }
732   }
733 
TestAsesActive(LeAudioCodecId codec_id,uint8_t sampling_frequency,uint8_t frame_duration,uint16_t octets_per_frame)734   void TestAsesActive(LeAudioCodecId codec_id, uint8_t sampling_frequency,
735                       uint8_t frame_duration, uint16_t octets_per_frame) {
736     bool active_ase = false;
737 
738     for (const auto& device : devices_) {
739       for (const auto& ase : device->ases_) {
740         if (!ase.active) continue;
741 
742         /* Configure may request only partial ases to be activated */
743         if (!active_ase && ase.active) active_ase = true;
744 
745         ASSERT_EQ(ase.codec_id, codec_id);
746 
747         /* FIXME: Validate other codec parameters than LC3 if any */
748         ASSERT_EQ(ase.codec_id, LeAudioCodecIdLc3);
749         if (ase.codec_id == LeAudioCodecIdLc3) {
750           ASSERT_EQ(ase.codec_config.sampling_frequency, sampling_frequency);
751           ASSERT_EQ(ase.codec_config.frame_duration, frame_duration);
752           ASSERT_EQ(ase.codec_config.octets_per_codec_frame, octets_per_frame);
753         }
754       }
755     }
756 
757     ASSERT_TRUE(active_ase);
758   }
759 
TestActiveAses(void)760   void TestActiveAses(void) {
761     for (auto& device : devices_) {
762       for (const auto& ase : device->ases_) {
763         if (ase.active) {
764           ASSERT_FALSE(ase.cis_id == ::le_audio::kInvalidCisId);
765         }
766       }
767     }
768   }
769 
TestAsesInactivated(const LeAudioDevice * device)770   void TestAsesInactivated(const LeAudioDevice* device) {
771     for (const auto& ase : device->ases_) {
772       ASSERT_FALSE(ase.active);
773       ASSERT_TRUE(ase.cis_id == ::le_audio::kInvalidCisId);
774       ASSERT_TRUE(ase.cis_conn_hdl == 0);
775     }
776   }
777 
TestAsesInactive()778   void TestAsesInactive() {
779     for (const auto& device : devices_) {
780       for (const auto& ase : device->ases_) {
781         ASSERT_FALSE(ase.active);
782       }
783     }
784   }
785 
TestLc3CodecConfig(LeAudioContextType context_type)786   void TestLc3CodecConfig(LeAudioContextType context_type) {
787     for (int i = Lc3SettingIdBegin; i < Lc3SettingIdEnd; i++) {
788       // test each configuration parameter against valid and invalid value
789       std::array<Lc3SettingId, 2> test_variants = {static_cast<Lc3SettingId>(i),
790                                                    Lc3SettingId::UNSUPPORTED};
791 
792       const bool is_lc3_setting_supported =
793           IsLc3SettingSupported(context_type, static_cast<Lc3SettingId>(i));
794 
795       for (const auto sf_variant : test_variants) {
796         uint8_t sampling_frequency = GetSamplingFrequency(sf_variant);
797         for (const auto fd_variant : test_variants) {
798           uint8_t frame_duration = GetFrameDuration(fd_variant);
799           for (const auto opcf_variant : test_variants) {
800             uint16_t octets_per_frame = GetOctetsPerCodecFrame(opcf_variant);
801 
802             PublishedAudioCapabilitiesBuilder pac_builder;
803             pac_builder.Add(LeAudioCodecIdLc3, sampling_frequency,
804                             frame_duration,
805                             kLeAudioCodecLC3ChannelCountSingleChannel |
806                                 kLeAudioCodecLC3ChannelCountTwoChannel,
807                             octets_per_frame);
808             for (auto& device : devices_) {
809               /* For simplicity configure both PACs with the same
810               parameters*/
811               device->snk_pacs_ = pac_builder.Get();
812               device->src_pacs_ = pac_builder.Get();
813             }
814 
815             bool success_expected = is_lc3_setting_supported;
816             if (is_lc3_setting_supported &&
817                 (sf_variant == Lc3SettingId::UNSUPPORTED ||
818                  fd_variant == Lc3SettingId::UNSUPPORTED ||
819                  opcf_variant == Lc3SettingId::UNSUPPORTED)) {
820               success_expected = false;
821             }
822 
823             /* Stimulate update of available context map */
824             group_->UpdateAudioContextTypeAvailability(
825                 AudioContexts(context_type));
826             BidirectionalPair<AudioContexts> group_audio_locations = {
827                 .sink = AudioContexts(context_type),
828                 .source = AudioContexts(context_type)};
829             ASSERT_EQ(success_expected,
830                       group_->Configure(context_type, group_audio_locations));
831             if (success_expected) {
832               TestAsesActive(LeAudioCodecIdLc3, sampling_frequency,
833                              frame_duration, octets_per_frame);
834               group_->Deactivate();
835             }
836 
837             TestAsesInactive();
838           }
839         }
840       }
841     }
842   }
843 
SetAsesToCachedConfiguration(LeAudioDevice * device,LeAudioContextType context_type,uint8_t directions)844   void SetAsesToCachedConfiguration(LeAudioDevice* device,
845                                     LeAudioContextType context_type,
846                                     uint8_t directions) {
847     for (struct ase& ase : device->ases_) {
848       if (ase.direction & directions) {
849         ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
850         ase.active = false;
851         ase.configured_for_context_type = context_type;
852       }
853     }
854   }
855 
856   const int group_id_ = 6;
857   std::vector<std::shared_ptr<LeAudioDevice>> devices_;
858   std::vector<RawAddress> addresses_;
859   LeAudioDeviceGroup* group_ = nullptr;
860   bluetooth::manager::MockBtmInterface btm_interface_;
861   controller::MockControllerInterface controller_interface_;
862   MockCsisClient mock_csis_client_module_;
863 };
864 
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_ringtone)865 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_ringtone) {
866   LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
867   TestGroupAseConfigurationData data(
868       {mono_speaker, kLeAudioCodecLC3ChannelCountSingleChannel,
869        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0});
870 
871   /* mono, change location as by default it is stereo */
872   mono_speaker->snk_audio_locations_ =
873       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
874   group_->ReloadAudioLocations();
875 
876   uint8_t direction_to_verify = kLeAudioDirectionSink;
877   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1,
878                             direction_to_verify);
879 }
880 
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_conversational)881 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_conversational) {
882   LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
883   TestGroupAseConfigurationData data({mono_speaker,
884                                       kLeAudioCodecLC3ChannelCountSingleChannel,
885                                       kLeAudioCodecLC3ChannelCountNone, 1, 0});
886 
887   /* mono, change location as by default it is stereo */
888   mono_speaker->snk_audio_locations_ =
889       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
890   group_->ReloadAudioLocations();
891 
892   /* Microphone should be used on the phone */
893   uint8_t direction_to_verify = kLeAudioDirectionSink;
894   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1,
895                             direction_to_verify);
896 }
897 
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_media)898 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_media) {
899   LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
900   TestGroupAseConfigurationData data({mono_speaker,
901                                       kLeAudioCodecLC3ChannelCountSingleChannel,
902                                       kLeAudioCodecLC3ChannelCountNone, 1, 0});
903 
904   /* mono, change location as by default it is stereo */
905   mono_speaker->snk_audio_locations_ =
906       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
907   group_->ReloadAudioLocations();
908 
909   uint8_t direction_to_verify = kLeAudioDirectionSink;
910   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
911                             direction_to_verify);
912 }
913 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_ringtone)914 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_ringtone) {
915   LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
916   TestGroupAseConfigurationData data(
917       {bounded_headphones, kLeAudioCodecLC3ChannelCountTwoChannel,
918        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
919 
920   uint8_t direction_to_verify = kLeAudioDirectionSink;
921   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1,
922                             direction_to_verify);
923 }
924 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_conversional)925 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_conversional) {
926   LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
927   TestGroupAseConfigurationData data({bounded_headphones,
928                                       kLeAudioCodecLC3ChannelCountTwoChannel,
929                                       kLeAudioCodecLC3ChannelCountNone, 2, 0});
930 
931   uint8_t direction_to_verify = kLeAudioDirectionSink;
932   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1,
933                             direction_to_verify);
934 }
935 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_media)936 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_media) {
937   LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
938   TestGroupAseConfigurationData data({bounded_headphones,
939                                       kLeAudioCodecLC3ChannelCountTwoChannel,
940                                       kLeAudioCodecLC3ChannelCountNone, 2, 0});
941 
942   uint8_t direction_to_verify = kLeAudioDirectionSink;
943   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
944                             direction_to_verify);
945 }
946 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_ringtone_mono_microphone)947 TEST_F(LeAudioAseConfigurationTest,
948        test_bounded_headset_ringtone_mono_microphone) {
949   LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
950   TestGroupAseConfigurationData data(
951       {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
952        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
953 
954   /* mono, change location as by default it is stereo */
955   bounded_headset->src_audio_locations_ =
956       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
957   group_->ReloadAudioLocations();
958 
959   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
960 }
961 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_ringtone_stereo_microphone)962 TEST_F(LeAudioAseConfigurationTest,
963        test_bounded_headset_ringtone_stereo_microphone) {
964   LeAudioDevice* bounded_headset = AddTestDevice(2, 2);
965   TestGroupAseConfigurationData data(
966       {bounded_headset,
967        kLeAudioCodecLC3ChannelCountSingleChannel |
968            kLeAudioCodecLC3ChannelCountTwoChannel,
969        kLeAudioCodecLC3ChannelCountSingleChannel |
970            kLeAudioCodecLC3ChannelCountTwoChannel,
971        2, 2});
972 
973   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
974 }
975 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_conversional)976 TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_conversional) {
977   LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
978   TestGroupAseConfigurationData data(
979       {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
980        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
981 
982   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
983 }
984 
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_media)985 TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_media) {
986   LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
987   TestGroupAseConfigurationData data(
988       {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
989        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
990 
991   uint8_t directions_to_verify = kLeAudioDirectionSink;
992   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
993                             directions_to_verify);
994 }
995 
TEST_F(LeAudioAseConfigurationTest,test_earbuds_ringtone)996 TEST_F(LeAudioAseConfigurationTest, test_earbuds_ringtone) {
997   LeAudioDevice* left = AddTestDevice(1, 1);
998   LeAudioDevice* right = AddTestDevice(1, 1);
999   TestGroupAseConfigurationData data[] = {
1000       {left, kLeAudioCodecLC3ChannelCountSingleChannel,
1001        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1},
1002       {right, kLeAudioCodecLC3ChannelCountSingleChannel,
1003        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1}};
1004 
1005   /* Change location as by default it is stereo */
1006   left->snk_audio_locations_ =
1007       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1008   left->src_audio_locations_ =
1009       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1010   right->snk_audio_locations_ =
1011       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1012   right->src_audio_locations_ =
1013       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1014   group_->ReloadAudioLocations();
1015 
1016   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, data, 2);
1017 }
1018 
TEST_F(LeAudioAseConfigurationTest,test_earbuds_conversional)1019 TEST_F(LeAudioAseConfigurationTest, test_earbuds_conversional) {
1020   LeAudioDevice* left = AddTestDevice(1, 1);
1021   LeAudioDevice* right = AddTestDevice(1, 1);
1022   TestGroupAseConfigurationData data[] = {
1023       {left, kLeAudioCodecLC3ChannelCountSingleChannel,
1024        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1},
1025       {right, kLeAudioCodecLC3ChannelCountSingleChannel,
1026        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1}};
1027 
1028   /* Change location as by default it is stereo */
1029   left->snk_audio_locations_ =
1030       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1031   left->src_audio_locations_ =
1032       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1033   right->snk_audio_locations_ =
1034       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1035   right->src_audio_locations_ =
1036       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1037   group_->ReloadAudioLocations();
1038 
1039   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, data, 2);
1040 }
1041 
TEST_F(LeAudioAseConfigurationTest,test_earbuds_media)1042 TEST_F(LeAudioAseConfigurationTest, test_earbuds_media) {
1043   LeAudioDevice* left = AddTestDevice(1, 1);
1044   LeAudioDevice* right = AddTestDevice(1, 1);
1045   TestGroupAseConfigurationData data[] = {
1046       {left, kLeAudioCodecLC3ChannelCountSingleChannel,
1047        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0},
1048       {right, kLeAudioCodecLC3ChannelCountSingleChannel,
1049        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0}};
1050 
1051   /* Change location as by default it is stereo */
1052   left->snk_audio_locations_ =
1053       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1054   left->src_audio_locations_ =
1055       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1056   right->snk_audio_locations_ =
1057       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1058   right->src_audio_locations_ =
1059       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1060   group_->ReloadAudioLocations();
1061 
1062   uint8_t directions_to_verify = kLeAudioDirectionSink;
1063   TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, 2,
1064                             directions_to_verify);
1065 }
1066 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_mono_ringtone)1067 TEST_F(LeAudioAseConfigurationTest, test_handsfree_mono_ringtone) {
1068   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1069   TestGroupAseConfigurationData data(
1070       {handsfree, kLeAudioCodecLC3ChannelCountSingleChannel,
1071        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1});
1072 
1073   handsfree->snk_audio_locations_ =
1074       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1075   handsfree->src_audio_locations_ =
1076       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1077   group_->ReloadAudioLocations();
1078 
1079   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1080 }
1081 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_stereo_ringtone)1082 TEST_F(LeAudioAseConfigurationTest, test_handsfree_stereo_ringtone) {
1083   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1084   TestGroupAseConfigurationData data(
1085       {handsfree,
1086        kLeAudioCodecLC3ChannelCountSingleChannel |
1087            kLeAudioCodecLC3ChannelCountTwoChannel,
1088        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1089 
1090   TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1091 }
1092 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_mono_conversional)1093 TEST_F(LeAudioAseConfigurationTest, test_handsfree_mono_conversional) {
1094   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1095   TestGroupAseConfigurationData data(
1096       {handsfree, kLeAudioCodecLC3ChannelCountSingleChannel,
1097        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1});
1098 
1099   handsfree->snk_audio_locations_ =
1100       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1101   handsfree->src_audio_locations_ =
1102       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1103   group_->ReloadAudioLocations();
1104 
1105   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1106 }
1107 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_stereo_conversional)1108 TEST_F(LeAudioAseConfigurationTest, test_handsfree_stereo_conversional) {
1109   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1110   TestGroupAseConfigurationData data(
1111       {handsfree,
1112        kLeAudioCodecLC3ChannelCountSingleChannel |
1113            kLeAudioCodecLC3ChannelCountTwoChannel,
1114        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1115 
1116   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1117 }
1118 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_full_cached_conversional)1119 TEST_F(LeAudioAseConfigurationTest, test_handsfree_full_cached_conversional) {
1120   LeAudioDevice* handsfree = AddTestDevice(0, 0, 1, 1);
1121   TestGroupAseConfigurationData data(
1122       {handsfree,
1123        kLeAudioCodecLC3ChannelCountSingleChannel |
1124            kLeAudioCodecLC3ChannelCountTwoChannel,
1125        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1126 
1127   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1128 }
1129 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_partial_cached_conversional)1130 TEST_F(LeAudioAseConfigurationTest,
1131        test_handsfree_partial_cached_conversional) {
1132   LeAudioDevice* handsfree = AddTestDevice(1, 0, 0, 1);
1133   TestGroupAseConfigurationData data(
1134       {handsfree,
1135        kLeAudioCodecLC3ChannelCountSingleChannel |
1136            kLeAudioCodecLC3ChannelCountTwoChannel,
1137        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1138 
1139   TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1140 }
1141 
TEST_F(LeAudioAseConfigurationTest,test_handsfree_media_two_channels_allocation_stereo)1142 TEST_F(LeAudioAseConfigurationTest,
1143        test_handsfree_media_two_channels_allocation_stereo) {
1144   LeAudioDevice* handsfree = AddTestDevice(1, 1);
1145   TestGroupAseConfigurationData data(
1146       {handsfree,
1147        kLeAudioCodecLC3ChannelCountSingleChannel |
1148            kLeAudioCodecLC3ChannelCountTwoChannel,
1149        kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
1150 
1151   uint8_t directions_to_verify = kLeAudioDirectionSink;
1152   TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
1153                             directions_to_verify);
1154 }
1155 
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_ringtone)1156 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_ringtone) {
1157   AddTestDevice(1, 1);
1158 
1159   TestLc3CodecConfig(LeAudioContextType::RINGTONE);
1160 }
1161 
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_conversional)1162 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_conversional) {
1163   AddTestDevice(1, 1);
1164 
1165   TestLc3CodecConfig(LeAudioContextType::CONVERSATIONAL);
1166 }
1167 
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_media)1168 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_media) {
1169   AddTestDevice(1, 1);
1170 
1171   TestLc3CodecConfig(LeAudioContextType::MEDIA);
1172 }
1173 
TEST_F(LeAudioAseConfigurationTest,test_unsupported_codec)1174 TEST_F(LeAudioAseConfigurationTest, test_unsupported_codec) {
1175   const LeAudioCodecId UnsupportedCodecId = {
1176       .coding_format = kLeAudioCodingFormatVendorSpecific,
1177       .vendor_company_id = 0xBAD,
1178       .vendor_codec_id = 0xC0DE,
1179   };
1180 
1181   LeAudioDevice* device = AddTestDevice(1, 0);
1182 
1183   PublishedAudioCapabilitiesBuilder pac_builder;
1184   pac_builder.Add(UnsupportedCodecId,
1185                   GetSamplingFrequency(Lc3SettingId::LC3_16_2),
1186                   GetFrameDuration(Lc3SettingId::LC3_16_2),
1187                   kLeAudioCodecLC3ChannelCountSingleChannel,
1188                   GetOctetsPerCodecFrame(Lc3SettingId::LC3_16_2));
1189   device->snk_pacs_ = pac_builder.Get();
1190   device->src_pacs_ = pac_builder.Get();
1191 
1192   ASSERT_FALSE(
1193       group_->Configure(LeAudioContextType::RINGTONE,
1194                         {AudioContexts(LeAudioContextType::RINGTONE),
1195                          AudioContexts(LeAudioContextType::RINGTONE)}));
1196   TestAsesInactive();
1197 }
1198 
TEST_F(LeAudioAseConfigurationTest,test_reconnection_media)1199 TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) {
1200   LeAudioDevice* left = AddTestDevice(2, 1);
1201   LeAudioDevice* right = AddTestDevice(2, 1);
1202 
1203   /* Change location as by default it is stereo */
1204   left->snk_audio_locations_ =
1205       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1206   left->src_audio_locations_ =
1207       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1208   right->snk_audio_locations_ =
1209       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1210   right->src_audio_locations_ =
1211       ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1212   group_->ReloadAudioLocations();
1213 
1214   TestGroupAseConfigurationData data[] = {
1215       {left, kLeAudioCodecLC3ChannelCountSingleChannel,
1216        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0},
1217       {right, kLeAudioCodecLC3ChannelCountSingleChannel,
1218        kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0}};
1219 
1220   auto all_configurations =
1221       ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1222           LeAudioContextType::MEDIA);
1223   ASSERT_NE(nullptr, all_configurations);
1224   ASSERT_NE(all_configurations->end(), all_configurations->begin());
1225   auto configuration = *all_configurations->begin();
1226 
1227   uint8_t direction_to_verify = kLeAudioDirectionSink;
1228   TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, configuration,
1229                              direction_to_verify);
1230 
1231   /* Generate CISes, symulate CIG creation and assign cis handles to ASEs.*/
1232   group_->CigGenerateCisIds(LeAudioContextType::MEDIA);
1233   std::vector<uint16_t> handles = {0x0012, 0x0013};
1234   group_->CigAssignCisConnHandles(handles);
1235   group_->CigAssignCisIds(left);
1236   group_->CigAssignCisIds(right);
1237 
1238   TestActiveAses();
1239   /* Left got disconnected */
1240   left->DeactivateAllAses();
1241 
1242   /* Unassign from the group*/
1243   group_->CigUnassignCis(left);
1244 
1245   TestAsesInactivated(left);
1246 
1247   /* Prepare reconfiguration */
1248   uint8_t number_of_active_ases = 1;  // Right one
1249   auto* ase = right->GetFirstActiveAseByDirection(kLeAudioDirectionSink);
1250   BidirectionalPair<AudioLocations> group_audio_locations = {
1251       .sink = *ase->codec_config.audio_channel_allocation,
1252       .source = *ase->codec_config.audio_channel_allocation};
1253 
1254   /* Get entry for the sink direction and use it to set configuration */
1255   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
1256   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(),
1257                                                      AudioContexts()};
1258   for (auto& ent : configuration->confs) {
1259     if (ent.direction == ::le_audio::types::kLeAudioDirectionSink) {
1260       left->ConfigureAses(ent, group_->GetConfigurationContextType(),
1261                           &number_of_active_ases, group_audio_locations,
1262                           audio_contexts, ccid_lists, false);
1263     }
1264   }
1265 
1266   ASSERT_TRUE(number_of_active_ases == 2);
1267   ASSERT_TRUE(group_audio_locations.sink == kChannelAllocationStereo);
1268 
1269   uint8_t directions_to_verify = ::le_audio::types::kLeAudioDirectionSink;
1270   for (int i = 0; i < 2; i++) {
1271     TestGroupAseConfigurationVerdict(data[i], directions_to_verify);
1272   }
1273 
1274   /* Before device is rejoining, and group already exist, cis handles are
1275    * assigned before sending codec config
1276    */
1277   group_->CigAssignCisIds(left);
1278   group_->CigAssignCisConnHandlesToAses(left);
1279 
1280   TestActiveAses();
1281 }
1282 
1283 /*
1284  * Failure happens when restarting conversational scenario and when
1285  * remote device uses caching.
1286  *
1287  * Failing scenario.
1288  * 1. Conversational scenario set up with
1289  *  - ASE 1 and ASE 5 using bidirectional CIS 0
1290  *  - ASE 2  being unidirectional on CIS 1
1291  * 2. Stop stream and go to CONFIGURED STATE.
1292  * 3. Trying to configure ASES again would end up in incorrectly assigned
1293  *    CISes
1294  *  - ASE 1 and ASE 5 set to CIS 0
1295  *  - ASE 2 stay on CIS 1 but ASE 5 got reassigned to CIS 1 (error)
1296  *
1297  * The problem is finding matching_bidir_ase which shall not be just next
1298  * active ase with different direction, but it shall be also available (Cis
1299  * not assigned) or assigned to the same CIS ID as the opposite direction.
1300  */
TEST_F(LeAudioAseConfigurationTest,test_reactivation_conversational)1301 TEST_F(LeAudioAseConfigurationTest, test_reactivation_conversational) {
1302   LeAudioDevice* tws_headset = AddTestDevice(0, 0, 2, 1, true);
1303 
1304   /* Change location as by default it is stereo */
1305   tws_headset->snk_audio_locations_ = kChannelAllocationStereo;
1306   tws_headset->src_audio_locations_ =
1307       ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1308   group_->ReloadAudioLocations();
1309 
1310   auto all_configurations =
1311       ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1312           LeAudioContextType::CONVERSATIONAL);
1313   ASSERT_NE(nullptr, all_configurations);
1314   ASSERT_NE(all_configurations->end(), all_configurations->begin());
1315 
1316   /* Pick TWS configuration for conversational */
1317   auto iter = std::find_if(all_configurations->begin(),
1318                            all_configurations->end(), [](auto& configuration) {
1319                              return configuration->name ==
1320                                     "SingleDev_OneChanStereoSnk_OneChanMonoSrc_"
1321                                     "16_2_Low_Latency";
1322                            });
1323 
1324   ASSERT_NE(iter, all_configurations->end());
1325 
1326   auto conversational_configuration = *iter;
1327 
1328   // Build PACs for device
1329   PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
1330   snk_pac_builder.Reset();
1331   src_pac_builder.Reset();
1332 
1333   /* Create PACs for conversational scenario which covers also media. Single
1334    * PAC for each direction is enough.
1335    */
1336   for (const auto& entry : (*conversational_configuration).confs) {
1337     if (entry.direction == kLeAudioDirectionSink) {
1338       snk_pac_builder.Add(entry.codec, 1);
1339     } else {
1340       src_pac_builder.Add(entry.codec, 1);
1341     }
1342   }
1343 
1344   tws_headset->snk_pacs_ = snk_pac_builder.Get();
1345   tws_headset->src_pacs_ = src_pac_builder.Get();
1346 
1347   ::le_audio::types::AudioLocations group_snk_audio_locations = 0;
1348   ::le_audio::types::AudioLocations group_src_audio_locations = 0;
1349   uint8_t number_of_already_active_ases = 0;
1350 
1351   BidirectionalPair<AudioLocations> group_audio_locations = {
1352       .sink = group_snk_audio_locations, .source = group_src_audio_locations};
1353 
1354   /* Get entry for the sink direction and use it to set configuration */
1355   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
1356   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(),
1357                                                      AudioContexts()};
1358 
1359   /* Get entry for the sink direction and use it to set configuration */
1360   for (auto& ent : conversational_configuration->confs) {
1361     tws_headset->ConfigureAses(ent, group_->GetConfigurationContextType(),
1362                                &number_of_already_active_ases,
1363                                group_audio_locations, audio_contexts,
1364                                ccid_lists, false);
1365   }
1366 
1367   /* Generate CISes, simulate CIG creation and assign cis handles to ASEs.*/
1368   std::vector<uint16_t> handles = {0x0012, 0x0013};
1369   group_->CigGenerateCisIds(LeAudioContextType::CONVERSATIONAL);
1370   group_->CigAssignCisConnHandles(handles);
1371   group_->CigAssignCisIds(tws_headset);
1372 
1373   TestActiveAses();
1374 
1375   /* Simulate stopping stream with caching codec configuration in ASEs */
1376   group_->CigUnassignCis(tws_headset);
1377   SetAsesToCachedConfiguration(tws_headset, LeAudioContextType::CONVERSATIONAL,
1378                                kLeAudioDirectionSink | kLeAudioDirectionSource);
1379 
1380   /* As context type is the same as previous and no changes were made in PACs
1381    * the same CIS ID can be used. This would lead to only activating group
1382    * without reconfiguring CIG.
1383    */
1384   group_->Activate(LeAudioContextType::CONVERSATIONAL);
1385 
1386   TestActiveAses();
1387 
1388   /* Verify ASEs assigned CISes by counting assigned to bi-directional CISes */
1389   int bi_dir_ases_count = std::count_if(
1390       tws_headset->ases_.begin(), tws_headset->ases_.end(), [=](auto& ase) {
1391         return this->group_->cises_[ase.cis_id].type ==
1392                CisType::CIS_TYPE_BIDIRECTIONAL;
1393       });
1394 
1395   /* Only two ASEs can be bonded to one bi-directional CIS */
1396   ASSERT_EQ(bi_dir_ases_count, 2);
1397 }
1398 
TEST_F(LeAudioAseConfigurationTest,test_num_of_connected)1399 TEST_F(LeAudioAseConfigurationTest, test_num_of_connected) {
1400   auto device1 = AddTestDevice(2, 1);
1401   auto device2 = AddTestDevice(2, 1);
1402   ASSERT_EQ(2, group_->NumOfConnected());
1403 
1404   // Drop the ACL connection
1405   device1->conn_id_ = GATT_INVALID_CONN_ID;
1406   ASSERT_EQ(1, group_->NumOfConnected());
1407 
1408   // Fully disconnect the other device
1409   device2->SetConnectionState(DeviceConnectState::DISCONNECTING);
1410   ASSERT_EQ(0, group_->NumOfConnected());
1411 }
1412 
1413 /*
1414  * Failure happens when there is no matching single device scenario for dual
1415  * device scanario. Stereo location for single earbud seems to be invalid but
1416  * possible and stack should handle it.
1417  *
1418  * Failing scenario:
1419  * 1. Connect two - stereo location earbuds
1420  * 2. Disconnect one of earbud
1421  * 3. CIS generator will look for dual device scenario with matching strategy
1422  * 4. There is no dual device scenario with strategy stereo channels per device
1423  */
TEST_F(LeAudioAseConfigurationTest,test_getting_cis_count)1424 TEST_F(LeAudioAseConfigurationTest, test_getting_cis_count) {
1425   LeAudioDevice* left = AddTestDevice(2, 1);
1426   LeAudioDevice* right = AddTestDevice(0, 0, 0, 0, false, true);
1427 
1428   /* Change location as by default it is stereo */
1429   left->snk_audio_locations_ = kChannelAllocationStereo;
1430   right->snk_audio_locations_ = kChannelAllocationStereo;
1431   group_->ReloadAudioLocations();
1432 
1433   auto all_configurations =
1434       ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1435           LeAudioContextType::MEDIA);
1436   ASSERT_NE(nullptr, all_configurations);
1437   ASSERT_NE(all_configurations->end(), all_configurations->begin());
1438 
1439   /* Pick configuration for media */
1440   auto iter = std::find_if(all_configurations->begin(),
1441                            all_configurations->end(), [](auto& configuration) {
1442                              return configuration->name ==
1443                                     "SingleDev_TwoChanStereoSnk_48_4_High_"
1444                                     "Reliability";
1445                            });
1446 
1447   ASSERT_NE(iter, all_configurations->end());
1448 
1449   auto media_configuration = *iter;
1450 
1451   // Build PACs for device
1452   PublishedAudioCapabilitiesBuilder snk_pac_builder;
1453   snk_pac_builder.Reset();
1454 
1455   /* Create PACs for media. Single PAC for each direction is enough.
1456    */
1457   for (const auto& entry : (*media_configuration).confs) {
1458     if (entry.direction == kLeAudioDirectionSink) {
1459       snk_pac_builder.Add(LeAudioCodecIdLc3, 0x00b5, 0x03, 0x03, 0x001a, 0x00f0,
1460                           2);
1461     }
1462   }
1463 
1464   left->snk_pacs_ = snk_pac_builder.Get();
1465   left->snk_pacs_ = snk_pac_builder.Get();
1466 
1467   ::le_audio::types::AudioLocations group_snk_audio_locations = 3;
1468   ::le_audio::types::AudioLocations group_src_audio_locations = 0;
1469   uint8_t number_of_already_active_ases = 0;
1470 
1471   BidirectionalPair<AudioLocations> group_audio_locations = {
1472       .sink = group_snk_audio_locations, .source = group_src_audio_locations};
1473 
1474   /* Get entry for the sink direction and use it to set configuration */
1475   BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
1476   BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(),
1477                                                      AudioContexts()};
1478 
1479   /* Get entry for the sink direction and use it to set configuration */
1480   for (auto& ent : media_configuration->confs) {
1481     left->ConfigureAses(ent, group_->GetConfigurationContextType(),
1482                         &number_of_already_active_ases, group_audio_locations,
1483                         audio_contexts, ccid_lists, false);
1484   }
1485 
1486   /* Generate CIS, simulate CIG creation and assign cis handles to ASEs.*/
1487   std::vector<uint16_t> handles = {0x0012};
1488   group_->CigGenerateCisIds(LeAudioContextType::MEDIA);
1489 
1490   /* Verify prepared CISes by counting generated entries */
1491   int snk_cis_count = std::count_if(
1492       this->group_->cises_.begin(), this->group_->cises_.end(), [](auto& cis) {
1493         return cis.type == CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
1494       });
1495 
1496   /* Two CIS should be prepared for dual dev expected set */
1497   ASSERT_EQ(snk_cis_count, 2);
1498 }
1499 
1500 }  // namespace
1501 }  // namespace internal
1502 }  // namespace le_audio
1503 }  // namespace bluetooth
1504