blob: 307403b45163228ac1a30118991c09dc5ffa571e [file] [log] [blame]
Josh Wu049e2cd2022-01-12 05:42:58 -08001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <aidl/Gtest.h>
17#include <aidl/Vintf.h>
18#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioPort.h>
19#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h>
20#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
21#include <android/binder_auto_utils.h>
22#include <android/binder_manager.h>
23#include <android/binder_process.h>
24#include <binder/IServiceManager.h>
25#include <binder/ProcessState.h>
26#include <fmq/AidlMessageQueue.h>
27
28#include <cstdint>
29#include <future>
30#include <unordered_set>
31#include <vector>
32
33using aidl::android::hardware::audio::common::SinkMetadata;
34using aidl::android::hardware::audio::common::SourceMetadata;
35using aidl::android::hardware::bluetooth::audio::AacCapabilities;
36using aidl::android::hardware::bluetooth::audio::AacConfiguration;
37using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
38using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
39using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
40using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
41using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
42using aidl::android::hardware::bluetooth::audio::ChannelMode;
43using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
44using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
45using aidl::android::hardware::bluetooth::audio::CodecType;
46using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
47using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
48using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
49using aidl::android::hardware::bluetooth::audio::LatencyMode;
50using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
51using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
52using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
53using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
54using aidl::android::hardware::bluetooth::audio::
55 LeAudioCodecCapabilitiesSetting;
56using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
57using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
58using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
59using aidl::android::hardware::bluetooth::audio::PresentationPosition;
60using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
61using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
62using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
63using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
64using aidl::android::hardware::bluetooth::audio::SessionType;
65using aidl::android::hardware::bluetooth::audio::UnicastCapability;
66using aidl::android::hardware::common::fmq::MQDescriptor;
67using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
68using android::AidlMessageQueue;
69using android::ProcessState;
70using android::String16;
71using ndk::ScopedAStatus;
72using ndk::SpAIBinder;
73
74using MqDataType = int8_t;
75using MqDataMode = SynchronizedReadWrite;
76using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
77using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
78
79// Constants
80
81static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
82static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
83static constexpr ChannelMode a2dp_channel_modes[] = {
84 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
85static constexpr CodecType a2dp_codec_types[] = {
86 CodecType::UNKNOWN, CodecType::SBC, CodecType::AAC,
87 CodecType::APTX, CodecType::APTX_HD, CodecType::LDAC,
88 CodecType::LC3, CodecType::APTX_ADAPTIVE};
89
90// Helpers
91
92template <typename T>
93struct identity {
94 typedef T type;
95};
96
97template <class T>
98bool contained_in_vector(const std::vector<T>& vector,
99 const typename identity<T>::type& target) {
100 return std::find(vector.begin(), vector.end(), target) != vector.end();
101}
102
103void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
104 const CodecConfiguration::CodecSpecific& src) {
105 switch (src.getTag()) {
106 case CodecConfiguration::CodecSpecific::sbcConfig:
107 dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
108 src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
109 break;
110 case CodecConfiguration::CodecSpecific::aacConfig:
111 dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
112 src.get<CodecConfiguration::CodecSpecific::aacConfig>());
113 break;
114 case CodecConfiguration::CodecSpecific::ldacConfig:
115 dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
116 src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
117 break;
118 case CodecConfiguration::CodecSpecific::aptxConfig:
119 dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
120 src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
121 break;
122 case CodecConfiguration::CodecSpecific::lc3Config:
123 dst.set<CodecConfiguration::CodecSpecific::lc3Config>(
124 src.get<CodecConfiguration::CodecSpecific::lc3Config>());
125 break;
126 case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
127 dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
128 src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
129 break;
130 default:
131 break;
132 }
133}
134
135class BluetoothAudioPort : public BnBluetoothAudioPort {
136 public:
137 BluetoothAudioPort() {}
138
139 ndk::ScopedAStatus startStream() { return ScopedAStatus::ok(); }
140
141 ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
142
143 ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }
144
145 ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
146 return ScopedAStatus::ok();
147 }
148
149 ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
150 return ScopedAStatus::ok();
151 }
152
153 ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
154 return ScopedAStatus::ok();
155 }
156
157 ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
158 return ScopedAStatus::ok();
159 }
160
161 ndk::ScopedAStatus setCodecType(const CodecType) {
162 return ScopedAStatus::ok();
163 }
164
165 protected:
166 virtual ~BluetoothAudioPort() = default;
167};
168
169class BluetoothAudioProviderFactoryAidl
170 : public testing::TestWithParam<std::string> {
171 public:
172 virtual void SetUp() override {
173 provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
174 SpAIBinder(AServiceManager_getService(GetParam().c_str())));
175 audio_provider_ = nullptr;
176 ASSERT_NE(provider_factory_, nullptr);
177 }
178
179 virtual void TearDown() override { provider_factory_ = nullptr; }
180
181 void GetProviderCapabilitiesHelper(const SessionType& session_type) {
182 temp_provider_capabilities_.clear();
183 auto aidl_retval = provider_factory_->getProviderCapabilities(
184 session_type, &temp_provider_capabilities_);
185 // AIDL calls should not be failed and callback has to be executed
186 ASSERT_TRUE(aidl_retval.isOk());
187 switch (session_type) {
188 case SessionType::UNKNOWN: {
189 ASSERT_TRUE(temp_provider_capabilities_.empty());
190 } break;
191 case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
192 case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
193 case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
194 case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
195 case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: {
196 // All software paths are mandatory and must have exact 1
197 // "PcmParameters"
198 ASSERT_EQ(temp_provider_capabilities_.size(), 1);
199 ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
200 AudioCapabilities::pcmCapabilities);
201 } break;
202 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
203 std::unordered_set<CodecType> codec_types;
204 // empty capability means offload is unsupported
205 for (auto& audio_capability : temp_provider_capabilities_) {
206 ASSERT_EQ(audio_capability.getTag(),
207 AudioCapabilities::a2dpCapabilities);
208 const auto& codec_capabilities =
209 audio_capability.get<AudioCapabilities::a2dpCapabilities>();
210 // Every codec can present once at most
211 ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
212 switch (codec_capabilities.codecType) {
213 case CodecType::SBC:
214 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
215 CodecCapabilities::Capabilities::sbcCapabilities);
216 break;
217 case CodecType::AAC:
218 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
219 CodecCapabilities::Capabilities::aacCapabilities);
220 break;
221 case CodecType::APTX:
222 case CodecType::APTX_HD:
223 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
224 CodecCapabilities::Capabilities::aptxCapabilities);
225 break;
226 case CodecType::LDAC:
227 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
228 CodecCapabilities::Capabilities::ldacCapabilities);
229 break;
230 case CodecType::LC3:
231 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
232 CodecCapabilities::Capabilities::lc3Capabilities);
233 break;
234 case CodecType::APTX_ADAPTIVE:
235 case CodecType::VENDOR:
236 case CodecType::UNKNOWN:
237 break;
238 }
239 codec_types.insert(codec_capabilities.codecType);
240 }
241 } break;
242 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
243 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
244 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
245 ASSERT_FALSE(temp_provider_capabilities_.empty());
246 for (auto audio_capability : temp_provider_capabilities_) {
247 ASSERT_EQ(audio_capability.getTag(),
248 AudioCapabilities::leAudioCapabilities);
249 }
250 } break;
251 }
252 }
253
254 /***
255 * This helps to open the specified provider and check the openProvider()
256 * has corruct return values. BUT, to keep it simple, it does not consider
257 * the capability, and please do so at the SetUp of each session's test.
258 ***/
259 void OpenProviderHelper(const SessionType& session_type) {
260 auto aidl_retval =
261 provider_factory_->openProvider(session_type, &audio_provider_);
262 if (aidl_retval.isOk()) {
263 ASSERT_NE(session_type, SessionType::UNKNOWN);
264 ASSERT_NE(audio_provider_, nullptr);
265 audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
266 } else {
267 // Hardware offloading is optional
268 ASSERT_TRUE(
269 session_type == SessionType::UNKNOWN ||
270 session_type ==
271 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
272 session_type ==
273 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
274 session_type ==
275 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
276 session_type ==
277 SessionType::
278 LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
279 ASSERT_EQ(audio_provider_, nullptr);
280 }
281 }
282
283 bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
284 if (temp_provider_capabilities_.size() != 1 ||
285 temp_provider_capabilities_[0].getTag() !=
286 AudioCapabilities::pcmCapabilities) {
287 return false;
288 }
289 auto pcm_capability = temp_provider_capabilities_[0]
290 .get<AudioCapabilities::pcmCapabilities>();
291 return (contained_in_vector(pcm_capability.channelMode,
292 pcm_config.channelMode) &&
293 contained_in_vector(pcm_capability.sampleRateHz,
294 pcm_config.sampleRateHz) &&
295 contained_in_vector(pcm_capability.bitsPerSample,
296 pcm_config.bitsPerSample));
297 }
298
299 std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
300 std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
301 std::shared_ptr<IBluetoothAudioPort> audio_port_;
302 std::vector<AudioCapabilities> temp_provider_capabilities_;
303
304 static constexpr SessionType kSessionTypes[] = {
305 SessionType::UNKNOWN,
306 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
307 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
308 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
309 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
310 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
311 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
312 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
313 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
314 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
315 };
316};
317
318/**
319 * Test whether we can get the FactoryService from HIDL
320 */
321TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
322
323/**
324 * Test whether we can open a provider for each provider returned by
325 * getProviderCapabilities() with non-empty capabalities
326 */
327TEST_P(BluetoothAudioProviderFactoryAidl,
328 OpenProviderAndCheckCapabilitiesBySession) {
329 for (auto session_type : kSessionTypes) {
330 GetProviderCapabilitiesHelper(session_type);
331 OpenProviderHelper(session_type);
332 // We must be able to open a provider if its getProviderCapabilities()
333 // returns non-empty list.
334 EXPECT_TRUE(temp_provider_capabilities_.empty() ||
335 audio_provider_ != nullptr);
336 }
337}
338
339/**
340 * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
341 */
342class BluetoothAudioProviderA2dpSoftwareAidl
343 : public BluetoothAudioProviderFactoryAidl {
344 public:
345 virtual void SetUp() override {
346 BluetoothAudioProviderFactoryAidl::SetUp();
347 GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
348 OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
349 ASSERT_NE(audio_provider_, nullptr);
350 }
351
352 virtual void TearDown() override {
353 audio_port_ = nullptr;
354 audio_provider_ = nullptr;
355 BluetoothAudioProviderFactoryAidl::TearDown();
356 }
357};
358
359/**
360 * Test whether we can open a provider of type
361 */
362TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, OpenA2dpSoftwareProvider) {}
363
364/**
365 * Test whether each provider of type
366 * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
367 * different PCM config
368 */
369TEST_P(BluetoothAudioProviderA2dpSoftwareAidl,
370 StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
371 for (auto sample_rate : a2dp_sample_rates) {
372 for (auto bits_per_sample : a2dp_bits_per_samples) {
373 for (auto channel_mode : a2dp_channel_modes) {
374 PcmConfiguration pcm_config{
375 .sampleRateHz = sample_rate,
376 .bitsPerSample = bits_per_sample,
377 .channelMode = channel_mode,
378 };
379 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
380 DataMQDesc mq_desc;
381 auto aidl_retval = audio_provider_->startSession(
382 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
383 DataMQ data_mq(mq_desc);
384
385 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
386 if (is_codec_config_valid) {
387 EXPECT_TRUE(data_mq.isValid());
388 }
389 EXPECT_TRUE(audio_provider_->endSession().isOk());
390 }
391 }
392 }
393}
394
395/**
396 * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
397 */
398class BluetoothAudioProviderA2dpHardwareAidl
399 : public BluetoothAudioProviderFactoryAidl {
400 public:
401 virtual void SetUp() override {
402 BluetoothAudioProviderFactoryAidl::SetUp();
403 GetProviderCapabilitiesHelper(
404 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
405 OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
406 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
407 audio_provider_ != nullptr);
408 }
409
410 virtual void TearDown() override {
411 audio_port_ = nullptr;
412 audio_provider_ = nullptr;
413 BluetoothAudioProviderFactoryAidl::TearDown();
414 }
415
416 bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
417
418 void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
419 temp_codec_capabilities_ = nullptr;
420 for (auto codec_capability : temp_provider_capabilities_) {
421 auto& a2dp_capabilities =
422 codec_capability.get<AudioCapabilities::a2dpCapabilities>();
423 if (a2dp_capabilities.codecType != codec_type) {
424 continue;
425 }
426 temp_codec_capabilities_ = &a2dp_capabilities;
427 }
428 }
429
430 std::vector<CodecConfiguration::CodecSpecific>
431 GetSbcCodecSpecificSupportedList(bool supported) {
432 std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
433 if (!supported) {
434 SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
435 sbc_codec_specifics.push_back(
436 CodecConfiguration::CodecSpecific(sbc_config));
437 return sbc_codec_specifics;
438 }
439 GetA2dpOffloadCapabilityHelper(CodecType::SBC);
440 if (temp_codec_capabilities_ == nullptr ||
441 temp_codec_capabilities_->codecType != CodecType::SBC) {
442 return sbc_codec_specifics;
443 }
444 // parse the capability
445 auto& sbc_capability =
446 temp_codec_capabilities_->capabilities
447 .get<CodecCapabilities::Capabilities::sbcCapabilities>();
448 if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
449 return sbc_codec_specifics;
450 }
451
452 // combine those parameters into one list of
453 // CodecConfiguration::CodecSpecific
454 for (int32_t sample_rate : sbc_capability.sampleRateHz) {
455 for (int8_t block_length : sbc_capability.blockLength) {
456 for (int8_t num_subbands : sbc_capability.numSubbands) {
457 for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
458 for (auto channel_mode : sbc_capability.channelMode) {
459 for (auto alloc_method : sbc_capability.allocMethod) {
460 SbcConfiguration sbc_data = {
461 .sampleRateHz = sample_rate,
462 .channelMode = channel_mode,
463 .blockLength = block_length,
464 .numSubbands = num_subbands,
465 .allocMethod = alloc_method,
466 .bitsPerSample = bits_per_sample,
467 .minBitpool = sbc_capability.minBitpool,
468 .maxBitpool = sbc_capability.maxBitpool};
469 sbc_codec_specifics.push_back(
470 CodecConfiguration::CodecSpecific(sbc_data));
471 }
472 }
473 }
474 }
475 }
476 }
477 return sbc_codec_specifics;
478 }
479
480 std::vector<CodecConfiguration::CodecSpecific>
481 GetAacCodecSpecificSupportedList(bool supported) {
482 std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
483 if (!supported) {
484 AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
485 aac_codec_specifics.push_back(
486 CodecConfiguration::CodecSpecific(aac_config));
487 return aac_codec_specifics;
488 }
489 GetA2dpOffloadCapabilityHelper(CodecType::AAC);
490 if (temp_codec_capabilities_ == nullptr ||
491 temp_codec_capabilities_->codecType != CodecType::AAC) {
492 return aac_codec_specifics;
493 }
494 // parse the capability
495 auto& aac_capability =
496 temp_codec_capabilities_->capabilities
497 .get<CodecCapabilities::Capabilities::aacCapabilities>();
498
499 std::vector<bool> variable_bit_rate_enableds = {false};
500 if (aac_capability.variableBitRateSupported) {
501 variable_bit_rate_enableds.push_back(true);
502 }
503
504 // combine those parameters into one list of
505 // CodecConfiguration::CodecSpecific
506 for (auto object_type : aac_capability.objectType) {
507 for (int32_t sample_rate : aac_capability.sampleRateHz) {
508 for (auto channel_mode : aac_capability.channelMode) {
509 for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
510 for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
511 AacConfiguration aac_data{
512 .objectType = object_type,
513 .sampleRateHz = sample_rate,
514 .channelMode = channel_mode,
515 .variableBitRateEnabled = variable_bit_rate_enabled,
516 .bitsPerSample = bits_per_sample};
517 aac_codec_specifics.push_back(
518 CodecConfiguration::CodecSpecific(aac_data));
519 }
520 }
521 }
522 }
523 }
524 return aac_codec_specifics;
525 }
526
527 std::vector<CodecConfiguration::CodecSpecific>
528 GetLdacCodecSpecificSupportedList(bool supported) {
529 std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
530 if (!supported) {
531 LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
532 ldac_codec_specifics.push_back(
533 CodecConfiguration::CodecSpecific(ldac_config));
534 return ldac_codec_specifics;
535 }
536 GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
537 if (temp_codec_capabilities_ == nullptr ||
538 temp_codec_capabilities_->codecType != CodecType::LDAC) {
539 return ldac_codec_specifics;
540 }
541 // parse the capability
542 auto& ldac_capability =
543 temp_codec_capabilities_->capabilities
544 .get<CodecCapabilities::Capabilities::ldacCapabilities>();
545
546 // combine those parameters into one list of
547 // CodecConfiguration::CodecSpecific
548 for (int32_t sample_rate : ldac_capability.sampleRateHz) {
549 for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
550 for (auto channel_mode : ldac_capability.channelMode) {
551 for (auto quality_index : ldac_capability.qualityIndex) {
552 LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
553 .channelMode = channel_mode,
554 .qualityIndex = quality_index,
555 .bitsPerSample = bits_per_sample};
556 ldac_codec_specifics.push_back(
557 CodecConfiguration::CodecSpecific(ldac_data));
558 }
559 }
560 }
561 }
562 return ldac_codec_specifics;
563 }
564
565 std::vector<CodecConfiguration::CodecSpecific>
566 GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
567 std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
568 if (!supported) {
569 AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
570 aptx_codec_specifics.push_back(
571 CodecConfiguration::CodecSpecific(aptx_config));
572 return aptx_codec_specifics;
573 }
574 GetA2dpOffloadCapabilityHelper(
575 (is_hd ? CodecType::APTX_HD : CodecType::APTX));
576 if (temp_codec_capabilities_ == nullptr) {
577 return aptx_codec_specifics;
578 }
579 if ((is_hd && temp_codec_capabilities_->codecType != CodecType::APTX_HD) ||
580 (!is_hd && temp_codec_capabilities_->codecType != CodecType::APTX)) {
581 return aptx_codec_specifics;
582 }
583
584 // parse the capability
585 auto& aptx_capability =
586 temp_codec_capabilities_->capabilities
587 .get<CodecCapabilities::Capabilities::aptxCapabilities>();
588
589 // combine those parameters into one list of
590 // CodecConfiguration::CodecSpecific
591 for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
592 for (int32_t sample_rate : aptx_capability.sampleRateHz) {
593 for (auto channel_mode : aptx_capability.channelMode) {
594 AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
595 .channelMode = channel_mode,
596 .bitsPerSample = bits_per_sample};
597 aptx_codec_specifics.push_back(
598 CodecConfiguration::CodecSpecific(aptx_data));
599 }
600 }
601 }
602 return aptx_codec_specifics;
603 }
604
605 std::vector<CodecConfiguration::CodecSpecific>
606 GetLc3CodecSpecificSupportedList(bool supported) {
607 std::vector<CodecConfiguration::CodecSpecific> lc3_codec_specifics;
608 if (!supported) {
609 Lc3Configuration lc3_config{.samplingFrequencyHz = 0,
610 .frameDurationUs = 0};
611 lc3_codec_specifics.push_back(
612 CodecConfiguration::CodecSpecific(lc3_config));
613 return lc3_codec_specifics;
614 }
615 GetA2dpOffloadCapabilityHelper(CodecType::LC3);
616 if (temp_codec_capabilities_ == nullptr ||
617 temp_codec_capabilities_->codecType != CodecType::LC3) {
618 return lc3_codec_specifics;
619 }
620 // parse the capability
621 auto& lc3_capability =
622 temp_codec_capabilities_->capabilities
623 .get<CodecCapabilities::Capabilities::lc3Capabilities>();
624
625 // combine those parameters into one list of
626 // CodecConfiguration::CodecSpecific
627 for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
628 for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
629 for (auto channel_mode : lc3_capability.channelMode) {
630 Lc3Configuration lc3_data{.samplingFrequencyHz = samplingFrequencyHz,
631 .channelMode = channel_mode,
632 .frameDurationUs = frameDurationUs};
633 lc3_codec_specifics.push_back(
634 CodecConfiguration::CodecSpecific(lc3_data));
635 }
636 }
637 }
638 return lc3_codec_specifics;
639 }
640
641 // temp storage saves the specified codec capability by
642 // GetOffloadCodecCapabilityHelper()
643 CodecCapabilities* temp_codec_capabilities_;
644};
645
646/**
647 * Test whether we can open a provider of type
648 */
649TEST_P(BluetoothAudioProviderA2dpHardwareAidl, OpenA2dpHardwareProvider) {}
650
651/**
652 * Test whether each provider of type
653 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
654 * SBC hardware encoding config
655 */
656TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
657 StartAndEndA2dpSbcHardwareSession) {
658 if (!IsOffloadSupported()) {
659 return;
660 }
661
662 CodecConfiguration codec_config = {
663 .codecType = CodecType::SBC,
664 .encodedAudioBitrate = 328000,
665 .peerMtu = 1005,
666 .isScmstEnabled = false,
667 };
668 auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
669
670 for (auto& codec_specific : sbc_codec_specifics) {
671 copy_codec_specific(codec_config.config, codec_specific);
672 DataMQDesc mq_desc;
673 auto aidl_retval = audio_provider_->startSession(
674 audio_port_, AudioConfiguration(codec_config), &mq_desc);
675
676 ASSERT_TRUE(aidl_retval.isOk());
677 EXPECT_TRUE(audio_provider_->endSession().isOk());
678 }
679}
680
681/**
682 * Test whether each provider of type
683 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
684 * AAC hardware encoding config
685 */
686TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
687 StartAndEndA2dpAacHardwareSession) {
688 if (!IsOffloadSupported()) {
689 return;
690 }
691
692 CodecConfiguration codec_config = {
693 .codecType = CodecType::AAC,
694 .encodedAudioBitrate = 320000,
695 .peerMtu = 1005,
696 .isScmstEnabled = false,
697 };
698 auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
699
700 for (auto& codec_specific : aac_codec_specifics) {
701 copy_codec_specific(codec_config.config, codec_specific);
702 DataMQDesc mq_desc;
703 auto aidl_retval = audio_provider_->startSession(
704 audio_port_, AudioConfiguration(codec_config), &mq_desc);
705
706 ASSERT_TRUE(aidl_retval.isOk());
707 EXPECT_TRUE(audio_provider_->endSession().isOk());
708 }
709}
710
711/**
712 * Test whether each provider of type
713 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
714 * LDAC hardware encoding config
715 */
716TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
717 StartAndEndA2dpLdacHardwareSession) {
718 if (!IsOffloadSupported()) {
719 return;
720 }
721
722 CodecConfiguration codec_config = {
723 .codecType = CodecType::LDAC,
724 .encodedAudioBitrate = 990000,
725 .peerMtu = 1005,
726 .isScmstEnabled = false,
727 };
728 auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
729
730 for (auto& codec_specific : ldac_codec_specifics) {
731 copy_codec_specific(codec_config.config, codec_specific);
732 DataMQDesc mq_desc;
733 auto aidl_retval = audio_provider_->startSession(
734 audio_port_, AudioConfiguration(codec_config), &mq_desc);
735
736 ASSERT_TRUE(aidl_retval.isOk());
737 EXPECT_TRUE(audio_provider_->endSession().isOk());
738 }
739}
740
741/**
742 * Test whether each provider of type
743 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
744 * LDAC hardware encoding config
745 */
746TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
747 StartAndEndA2dpLc3HardwareSession) {
748 if (!IsOffloadSupported()) {
749 return;
750 }
751
752 CodecConfiguration codec_config = {
753 .codecType = CodecType::LC3,
754 .encodedAudioBitrate = 990000,
755 .peerMtu = 1005,
756 .isScmstEnabled = false,
757 };
758 auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
759
760 for (auto& codec_specific : lc3_codec_specifics) {
761 copy_codec_specific(codec_config.config, codec_specific);
762 DataMQDesc mq_desc;
763 auto aidl_retval = audio_provider_->startSession(
764 audio_port_, AudioConfiguration(codec_config), &mq_desc);
765
766 ASSERT_TRUE(aidl_retval.isOk());
767 EXPECT_TRUE(audio_provider_->endSession().isOk());
768 }
769}
770
771/**
772 * Test whether each provider of type
773 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
774 * AptX hardware encoding config
775 */
776TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
777 StartAndEndA2dpAptxHardwareSession) {
778 if (!IsOffloadSupported()) {
779 return;
780 }
781
782 for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
783 CodecConfiguration codec_config = {
784 .codecType = codec_type,
785 .encodedAudioBitrate =
786 (codec_type == CodecType::APTX ? 352000 : 576000),
787 .peerMtu = 1005,
788 .isScmstEnabled = false,
789 };
790
791 auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
792 (codec_type == CodecType::APTX_HD ? true : false), true);
793
794 for (auto& codec_specific : aptx_codec_specifics) {
795 copy_codec_specific(codec_config.config, codec_specific);
796 DataMQDesc mq_desc;
797 auto aidl_retval = audio_provider_->startSession(
798 audio_port_, AudioConfiguration(codec_config), &mq_desc);
799
800 ASSERT_TRUE(aidl_retval.isOk());
801 EXPECT_TRUE(audio_provider_->endSession().isOk());
802 }
803 }
804}
805
806/**
807 * Test whether each provider of type
808 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
809 * an invalid codec config
810 */
811TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
812 StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
813 if (!IsOffloadSupported()) {
814 return;
815 }
816 ASSERT_NE(audio_provider_, nullptr);
817
818 std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
819 for (auto codec_type : a2dp_codec_types) {
820 switch (codec_type) {
821 case CodecType::SBC:
822 codec_specifics = GetSbcCodecSpecificSupportedList(false);
823 break;
824 case CodecType::AAC:
825 codec_specifics = GetAacCodecSpecificSupportedList(false);
826 break;
827 case CodecType::LDAC:
828 codec_specifics = GetLdacCodecSpecificSupportedList(false);
829 break;
830 case CodecType::APTX:
831 codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
832 break;
833 case CodecType::APTX_HD:
834 codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
835 break;
836 case CodecType::LC3:
837 codec_specifics = GetLc3CodecSpecificSupportedList(false);
838 continue;
839 case CodecType::APTX_ADAPTIVE:
840 case CodecType::VENDOR:
841 case CodecType::UNKNOWN:
842 codec_specifics.clear();
843 break;
844 }
845 if (codec_specifics.empty()) {
846 continue;
847 }
848
849 CodecConfiguration codec_config = {
850 .codecType = codec_type,
851 .encodedAudioBitrate = 328000,
852 .peerMtu = 1005,
853 .isScmstEnabled = false,
854 };
855 for (auto codec_specific : codec_specifics) {
856 copy_codec_specific(codec_config.config, codec_specific);
857 DataMQDesc mq_desc;
858 auto aidl_retval = audio_provider_->startSession(
859 audio_port_, AudioConfiguration(codec_config), &mq_desc);
860
861 // AIDL call should fail on invalid codec
862 ASSERT_FALSE(aidl_retval.isOk());
863 EXPECT_TRUE(audio_provider_->endSession().isOk());
864 }
865 }
866}
867
868/**
869 * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
870 */
871class BluetoothAudioProviderHearingAidSoftwareAidl
872 : public BluetoothAudioProviderFactoryAidl {
873 public:
874 virtual void SetUp() override {
875 BluetoothAudioProviderFactoryAidl::SetUp();
876 GetProviderCapabilitiesHelper(
877 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
878 OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
879 ASSERT_NE(audio_provider_, nullptr);
880 }
881
882 virtual void TearDown() override {
883 audio_port_ = nullptr;
884 audio_provider_ = nullptr;
885 BluetoothAudioProviderFactoryAidl::TearDown();
886 }
887
888 static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
889 static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
890 static constexpr ChannelMode hearing_aid_channel_modes_[] = {
891 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
892};
893
894/**
895 * Test whether we can open a provider of type
896 */
897TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
898 OpenHearingAidSoftwareProvider) {}
899
900/**
901 * Test whether each provider of type
902 * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
903 * stopped with different PCM config
904 */
905TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
906 StartAndEndHearingAidSessionWithPossiblePcmConfig) {
907 for (int32_t sample_rate : hearing_aid_sample_rates_) {
908 for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
909 for (auto channel_mode : hearing_aid_channel_modes_) {
910 PcmConfiguration pcm_config{
911 .sampleRateHz = sample_rate,
912 .bitsPerSample = bits_per_sample,
913 .channelMode = channel_mode,
914 };
915 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
916 DataMQDesc mq_desc;
917 auto aidl_retval = audio_provider_->startSession(
918 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
919 DataMQ data_mq(mq_desc);
920
921 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
922 if (is_codec_config_valid) {
923 EXPECT_TRUE(data_mq.isValid());
924 }
925 EXPECT_TRUE(audio_provider_->endSession().isOk());
926 }
927 }
928 }
929}
930
931/**
932 * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
933 */
934class BluetoothAudioProviderLeAudioOutputSoftwareAidl
935 : public BluetoothAudioProviderFactoryAidl {
936 public:
937 virtual void SetUp() override {
938 BluetoothAudioProviderFactoryAidl::SetUp();
939 GetProviderCapabilitiesHelper(
940 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
941 OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
942 ASSERT_NE(audio_provider_, nullptr);
943 }
944
945 virtual void TearDown() override {
946 audio_port_ = nullptr;
947 audio_provider_ = nullptr;
948 BluetoothAudioProviderFactoryAidl::TearDown();
949 }
950
951 static constexpr int32_t le_audio_output_sample_rates_[] = {
952 0, 8000, 16000, 24000, 32000, 44100, 48000,
953 };
954 static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
955 static constexpr ChannelMode le_audio_output_channel_modes_[] = {
956 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
957 static constexpr int32_t le_audio_output_data_interval_us_[] = {
958 0 /* Invalid */, 10000 /* Valid 10ms */};
959};
960
961/**
962 * Test whether each provider of type
963 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
964 * stopped
965 */
966TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
967 OpenLeAudioOutputSoftwareProvider) {}
968
969/**
970 * Test whether each provider of type
971 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
972 * stopped with different PCM config
973 */
974TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
975 StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
976 for (auto sample_rate : le_audio_output_sample_rates_) {
977 for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
978 for (auto channel_mode : le_audio_output_channel_modes_) {
979 for (auto data_interval_us : le_audio_output_data_interval_us_) {
980 PcmConfiguration pcm_config{
981 .sampleRateHz = sample_rate,
982 .bitsPerSample = bits_per_sample,
983 .channelMode = channel_mode,
984 .dataIntervalUs = data_interval_us,
985 };
986 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
987 DataMQDesc mq_desc;
988 auto aidl_retval = audio_provider_->startSession(
989 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
990 DataMQ data_mq(mq_desc);
991
992 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
993 if (is_codec_config_valid) {
994 EXPECT_TRUE(data_mq.isValid());
995 }
996 EXPECT_TRUE(audio_provider_->endSession().isOk());
997 }
998 }
999 }
1000 }
1001}
1002
1003/**
1004 * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH
1005 */
1006class BluetoothAudioProviderLeAudioInputSoftwareAidl
1007 : public BluetoothAudioProviderFactoryAidl {
1008 public:
1009 virtual void SetUp() override {
1010 BluetoothAudioProviderFactoryAidl::SetUp();
1011 GetProviderCapabilitiesHelper(
1012 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
1013 OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
1014 ASSERT_NE(audio_provider_, nullptr);
1015 }
1016
1017 virtual void TearDown() override {
1018 audio_port_ = nullptr;
1019 audio_provider_ = nullptr;
1020 BluetoothAudioProviderFactoryAidl::TearDown();
1021 }
1022
1023 static constexpr int32_t le_audio_input_sample_rates_[] = {
1024 0, 8000, 16000, 24000, 32000, 44100, 48000};
1025 static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
1026 static constexpr ChannelMode le_audio_input_channel_modes_[] = {
1027 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
1028 static constexpr int32_t le_audio_input_data_interval_us_[] = {
1029 0 /* Invalid */, 10000 /* Valid 10ms */};
1030};
1031
1032/**
1033 * Test whether each provider of type
1034 * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
1035 * stopped
1036 */
1037TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
1038 OpenLeAudioInputSoftwareProvider) {}
1039
1040/**
1041 * Test whether each provider of type
1042 * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
1043 * stopped with different PCM config
1044 */
1045TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
1046 StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
1047 for (auto sample_rate : le_audio_input_sample_rates_) {
1048 for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
1049 for (auto channel_mode : le_audio_input_channel_modes_) {
1050 for (auto data_interval_us : le_audio_input_data_interval_us_) {
1051 PcmConfiguration pcm_config{
1052 .sampleRateHz = sample_rate,
1053 .bitsPerSample = bits_per_sample,
1054 .channelMode = channel_mode,
1055 .dataIntervalUs = data_interval_us,
1056 };
1057 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
1058 DataMQDesc mq_desc;
1059 auto aidl_retval = audio_provider_->startSession(
1060 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
1061 DataMQ data_mq(mq_desc);
1062
1063 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
1064 if (is_codec_config_valid) {
1065 EXPECT_TRUE(data_mq.isValid());
1066 }
1067 EXPECT_TRUE(audio_provider_->endSession().isOk());
1068 }
1069 }
1070 }
1071 }
1072}
1073
1074/**
1075 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODED_DATAPATH
1076 */
1077class BluetoothAudioProviderLeAudioOutputHardwareAidl
1078 : public BluetoothAudioProviderFactoryAidl {
1079 public:
1080 virtual void SetUp() override {
1081 BluetoothAudioProviderFactoryAidl::SetUp();
1082 GetProviderCapabilitiesHelper(
1083 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1084 OpenProviderHelper(
1085 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1086 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1087 audio_provider_ != nullptr);
1088 }
1089
1090 virtual void TearDown() override {
1091 audio_port_ = nullptr;
1092 audio_provider_ = nullptr;
1093 BluetoothAudioProviderFactoryAidl::TearDown();
1094 }
1095
1096 bool IsOffloadOutputSupported() {
1097 for (auto& capability : temp_provider_capabilities_) {
1098 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1099 continue;
1100 }
1101 auto& le_audio_capability =
1102 capability.get<AudioCapabilities::leAudioCapabilities>();
1103 if (le_audio_capability.unicastEncodeCapability.codecType !=
1104 CodecType::UNKNOWN)
1105 return true;
1106 }
1107 return false;
1108 }
1109
1110 std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
1111 bool supported) {
1112 std::vector<Lc3Configuration> le_audio_codec_configs;
1113 if (!supported) {
1114 Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
1115 le_audio_codec_configs.push_back(lc3_config);
1116 return le_audio_codec_configs;
1117 }
1118
1119 // There might be more than one LeAudioCodecCapabilitiesSetting
1120 std::vector<Lc3Capabilities> lc3_capabilities;
1121 for (auto& capability : temp_provider_capabilities_) {
1122 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1123 continue;
1124 }
1125 auto& le_audio_capability =
1126 capability.get<AudioCapabilities::leAudioCapabilities>();
1127 auto& unicast_capability =
1128 decoding ? le_audio_capability.unicastDecodeCapability
1129 : le_audio_capability.unicastEncodeCapability;
1130 if (unicast_capability.codecType != CodecType::LC3) {
1131 continue;
1132 }
1133 auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
1134 UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
1135 lc3_capabilities.push_back(lc3_capability);
1136 }
1137
1138 // Combine those parameters into one list of LeAudioCodecConfiguration
1139 // This seems horrible, but usually each Lc3Capability only contains a
1140 // single Lc3Configuration, which means every array has a length of 1.
1141 for (auto& lc3_capability : lc3_capabilities) {
1142 for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
1143 for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
1144 for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
1145 Lc3Configuration lc3_config = {
1146 .samplingFrequencyHz = samplingFrequencyHz,
1147 .frameDurationUs = frameDurationUs,
1148 .octetsPerFrame = octetsPerFrame,
1149 };
1150 le_audio_codec_configs.push_back(lc3_config);
1151 }
1152 }
1153 }
1154 }
1155
1156 return le_audio_codec_configs;
1157 }
1158
1159 LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
1160};
1161
1162/**
1163 * Test whether each provider of type
1164 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1165 * stopped
1166 */
1167TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1168 OpenLeAudioOutputHardwareProvider) {}
1169
1170/**
1171 * Test whether each provider of type
1172 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1173 * stopped with Unicast hardware encoding config
1174 */
1175TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1176 StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
1177 if (!IsOffloadOutputSupported()) {
1178 return;
1179 }
1180
1181 auto lc3_codec_configs =
1182 GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
1183 LeAudioConfiguration le_audio_config = {
1184 .codecType = CodecType::LC3,
1185 .peerDelayUs = 0,
1186 };
1187
1188 for (auto& lc3_config : lc3_codec_configs) {
1189 le_audio_config.leAudioCodecConfig
1190 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1191 DataMQDesc mq_desc;
1192 auto aidl_retval = audio_provider_->startSession(
1193 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1194
1195 ASSERT_TRUE(aidl_retval.isOk());
1196 EXPECT_TRUE(audio_provider_->endSession().isOk());
1197 }
1198}
1199
1200/**
1201 * Test whether each provider of type
1202 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1203 * stopped with Unicast hardware encoding config
1204 *
1205 * Disabled since offload codec checking is not ready
1206 */
1207TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1208 DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
1209 if (!IsOffloadOutputSupported()) {
1210 return;
1211 }
1212
1213 auto lc3_codec_configs =
1214 GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
1215 LeAudioConfiguration le_audio_config = {
1216 .codecType = CodecType::LC3,
1217 .peerDelayUs = 0,
1218 };
1219
1220 for (auto& lc3_config : lc3_codec_configs) {
1221 le_audio_config.leAudioCodecConfig
1222 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1223 DataMQDesc mq_desc;
1224 auto aidl_retval = audio_provider_->startSession(
1225 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1226
1227 // AIDL call should fail on invalid codec
1228 ASSERT_FALSE(aidl_retval.isOk());
1229 EXPECT_TRUE(audio_provider_->endSession().isOk());
1230 }
1231}
1232
1233/**
1234 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
1235 */
1236class BluetoothAudioProviderLeAudioInputHardwareAidl
1237 : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
1238 public:
1239 virtual void SetUp() override {
1240 BluetoothAudioProviderFactoryAidl::SetUp();
1241 GetProviderCapabilitiesHelper(
1242 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
1243 OpenProviderHelper(
1244 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
1245 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1246 audio_provider_ != nullptr);
1247 }
1248
1249 bool IsOffloadInputSupported() {
1250 for (auto& capability : temp_provider_capabilities_) {
1251 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1252 continue;
1253 }
1254 auto& le_audio_capability =
1255 capability.get<AudioCapabilities::leAudioCapabilities>();
1256 if (le_audio_capability.unicastDecodeCapability.codecType !=
1257 CodecType::UNKNOWN)
1258 return true;
1259 }
1260 return false;
1261 }
1262
1263 virtual void TearDown() override {
1264 audio_port_ = nullptr;
1265 audio_provider_ = nullptr;
1266 BluetoothAudioProviderFactoryAidl::TearDown();
1267 }
1268};
1269
1270/**
1271 * Test whether each provider of type
1272 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1273 * stopped
1274 */
1275TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1276 OpenLeAudioInputHardwareProvider) {}
1277
1278/**
1279 * Test whether each provider of type
1280 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1281 * stopped with Unicast hardware encoding config
1282 */
1283TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1284 StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
1285 if (!IsOffloadInputSupported()) {
1286 return;
1287 }
1288
1289 auto lc3_codec_configs =
1290 GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
1291 LeAudioConfiguration le_audio_config = {
1292 .codecType = CodecType::LC3,
1293 .peerDelayUs = 0,
1294 };
1295
1296 for (auto& lc3_config : lc3_codec_configs) {
1297 le_audio_config.leAudioCodecConfig
1298 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1299 DataMQDesc mq_desc;
1300 auto aidl_retval = audio_provider_->startSession(
1301 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1302
1303 ASSERT_TRUE(aidl_retval.isOk());
1304 EXPECT_TRUE(audio_provider_->endSession().isOk());
1305 }
1306}
1307
1308/**
1309 * Test whether each provider of type
1310 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1311 * stopped with Unicast hardware encoding config
1312 *
1313 * Disabled since offload codec checking is not ready
1314 */
1315TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1316 DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
1317 if (!IsOffloadInputSupported()) {
1318 return;
1319 }
1320
1321 auto lc3_codec_configs =
1322 GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
1323 LeAudioConfiguration le_audio_config = {
1324 .codecType = CodecType::LC3,
1325 .peerDelayUs = 0,
1326 };
1327
1328 for (auto& lc3_config : lc3_codec_configs) {
1329 le_audio_config.leAudioCodecConfig
1330 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1331
1332 DataMQDesc mq_desc;
1333 auto aidl_retval = audio_provider_->startSession(
1334 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1335
1336 // AIDL call should fail on invalid codec
1337 ASSERT_FALSE(aidl_retval.isOk());
1338 EXPECT_TRUE(audio_provider_->endSession().isOk());
1339 }
1340}
1341
1342/**
1343 * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
1344 */
1345class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
1346 : public BluetoothAudioProviderFactoryAidl {
1347 public:
1348 virtual void SetUp() override {
1349 BluetoothAudioProviderFactoryAidl::SetUp();
1350 GetProviderCapabilitiesHelper(
1351 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
1352 OpenProviderHelper(
1353 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
1354 ASSERT_NE(audio_provider_, nullptr);
1355 }
1356
1357 virtual void TearDown() override {
1358 audio_port_ = nullptr;
1359 audio_provider_ = nullptr;
1360 BluetoothAudioProviderFactoryAidl::TearDown();
1361 }
1362
1363 static constexpr int32_t le_audio_output_sample_rates_[] = {
1364 0, 8000, 16000, 24000, 32000, 44100, 48000,
1365 };
1366 static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
1367 static constexpr ChannelMode le_audio_output_channel_modes_[] = {
1368 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
1369 static constexpr int32_t le_audio_output_data_interval_us_[] = {
1370 0 /* Invalid */, 10000 /* Valid 10ms */};
1371};
1372
1373/**
1374 * Test whether each provider of type
1375 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
1376 * stopped
1377 */
1378TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1379 DISABLED_OpenLeAudioOutputSoftwareProvider) {}
1380
1381/**
1382 * Test whether each provider of type
1383 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
1384 * stopped with different PCM config
1385 */
1386TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1387 DISABLED_StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
1388 for (auto sample_rate : le_audio_output_sample_rates_) {
1389 for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
1390 for (auto channel_mode : le_audio_output_channel_modes_) {
1391 for (auto data_interval_us : le_audio_output_data_interval_us_) {
1392 PcmConfiguration pcm_config{
1393 .sampleRateHz = sample_rate,
1394 .bitsPerSample = bits_per_sample,
1395 .channelMode = channel_mode,
1396 .dataIntervalUs = data_interval_us,
1397 };
1398 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
1399 DataMQDesc mq_desc;
1400 auto aidl_retval = audio_provider_->startSession(
1401 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
1402 DataMQ data_mq(mq_desc);
1403
1404 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
1405 if (is_codec_config_valid) {
1406 EXPECT_TRUE(data_mq.isValid());
1407 }
1408 EXPECT_TRUE(audio_provider_->endSession().isOk());
1409 }
1410 }
1411 }
1412 }
1413}
1414
1415GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1416 BluetoothAudioProviderFactoryAidl);
1417INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
1418 testing::ValuesIn(android::getAidlHalInstanceNames(
1419 IBluetoothAudioProviderFactory::descriptor)),
1420 android::PrintInstanceNameToString);
1421
1422GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1423 BluetoothAudioProviderA2dpSoftwareAidl);
1424INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl,
1425 testing::ValuesIn(android::getAidlHalInstanceNames(
1426 IBluetoothAudioProviderFactory::descriptor)),
1427 android::PrintInstanceNameToString);
1428
1429GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1430 BluetoothAudioProviderA2dpHardwareAidl);
1431INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl,
1432 testing::ValuesIn(android::getAidlHalInstanceNames(
1433 IBluetoothAudioProviderFactory::descriptor)),
1434 android::PrintInstanceNameToString);
1435
1436GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1437 BluetoothAudioProviderHearingAidSoftwareAidl);
1438INSTANTIATE_TEST_SUITE_P(PerInstance,
1439 BluetoothAudioProviderHearingAidSoftwareAidl,
1440 testing::ValuesIn(android::getAidlHalInstanceNames(
1441 IBluetoothAudioProviderFactory::descriptor)),
1442 android::PrintInstanceNameToString);
1443
1444GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1445 BluetoothAudioProviderLeAudioOutputSoftwareAidl);
1446INSTANTIATE_TEST_SUITE_P(PerInstance,
1447 BluetoothAudioProviderLeAudioOutputSoftwareAidl,
1448 testing::ValuesIn(android::getAidlHalInstanceNames(
1449 IBluetoothAudioProviderFactory::descriptor)),
1450 android::PrintInstanceNameToString);
1451
1452GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1453 BluetoothAudioProviderLeAudioInputSoftwareAidl);
1454INSTANTIATE_TEST_SUITE_P(PerInstance,
1455 BluetoothAudioProviderLeAudioInputSoftwareAidl,
1456 testing::ValuesIn(android::getAidlHalInstanceNames(
1457 IBluetoothAudioProviderFactory::descriptor)),
1458 android::PrintInstanceNameToString);
1459
1460GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1461 BluetoothAudioProviderLeAudioOutputHardwareAidl);
1462INSTANTIATE_TEST_SUITE_P(PerInstance,
1463 BluetoothAudioProviderLeAudioOutputHardwareAidl,
1464 testing::ValuesIn(android::getAidlHalInstanceNames(
1465 IBluetoothAudioProviderFactory::descriptor)),
1466 android::PrintInstanceNameToString);
1467
1468GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1469 BluetoothAudioProviderLeAudioInputHardwareAidl);
1470INSTANTIATE_TEST_SUITE_P(PerInstance,
1471 BluetoothAudioProviderLeAudioInputHardwareAidl,
1472 testing::ValuesIn(android::getAidlHalInstanceNames(
1473 IBluetoothAudioProviderFactory::descriptor)),
1474 android::PrintInstanceNameToString);
1475
1476GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1477 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
1478INSTANTIATE_TEST_SUITE_P(PerInstance,
1479 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1480 testing::ValuesIn(android::getAidlHalInstanceNames(
1481 IBluetoothAudioProviderFactory::descriptor)),
1482 android::PrintInstanceNameToString);
1483
1484// TODO(219668925): Add LE Audio Broadcast VTS
1485// GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1486// BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
1487// INSTANTIATE_TEST_SUITE_P(PerInstance,
1488// BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
1489// testing::ValuesIn(android::getAidlHalInstanceNames(
1490// IBluetoothAudioProviderFactory::descriptor)),
1491// android::PrintInstanceNameToString);
1492
1493int main(int argc, char** argv) {
1494 ::testing::InitGoogleTest(&argc, argv);
1495 ABinderProcess_setThreadPoolMaxThreadCount(1);
1496 ABinderProcess_startThreadPool();
1497 return RUN_ALL_TESTS();
1498}