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::LeAudioContextType;
47 using testing::_;
48 using testing::Invoke;
49 using testing::Return;
50 using testing::Test;
51
GetTestAddress(int index)52 RawAddress GetTestAddress(int index) {
53 CHECK_LT(index, UINT8_MAX);
54 RawAddress result = {
55 {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
56 return result;
57 }
58
59 class LeAudioDevicesTest : public Test {
60 protected:
SetUp()61 void SetUp() override {
62 devices_ = new LeAudioDevices();
63 bluetooth::manager::SetMockBtmInterface(&btm_interface);
64 controller::SetMockControllerInterface(&controller_interface_);
65 }
66
TearDown()67 void TearDown() override {
68 controller::SetMockControllerInterface(nullptr);
69 bluetooth::manager::SetMockBtmInterface(nullptr);
70 delete devices_;
71 }
72
73 LeAudioDevices* devices_ = nullptr;
74 bluetooth::manager::MockBtmInterface btm_interface;
75 controller::MockControllerInterface controller_interface_;
76 };
77
TEST_F(LeAudioDevicesTest,test_add)78 TEST_F(LeAudioDevicesTest, test_add) {
79 RawAddress test_address_0 = GetTestAddress(0);
80 ASSERT_EQ((size_t)0, devices_->Size());
81 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
82 ASSERT_EQ((size_t)1, devices_->Size());
83 devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 1);
84 ASSERT_EQ((size_t)2, devices_->Size());
85 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
86 ASSERT_EQ((size_t)2, devices_->Size());
87 devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER, 2);
88 ASSERT_EQ((size_t)2, devices_->Size());
89 }
90
TEST_F(LeAudioDevicesTest,test_remove)91 TEST_F(LeAudioDevicesTest, test_remove) {
92 RawAddress test_address_0 = GetTestAddress(0);
93 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
94 RawAddress test_address_1 = GetTestAddress(1);
95 devices_->Add(test_address_1, DeviceConnectState::CONNECTING_BY_USER);
96 RawAddress test_address_2 = GetTestAddress(2);
97 devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
98 ASSERT_EQ((size_t)3, devices_->Size());
99 devices_->Remove(test_address_0);
100 ASSERT_EQ((size_t)2, devices_->Size());
101 devices_->Remove(GetTestAddress(3));
102 ASSERT_EQ((size_t)2, devices_->Size());
103 devices_->Remove(test_address_0);
104 ASSERT_EQ((size_t)2, devices_->Size());
105 }
106
TEST_F(LeAudioDevicesTest,test_find_by_address_success)107 TEST_F(LeAudioDevicesTest, test_find_by_address_success) {
108 RawAddress test_address_0 = GetTestAddress(0);
109 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
110 RawAddress test_address_1 = GetTestAddress(1);
111 devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
112 RawAddress test_address_2 = GetTestAddress(2);
113 devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
114 LeAudioDevice* device = devices_->FindByAddress(test_address_1);
115 ASSERT_NE(nullptr, device);
116 ASSERT_EQ(test_address_1, device->address_);
117 }
118
TEST_F(LeAudioDevicesTest,test_find_by_address_failed)119 TEST_F(LeAudioDevicesTest, test_find_by_address_failed) {
120 RawAddress test_address_0 = GetTestAddress(0);
121 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
122 RawAddress test_address_2 = GetTestAddress(2);
123 devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
124 LeAudioDevice* device = devices_->FindByAddress(GetTestAddress(1));
125 ASSERT_EQ(nullptr, device);
126 }
127
TEST_F(LeAudioDevicesTest,test_get_by_address_success)128 TEST_F(LeAudioDevicesTest, test_get_by_address_success) {
129 RawAddress test_address_0 = GetTestAddress(0);
130 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
131 RawAddress test_address_1 = GetTestAddress(1);
132 devices_->Add(test_address_1, DeviceConnectState::DISCONNECTED);
133 RawAddress test_address_2 = GetTestAddress(2);
134 devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
135 std::shared_ptr<LeAudioDevice> device =
136 devices_->GetByAddress(test_address_1);
137 ASSERT_NE(nullptr, device);
138 ASSERT_EQ(test_address_1, device->address_);
139 }
140
TEST_F(LeAudioDevicesTest,test_get_by_address_failed)141 TEST_F(LeAudioDevicesTest, test_get_by_address_failed) {
142 RawAddress test_address_0 = GetTestAddress(0);
143 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
144 RawAddress test_address_2 = GetTestAddress(2);
145 devices_->Add(test_address_2, DeviceConnectState::CONNECTING_BY_USER);
146 std::shared_ptr<LeAudioDevice> device =
147 devices_->GetByAddress(GetTestAddress(1));
148 ASSERT_EQ(nullptr, device);
149 }
150
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_success)151 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_success) {
152 devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
153 RawAddress test_address_0 = GetTestAddress(0);
154 devices_->Add(test_address_0, DeviceConnectState::CONNECTING_BY_USER);
155 devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
156 LeAudioDevice* device = devices_->FindByAddress(test_address_0);
157 device->conn_id_ = 0x0005;
158 ASSERT_EQ(device, devices_->FindByConnId(0x0005));
159 }
160
TEST_F(LeAudioDevicesTest,test_find_by_conn_id_failed)161 TEST_F(LeAudioDevicesTest, test_find_by_conn_id_failed) {
162 devices_->Add(GetTestAddress(1), DeviceConnectState::CONNECTING_BY_USER);
163 devices_->Add(GetTestAddress(0), DeviceConnectState::CONNECTING_BY_USER);
164 devices_->Add(GetTestAddress(4), DeviceConnectState::CONNECTING_BY_USER);
165 ASSERT_EQ(nullptr, devices_->FindByConnId(0x0006));
166 }
167
168 /* TODO: Add FindByCisConnHdl test cases (ASE) */
169
170 } // namespace
171
172 namespace {
173 using namespace ::le_audio::codec_spec_caps;
174 using namespace ::le_audio::set_configurations;
175 using namespace ::le_audio::types;
176
177 static const hdl_pair hdl_pair_nil = hdl_pair(0x0000, 0x0000);
178
179 enum class Lc3SettingId {
180 _BEGIN,
181 LC3_8_1 = _BEGIN,
182 LC3_8_2,
183 LC3_16_1,
184 LC3_16_2,
185 LC3_24_1,
186 LC3_24_2,
187 LC3_32_1,
188 LC3_32_2,
189 LC3_441_1,
190 LC3_441_2,
191 LC3_48_1,
192 LC3_48_2,
193 LC3_48_3,
194 LC3_48_4,
195 LC3_48_5,
196 LC3_48_6,
197 LC3_VND_1,
198 _END,
199 UNSUPPORTED = _END,
200 };
201 static constexpr int Lc3SettingIdBegin = static_cast<int>(Lc3SettingId::_BEGIN);
202 static constexpr int Lc3SettingIdEnd = static_cast<int>(Lc3SettingId::_END);
203
IsLc3SettingSupported(LeAudioContextType context_type,Lc3SettingId id)204 bool IsLc3SettingSupported(LeAudioContextType context_type, Lc3SettingId id) {
205 /* Update those values, on any change of codec linked with content type */
206 switch (context_type) {
207 case LeAudioContextType::RINGTONE:
208 case LeAudioContextType::CONVERSATIONAL:
209 if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
210 id == Lc3SettingId::LC3_24_1 || id == Lc3SettingId::LC3_24_2 ||
211 id == Lc3SettingId::LC3_32_1 || id == Lc3SettingId::LC3_32_2 ||
212 id == Lc3SettingId::LC3_48_1 || id == Lc3SettingId::LC3_48_2 ||
213 id == Lc3SettingId::LC3_48_3 || id == Lc3SettingId::LC3_48_4 ||
214 id == Lc3SettingId::LC3_VND_1)
215 return true;
216
217 break;
218
219 case LeAudioContextType::MEDIA:
220 case LeAudioContextType::ALERTS:
221 case LeAudioContextType::INSTRUCTIONAL:
222 case LeAudioContextType::NOTIFICATIONS:
223 case LeAudioContextType::EMERGENCYALARM:
224 case LeAudioContextType::UNSPECIFIED:
225 if (id == Lc3SettingId::LC3_16_1 || id == Lc3SettingId::LC3_16_2 ||
226 id == Lc3SettingId::LC3_48_4 || id == Lc3SettingId::LC3_48_2 ||
227 id == Lc3SettingId::LC3_VND_1 || id == Lc3SettingId::LC3_24_2)
228 return true;
229
230 break;
231
232 default:
233 if (id == Lc3SettingId::LC3_16_2) return true;
234
235 break;
236 };
237
238 return false;
239 }
240
241 static constexpr uint8_t kLeAudioSamplingFreqRfu = 0x0E;
GetSamplingFrequency(Lc3SettingId id)242 uint8_t GetSamplingFrequency(Lc3SettingId id) {
243 switch (id) {
244 case Lc3SettingId::LC3_8_1:
245 case Lc3SettingId::LC3_8_2:
246 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq8000Hz;
247 case Lc3SettingId::LC3_16_1:
248 case Lc3SettingId::LC3_16_2:
249 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq16000Hz;
250 case Lc3SettingId::LC3_24_1:
251 case Lc3SettingId::LC3_24_2:
252 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq24000Hz;
253 case Lc3SettingId::LC3_32_1:
254 case Lc3SettingId::LC3_32_2:
255 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq32000Hz;
256 case Lc3SettingId::LC3_441_1:
257 case Lc3SettingId::LC3_441_2:
258 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq44100Hz;
259 case Lc3SettingId::LC3_48_1:
260 case Lc3SettingId::LC3_48_2:
261 case Lc3SettingId::LC3_48_3:
262 case Lc3SettingId::LC3_48_4:
263 case Lc3SettingId::LC3_48_5:
264 case Lc3SettingId::LC3_48_6:
265 case Lc3SettingId::LC3_VND_1:
266 return ::le_audio::codec_spec_conf::kLeAudioSamplingFreq48000Hz;
267 case Lc3SettingId::UNSUPPORTED:
268 return kLeAudioSamplingFreqRfu;
269 }
270 }
271
272 static constexpr uint8_t kLeAudioCodecLC3FrameDurRfu = 0x02;
GetFrameDuration(Lc3SettingId id)273 uint8_t GetFrameDuration(Lc3SettingId id) {
274 switch (id) {
275 case Lc3SettingId::LC3_8_1:
276 case Lc3SettingId::LC3_16_1:
277 case Lc3SettingId::LC3_24_1:
278 case Lc3SettingId::LC3_32_1:
279 case Lc3SettingId::LC3_441_1:
280 case Lc3SettingId::LC3_48_1:
281 case Lc3SettingId::LC3_48_3:
282 case Lc3SettingId::LC3_48_5:
283 return ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur7500us;
284 case Lc3SettingId::LC3_8_2:
285 case Lc3SettingId::LC3_16_2:
286 case Lc3SettingId::LC3_24_2:
287 case Lc3SettingId::LC3_32_2:
288 case Lc3SettingId::LC3_441_2:
289 case Lc3SettingId::LC3_48_2:
290 case Lc3SettingId::LC3_48_4:
291 case Lc3SettingId::LC3_48_6:
292 case Lc3SettingId::LC3_VND_1:
293 return ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur10000us;
294 case Lc3SettingId::UNSUPPORTED:
295 return kLeAudioCodecLC3FrameDurRfu;
296 }
297 }
298
299 static constexpr uint8_t kLeAudioCodecLC3OctetsPerCodecFrameInvalid = 0;
GetOctetsPerCodecFrame(Lc3SettingId id)300 uint16_t GetOctetsPerCodecFrame(Lc3SettingId id) {
301 switch (id) {
302 case Lc3SettingId::LC3_8_1:
303 return 26;
304 case Lc3SettingId::LC3_8_2:
305 case Lc3SettingId::LC3_16_1:
306 return 30;
307 case Lc3SettingId::LC3_16_2:
308 return 40;
309 case Lc3SettingId::LC3_24_1:
310 return 45;
311 case Lc3SettingId::LC3_24_2:
312 case Lc3SettingId::LC3_32_1:
313 return 60;
314 case Lc3SettingId::LC3_32_2:
315 return 80;
316 case Lc3SettingId::LC3_441_1:
317 return 97;
318 case Lc3SettingId::LC3_441_2:
319 return 130;
320 case Lc3SettingId::LC3_48_1:
321 return 75;
322 case Lc3SettingId::LC3_48_2:
323 case Lc3SettingId::LC3_VND_1:
324 return 100;
325 case Lc3SettingId::LC3_48_3:
326 return 90;
327 case Lc3SettingId::LC3_48_4:
328 return 120;
329 case Lc3SettingId::LC3_48_5:
330 return 116;
331 case Lc3SettingId::LC3_48_6:
332 return 155;
333 case Lc3SettingId::UNSUPPORTED:
334 return kLeAudioCodecLC3OctetsPerCodecFrameInvalid;
335 }
336 }
337
338 class PublishedAudioCapabilitiesBuilder {
339 public:
PublishedAudioCapabilitiesBuilder()340 PublishedAudioCapabilitiesBuilder() {}
341
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)342 void Add(LeAudioCodecId codec_id, uint8_t conf_sampling_frequency,
343 uint8_t conf_frame_duration, uint8_t audio_channel_counts,
344 uint16_t octets_per_frame, uint8_t codec_frames_per_sdu = 0) {
345 uint16_t sampling_frequencies =
346 SamplingFreqConfig2Capability(conf_sampling_frequency);
347 uint8_t frame_durations =
348 FrameDurationConfig2Capability(conf_frame_duration);
349 uint8_t max_codec_frames_per_sdu = codec_frames_per_sdu;
350 uint32_t octets_per_frame_range =
351 octets_per_frame | (octets_per_frame << 16);
352
353 pac_records_.push_back(
354 acs_ac_record({.codec_id = codec_id,
355 .codec_spec_caps = LeAudioLtvMap({
356 {kLeAudioCodecLC3TypeSamplingFreq,
357 UINT16_TO_VEC_UINT8(sampling_frequencies)},
358 {kLeAudioCodecLC3TypeFrameDuration,
359 UINT8_TO_VEC_UINT8(frame_durations)},
360 {kLeAudioCodecLC3TypeAudioChannelCounts,
361 UINT8_TO_VEC_UINT8(audio_channel_counts)},
362 {kLeAudioCodecLC3TypeOctetPerFrame,
363 UINT32_TO_VEC_UINT8(octets_per_frame_range)},
364 {kLeAudioCodecLC3TypeMaxCodecFramesPerSdu,
365 UINT8_TO_VEC_UINT8(max_codec_frames_per_sdu)},
366 }),
367 .metadata = std::vector<uint8_t>(0)}));
368 }
369
Add(const CodecCapabilitySetting & setting,uint8_t audio_channel_counts)370 void Add(const CodecCapabilitySetting& setting,
371 uint8_t audio_channel_counts) {
372 if (setting.id != LeAudioCodecIdLc3) return;
373
374 const LeAudioLc3Config config = std::get<LeAudioLc3Config>(setting.config);
375
376 Add(setting.id, *config.sampling_frequency, *config.frame_duration,
377 audio_channel_counts, *config.octets_per_codec_frame);
378 }
379
Reset()380 void Reset() { pac_records_.clear(); }
381
Get()382 PublishedAudioCapabilities Get() {
383 return PublishedAudioCapabilities({{hdl_pair_nil, pac_records_}});
384 }
385
386 private:
387 std::vector<acs_ac_record> pac_records_;
388 };
389
390 struct TestGroupAseConfigurationData {
391 LeAudioDevice* device;
392 uint8_t audio_channel_counts_snk;
393 uint8_t audio_channel_counts_src;
394
395 /* Note, do not confuse ASEs with channels num. */
396 uint8_t expected_active_channel_num_snk;
397 uint8_t expected_active_channel_num_src;
398 };
399
400 class LeAudioAseConfigurationTest : public Test {
401 protected:
SetUp()402 void SetUp() override {
403 group_ = new LeAudioDeviceGroup(group_id_);
404 bluetooth::manager::SetMockBtmInterface(&btm_interface_);
405 controller::SetMockControllerInterface(&controller_interface_);
406 ::le_audio::AudioSetConfigurationProvider::Initialize();
407 MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
408 ON_CALL(mock_csis_client_module_, Get())
409 .WillByDefault(Return(&mock_csis_client_module_));
410 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
411 .WillByDefault(Return(true));
412 ON_CALL(mock_csis_client_module_, GetDeviceList(_))
413 .WillByDefault(Invoke([this](int group_id) { return addresses_; }));
414 ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
415 .WillByDefault(
416 Invoke([this](int group_id) { return (int)(addresses_.size()); }));
417 }
418
TearDown()419 void TearDown() override {
420 controller::SetMockControllerInterface(nullptr);
421 bluetooth::manager::SetMockBtmInterface(nullptr);
422 devices_.clear();
423 addresses_.clear();
424 delete group_;
425 ::le_audio::AudioSetConfigurationProvider::Cleanup();
426 }
427
AddTestDevice(int snk_ase_num,int src_ase_num,int snk_ase_num_cached=0,int src_ase_num_cached=0)428 LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num,
429 int snk_ase_num_cached = 0,
430 int src_ase_num_cached = 0) {
431 int index = group_->Size() + 1;
432 auto device = (std::make_shared<LeAudioDevice>(
433 GetTestAddress(index), DeviceConnectState::DISCONNECTED));
434 devices_.push_back(device);
435 LOG_INFO(" addresses %d", (int)(addresses_.size()));
436 addresses_.push_back(device->address_);
437 LOG_INFO(" Addresses %d", (int)(addresses_.size()));
438
439 group_->AddNode(device);
440
441 int ase_id = 1;
442 for (int i = 0; i < src_ase_num; i++) {
443 device->ases_.emplace_back(0x0000, 0x0000, kLeAudioDirectionSource,
444 ase_id++);
445 }
446
447 for (int i = 0; i < snk_ase_num; i++) {
448 device->ases_.emplace_back(0x0000, 0x0000, kLeAudioDirectionSink,
449 ase_id++);
450 }
451
452 for (int i = 0; i < src_ase_num_cached; i++) {
453 struct ase ase(0x0000, 0x0000, kLeAudioDirectionSource, ase_id++);
454 ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
455 device->ases_.push_back(ase);
456 }
457
458 for (int i = 0; i < snk_ase_num_cached; i++) {
459 struct ase ase(0x0000, 0x0000, kLeAudioDirectionSink, ase_id++);
460 ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
461 device->ases_.push_back(ase);
462 }
463
464 device->SetSupportedContexts(AudioContexts(kLeAudioContextAllTypes),
465 AudioContexts(kLeAudioContextAllTypes));
466 device->SetAvailableContexts(AudioContexts(kLeAudioContextAllTypes),
467 AudioContexts(kLeAudioContextAllTypes));
468 device->snk_audio_locations_ =
469 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
470 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
471 device->src_audio_locations_ =
472 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
473 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
474
475 device->conn_id_ = index;
476 device->SetConnectionState(DeviceConnectState::CONNECTED);
477 group_->ReloadAudioDirections();
478 group_->ReloadAudioLocations();
479 return device.get();
480 }
481
TestGroupAseConfigurationVerdict(const TestGroupAseConfigurationData & data,uint8_t directions_to_verify)482 bool TestGroupAseConfigurationVerdict(
483 const TestGroupAseConfigurationData& data, uint8_t directions_to_verify) {
484 uint8_t active_channel_num_snk = 0;
485 uint8_t active_channel_num_src = 0;
486
487 if (directions_to_verify == 0) return false;
488 if (data.device->HaveActiveAse() == 0) return false;
489
490 for (ase* ase = data.device->GetFirstActiveAse(); ase;
491 ase = data.device->GetNextActiveAse(ase)) {
492 if (ase->direction == kLeAudioDirectionSink)
493 active_channel_num_snk +=
494 GetAudioChannelCounts(*ase->codec_config.audio_channel_allocation);
495 else
496 active_channel_num_src +=
497 GetAudioChannelCounts(*ase->codec_config.audio_channel_allocation);
498 }
499
500 bool result = true;
501 if (directions_to_verify & kLeAudioDirectionSink) {
502 result &=
503 (data.expected_active_channel_num_snk == active_channel_num_snk);
504 }
505 if (directions_to_verify & kLeAudioDirectionSource) {
506 result &=
507 (data.expected_active_channel_num_src == active_channel_num_src);
508 }
509
510 return result;
511 }
512
SetCisInformationToActiveAse(void)513 void SetCisInformationToActiveAse(void) {
514 uint8_t cis_id = 1;
515 uint16_t cis_conn_hdl = 0x0060;
516
517 for (auto& device : devices_) {
518 for (auto& ase : device->ases_) {
519 if (ase.active) {
520 ase.cis_id = cis_id++;
521 ase.cis_conn_hdl = cis_conn_hdl++;
522 }
523 }
524 }
525 }
526
TestSingleAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,const AudioSetConfiguration * audio_set_conf,uint8_t directions_to_verify)527 void TestSingleAseConfiguration(LeAudioContextType context_type,
528 TestGroupAseConfigurationData* data,
529 uint8_t data_size,
530 const AudioSetConfiguration* audio_set_conf,
531 uint8_t directions_to_verify) {
532 // the configuration should fail if there are no active ases expected
533 bool success_expected = data_size > 0;
534 uint8_t configuration_directions = 0;
535
536 for (int i = 0; i < data_size; i++) {
537 success_expected &= (data[i].expected_active_channel_num_snk +
538 data[i].expected_active_channel_num_src) > 0;
539
540 /* Prepare PAC's */
541 PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
542 for (const auto& entry : (*audio_set_conf).confs) {
543 if (entry.direction == kLeAudioDirectionSink) {
544 configuration_directions |= kLeAudioDirectionSink;
545 snk_pac_builder.Add(entry.codec, data[i].audio_channel_counts_snk);
546 } else {
547 configuration_directions |= kLeAudioDirectionSource;
548 src_pac_builder.Add(entry.codec, data[i].audio_channel_counts_src);
549 }
550 }
551
552 data[i].device->snk_pacs_ = snk_pac_builder.Get();
553 data[i].device->src_pacs_ = src_pac_builder.Get();
554 }
555
556 /* Stimulate update of available context map */
557 group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type));
558 ASSERT_EQ(success_expected,
559 group_->Configure(context_type, AudioContexts(context_type)));
560
561 bool result = true;
562 for (int i = 0; i < data_size; i++) {
563 result &= TestGroupAseConfigurationVerdict(
564 data[i], directions_to_verify & configuration_directions);
565 }
566 ASSERT_TRUE(result);
567 }
568
getNumOfAses(LeAudioDevice * device,uint8_t direction)569 int getNumOfAses(LeAudioDevice* device, uint8_t direction) {
570 return std::count_if(
571 device->ases_.begin(), device->ases_.end(),
572 [direction](auto& a) { return a.direction == direction; });
573 }
574
TestGroupAseConfiguration(LeAudioContextType context_type,TestGroupAseConfigurationData * data,uint8_t data_size,uint8_t directions_to_verify=kLeAudioDirectionSink|kLeAudioDirectionSource)575 void TestGroupAseConfiguration(
576 LeAudioContextType context_type, TestGroupAseConfigurationData* data,
577 uint8_t data_size,
578 uint8_t directions_to_verify = kLeAudioDirectionSink |
579 kLeAudioDirectionSource) {
580 const auto* configurations =
581 ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
582 context_type);
583
584 bool success_expected = directions_to_verify != 0;
585 int num_of_matching_configurations = 0;
586 for (const auto& audio_set_conf : *configurations) {
587 bool interesting_configuration = true;
588 uint8_t configuration_directions = 0;
589
590 // the configuration should fail if there are no active ases expected
591 PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
592 snk_pac_builder.Reset();
593 src_pac_builder.Reset();
594
595 /* Let's go thru devices in the group and configure them*/
596 for (int i = 0; i < data_size; i++) {
597 int num_of_ase_snk_per_dev = 0;
598 int num_of_ase_src_per_dev = 0;
599
600 /* Prepare PAC's for each device. Also make sure configuration is in our
601 * interest to test */
602 for (const auto& entry : (*audio_set_conf).confs) {
603 /* We are interested in the configurations which contains exact number
604 * of devices and number of ases is same the number of expected ases
605 * to active
606 */
607 if (entry.device_cnt != data_size) {
608 interesting_configuration = false;
609 }
610
611 /* Make sure the strategy is the expected one */
612 if (entry.direction == kLeAudioDirectionSink &&
613 group_->GetGroupStrategy() != entry.strategy) {
614 interesting_configuration = false;
615 }
616
617 if (entry.direction == kLeAudioDirectionSink) {
618 configuration_directions |= kLeAudioDirectionSink;
619 num_of_ase_snk_per_dev = entry.ase_cnt / data_size;
620 snk_pac_builder.Add(entry.codec, data[i].audio_channel_counts_snk);
621 } else {
622 configuration_directions |= kLeAudioDirectionSource;
623 num_of_ase_src_per_dev = entry.ase_cnt / data_size;
624 src_pac_builder.Add(entry.codec, data[i].audio_channel_counts_src);
625 }
626
627 data[i].device->snk_pacs_ = snk_pac_builder.Get();
628 data[i].device->src_pacs_ = src_pac_builder.Get();
629 }
630
631 /* Make sure configuration can satisfy number of expected active ASEs*/
632 if (num_of_ase_snk_per_dev >
633 data[i].device->GetAseCount(kLeAudioDirectionSink)) {
634 interesting_configuration = false;
635 }
636
637 if (num_of_ase_src_per_dev >
638 data[i].device->GetAseCount(kLeAudioDirectionSource)) {
639 interesting_configuration = false;
640 }
641 }
642 /* Stimulate update of available context map */
643 group_->UpdateAudioContextTypeAvailability(AudioContexts(context_type));
644 auto configuration_result =
645 group_->Configure(context_type, AudioContexts(context_type));
646
647 /* In case of configuration #ase is same as the one we expected to be
648 * activated verify, ASEs are actually active */
649 if (interesting_configuration &&
650 (directions_to_verify == configuration_directions)) {
651 ASSERT_TRUE(configuration_result);
652
653 bool matching_conf = true;
654 /* Check if each of the devices has activated ASEs as expected */
655 for (int i = 0; i < data_size; i++) {
656 matching_conf &= TestGroupAseConfigurationVerdict(
657 data[i], configuration_directions);
658 }
659
660 if (matching_conf) num_of_matching_configurations++;
661 }
662 group_->Deactivate();
663 TestAsesInactive();
664 }
665
666 if (success_expected) {
667 ASSERT_TRUE((num_of_matching_configurations > 0));
668 } else {
669 ASSERT_TRUE(num_of_matching_configurations == 0);
670 }
671 }
672
TestAsesActive(LeAudioCodecId codec_id,uint8_t sampling_frequency,uint8_t frame_duration,uint16_t octets_per_frame)673 void TestAsesActive(LeAudioCodecId codec_id, uint8_t sampling_frequency,
674 uint8_t frame_duration, uint16_t octets_per_frame) {
675 bool active_ase = false;
676
677 for (const auto& device : devices_) {
678 for (const auto& ase : device->ases_) {
679 if (!ase.active) continue;
680
681 /* Configure may request only partial ases to be activated */
682 if (!active_ase && ase.active) active_ase = true;
683
684 ASSERT_EQ(ase.codec_id, codec_id);
685
686 /* FIXME: Validate other codec parameters than LC3 if any */
687 ASSERT_EQ(ase.codec_id, LeAudioCodecIdLc3);
688 if (ase.codec_id == LeAudioCodecIdLc3) {
689 ASSERT_EQ(ase.codec_config.sampling_frequency, sampling_frequency);
690 ASSERT_EQ(ase.codec_config.frame_duration, frame_duration);
691 ASSERT_EQ(ase.codec_config.octets_per_codec_frame, octets_per_frame);
692 }
693 }
694 }
695
696 ASSERT_TRUE(active_ase);
697 }
698
TestActiveAses(void)699 void TestActiveAses(void) {
700 for (auto& device : devices_) {
701 for (const auto& ase : device->ases_) {
702 if (ase.active) {
703 ASSERT_FALSE(ase.cis_id == ::le_audio::kInvalidCisId);
704 }
705 }
706 }
707 }
708
TestAsesInactivated(const LeAudioDevice * device)709 void TestAsesInactivated(const LeAudioDevice* device) {
710 for (const auto& ase : device->ases_) {
711 ASSERT_FALSE(ase.active);
712 ASSERT_TRUE(ase.cis_id == ::le_audio::kInvalidCisId);
713 ASSERT_TRUE(ase.cis_conn_hdl == 0);
714 }
715 }
716
TestAsesInactive()717 void TestAsesInactive() {
718 for (const auto& device : devices_) {
719 for (const auto& ase : device->ases_) {
720 ASSERT_FALSE(ase.active);
721 }
722 }
723 }
724
TestLc3CodecConfig(LeAudioContextType context_type)725 void TestLc3CodecConfig(LeAudioContextType context_type) {
726 for (int i = Lc3SettingIdBegin; i < Lc3SettingIdEnd; i++) {
727 // test each configuration parameter against valid and invalid value
728 std::array<Lc3SettingId, 2> test_variants = {static_cast<Lc3SettingId>(i),
729 Lc3SettingId::UNSUPPORTED};
730
731 const bool is_lc3_setting_supported =
732 IsLc3SettingSupported(context_type, static_cast<Lc3SettingId>(i));
733
734 for (const auto sf_variant : test_variants) {
735 uint8_t sampling_frequency = GetSamplingFrequency(sf_variant);
736 for (const auto fd_variant : test_variants) {
737 uint8_t frame_duration = GetFrameDuration(fd_variant);
738 for (const auto opcf_variant : test_variants) {
739 uint16_t octets_per_frame = GetOctetsPerCodecFrame(opcf_variant);
740
741 PublishedAudioCapabilitiesBuilder pac_builder;
742 pac_builder.Add(LeAudioCodecIdLc3, sampling_frequency,
743 frame_duration,
744 kLeAudioCodecLC3ChannelCountSingleChannel |
745 kLeAudioCodecLC3ChannelCountTwoChannel,
746 octets_per_frame);
747 for (auto& device : devices_) {
748 /* For simplicity configure both PACs with the same
749 parameters*/
750 device->snk_pacs_ = pac_builder.Get();
751 device->src_pacs_ = pac_builder.Get();
752 }
753
754 bool success_expected = is_lc3_setting_supported;
755 if (is_lc3_setting_supported &&
756 (sf_variant == Lc3SettingId::UNSUPPORTED ||
757 fd_variant == Lc3SettingId::UNSUPPORTED ||
758 opcf_variant == Lc3SettingId::UNSUPPORTED)) {
759 success_expected = false;
760 }
761
762 /* Stimulate update of available context map */
763 group_->UpdateAudioContextTypeAvailability(
764 AudioContexts(context_type));
765 ASSERT_EQ(
766 success_expected,
767 group_->Configure(context_type, AudioContexts(context_type)));
768 if (success_expected) {
769 TestAsesActive(LeAudioCodecIdLc3, sampling_frequency,
770 frame_duration, octets_per_frame);
771 group_->Deactivate();
772 }
773
774 TestAsesInactive();
775 }
776 }
777 }
778 }
779 }
780
781 const int group_id_ = 6;
782 std::vector<std::shared_ptr<LeAudioDevice>> devices_;
783 std::vector<RawAddress> addresses_;
784 LeAudioDeviceGroup* group_ = nullptr;
785 bluetooth::manager::MockBtmInterface btm_interface_;
786 controller::MockControllerInterface controller_interface_;
787 MockCsisClient mock_csis_client_module_;
788 };
789
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_ringtone)790 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_ringtone) {
791 LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
792 TestGroupAseConfigurationData data(
793 {mono_speaker, kLeAudioCodecLC3ChannelCountSingleChannel,
794 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0});
795
796 /* mono, change location as by default it is stereo */
797 mono_speaker->snk_audio_locations_ =
798 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
799 group_->ReloadAudioLocations();
800
801 uint8_t direction_to_verify = kLeAudioDirectionSink;
802 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1,
803 direction_to_verify);
804 }
805
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_conversational)806 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_conversational) {
807 LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
808 TestGroupAseConfigurationData data({mono_speaker,
809 kLeAudioCodecLC3ChannelCountSingleChannel,
810 kLeAudioCodecLC3ChannelCountNone, 1, 0});
811
812 /* mono, change location as by default it is stereo */
813 mono_speaker->snk_audio_locations_ =
814 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
815 group_->ReloadAudioLocations();
816
817 /* Microphone should be used on the phone */
818 uint8_t direction_to_verify = kLeAudioDirectionSink;
819 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1,
820 direction_to_verify);
821 }
822
TEST_F(LeAudioAseConfigurationTest,test_mono_speaker_media)823 TEST_F(LeAudioAseConfigurationTest, test_mono_speaker_media) {
824 LeAudioDevice* mono_speaker = AddTestDevice(1, 0);
825 TestGroupAseConfigurationData data({mono_speaker,
826 kLeAudioCodecLC3ChannelCountSingleChannel,
827 kLeAudioCodecLC3ChannelCountNone, 1, 0});
828
829 /* mono, change location as by default it is stereo */
830 mono_speaker->snk_audio_locations_ =
831 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
832 group_->ReloadAudioLocations();
833
834 uint8_t direction_to_verify = kLeAudioDirectionSink;
835 TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
836 direction_to_verify);
837 }
838
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_ringtone)839 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_ringtone) {
840 LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
841 TestGroupAseConfigurationData data(
842 {bounded_headphones, kLeAudioCodecLC3ChannelCountTwoChannel,
843 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
844
845 uint8_t direction_to_verify = kLeAudioDirectionSink;
846 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1,
847 direction_to_verify);
848 }
849
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_conversional)850 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_conversional) {
851 LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
852 TestGroupAseConfigurationData data({bounded_headphones,
853 kLeAudioCodecLC3ChannelCountTwoChannel,
854 kLeAudioCodecLC3ChannelCountNone, 2, 0});
855
856 uint8_t direction_to_verify = kLeAudioDirectionSink;
857 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1,
858 direction_to_verify);
859 }
860
TEST_F(LeAudioAseConfigurationTest,test_bounded_headphones_media)861 TEST_F(LeAudioAseConfigurationTest, test_bounded_headphones_media) {
862 LeAudioDevice* bounded_headphones = AddTestDevice(2, 0);
863 TestGroupAseConfigurationData data({bounded_headphones,
864 kLeAudioCodecLC3ChannelCountTwoChannel,
865 kLeAudioCodecLC3ChannelCountNone, 2, 0});
866
867 uint8_t direction_to_verify = kLeAudioDirectionSink;
868 TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
869 direction_to_verify);
870 }
871
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_ringtone_mono_microphone)872 TEST_F(LeAudioAseConfigurationTest,
873 test_bounded_headset_ringtone_mono_microphone) {
874 LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
875 TestGroupAseConfigurationData data(
876 {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
877 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
878
879 /* mono, change location as by default it is stereo */
880 bounded_headset->src_audio_locations_ =
881 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
882 group_->ReloadAudioLocations();
883
884 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
885 }
886
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_ringtone_stereo_microphone)887 TEST_F(LeAudioAseConfigurationTest,
888 test_bounded_headset_ringtone_stereo_microphone) {
889 LeAudioDevice* bounded_headset = AddTestDevice(2, 2);
890 TestGroupAseConfigurationData data(
891 {bounded_headset,
892 kLeAudioCodecLC3ChannelCountSingleChannel |
893 kLeAudioCodecLC3ChannelCountTwoChannel,
894 kLeAudioCodecLC3ChannelCountSingleChannel |
895 kLeAudioCodecLC3ChannelCountTwoChannel,
896 2, 2});
897
898 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
899 }
900
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_conversional)901 TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_conversional) {
902 LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
903 TestGroupAseConfigurationData data(
904 {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
905 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
906
907 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
908 }
909
TEST_F(LeAudioAseConfigurationTest,test_bounded_headset_media)910 TEST_F(LeAudioAseConfigurationTest, test_bounded_headset_media) {
911 LeAudioDevice* bounded_headset = AddTestDevice(2, 1);
912 TestGroupAseConfigurationData data(
913 {bounded_headset, kLeAudioCodecLC3ChannelCountTwoChannel,
914 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
915
916 uint8_t directions_to_verify = kLeAudioDirectionSink;
917 TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
918 directions_to_verify);
919 }
920
TEST_F(LeAudioAseConfigurationTest,test_earbuds_ringtone)921 TEST_F(LeAudioAseConfigurationTest, test_earbuds_ringtone) {
922 LeAudioDevice* left = AddTestDevice(1, 1);
923 LeAudioDevice* right = AddTestDevice(1, 1);
924 TestGroupAseConfigurationData data[] = {
925 {left, kLeAudioCodecLC3ChannelCountSingleChannel,
926 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1},
927 {right, kLeAudioCodecLC3ChannelCountSingleChannel,
928 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1}};
929
930 /* Change location as by default it is stereo */
931 left->snk_audio_locations_ =
932 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
933 left->src_audio_locations_ =
934 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
935 right->snk_audio_locations_ =
936 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
937 right->src_audio_locations_ =
938 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
939 group_->ReloadAudioLocations();
940
941 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, data, 2);
942 }
943
TEST_F(LeAudioAseConfigurationTest,test_earbuds_conversional)944 TEST_F(LeAudioAseConfigurationTest, test_earbuds_conversional) {
945 LeAudioDevice* left = AddTestDevice(1, 1);
946 LeAudioDevice* right = AddTestDevice(1, 1);
947 TestGroupAseConfigurationData data[] = {
948 {left, kLeAudioCodecLC3ChannelCountSingleChannel,
949 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1},
950 {right, kLeAudioCodecLC3ChannelCountSingleChannel,
951 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1}};
952
953 /* Change location as by default it is stereo */
954 left->snk_audio_locations_ =
955 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
956 left->src_audio_locations_ =
957 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
958 right->snk_audio_locations_ =
959 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
960 right->src_audio_locations_ =
961 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
962 group_->ReloadAudioLocations();
963
964 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, data, 2);
965 }
966
TEST_F(LeAudioAseConfigurationTest,test_earbuds_media)967 TEST_F(LeAudioAseConfigurationTest, test_earbuds_media) {
968 LeAudioDevice* left = AddTestDevice(1, 1);
969 LeAudioDevice* right = AddTestDevice(1, 1);
970 TestGroupAseConfigurationData data[] = {
971 {left, kLeAudioCodecLC3ChannelCountSingleChannel,
972 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0},
973 {right, kLeAudioCodecLC3ChannelCountSingleChannel,
974 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0}};
975
976 /* Change location as by default it is stereo */
977 left->snk_audio_locations_ =
978 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
979 left->src_audio_locations_ =
980 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
981 right->snk_audio_locations_ =
982 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
983 right->src_audio_locations_ =
984 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
985 group_->ReloadAudioLocations();
986
987 uint8_t directions_to_verify = kLeAudioDirectionSink;
988 TestGroupAseConfiguration(LeAudioContextType::MEDIA, data, 2,
989 directions_to_verify);
990 }
991
TEST_F(LeAudioAseConfigurationTest,test_handsfree_mono_ringtone)992 TEST_F(LeAudioAseConfigurationTest, test_handsfree_mono_ringtone) {
993 LeAudioDevice* handsfree = AddTestDevice(1, 1);
994 TestGroupAseConfigurationData data(
995 {handsfree, kLeAudioCodecLC3ChannelCountSingleChannel,
996 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1});
997
998 handsfree->snk_audio_locations_ =
999 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1000 handsfree->src_audio_locations_ =
1001 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1002 group_->ReloadAudioLocations();
1003
1004 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1005 }
1006
TEST_F(LeAudioAseConfigurationTest,test_handsfree_stereo_ringtone)1007 TEST_F(LeAudioAseConfigurationTest, test_handsfree_stereo_ringtone) {
1008 LeAudioDevice* handsfree = AddTestDevice(1, 1);
1009 TestGroupAseConfigurationData data(
1010 {handsfree,
1011 kLeAudioCodecLC3ChannelCountSingleChannel |
1012 kLeAudioCodecLC3ChannelCountTwoChannel,
1013 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1014
1015 TestGroupAseConfiguration(LeAudioContextType::RINGTONE, &data, 1);
1016 }
1017
TEST_F(LeAudioAseConfigurationTest,test_handsfree_mono_conversional)1018 TEST_F(LeAudioAseConfigurationTest, test_handsfree_mono_conversional) {
1019 LeAudioDevice* handsfree = AddTestDevice(1, 1);
1020 TestGroupAseConfigurationData data(
1021 {handsfree, kLeAudioCodecLC3ChannelCountSingleChannel,
1022 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 1});
1023
1024 handsfree->snk_audio_locations_ =
1025 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1026 handsfree->src_audio_locations_ =
1027 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1028 group_->ReloadAudioLocations();
1029
1030 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1031 }
1032
TEST_F(LeAudioAseConfigurationTest,test_handsfree_stereo_conversional)1033 TEST_F(LeAudioAseConfigurationTest, test_handsfree_stereo_conversional) {
1034 LeAudioDevice* handsfree = AddTestDevice(1, 1);
1035 TestGroupAseConfigurationData data(
1036 {handsfree,
1037 kLeAudioCodecLC3ChannelCountSingleChannel |
1038 kLeAudioCodecLC3ChannelCountTwoChannel,
1039 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1040
1041 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1042 }
1043
TEST_F(LeAudioAseConfigurationTest,test_handsfree_full_cached_conversional)1044 TEST_F(LeAudioAseConfigurationTest, test_handsfree_full_cached_conversional) {
1045 LeAudioDevice* handsfree = AddTestDevice(0, 0, 1, 1);
1046 TestGroupAseConfigurationData data(
1047 {handsfree,
1048 kLeAudioCodecLC3ChannelCountSingleChannel |
1049 kLeAudioCodecLC3ChannelCountTwoChannel,
1050 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1051
1052 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1053 }
1054
TEST_F(LeAudioAseConfigurationTest,test_handsfree_partial_cached_conversional)1055 TEST_F(LeAudioAseConfigurationTest,
1056 test_handsfree_partial_cached_conversional) {
1057 LeAudioDevice* handsfree = AddTestDevice(1, 0, 0, 1);
1058 TestGroupAseConfigurationData data(
1059 {handsfree,
1060 kLeAudioCodecLC3ChannelCountSingleChannel |
1061 kLeAudioCodecLC3ChannelCountTwoChannel,
1062 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 1});
1063
1064 TestGroupAseConfiguration(LeAudioContextType::CONVERSATIONAL, &data, 1);
1065 }
1066
TEST_F(LeAudioAseConfigurationTest,test_handsfree_media_two_channels_allocation_stereo)1067 TEST_F(LeAudioAseConfigurationTest,
1068 test_handsfree_media_two_channels_allocation_stereo) {
1069 LeAudioDevice* handsfree = AddTestDevice(1, 1);
1070 TestGroupAseConfigurationData data(
1071 {handsfree,
1072 kLeAudioCodecLC3ChannelCountSingleChannel |
1073 kLeAudioCodecLC3ChannelCountTwoChannel,
1074 kLeAudioCodecLC3ChannelCountSingleChannel, 2, 0});
1075
1076 uint8_t directions_to_verify = kLeAudioDirectionSink;
1077 TestGroupAseConfiguration(LeAudioContextType::MEDIA, &data, 1,
1078 directions_to_verify);
1079 }
1080
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_ringtone)1081 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_ringtone) {
1082 AddTestDevice(1, 1);
1083
1084 TestLc3CodecConfig(LeAudioContextType::RINGTONE);
1085 }
1086
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_conversional)1087 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_conversional) {
1088 AddTestDevice(1, 1);
1089
1090 TestLc3CodecConfig(LeAudioContextType::CONVERSATIONAL);
1091 }
1092
TEST_F(LeAudioAseConfigurationTest,test_lc3_config_media)1093 TEST_F(LeAudioAseConfigurationTest, test_lc3_config_media) {
1094 AddTestDevice(1, 1);
1095
1096 TestLc3CodecConfig(LeAudioContextType::MEDIA);
1097 }
1098
TEST_F(LeAudioAseConfigurationTest,test_unsupported_codec)1099 TEST_F(LeAudioAseConfigurationTest, test_unsupported_codec) {
1100 const LeAudioCodecId UnsupportedCodecId = {
1101 .coding_format = kLeAudioCodingFormatVendorSpecific,
1102 .vendor_company_id = 0xBAD,
1103 .vendor_codec_id = 0xC0DE,
1104 };
1105
1106 LeAudioDevice* device = AddTestDevice(1, 0);
1107
1108 PublishedAudioCapabilitiesBuilder pac_builder;
1109 pac_builder.Add(UnsupportedCodecId,
1110 GetSamplingFrequency(Lc3SettingId::LC3_16_2),
1111 GetFrameDuration(Lc3SettingId::LC3_16_2),
1112 kLeAudioCodecLC3ChannelCountSingleChannel,
1113 GetOctetsPerCodecFrame(Lc3SettingId::LC3_16_2));
1114 device->snk_pacs_ = pac_builder.Get();
1115 device->src_pacs_ = pac_builder.Get();
1116
1117 ASSERT_FALSE(group_->Configure(
1118 LeAudioContextType::RINGTONE,
1119 AudioContexts(static_cast<uint16_t>(LeAudioContextType::RINGTONE))));
1120 TestAsesInactive();
1121 }
1122
TEST_F(LeAudioAseConfigurationTest,test_reconnection_media)1123 TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) {
1124 LeAudioDevice* left = AddTestDevice(2, 1);
1125 LeAudioDevice* right = AddTestDevice(2, 1);
1126
1127 /* Change location as by default it is stereo */
1128 left->snk_audio_locations_ =
1129 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1130 left->src_audio_locations_ =
1131 ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
1132 right->snk_audio_locations_ =
1133 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1134 right->src_audio_locations_ =
1135 ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
1136 group_->ReloadAudioLocations();
1137
1138 TestGroupAseConfigurationData data[] = {
1139 {left, kLeAudioCodecLC3ChannelCountSingleChannel,
1140 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0},
1141 {right, kLeAudioCodecLC3ChannelCountSingleChannel,
1142 kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0}};
1143
1144 auto all_configurations =
1145 ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1146 LeAudioContextType::MEDIA);
1147 ASSERT_NE(nullptr, all_configurations);
1148 ASSERT_NE(all_configurations->end(), all_configurations->begin());
1149 auto configuration = *all_configurations->begin();
1150
1151 uint8_t direction_to_verify = kLeAudioDirectionSink;
1152 TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, configuration,
1153 direction_to_verify);
1154
1155 /* Generate CISes, symulate CIG creation and assign cis handles to ASEs.*/
1156 group_->CigGenerateCisIds(LeAudioContextType::MEDIA);
1157 std::vector<uint16_t> handles = {0x0012, 0x0013};
1158 group_->CigAssignCisConnHandles(handles);
1159 group_->CigAssignCisIds(left);
1160 group_->CigAssignCisIds(right);
1161
1162 TestActiveAses();
1163 /* Left got disconnected */
1164 left->DeactivateAllAses();
1165
1166 /* Unassign from the group*/
1167 group_->CigUnassignCis(left);
1168
1169 TestAsesInactivated(left);
1170
1171 /* Prepare reconfiguration */
1172 uint8_t number_of_active_ases = 1; // Right one
1173 auto* ase = right->GetFirstActiveAseByDirection(kLeAudioDirectionSink);
1174 ::le_audio::types::AudioLocations group_snk_audio_location =
1175 *ase->codec_config.audio_channel_allocation;
1176 ::le_audio::types::AudioLocations group_src_audio_location =
1177 *ase->codec_config.audio_channel_allocation;
1178
1179 /* Get entry for the sink direction and use it to set configuration */
1180 std::vector<uint8_t> ccid_list;
1181 for (auto& ent : configuration->confs) {
1182 if (ent.direction == ::le_audio::types::kLeAudioDirectionSink) {
1183 left->ConfigureAses(ent, group_->GetConfigurationContextType(),
1184 &number_of_active_ases, group_snk_audio_location,
1185 group_src_audio_location, false,
1186 ::le_audio::types::AudioContexts(), ccid_list);
1187 }
1188 }
1189
1190 ASSERT_TRUE(number_of_active_ases == 2);
1191 ASSERT_TRUE(group_snk_audio_location == kChannelAllocationStereo);
1192
1193 uint8_t directions_to_verify = ::le_audio::types::kLeAudioDirectionSink;
1194 for (int i = 0; i < 2; i++) {
1195 TestGroupAseConfigurationVerdict(data[i], directions_to_verify);
1196 }
1197
1198 /* Before device is rejoining, and group already exist, cis handles are
1199 * assigned before sending codec config
1200 */
1201 group_->CigAssignCisIds(left);
1202 group_->CigAssignCisConnHandlesToAses(left);
1203
1204 TestActiveAses();
1205 }
1206 } // namespace
1207 } // namespace internal
1208 } // namespace le_audio
1209 } // namespace bluetooth
1210