blob: 38a6b0d6a602ec5028877be09b7431d3abb3938c [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 };
Josh Wu8a1be762022-02-15 09:37:29 -0800986 bool is_codec_config_valid =
987 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -0800988 DataMQDesc mq_desc;
989 auto aidl_retval = audio_provider_->startSession(
990 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
991 DataMQ data_mq(mq_desc);
992
993 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
994 if (is_codec_config_valid) {
995 EXPECT_TRUE(data_mq.isValid());
996 }
997 EXPECT_TRUE(audio_provider_->endSession().isOk());
998 }
999 }
1000 }
1001 }
1002}
1003
1004/**
1005 * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH
1006 */
1007class BluetoothAudioProviderLeAudioInputSoftwareAidl
1008 : public BluetoothAudioProviderFactoryAidl {
1009 public:
1010 virtual void SetUp() override {
1011 BluetoothAudioProviderFactoryAidl::SetUp();
1012 GetProviderCapabilitiesHelper(
1013 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
1014 OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
1015 ASSERT_NE(audio_provider_, nullptr);
1016 }
1017
1018 virtual void TearDown() override {
1019 audio_port_ = nullptr;
1020 audio_provider_ = nullptr;
1021 BluetoothAudioProviderFactoryAidl::TearDown();
1022 }
1023
1024 static constexpr int32_t le_audio_input_sample_rates_[] = {
1025 0, 8000, 16000, 24000, 32000, 44100, 48000};
1026 static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
1027 static constexpr ChannelMode le_audio_input_channel_modes_[] = {
1028 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
1029 static constexpr int32_t le_audio_input_data_interval_us_[] = {
1030 0 /* Invalid */, 10000 /* Valid 10ms */};
1031};
1032
1033/**
1034 * Test whether each provider of type
1035 * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
1036 * stopped
1037 */
1038TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
1039 OpenLeAudioInputSoftwareProvider) {}
1040
1041/**
1042 * Test whether each provider of type
1043 * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
1044 * stopped with different PCM config
1045 */
1046TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
1047 StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
1048 for (auto sample_rate : le_audio_input_sample_rates_) {
1049 for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
1050 for (auto channel_mode : le_audio_input_channel_modes_) {
1051 for (auto data_interval_us : le_audio_input_data_interval_us_) {
1052 PcmConfiguration pcm_config{
1053 .sampleRateHz = sample_rate,
1054 .bitsPerSample = bits_per_sample,
1055 .channelMode = channel_mode,
1056 .dataIntervalUs = data_interval_us,
1057 };
Josh Wu8a1be762022-02-15 09:37:29 -08001058 bool is_codec_config_valid =
1059 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -08001060 DataMQDesc mq_desc;
1061 auto aidl_retval = audio_provider_->startSession(
1062 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
1063 DataMQ data_mq(mq_desc);
1064
1065 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
1066 if (is_codec_config_valid) {
1067 EXPECT_TRUE(data_mq.isValid());
1068 }
1069 EXPECT_TRUE(audio_provider_->endSession().isOk());
1070 }
1071 }
1072 }
1073 }
1074}
1075
1076/**
1077 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODED_DATAPATH
1078 */
1079class BluetoothAudioProviderLeAudioOutputHardwareAidl
1080 : public BluetoothAudioProviderFactoryAidl {
1081 public:
1082 virtual void SetUp() override {
1083 BluetoothAudioProviderFactoryAidl::SetUp();
1084 GetProviderCapabilitiesHelper(
1085 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1086 OpenProviderHelper(
1087 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1088 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1089 audio_provider_ != nullptr);
1090 }
1091
1092 virtual void TearDown() override {
1093 audio_port_ = nullptr;
1094 audio_provider_ = nullptr;
1095 BluetoothAudioProviderFactoryAidl::TearDown();
1096 }
1097
1098 bool IsOffloadOutputSupported() {
1099 for (auto& capability : temp_provider_capabilities_) {
1100 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1101 continue;
1102 }
1103 auto& le_audio_capability =
1104 capability.get<AudioCapabilities::leAudioCapabilities>();
1105 if (le_audio_capability.unicastEncodeCapability.codecType !=
1106 CodecType::UNKNOWN)
1107 return true;
1108 }
1109 return false;
1110 }
1111
1112 std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
1113 bool supported) {
1114 std::vector<Lc3Configuration> le_audio_codec_configs;
1115 if (!supported) {
1116 Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
1117 le_audio_codec_configs.push_back(lc3_config);
1118 return le_audio_codec_configs;
1119 }
1120
1121 // There might be more than one LeAudioCodecCapabilitiesSetting
1122 std::vector<Lc3Capabilities> lc3_capabilities;
1123 for (auto& capability : temp_provider_capabilities_) {
1124 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1125 continue;
1126 }
1127 auto& le_audio_capability =
1128 capability.get<AudioCapabilities::leAudioCapabilities>();
1129 auto& unicast_capability =
1130 decoding ? le_audio_capability.unicastDecodeCapability
1131 : le_audio_capability.unicastEncodeCapability;
1132 if (unicast_capability.codecType != CodecType::LC3) {
1133 continue;
1134 }
1135 auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
1136 UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
1137 lc3_capabilities.push_back(lc3_capability);
1138 }
1139
1140 // Combine those parameters into one list of LeAudioCodecConfiguration
1141 // This seems horrible, but usually each Lc3Capability only contains a
1142 // single Lc3Configuration, which means every array has a length of 1.
1143 for (auto& lc3_capability : lc3_capabilities) {
1144 for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
1145 for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
1146 for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
1147 Lc3Configuration lc3_config = {
1148 .samplingFrequencyHz = samplingFrequencyHz,
1149 .frameDurationUs = frameDurationUs,
1150 .octetsPerFrame = octetsPerFrame,
1151 };
1152 le_audio_codec_configs.push_back(lc3_config);
1153 }
1154 }
1155 }
1156 }
1157
1158 return le_audio_codec_configs;
1159 }
1160
1161 LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
1162};
1163
1164/**
1165 * Test whether each provider of type
1166 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1167 * stopped
1168 */
1169TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1170 OpenLeAudioOutputHardwareProvider) {}
1171
1172/**
1173 * Test whether each provider of type
1174 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1175 * stopped with Unicast hardware encoding config
1176 */
1177TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1178 StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
1179 if (!IsOffloadOutputSupported()) {
1180 return;
1181 }
1182
1183 auto lc3_codec_configs =
1184 GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
1185 LeAudioConfiguration le_audio_config = {
1186 .codecType = CodecType::LC3,
1187 .peerDelayUs = 0,
1188 };
1189
1190 for (auto& lc3_config : lc3_codec_configs) {
1191 le_audio_config.leAudioCodecConfig
1192 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1193 DataMQDesc mq_desc;
1194 auto aidl_retval = audio_provider_->startSession(
1195 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1196
1197 ASSERT_TRUE(aidl_retval.isOk());
1198 EXPECT_TRUE(audio_provider_->endSession().isOk());
1199 }
1200}
1201
1202/**
1203 * Test whether each provider of type
1204 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1205 * stopped with Unicast hardware encoding config
1206 *
1207 * Disabled since offload codec checking is not ready
1208 */
1209TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
1210 DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
1211 if (!IsOffloadOutputSupported()) {
1212 return;
1213 }
1214
1215 auto lc3_codec_configs =
1216 GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
1217 LeAudioConfiguration le_audio_config = {
1218 .codecType = CodecType::LC3,
1219 .peerDelayUs = 0,
1220 };
1221
1222 for (auto& lc3_config : lc3_codec_configs) {
1223 le_audio_config.leAudioCodecConfig
1224 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1225 DataMQDesc mq_desc;
1226 auto aidl_retval = audio_provider_->startSession(
1227 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1228
1229 // AIDL call should fail on invalid codec
1230 ASSERT_FALSE(aidl_retval.isOk());
1231 EXPECT_TRUE(audio_provider_->endSession().isOk());
1232 }
1233}
1234
1235/**
1236 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
1237 */
1238class BluetoothAudioProviderLeAudioInputHardwareAidl
1239 : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
1240 public:
1241 virtual void SetUp() override {
1242 BluetoothAudioProviderFactoryAidl::SetUp();
1243 GetProviderCapabilitiesHelper(
1244 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
1245 OpenProviderHelper(
1246 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
1247 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1248 audio_provider_ != nullptr);
1249 }
1250
1251 bool IsOffloadInputSupported() {
1252 for (auto& capability : temp_provider_capabilities_) {
1253 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
1254 continue;
1255 }
1256 auto& le_audio_capability =
1257 capability.get<AudioCapabilities::leAudioCapabilities>();
1258 if (le_audio_capability.unicastDecodeCapability.codecType !=
1259 CodecType::UNKNOWN)
1260 return true;
1261 }
1262 return false;
1263 }
1264
1265 virtual void TearDown() override {
1266 audio_port_ = nullptr;
1267 audio_provider_ = nullptr;
1268 BluetoothAudioProviderFactoryAidl::TearDown();
1269 }
1270};
1271
1272/**
1273 * Test whether each provider of type
1274 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1275 * stopped
1276 */
1277TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1278 OpenLeAudioInputHardwareProvider) {}
1279
1280/**
1281 * Test whether each provider of type
1282 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1283 * stopped with Unicast hardware encoding config
1284 */
1285TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1286 StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
1287 if (!IsOffloadInputSupported()) {
1288 return;
1289 }
1290
1291 auto lc3_codec_configs =
1292 GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
1293 LeAudioConfiguration le_audio_config = {
1294 .codecType = CodecType::LC3,
1295 .peerDelayUs = 0,
1296 };
1297
1298 for (auto& lc3_config : lc3_codec_configs) {
1299 le_audio_config.leAudioCodecConfig
1300 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1301 DataMQDesc mq_desc;
1302 auto aidl_retval = audio_provider_->startSession(
1303 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1304
1305 ASSERT_TRUE(aidl_retval.isOk());
1306 EXPECT_TRUE(audio_provider_->endSession().isOk());
1307 }
1308}
1309
1310/**
1311 * Test whether each provider of type
1312 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
1313 * stopped with Unicast hardware encoding config
1314 *
1315 * Disabled since offload codec checking is not ready
1316 */
1317TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
1318 DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
1319 if (!IsOffloadInputSupported()) {
1320 return;
1321 }
1322
1323 auto lc3_codec_configs =
1324 GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
1325 LeAudioConfiguration le_audio_config = {
1326 .codecType = CodecType::LC3,
1327 .peerDelayUs = 0,
1328 };
1329
1330 for (auto& lc3_config : lc3_codec_configs) {
1331 le_audio_config.leAudioCodecConfig
1332 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
1333
1334 DataMQDesc mq_desc;
1335 auto aidl_retval = audio_provider_->startSession(
1336 audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
1337
1338 // AIDL call should fail on invalid codec
1339 ASSERT_FALSE(aidl_retval.isOk());
1340 EXPECT_TRUE(audio_provider_->endSession().isOk());
1341 }
1342}
1343
1344/**
1345 * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
1346 */
1347class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
1348 : public BluetoothAudioProviderFactoryAidl {
1349 public:
1350 virtual void SetUp() override {
1351 BluetoothAudioProviderFactoryAidl::SetUp();
1352 GetProviderCapabilitiesHelper(
1353 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
1354 OpenProviderHelper(
1355 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
1356 ASSERT_NE(audio_provider_, nullptr);
1357 }
1358
1359 virtual void TearDown() override {
1360 audio_port_ = nullptr;
1361 audio_provider_ = nullptr;
1362 BluetoothAudioProviderFactoryAidl::TearDown();
1363 }
1364
1365 static constexpr int32_t le_audio_output_sample_rates_[] = {
1366 0, 8000, 16000, 24000, 32000, 44100, 48000,
1367 };
1368 static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
1369 static constexpr ChannelMode le_audio_output_channel_modes_[] = {
1370 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
1371 static constexpr int32_t le_audio_output_data_interval_us_[] = {
1372 0 /* Invalid */, 10000 /* Valid 10ms */};
1373};
1374
1375/**
1376 * Test whether each provider of type
1377 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
1378 * stopped
1379 */
1380TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1381 DISABLED_OpenLeAudioOutputSoftwareProvider) {}
1382
1383/**
1384 * Test whether each provider of type
1385 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
1386 * stopped with different PCM config
1387 */
1388TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1389 DISABLED_StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
1390 for (auto sample_rate : le_audio_output_sample_rates_) {
1391 for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
1392 for (auto channel_mode : le_audio_output_channel_modes_) {
1393 for (auto data_interval_us : le_audio_output_data_interval_us_) {
1394 PcmConfiguration pcm_config{
1395 .sampleRateHz = sample_rate,
1396 .bitsPerSample = bits_per_sample,
1397 .channelMode = channel_mode,
1398 .dataIntervalUs = data_interval_us,
1399 };
Josh Wu8a1be762022-02-15 09:37:29 -08001400 bool is_codec_config_valid =
1401 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -08001402 DataMQDesc mq_desc;
1403 auto aidl_retval = audio_provider_->startSession(
1404 audio_port_, AudioConfiguration(pcm_config), &mq_desc);
1405 DataMQ data_mq(mq_desc);
1406
1407 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
1408 if (is_codec_config_valid) {
1409 EXPECT_TRUE(data_mq.isValid());
1410 }
1411 EXPECT_TRUE(audio_provider_->endSession().isOk());
1412 }
1413 }
1414 }
1415 }
1416}
1417
1418GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1419 BluetoothAudioProviderFactoryAidl);
1420INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
1421 testing::ValuesIn(android::getAidlHalInstanceNames(
1422 IBluetoothAudioProviderFactory::descriptor)),
1423 android::PrintInstanceNameToString);
1424
1425GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1426 BluetoothAudioProviderA2dpSoftwareAidl);
1427INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl,
1428 testing::ValuesIn(android::getAidlHalInstanceNames(
1429 IBluetoothAudioProviderFactory::descriptor)),
1430 android::PrintInstanceNameToString);
1431
1432GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1433 BluetoothAudioProviderA2dpHardwareAidl);
1434INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl,
1435 testing::ValuesIn(android::getAidlHalInstanceNames(
1436 IBluetoothAudioProviderFactory::descriptor)),
1437 android::PrintInstanceNameToString);
1438
1439GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1440 BluetoothAudioProviderHearingAidSoftwareAidl);
1441INSTANTIATE_TEST_SUITE_P(PerInstance,
1442 BluetoothAudioProviderHearingAidSoftwareAidl,
1443 testing::ValuesIn(android::getAidlHalInstanceNames(
1444 IBluetoothAudioProviderFactory::descriptor)),
1445 android::PrintInstanceNameToString);
1446
1447GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1448 BluetoothAudioProviderLeAudioOutputSoftwareAidl);
1449INSTANTIATE_TEST_SUITE_P(PerInstance,
1450 BluetoothAudioProviderLeAudioOutputSoftwareAidl,
1451 testing::ValuesIn(android::getAidlHalInstanceNames(
1452 IBluetoothAudioProviderFactory::descriptor)),
1453 android::PrintInstanceNameToString);
1454
1455GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1456 BluetoothAudioProviderLeAudioInputSoftwareAidl);
1457INSTANTIATE_TEST_SUITE_P(PerInstance,
1458 BluetoothAudioProviderLeAudioInputSoftwareAidl,
1459 testing::ValuesIn(android::getAidlHalInstanceNames(
1460 IBluetoothAudioProviderFactory::descriptor)),
1461 android::PrintInstanceNameToString);
1462
1463GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1464 BluetoothAudioProviderLeAudioOutputHardwareAidl);
1465INSTANTIATE_TEST_SUITE_P(PerInstance,
1466 BluetoothAudioProviderLeAudioOutputHardwareAidl,
1467 testing::ValuesIn(android::getAidlHalInstanceNames(
1468 IBluetoothAudioProviderFactory::descriptor)),
1469 android::PrintInstanceNameToString);
1470
1471GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1472 BluetoothAudioProviderLeAudioInputHardwareAidl);
1473INSTANTIATE_TEST_SUITE_P(PerInstance,
1474 BluetoothAudioProviderLeAudioInputHardwareAidl,
1475 testing::ValuesIn(android::getAidlHalInstanceNames(
1476 IBluetoothAudioProviderFactory::descriptor)),
1477 android::PrintInstanceNameToString);
1478
1479GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1480 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
1481INSTANTIATE_TEST_SUITE_P(PerInstance,
1482 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
1483 testing::ValuesIn(android::getAidlHalInstanceNames(
1484 IBluetoothAudioProviderFactory::descriptor)),
1485 android::PrintInstanceNameToString);
1486
1487// TODO(219668925): Add LE Audio Broadcast VTS
1488// GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
1489// BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
1490// INSTANTIATE_TEST_SUITE_P(PerInstance,
1491// BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
1492// testing::ValuesIn(android::getAidlHalInstanceNames(
1493// IBluetoothAudioProviderFactory::descriptor)),
1494// android::PrintInstanceNameToString);
1495
1496int main(int argc, char** argv) {
1497 ::testing::InitGoogleTest(&argc, argv);
1498 ABinderProcess_setThreadPoolMaxThreadCount(1);
1499 ABinderProcess_startThreadPool();
1500 return RUN_ALL_TESTS();
1501}