blob: 44812383057a4dd011ca8dabd925d02d0708073b [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>
shihchienc3ab9f5e2022-09-23 08:18:05 +000026#include <cutils/properties.h>
Josh Wu049e2cd2022-01-12 05:42:58 -080027#include <fmq/AidlMessageQueue.h>
28
29#include <cstdint>
30#include <future>
31#include <unordered_set>
32#include <vector>
33
34using aidl::android::hardware::audio::common::SinkMetadata;
35using aidl::android::hardware::audio::common::SourceMetadata;
Antoine SOULIER33c4e5a2023-09-28 21:59:19 +000036using aidl::android::hardware::bluetooth::audio::A2dpConfiguration;
37using aidl::android::hardware::bluetooth::audio::A2dpConfigurationHint;
38using aidl::android::hardware::bluetooth::audio::A2dpRemoteCapabilities;
39using aidl::android::hardware::bluetooth::audio::A2dpStatus;
40using aidl::android::hardware::bluetooth::audio::A2dpStreamConfiguration;
Josh Wu049e2cd2022-01-12 05:42:58 -080041using aidl::android::hardware::bluetooth::audio::AacCapabilities;
42using aidl::android::hardware::bluetooth::audio::AacConfiguration;
Sagar Verma62df9102022-12-07 17:56:04 +053043using aidl::android::hardware::bluetooth::audio::AptxAdaptiveLeCapabilities;
44using aidl::android::hardware::bluetooth::audio::AptxAdaptiveLeConfiguration;
Josh Wu049e2cd2022-01-12 05:42:58 -080045using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
46using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
47using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
48using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
Bao Doc36897d2023-12-06 01:27:54 +000049using aidl::android::hardware::bluetooth::audio::AudioContext;
Josh Wu049e2cd2022-01-12 05:42:58 -080050using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
Alice Kuo336d90c2022-02-16 09:09:59 +080051using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
Josh Wu049e2cd2022-01-12 05:42:58 -080052using aidl::android::hardware::bluetooth::audio::ChannelMode;
53using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
54using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
Antoine SOULIER8c90f1f2023-09-26 18:55:17 +000055using aidl::android::hardware::bluetooth::audio::CodecId;
56using aidl::android::hardware::bluetooth::audio::CodecInfo;
Antoine SOULIER33c4e5a2023-09-28 21:59:19 +000057using aidl::android::hardware::bluetooth::audio::CodecParameters;
Bao Doc36897d2023-12-06 01:27:54 +000058using aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv;
59using aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv;
Josh Wu049e2cd2022-01-12 05:42:58 -080060using aidl::android::hardware::bluetooth::audio::CodecType;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +000061using aidl::android::hardware::bluetooth::audio::ConfigurationFlags;
Bao Do72399432023-11-09 08:13:05 +000062using aidl::android::hardware::bluetooth::audio::HfpConfiguration;
Josh Wu049e2cd2022-01-12 05:42:58 -080063using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
64using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
65using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
66using aidl::android::hardware::bluetooth::audio::LatencyMode;
67using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
68using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
69using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
70using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
Bao Doc36897d2023-12-06 01:27:54 +000071using aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +000072using aidl::android::hardware::bluetooth::audio::LeAudioBisConfiguration;
Alice Kuo336d90c2022-02-16 09:09:59 +080073using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
Josh Wu049e2cd2022-01-12 05:42:58 -080074using aidl::android::hardware::bluetooth::audio::
75 LeAudioCodecCapabilitiesSetting;
76using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
77using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
Bao Doc36897d2023-12-06 01:27:54 +000078using aidl::android::hardware::bluetooth::audio::MetadataLtv;
Omer Osmana2587da2022-05-01 03:54:11 +000079using aidl::android::hardware::bluetooth::audio::OpusCapabilities;
80using aidl::android::hardware::bluetooth::audio::OpusConfiguration;
Josh Wu049e2cd2022-01-12 05:42:58 -080081using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
82using aidl::android::hardware::bluetooth::audio::PresentationPosition;
83using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
84using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
85using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
86using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
87using aidl::android::hardware::bluetooth::audio::SessionType;
88using aidl::android::hardware::bluetooth::audio::UnicastCapability;
89using aidl::android::hardware::common::fmq::MQDescriptor;
90using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
91using android::AidlMessageQueue;
92using android::ProcessState;
93using android::String16;
94using ndk::ScopedAStatus;
95using ndk::SpAIBinder;
96
97using MqDataType = int8_t;
98using MqDataMode = SynchronizedReadWrite;
99using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
100using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
101
Bao Doc36897d2023-12-06 01:27:54 +0000102using LeAudioAseConfigurationSetting =
103 IBluetoothAudioProvider::LeAudioAseConfigurationSetting;
104using AseDirectionRequirement = IBluetoothAudioProvider::
105 LeAudioConfigurationRequirement::AseDirectionRequirement;
106using AseDirectionConfiguration = IBluetoothAudioProvider::
107 LeAudioAseConfigurationSetting::AseDirectionConfiguration;
108using AseQosDirectionRequirement = IBluetoothAudioProvider::
109 LeAudioAseQosConfigurationRequirement::AseQosDirectionRequirement;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +0000110using LeAudioAseQosConfigurationRequirement =
111 IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement;
Bao Doc36897d2023-12-06 01:27:54 +0000112using LeAudioAseQosConfiguration =
113 IBluetoothAudioProvider::LeAudioAseQosConfiguration;
114using LeAudioDeviceCapabilities =
115 IBluetoothAudioProvider::LeAudioDeviceCapabilities;
116using LeAudioConfigurationRequirement =
117 IBluetoothAudioProvider::LeAudioConfigurationRequirement;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +0000118using LeAudioBroadcastConfigurationRequirement =
119 IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement;
120using LeAudioBroadcastSubgroupConfiguration =
121 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration;
122using LeAudioBroadcastSubgroupConfigurationRequirement =
123 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfigurationRequirement;
124using LeAudioBroadcastConfigurationSetting =
125 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting;
126using LeAudioSubgroupBisConfiguration =
127 IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration;
Bao Doc36897d2023-12-06 01:27:54 +0000128
Josh Wu049e2cd2022-01-12 05:42:58 -0800129// Constants
130
131static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
132static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
133static constexpr ChannelMode a2dp_channel_modes[] = {
134 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
Chen Chenc92270e2022-02-14 18:29:52 -0800135static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
Bao Do72399432023-11-09 08:13:05 +0000136
Bao Dob487a852023-12-25 10:12:09 +0800137enum class BluetoothAudioHalVersion : int32_t {
138 VERSION_UNAVAILABLE = 0,
139 VERSION_2_0,
140 VERSION_2_1,
141 VERSION_AIDL_V1,
142 VERSION_AIDL_V2,
143 VERSION_AIDL_V3,
144 VERSION_AIDL_V4,
Jakub Tyszkowski291b5d72024-08-02 13:03:37 +0000145 VERSION_AIDL_V5,
Bao Dob487a852023-12-25 10:12:09 +0800146};
147
Bao Do72399432023-11-09 08:13:05 +0000148// Some valid configs for HFP PCM configuration (software sessions)
149static constexpr int32_t hfp_sample_rates_[] = {8000, 16000, 32000};
150static constexpr int8_t hfp_bits_per_samples_[] = {16};
151static constexpr ChannelMode hfp_channel_modes_[] = {ChannelMode::MONO};
152static constexpr int32_t hfp_data_interval_us_[] = {7500};
153
Josh Wu049e2cd2022-01-12 05:42:58 -0800154// Helpers
155
156template <typename T>
157struct identity {
158 typedef T type;
159};
160
161template <class T>
162bool contained_in_vector(const std::vector<T>& vector,
163 const typename identity<T>::type& target) {
164 return std::find(vector.begin(), vector.end(), target) != vector.end();
165}
166
167void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
168 const CodecConfiguration::CodecSpecific& src) {
169 switch (src.getTag()) {
170 case CodecConfiguration::CodecSpecific::sbcConfig:
171 dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
172 src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
173 break;
174 case CodecConfiguration::CodecSpecific::aacConfig:
175 dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
176 src.get<CodecConfiguration::CodecSpecific::aacConfig>());
177 break;
178 case CodecConfiguration::CodecSpecific::ldacConfig:
179 dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
180 src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
181 break;
182 case CodecConfiguration::CodecSpecific::aptxConfig:
183 dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
184 src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
185 break;
Omer Osmana2587da2022-05-01 03:54:11 +0000186 case CodecConfiguration::CodecSpecific::opusConfig:
187 dst.set<CodecConfiguration::CodecSpecific::opusConfig>(
188 src.get<CodecConfiguration::CodecSpecific::opusConfig>());
Josh Wu049e2cd2022-01-12 05:42:58 -0800189 break;
190 case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
191 dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
192 src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
193 break;
194 default:
195 break;
196 }
197}
198
Jakub Tyszkowski11178a62024-06-18 10:07:26 +0000199static std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
200 const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
201 CodecSpecificConfigurationLtv::Tag tag) {
202 for (const auto ltv : configurationLtvs) {
203 if (ltv.getTag() == tag) {
204 return ltv;
205 }
206 }
207 return std::nullopt;
208}
209
Josh Wu049e2cd2022-01-12 05:42:58 -0800210class BluetoothAudioPort : public BnBluetoothAudioPort {
211 public:
212 BluetoothAudioPort() {}
213
Chen Chen0a68a922022-02-15 18:43:26 -0800214 ndk::ScopedAStatus startStream(bool) { return ScopedAStatus::ok(); }
Josh Wu049e2cd2022-01-12 05:42:58 -0800215
216 ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
217
218 ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }
219
220 ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
221 return ScopedAStatus::ok();
222 }
223
224 ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
225 return ScopedAStatus::ok();
226 }
227
228 ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
229 return ScopedAStatus::ok();
230 }
231
232 ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
233 return ScopedAStatus::ok();
234 }
235
236 ndk::ScopedAStatus setCodecType(const CodecType) {
237 return ScopedAStatus::ok();
238 }
239
240 protected:
241 virtual ~BluetoothAudioPort() = default;
242};
243
244class BluetoothAudioProviderFactoryAidl
245 : public testing::TestWithParam<std::string> {
246 public:
247 virtual void SetUp() override {
248 provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
249 SpAIBinder(AServiceManager_getService(GetParam().c_str())));
250 audio_provider_ = nullptr;
251 ASSERT_NE(provider_factory_, nullptr);
252 }
253
254 virtual void TearDown() override { provider_factory_ = nullptr; }
255
Bao Doc36897d2023-12-06 01:27:54 +0000256 void GetProviderInfoHelper(const SessionType& session_type) {
257 temp_provider_info_ = std::nullopt;
258 auto aidl_reval =
259 provider_factory_->getProviderInfo(session_type, &temp_provider_info_);
Bao Doc36897d2023-12-06 01:27:54 +0000260 }
261
Josh Wu049e2cd2022-01-12 05:42:58 -0800262 void GetProviderCapabilitiesHelper(const SessionType& session_type) {
263 temp_provider_capabilities_.clear();
264 auto aidl_retval = provider_factory_->getProviderCapabilities(
265 session_type, &temp_provider_capabilities_);
266 // AIDL calls should not be failed and callback has to be executed
267 ASSERT_TRUE(aidl_retval.isOk());
268 switch (session_type) {
269 case SessionType::UNKNOWN: {
270 ASSERT_TRUE(temp_provider_capabilities_.empty());
271 } break;
272 case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
273 case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
274 case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
275 case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
Bao Do72399432023-11-09 08:13:05 +0000276 case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH:
277 case SessionType::HFP_SOFTWARE_ENCODING_DATAPATH: {
Josh Wu049e2cd2022-01-12 05:42:58 -0800278 // All software paths are mandatory and must have exact 1
279 // "PcmParameters"
280 ASSERT_EQ(temp_provider_capabilities_.size(), 1);
281 ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
282 AudioCapabilities::pcmCapabilities);
283 } break;
Alice Kuoadcceec2022-03-28 13:28:43 +0800284 case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
285 case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: {
Josh Wu049e2cd2022-01-12 05:42:58 -0800286 std::unordered_set<CodecType> codec_types;
287 // empty capability means offload is unsupported
288 for (auto& audio_capability : temp_provider_capabilities_) {
289 ASSERT_EQ(audio_capability.getTag(),
290 AudioCapabilities::a2dpCapabilities);
291 const auto& codec_capabilities =
292 audio_capability.get<AudioCapabilities::a2dpCapabilities>();
293 // Every codec can present once at most
294 ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
295 switch (codec_capabilities.codecType) {
296 case CodecType::SBC:
297 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
298 CodecCapabilities::Capabilities::sbcCapabilities);
299 break;
300 case CodecType::AAC:
301 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
302 CodecCapabilities::Capabilities::aacCapabilities);
303 break;
304 case CodecType::APTX:
305 case CodecType::APTX_HD:
306 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
307 CodecCapabilities::Capabilities::aptxCapabilities);
308 break;
309 case CodecType::LDAC:
310 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
311 CodecCapabilities::Capabilities::ldacCapabilities);
312 break;
Omer Osmana2587da2022-05-01 03:54:11 +0000313 case CodecType::OPUS:
Josh Wu049e2cd2022-01-12 05:42:58 -0800314 ASSERT_EQ(codec_capabilities.capabilities.getTag(),
Omer Osmana2587da2022-05-01 03:54:11 +0000315 CodecCapabilities::Capabilities::opusCapabilities);
Josh Wu049e2cd2022-01-12 05:42:58 -0800316 break;
317 case CodecType::APTX_ADAPTIVE:
Sagar Verma62df9102022-12-07 17:56:04 +0530318 case CodecType::APTX_ADAPTIVE_LE:
319 case CodecType::APTX_ADAPTIVE_LEX:
Omer Osmana2587da2022-05-01 03:54:11 +0000320 case CodecType::LC3:
Josh Wu049e2cd2022-01-12 05:42:58 -0800321 case CodecType::VENDOR:
322 case CodecType::UNKNOWN:
323 break;
324 }
325 codec_types.insert(codec_capabilities.codecType);
326 }
327 } break;
328 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
329 case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
330 case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
shihchienc3ab9f5e2022-09-23 08:18:05 +0000331 // empty capability means offload is unsupported since capabilities are
332 // not hardcoded
Josh Wu049e2cd2022-01-12 05:42:58 -0800333 for (auto audio_capability : temp_provider_capabilities_) {
334 ASSERT_EQ(audio_capability.getTag(),
335 AudioCapabilities::leAudioCapabilities);
336 }
337 } break;
Bao Do72399432023-11-09 08:13:05 +0000338 case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH:
339 case SessionType::HFP_SOFTWARE_DECODING_DATAPATH: {
Alice Kuoadcceec2022-03-28 13:28:43 +0800340 if (!temp_provider_capabilities_.empty()) {
341 ASSERT_EQ(temp_provider_capabilities_.size(), 1);
342 ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
343 AudioCapabilities::pcmCapabilities);
344 }
345 } break;
346 default: {
347 ASSERT_TRUE(temp_provider_capabilities_.empty());
348 }
Josh Wu049e2cd2022-01-12 05:42:58 -0800349 }
350 }
351
352 /***
353 * This helps to open the specified provider and check the openProvider()
354 * has corruct return values. BUT, to keep it simple, it does not consider
355 * the capability, and please do so at the SetUp of each session's test.
356 ***/
357 void OpenProviderHelper(const SessionType& session_type) {
358 auto aidl_retval =
359 provider_factory_->openProvider(session_type, &audio_provider_);
360 if (aidl_retval.isOk()) {
361 ASSERT_NE(session_type, SessionType::UNKNOWN);
362 ASSERT_NE(audio_provider_, nullptr);
363 audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
364 } else {
Alice Kuoadcceec2022-03-28 13:28:43 +0800365 // optional session type
Josh Wu049e2cd2022-01-12 05:42:58 -0800366 ASSERT_TRUE(
367 session_type == SessionType::UNKNOWN ||
368 session_type ==
369 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
370 session_type ==
371 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
372 session_type ==
373 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
374 session_type ==
375 SessionType::
Alice Kuoadcceec2022-03-28 13:28:43 +0800376 LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
377 session_type ==
378 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
Bao Do72399432023-11-09 08:13:05 +0000379 session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
380 session_type == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH ||
381 session_type == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
382 session_type == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
Josh Wu049e2cd2022-01-12 05:42:58 -0800383 ASSERT_EQ(audio_provider_, nullptr);
384 }
385 }
386
Josh Wu049e2cd2022-01-12 05:42:58 -0800387 void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
388 temp_codec_capabilities_ = nullptr;
Josh Wu4d2938f2022-02-15 09:21:10 -0800389 for (auto& codec_capability : temp_provider_capabilities_) {
Josh Wu049e2cd2022-01-12 05:42:58 -0800390 auto& a2dp_capabilities =
391 codec_capability.get<AudioCapabilities::a2dpCapabilities>();
392 if (a2dp_capabilities.codecType != codec_type) {
393 continue;
394 }
395 temp_codec_capabilities_ = &a2dp_capabilities;
396 }
397 }
398
399 std::vector<CodecConfiguration::CodecSpecific>
400 GetSbcCodecSpecificSupportedList(bool supported) {
401 std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
402 if (!supported) {
403 SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
404 sbc_codec_specifics.push_back(
405 CodecConfiguration::CodecSpecific(sbc_config));
406 return sbc_codec_specifics;
407 }
408 GetA2dpOffloadCapabilityHelper(CodecType::SBC);
409 if (temp_codec_capabilities_ == nullptr ||
410 temp_codec_capabilities_->codecType != CodecType::SBC) {
411 return sbc_codec_specifics;
412 }
413 // parse the capability
414 auto& sbc_capability =
415 temp_codec_capabilities_->capabilities
416 .get<CodecCapabilities::Capabilities::sbcCapabilities>();
417 if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
418 return sbc_codec_specifics;
419 }
420
421 // combine those parameters into one list of
422 // CodecConfiguration::CodecSpecific
423 for (int32_t sample_rate : sbc_capability.sampleRateHz) {
424 for (int8_t block_length : sbc_capability.blockLength) {
425 for (int8_t num_subbands : sbc_capability.numSubbands) {
426 for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
427 for (auto channel_mode : sbc_capability.channelMode) {
428 for (auto alloc_method : sbc_capability.allocMethod) {
429 SbcConfiguration sbc_data = {
430 .sampleRateHz = sample_rate,
431 .channelMode = channel_mode,
432 .blockLength = block_length,
433 .numSubbands = num_subbands,
434 .allocMethod = alloc_method,
435 .bitsPerSample = bits_per_sample,
436 .minBitpool = sbc_capability.minBitpool,
437 .maxBitpool = sbc_capability.maxBitpool};
438 sbc_codec_specifics.push_back(
439 CodecConfiguration::CodecSpecific(sbc_data));
440 }
441 }
442 }
443 }
444 }
445 }
446 return sbc_codec_specifics;
447 }
448
449 std::vector<CodecConfiguration::CodecSpecific>
450 GetAacCodecSpecificSupportedList(bool supported) {
451 std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
452 if (!supported) {
453 AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
454 aac_codec_specifics.push_back(
455 CodecConfiguration::CodecSpecific(aac_config));
456 return aac_codec_specifics;
457 }
458 GetA2dpOffloadCapabilityHelper(CodecType::AAC);
459 if (temp_codec_capabilities_ == nullptr ||
460 temp_codec_capabilities_->codecType != CodecType::AAC) {
461 return aac_codec_specifics;
462 }
463 // parse the capability
464 auto& aac_capability =
465 temp_codec_capabilities_->capabilities
466 .get<CodecCapabilities::Capabilities::aacCapabilities>();
467
468 std::vector<bool> variable_bit_rate_enableds = {false};
469 if (aac_capability.variableBitRateSupported) {
470 variable_bit_rate_enableds.push_back(true);
471 }
472
Sagar Verma62df9102022-12-07 17:56:04 +0530473 std::vector<bool> adaptive_bit_rate_supporteds = {false};
474 if (aac_capability.adaptiveBitRateSupported) {
475 adaptive_bit_rate_supporteds.push_back(true);
476 }
477
Josh Wu049e2cd2022-01-12 05:42:58 -0800478 // combine those parameters into one list of
479 // CodecConfiguration::CodecSpecific
480 for (auto object_type : aac_capability.objectType) {
481 for (int32_t sample_rate : aac_capability.sampleRateHz) {
482 for (auto channel_mode : aac_capability.channelMode) {
483 for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
484 for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
Sagar Verma62df9102022-12-07 17:56:04 +0530485 for (auto adaptive_bit_rate_supported :
486 adaptive_bit_rate_supporteds) {
487 AacConfiguration aac_data{
488 .objectType = object_type,
489 .sampleRateHz = sample_rate,
490 .channelMode = channel_mode,
491 .variableBitRateEnabled = variable_bit_rate_enabled,
492 .bitsPerSample = bits_per_sample,
493 .adaptiveBitRateSupported = adaptive_bit_rate_supported};
494 aac_codec_specifics.push_back(
495 CodecConfiguration::CodecSpecific(aac_data));
496 }
Josh Wu049e2cd2022-01-12 05:42:58 -0800497 }
498 }
499 }
500 }
501 }
502 return aac_codec_specifics;
503 }
504
505 std::vector<CodecConfiguration::CodecSpecific>
506 GetLdacCodecSpecificSupportedList(bool supported) {
507 std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
508 if (!supported) {
509 LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
510 ldac_codec_specifics.push_back(
511 CodecConfiguration::CodecSpecific(ldac_config));
512 return ldac_codec_specifics;
513 }
514 GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
515 if (temp_codec_capabilities_ == nullptr ||
516 temp_codec_capabilities_->codecType != CodecType::LDAC) {
517 return ldac_codec_specifics;
518 }
519 // parse the capability
520 auto& ldac_capability =
521 temp_codec_capabilities_->capabilities
522 .get<CodecCapabilities::Capabilities::ldacCapabilities>();
523
524 // combine those parameters into one list of
525 // CodecConfiguration::CodecSpecific
526 for (int32_t sample_rate : ldac_capability.sampleRateHz) {
527 for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
528 for (auto channel_mode : ldac_capability.channelMode) {
529 for (auto quality_index : ldac_capability.qualityIndex) {
530 LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
531 .channelMode = channel_mode,
532 .qualityIndex = quality_index,
533 .bitsPerSample = bits_per_sample};
534 ldac_codec_specifics.push_back(
535 CodecConfiguration::CodecSpecific(ldac_data));
536 }
537 }
538 }
539 }
540 return ldac_codec_specifics;
541 }
542
543 std::vector<CodecConfiguration::CodecSpecific>
544 GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
545 std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
546 if (!supported) {
547 AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
548 aptx_codec_specifics.push_back(
549 CodecConfiguration::CodecSpecific(aptx_config));
550 return aptx_codec_specifics;
551 }
552 GetA2dpOffloadCapabilityHelper(
553 (is_hd ? CodecType::APTX_HD : CodecType::APTX));
554 if (temp_codec_capabilities_ == nullptr) {
555 return aptx_codec_specifics;
556 }
557 if ((is_hd && temp_codec_capabilities_->codecType != CodecType::APTX_HD) ||
558 (!is_hd && temp_codec_capabilities_->codecType != CodecType::APTX)) {
559 return aptx_codec_specifics;
560 }
561
562 // parse the capability
563 auto& aptx_capability =
564 temp_codec_capabilities_->capabilities
565 .get<CodecCapabilities::Capabilities::aptxCapabilities>();
566
567 // combine those parameters into one list of
568 // CodecConfiguration::CodecSpecific
569 for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
570 for (int32_t sample_rate : aptx_capability.sampleRateHz) {
571 for (auto channel_mode : aptx_capability.channelMode) {
572 AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
573 .channelMode = channel_mode,
574 .bitsPerSample = bits_per_sample};
575 aptx_codec_specifics.push_back(
576 CodecConfiguration::CodecSpecific(aptx_data));
577 }
578 }
579 }
580 return aptx_codec_specifics;
581 }
582
583 std::vector<CodecConfiguration::CodecSpecific>
Omer Osmana2587da2022-05-01 03:54:11 +0000584 GetOpusCodecSpecificSupportedList(bool supported) {
585 std::vector<CodecConfiguration::CodecSpecific> opus_codec_specifics;
Josh Wu049e2cd2022-01-12 05:42:58 -0800586 if (!supported) {
Omer Osmana2587da2022-05-01 03:54:11 +0000587 OpusConfiguration opus_config{.samplingFrequencyHz = 0,
588 .frameDurationUs = 0};
589 opus_codec_specifics.push_back(
590 CodecConfiguration::CodecSpecific(opus_config));
591 return opus_codec_specifics;
Josh Wu049e2cd2022-01-12 05:42:58 -0800592 }
Omer Osmana2587da2022-05-01 03:54:11 +0000593 GetA2dpOffloadCapabilityHelper(CodecType::OPUS);
Josh Wu049e2cd2022-01-12 05:42:58 -0800594 if (temp_codec_capabilities_ == nullptr ||
Omer Osmana2587da2022-05-01 03:54:11 +0000595 temp_codec_capabilities_->codecType != CodecType::OPUS) {
596 return opus_codec_specifics;
Josh Wu049e2cd2022-01-12 05:42:58 -0800597 }
598 // parse the capability
Omer Osmana2587da2022-05-01 03:54:11 +0000599 auto& opus_capability =
Josh Wu049e2cd2022-01-12 05:42:58 -0800600 temp_codec_capabilities_->capabilities
Omer Osmana2587da2022-05-01 03:54:11 +0000601 .get<CodecCapabilities::Capabilities::opusCapabilities>();
Josh Wu049e2cd2022-01-12 05:42:58 -0800602
603 // combine those parameters into one list of
604 // CodecConfiguration::CodecSpecific
Omer Osmana2587da2022-05-01 03:54:11 +0000605 for (int32_t samplingFrequencyHz : opus_capability->samplingFrequencyHz) {
606 for (int32_t frameDurationUs : opus_capability->frameDurationUs) {
607 for (auto channel_mode : opus_capability->channelMode) {
608 OpusConfiguration opus_data{
609 .samplingFrequencyHz = samplingFrequencyHz,
shihchienc3ab9f5e2022-09-23 08:18:05 +0000610 .frameDurationUs = frameDurationUs,
Omer Osmana2587da2022-05-01 03:54:11 +0000611 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +0000612 };
Omer Osmana2587da2022-05-01 03:54:11 +0000613 opus_codec_specifics.push_back(
614 CodecConfiguration::CodecSpecific(opus_data));
Josh Wu049e2cd2022-01-12 05:42:58 -0800615 }
616 }
617 }
Omer Osmana2587da2022-05-01 03:54:11 +0000618 return opus_codec_specifics;
Josh Wu049e2cd2022-01-12 05:42:58 -0800619 }
620
Alice Kuoadcceec2022-03-28 13:28:43 +0800621 bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
622 if (temp_provider_capabilities_.size() != 1 ||
623 temp_provider_capabilities_[0].getTag() !=
624 AudioCapabilities::pcmCapabilities) {
625 return false;
626 }
627 auto pcm_capability = temp_provider_capabilities_[0]
628 .get<AudioCapabilities::pcmCapabilities>();
629 return (contained_in_vector(pcm_capability.channelMode,
630 pcm_config.channelMode) &&
631 contained_in_vector(pcm_capability.sampleRateHz,
632 pcm_config.sampleRateHz) &&
633 contained_in_vector(pcm_capability.bitsPerSample,
634 pcm_config.bitsPerSample));
635 }
636
637 std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
638 std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
639 std::shared_ptr<IBluetoothAudioPort> audio_port_;
640 std::vector<AudioCapabilities> temp_provider_capabilities_;
Bao Doc36897d2023-12-06 01:27:54 +0000641 std::optional<IBluetoothAudioProviderFactory::ProviderInfo>
642 temp_provider_info_;
Alice Kuoadcceec2022-03-28 13:28:43 +0800643
Josh Wu049e2cd2022-01-12 05:42:58 -0800644 // temp storage saves the specified codec capability by
645 // GetOffloadCodecCapabilityHelper()
646 CodecCapabilities* temp_codec_capabilities_;
Alice Kuoadcceec2022-03-28 13:28:43 +0800647
648 static constexpr SessionType kSessionTypes[] = {
649 SessionType::UNKNOWN,
650 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
651 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
652 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
653 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
654 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
655 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
656 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
657 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
658 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
659 SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
660 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
Bao Dob487a852023-12-25 10:12:09 +0800661 };
662
663 static constexpr SessionType kAndroidVSessionType[] = {
Bao Do72399432023-11-09 08:13:05 +0000664 SessionType::HFP_SOFTWARE_ENCODING_DATAPATH,
665 SessionType::HFP_SOFTWARE_DECODING_DATAPATH,
Alice Kuoadcceec2022-03-28 13:28:43 +0800666 };
Bao Dob487a852023-12-25 10:12:09 +0800667
668 BluetoothAudioHalVersion GetProviderFactoryInterfaceVersion() {
669 int32_t aidl_version = 0;
670 if (provider_factory_ == nullptr) {
671 return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
672 }
673
674 auto aidl_retval = provider_factory_->getInterfaceVersion(&aidl_version);
675 if (!aidl_retval.isOk()) {
676 return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
677 }
678 switch (aidl_version) {
679 case 1:
680 return BluetoothAudioHalVersion::VERSION_AIDL_V1;
681 case 2:
682 return BluetoothAudioHalVersion::VERSION_AIDL_V2;
683 case 3:
684 return BluetoothAudioHalVersion::VERSION_AIDL_V3;
685 case 4:
686 return BluetoothAudioHalVersion::VERSION_AIDL_V4;
Jakub Tyszkowski291b5d72024-08-02 13:03:37 +0000687 case 5:
688 return BluetoothAudioHalVersion::VERSION_AIDL_V5;
Bao Dob487a852023-12-25 10:12:09 +0800689 default:
690 return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
691 }
692
693 return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
694 }
Alice Kuoadcceec2022-03-28 13:28:43 +0800695};
696
697/**
698 * Test whether we can get the FactoryService from HIDL
699 */
700TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
701
702/**
703 * Test whether we can open a provider for each provider returned by
704 * getProviderCapabilities() with non-empty capabalities
705 */
706TEST_P(BluetoothAudioProviderFactoryAidl,
707 OpenProviderAndCheckCapabilitiesBySession) {
708 for (auto session_type : kSessionTypes) {
709 GetProviderCapabilitiesHelper(session_type);
710 OpenProviderHelper(session_type);
711 // We must be able to open a provider if its getProviderCapabilities()
712 // returns non-empty list.
713 EXPECT_TRUE(temp_provider_capabilities_.empty() ||
714 audio_provider_ != nullptr);
715 }
Bao Dob487a852023-12-25 10:12:09 +0800716 if (GetProviderFactoryInterfaceVersion() >=
717 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
718 for (auto session_type : kAndroidVSessionType) {
719 GetProviderCapabilitiesHelper(session_type);
720 OpenProviderHelper(session_type);
721 EXPECT_TRUE(temp_provider_capabilities_.empty() ||
722 audio_provider_ != nullptr);
723 }
724 }
Alice Kuoadcceec2022-03-28 13:28:43 +0800725}
726
727/**
Antoine SOULIER8c90f1f2023-09-26 18:55:17 +0000728 * Test that getProviderInfo, when implemented,
729 * returns empty information for session types for
730 * software data paths.
731 */
732TEST_P(BluetoothAudioProviderFactoryAidl, getProviderInfo_invalidSessionTypes) {
733 static constexpr SessionType kInvalidSessionTypes[]{
734 SessionType::UNKNOWN,
735 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
736 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
737 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
738 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
739 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
740 SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
741 };
742
743 for (auto session_type : kInvalidSessionTypes) {
744 std::optional<IBluetoothAudioProviderFactory::ProviderInfo> provider_info =
745 std::nullopt;
746 auto aidl_retval =
747 provider_factory_->getProviderInfo(session_type, &provider_info);
748 if (!aidl_retval.isOk()) {
749 continue;
750 }
751
752 // If getProviderInfo is supported, the provider info
753 // must be empty for software session types.
754 ASSERT_FALSE(provider_info.has_value());
755 }
756}
757
758/**
759 * Test that getProviderInfo, when implemented,
760 * returns valid information for session types for
761 * a2dp hardware data paths.
762 */
763TEST_P(BluetoothAudioProviderFactoryAidl, getProviderInfo_a2dpSessionTypes) {
764 static constexpr SessionType kA2dpSessionTypes[]{
765 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
766 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
767 };
768
769 for (auto session_type : kA2dpSessionTypes) {
770 std::optional<IBluetoothAudioProviderFactory::ProviderInfo> provider_info =
771 std::nullopt;
772 auto aidl_retval =
773 provider_factory_->getProviderInfo(session_type, &provider_info);
774 if (!aidl_retval.isOk() || !provider_info.has_value()) {
775 continue;
776 }
777
778 for (auto const& codec_info : provider_info->codecInfos) {
779 // The codec id must not be core.
780 ASSERT_NE(codec_info.id.getTag(), CodecId::core);
781 // The codec info must contain the information
782 // for a2dp transport.
783 ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::a2dp);
784 }
785 }
786}
787
788/**
789 * Test that getProviderInfo, when implemented,
790 * returns valid information for session types for
791 * le audio hardware data paths.
792 */
793TEST_P(BluetoothAudioProviderFactoryAidl, getProviderInfo_leAudioSessionTypes) {
794 static constexpr SessionType kLeAudioSessionTypes[]{
795 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
796 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
797 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
798 };
799
800 for (auto session_type : kLeAudioSessionTypes) {
801 std::optional<IBluetoothAudioProviderFactory::ProviderInfo> provider_info =
802 std::nullopt;
803 auto aidl_retval =
804 provider_factory_->getProviderInfo(session_type, &provider_info);
805 if (!aidl_retval.isOk() || !provider_info.has_value()) {
806 continue;
807 }
808
809 for (auto const& codec_info : provider_info->codecInfos) {
810 // The codec id must not be a2dp.
811 ASSERT_NE(codec_info.id.getTag(), CodecId::a2dp);
812 // The codec info must contain the information
813 // for le audio transport.
Jakub Tyszkowski06781c02024-01-08 13:16:42 +0000814 ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::leAudio);
Antoine SOULIER8c90f1f2023-09-26 18:55:17 +0000815 }
816 }
817}
818
Antoine SOULIER33c4e5a2023-09-28 21:59:19 +0000819class BluetoothAudioProviderAidl : public BluetoothAudioProviderFactoryAidl {
820 protected:
821 std::optional<IBluetoothAudioProviderFactory::ProviderInfo>
822 a2dp_encoding_provider_info_{};
823 std::optional<IBluetoothAudioProviderFactory::ProviderInfo>
824 a2dp_decoding_provider_info_{};
825 std::shared_ptr<IBluetoothAudioProvider> a2dp_encoding_provider_{nullptr};
826 std::shared_ptr<IBluetoothAudioProvider> a2dp_decoding_provider_{nullptr};
827
828 public:
829 void SetUp() override {
830 BluetoothAudioProviderFactoryAidl::SetUp();
831 audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
832
833 (void)provider_factory_->getProviderInfo(
834 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
835 &a2dp_encoding_provider_info_);
836
837 (void)provider_factory_->getProviderInfo(
838 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
839 &a2dp_decoding_provider_info_);
840
841 (void)provider_factory_->openProvider(
842 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
843 &a2dp_encoding_provider_);
844
845 (void)provider_factory_->openProvider(
846 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
847 &a2dp_decoding_provider_);
848 }
849};
850
851/**
852 * Calling parseA2dpConfiguration on a session of a different type than
853 * A2DP_HARDWARE_OFFLOAD_(ENCODING|DECODING)_DATAPATH must fail.
854 */
855TEST_P(BluetoothAudioProviderAidl, parseA2dpConfiguration_invalidSessionType) {
856 static constexpr SessionType kInvalidSessionTypes[] = {
857 SessionType::UNKNOWN,
858 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
859 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
860 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
861 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
862 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
863 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
864 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
865 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
866 SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
867 };
868
869 for (auto session_type : kInvalidSessionTypes) {
870 // Open a BluetoothAudioProvider instance of the selected session type.
871 // Skip validation if the provider cannot be opened.
872 std::shared_ptr<IBluetoothAudioProvider> provider{nullptr};
873 (void)provider_factory_->openProvider(session_type, &provider);
874 if (provider == nullptr) {
875 continue;
876 }
877
878 // parseA2dpConfiguration must fail without returning an A2dpStatus.
879 CodecId codec_id(CodecId::A2dp::SBC);
880 CodecParameters codec_parameters;
881 A2dpStatus a2dp_status = A2dpStatus::OK;
882 auto aidl_retval = provider->parseA2dpConfiguration(
883 codec_id, std::vector<uint8_t>{}, &codec_parameters, &a2dp_status);
884 EXPECT_FALSE(aidl_retval.isOk());
885 }
886}
887
888/**
889 * Calling parseA2dpConfiguration with an unknown codec must fail
890 * with the A2dpStatus code INVALID_CODEC_TYPE or NOT_SUPPORTED_CODEC_TYPE.
891 */
892TEST_P(BluetoothAudioProviderAidl,
893 parseA2dpConfiguration_unsupportedCodecType) {
894 CodecId unsupported_core_id(CodecId::Core::CVSD);
895 CodecId unsupported_vendor_id(
896 CodecId::Vendor(0xFCB1, 0x42)); // Google Codec #42
897
898 for (auto& provider : {a2dp_encoding_provider_, a2dp_decoding_provider_}) {
899 if (provider == nullptr) {
900 continue;
901 }
902
903 CodecParameters codec_parameters;
904 A2dpStatus a2dp_status = A2dpStatus::OK;
905 ::ndk::ScopedAStatus aidl_retval;
906
907 // Test with two invalid codec identifiers: vendor or core.
908 aidl_retval = provider->parseA2dpConfiguration(
909 unsupported_core_id, std::vector<uint8_t>{}, &codec_parameters,
910 &a2dp_status);
911 EXPECT_TRUE(!aidl_retval.isOk() ||
912 a2dp_status == A2dpStatus::NOT_SUPPORTED_CODEC_TYPE);
913
914 aidl_retval = provider->parseA2dpConfiguration(
915 unsupported_vendor_id, std::vector<uint8_t>{}, &codec_parameters,
916 &a2dp_status);
917 EXPECT_TRUE(!aidl_retval.isOk() ||
918 a2dp_status == A2dpStatus::NOT_SUPPORTED_CODEC_TYPE);
919 }
920}
921
922/**
923 * Calling parseA2dpConfiguration with a known codec and invalid configuration
924 * must fail with an A2dpStatus code different from INVALID_CODEC_TYPE or
925 * NOT_SUPPORTED_CODEC_TYPE.
926 */
927TEST_P(BluetoothAudioProviderAidl,
928 parseA2dpConfiguration_invalidConfiguration) {
929 for (auto& [provider, provider_info] :
930 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
931 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
932 if (provider == nullptr || !provider_info.has_value() ||
933 provider_info->codecInfos.empty()) {
934 continue;
935 }
936
937 CodecParameters codec_parameters;
938 A2dpStatus a2dp_status = A2dpStatus::OK;
939 ::ndk::ScopedAStatus aidl_retval;
940
941 // Test with the first available codec in the provider info for testing.
942 // The test runs with an empty parameters array, anything more specific
943 // would need understanding the codec.
944 aidl_retval = provider->parseA2dpConfiguration(
945 provider_info->codecInfos[0].id, std::vector<uint8_t>{},
946 &codec_parameters, &a2dp_status);
947 ASSERT_TRUE(aidl_retval.isOk());
948 EXPECT_TRUE(a2dp_status != A2dpStatus::OK &&
949 a2dp_status != A2dpStatus::NOT_SUPPORTED_CODEC_TYPE &&
950 a2dp_status != A2dpStatus::INVALID_CODEC_TYPE);
951 }
952}
953
954/**
955 * Calling parseA2dpConfiguration with a known codec and valid parameters
956 * must return with A2dpStatus OK.
957 */
958TEST_P(BluetoothAudioProviderAidl, parseA2dpConfiguration_valid) {
959 for (auto& [provider, provider_info] :
960 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
961 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
962 if (provider == nullptr || !provider_info.has_value() ||
963 provider_info->codecInfos.empty()) {
964 continue;
965 }
966
967 CodecParameters codec_parameters;
968 A2dpStatus a2dp_status = A2dpStatus::OK;
969 ::ndk::ScopedAStatus aidl_retval;
970
971 // Test with the first available codec in the provider info for testing.
972 // To get a valid configuration (the capabilities array in the provider
973 // info is not a selection), getA2dpConfiguration is used with the
974 // selected codec parameters as input.
975 auto const& codec_info = provider_info->codecInfos[0];
976 auto transport = codec_info.transport.get<CodecInfo::Transport::a2dp>();
977 A2dpRemoteCapabilities remote_capabilities(/*seid*/ 0, codec_info.id,
978 transport.capabilities);
979 std::optional<A2dpConfiguration> configuration;
980 aidl_retval = provider->getA2dpConfiguration(
981 std::vector<A2dpRemoteCapabilities>{remote_capabilities},
982 A2dpConfigurationHint(), &configuration);
983 ASSERT_TRUE(aidl_retval.isOk());
984 ASSERT_TRUE(configuration.has_value());
985
986 aidl_retval = provider->parseA2dpConfiguration(
987 configuration->id, configuration->configuration, &codec_parameters,
988 &a2dp_status);
989 ASSERT_TRUE(aidl_retval.isOk());
990 EXPECT_TRUE(a2dp_status == A2dpStatus::OK);
991 EXPECT_EQ(codec_parameters, configuration->parameters);
992 }
993}
994
995/**
996 * Calling getA2dpConfiguration on a session of a different type than
997 * A2DP_HARDWARE_OFFLOAD_(ENCODING|DECODING)_DATAPATH must fail.
998 */
999TEST_P(BluetoothAudioProviderAidl, getA2dpConfiguration_invalidSessionType) {
1000 static constexpr SessionType kInvalidSessionTypes[] = {
1001 SessionType::UNKNOWN,
1002 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
1003 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
1004 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
1005 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
1006 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
1007 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
1008 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
1009 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
1010 SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
1011 };
1012
1013 for (auto session_type : kInvalidSessionTypes) {
1014 // Open a BluetoothAudioProvider instance of the selected session type.
1015 // Skip validation if the provider cannot be opened.
1016 std::shared_ptr<IBluetoothAudioProvider> provider{nullptr};
1017 auto aidl_retval = provider_factory_->openProvider(session_type, &provider);
1018 if (provider == nullptr) {
1019 continue;
1020 }
1021
1022 // getA2dpConfiguration must fail without returning a configuration.
1023 std::optional<A2dpConfiguration> configuration;
1024 aidl_retval =
1025 provider->getA2dpConfiguration(std::vector<A2dpRemoteCapabilities>{},
1026 A2dpConfigurationHint(), &configuration);
1027 EXPECT_FALSE(aidl_retval.isOk());
1028 }
1029}
1030
1031/**
1032 * Calling getA2dpConfiguration with empty or unknown remote capabilities
1033 * must return an empty configuration.
1034 */
1035TEST_P(BluetoothAudioProviderAidl,
1036 getA2dpConfiguration_unknownRemoteCapabilities) {
1037 for (auto& [provider, provider_info] :
1038 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1039 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1040 if (provider == nullptr || !provider_info.has_value() ||
1041 provider_info->codecInfos.empty()) {
1042 continue;
1043 }
1044
1045 std::optional<A2dpConfiguration> configuration;
1046 ::ndk::ScopedAStatus aidl_retval;
1047
1048 // Test with empty remote capabilities.
1049 aidl_retval =
1050 provider->getA2dpConfiguration(std::vector<A2dpRemoteCapabilities>{},
1051 A2dpConfigurationHint(), &configuration);
1052 ASSERT_TRUE(aidl_retval.isOk());
1053 EXPECT_FALSE(configuration.has_value());
1054
1055 // Test with unknown remote capabilities.
1056 A2dpRemoteCapabilities unknown_core_remote_capabilities(
1057 /*seid*/ 0, CodecId::Core::CVSD, std::vector<uint8_t>{1, 2, 3});
1058 A2dpRemoteCapabilities unknown_vendor_remote_capabilities(
1059 /*seid*/ 1,
1060 /* Google Codec #42 */ CodecId::Vendor(0xFCB1, 0x42),
1061 std::vector<uint8_t>{1, 2, 3});
1062 aidl_retval = provider->getA2dpConfiguration(
1063 std::vector<A2dpRemoteCapabilities>{
1064 unknown_core_remote_capabilities,
1065 unknown_vendor_remote_capabilities,
1066 },
1067 A2dpConfigurationHint(), &configuration);
1068 ASSERT_TRUE(aidl_retval.isOk());
1069 EXPECT_FALSE(configuration.has_value());
1070 }
1071}
1072
1073/**
1074 * Calling getA2dpConfiguration with invalid remote capabilities
1075 * must return an empty configuration.
1076 */
1077TEST_P(BluetoothAudioProviderAidl,
1078 getA2dpConfiguration_invalidRemoteCapabilities) {
1079 for (auto& [provider, provider_info] :
1080 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1081 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1082 if (provider == nullptr || !provider_info.has_value() ||
1083 provider_info->codecInfos.empty()) {
1084 continue;
1085 }
1086
1087 std::optional<A2dpConfiguration> configuration;
1088 ::ndk::ScopedAStatus aidl_retval;
1089
1090 // Use the first available codec in the provider info for testing.
1091 // The capabilities are modified to make them invalid.
1092 auto const& codec_info = provider_info->codecInfos[0];
1093 auto transport = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1094 std::vector<uint8_t> invalid_capabilities = transport.capabilities;
1095 invalid_capabilities.push_back(0x42); // adding bytes should be invalid.
1096 aidl_retval = provider->getA2dpConfiguration(
1097 std::vector<A2dpRemoteCapabilities>{
1098 A2dpRemoteCapabilities(/*seid*/ 0, codec_info.id,
1099 std::vector<uint8_t>()),
1100 A2dpRemoteCapabilities(/*seid*/ 1, codec_info.id,
1101 invalid_capabilities),
1102 },
1103 A2dpConfigurationHint(), &configuration);
1104 ASSERT_TRUE(aidl_retval.isOk());
1105 EXPECT_FALSE(configuration.has_value());
1106 }
1107}
1108
1109/**
1110 * Calling getA2dpConfiguration with valid remote capabilities
1111 * must return a valid configuration. The selected parameters must
1112 * be contained in the original capabilities. The returned configuration
1113 * must match the returned parameters. The returned SEID must match the
1114 * input SEID.
1115 */
1116TEST_P(BluetoothAudioProviderAidl,
1117 getA2dpConfiguration_validRemoteCapabilities) {
1118 for (auto& [provider, provider_info] :
1119 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1120 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1121 if (provider == nullptr || !provider_info.has_value() ||
1122 provider_info->codecInfos.empty()) {
1123 continue;
1124 }
1125
1126 // Test with all available codecs in the provider info.
1127 for (auto const& codec_info : provider_info->codecInfos) {
1128 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1129 std::optional<A2dpConfiguration> configuration{};
1130 ::ndk::ScopedAStatus aidl_retval;
1131
1132 aidl_retval = provider->getA2dpConfiguration(
1133 std::vector<A2dpRemoteCapabilities>{
1134 A2dpRemoteCapabilities(/*seid*/ 42, codec_info.id,
1135 a2dp_info.capabilities),
1136 },
1137 A2dpConfigurationHint(), &configuration);
1138
1139 ASSERT_TRUE(aidl_retval.isOk());
1140 ASSERT_TRUE(configuration.has_value());
1141
1142 // Returned configuration must have the same codec id
1143 // as the remote capability.
1144 EXPECT_EQ(configuration->id, codec_info.id);
1145
1146 // Returned configuration must have the same SEID
1147 // as the remote capability.
1148 EXPECT_EQ(configuration->remoteSeid, 42);
1149
1150 // Returned codec parameters must be in the range of input
1151 // parameters.
1152 EXPECT_NE(
1153 std::find(a2dp_info.channelMode.begin(), a2dp_info.channelMode.end(),
1154 configuration->parameters.channelMode),
1155 a2dp_info.channelMode.end());
1156 EXPECT_NE(std::find(a2dp_info.samplingFrequencyHz.begin(),
1157 a2dp_info.samplingFrequencyHz.end(),
1158 configuration->parameters.samplingFrequencyHz),
1159 a2dp_info.samplingFrequencyHz.end());
1160 EXPECT_NE(std::find(a2dp_info.bitdepth.begin(), a2dp_info.bitdepth.end(),
1161 configuration->parameters.bitdepth),
1162 a2dp_info.bitdepth.end());
1163 EXPECT_EQ(a2dp_info.lossless, configuration->parameters.lossless);
1164 EXPECT_TRUE(configuration->parameters.minBitrate <=
1165 configuration->parameters.maxBitrate);
1166
1167 // Returned configuration must be parsable by parseA2dpParameters
1168 // and match the codec parameters.
1169 CodecParameters codec_parameters;
1170 A2dpStatus a2dp_status = A2dpStatus::OK;
1171 aidl_retval = provider->parseA2dpConfiguration(
1172 configuration->id, configuration->configuration, &codec_parameters,
1173 &a2dp_status);
1174 ASSERT_TRUE(aidl_retval.isOk());
1175 EXPECT_TRUE(a2dp_status == A2dpStatus::OK);
1176 EXPECT_EQ(codec_parameters, configuration->parameters);
1177 }
1178 }
1179}
1180
1181/**
1182 * Calling getA2dpConfiguration with valid remote capabilities
1183 * with various hinted codec ids.
1184 */
1185TEST_P(BluetoothAudioProviderAidl, getA2dpConfiguration_hintCodecId) {
1186 for (auto& [provider, provider_info] :
1187 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1188 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1189 if (provider == nullptr || !provider_info.has_value() ||
1190 provider_info->codecInfos.empty()) {
1191 continue;
1192 }
1193
1194 // Build the remote capabilities with all supported codecs.
1195 std::vector<A2dpRemoteCapabilities> remote_capabilities;
1196 for (size_t n = 0; n < provider_info->codecInfos.size(); n++) {
1197 auto const& codec_info = provider_info->codecInfos[n];
1198 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1199 remote_capabilities.push_back(A2dpRemoteCapabilities(
1200 /*seid*/ n, codec_info.id, a2dp_info.capabilities));
1201 }
1202
1203 // Test with all supported codec identifiers,
1204 for (auto const& codec_info : provider_info->codecInfos) {
1205 std::optional<A2dpConfiguration> configuration{};
1206 ::ndk::ScopedAStatus aidl_retval;
1207
1208 A2dpConfigurationHint hint;
1209 hint.codecId = codec_info.id;
1210
1211 aidl_retval = provider->getA2dpConfiguration(remote_capabilities, hint,
1212 &configuration);
1213
1214 ASSERT_TRUE(aidl_retval.isOk());
1215 ASSERT_TRUE(configuration.has_value());
1216 EXPECT_EQ(configuration->id, codec_info.id);
1217 }
1218
1219 // Test with unknown codec identifiers: either core or vendor.
1220 for (auto& codec_id :
1221 {CodecId(CodecId::Core::CVSD),
1222 CodecId(CodecId::Vendor(0xFCB1, 0x42)) /*Google Codec #42*/}) {
1223 std::optional<A2dpConfiguration> configuration{};
1224 ::ndk::ScopedAStatus aidl_retval;
1225
1226 A2dpConfigurationHint hint;
1227 hint.codecId = codec_id;
1228
1229 aidl_retval = provider->getA2dpConfiguration(remote_capabilities, hint,
1230 &configuration);
1231
1232 ASSERT_TRUE(aidl_retval.isOk());
1233 ASSERT_TRUE(configuration.has_value());
1234 EXPECT_NE(configuration->id, codec_id);
1235 }
1236 }
1237}
1238
1239/**
1240 * Calling getA2dpConfiguration with valid remote capabilities
1241 * with various hinted channel modes.
1242 */
1243TEST_P(BluetoothAudioProviderAidl, getA2dpConfiguration_hintChannelMode) {
1244 for (auto& [provider, provider_info] :
1245 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1246 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1247 if (provider == nullptr || !provider_info.has_value() ||
1248 provider_info->codecInfos.empty()) {
1249 continue;
1250 }
1251
1252 // Test with all available codecs in the provider info.
1253 for (auto const& codec_info : provider_info->codecInfos) {
1254 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1255 std::optional<A2dpConfiguration> configuration{};
1256 ::ndk::ScopedAStatus aidl_retval;
1257
1258 for (auto& channel_mode :
1259 {ChannelMode::STEREO, ChannelMode::MONO, ChannelMode::DUALMONO}) {
1260 // Add the hint for the channel mode.
1261 A2dpConfigurationHint hint;
1262 auto& codec_parameters = hint.codecParameters.emplace();
1263 codec_parameters.channelMode = channel_mode;
1264
1265 aidl_retval = provider->getA2dpConfiguration(
1266 std::vector<A2dpRemoteCapabilities>{
1267 A2dpRemoteCapabilities(/*seid*/ 42, codec_info.id,
1268 a2dp_info.capabilities),
1269 },
1270 hint, &configuration);
1271
1272 ASSERT_TRUE(aidl_retval.isOk());
1273 ASSERT_TRUE(configuration.has_value());
1274
1275 // The hint must be ignored if the channel mode is not supported
1276 // by the codec, and applied otherwise.
1277 ASSERT_EQ(configuration->parameters.channelMode == channel_mode,
1278 std::find(a2dp_info.channelMode.begin(),
1279 a2dp_info.channelMode.end(),
1280 channel_mode) != a2dp_info.channelMode.end());
1281 }
1282 }
1283 }
1284}
1285
1286/**
1287 * Calling getA2dpConfiguration with valid remote capabilities
1288 * with various hinted sampling frequencies.
1289 */
1290TEST_P(BluetoothAudioProviderAidl,
1291 getA2dpConfiguration_hintSamplingFrequencyHz) {
1292 for (auto& [provider, provider_info] :
1293 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1294 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1295 if (provider == nullptr || !provider_info.has_value() ||
1296 provider_info->codecInfos.empty()) {
1297 continue;
1298 }
1299
1300 // Test with all available codecs in the provider info.
1301 for (auto const& codec_info : provider_info->codecInfos) {
1302 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1303 std::optional<A2dpConfiguration> configuration{};
1304 ::ndk::ScopedAStatus aidl_retval;
1305
1306 for (auto& sampling_frequency_hz : {
1307 0,
1308 1,
1309 8000,
1310 16000,
1311 24000,
1312 32000,
1313 44100,
1314 48000,
1315 88200,
1316 96000,
1317 176400,
1318 192000,
1319 }) {
1320 // Add the hint for the sampling frequency.
1321 A2dpConfigurationHint hint;
1322 auto& codec_parameters = hint.codecParameters.emplace();
1323 codec_parameters.samplingFrequencyHz = sampling_frequency_hz;
1324
1325 aidl_retval = provider->getA2dpConfiguration(
1326 std::vector<A2dpRemoteCapabilities>{
1327 A2dpRemoteCapabilities(/*seid*/ 42, codec_info.id,
1328 a2dp_info.capabilities),
1329 },
1330 hint, &configuration);
1331
1332 ASSERT_TRUE(aidl_retval.isOk());
1333 ASSERT_TRUE(configuration.has_value());
1334
1335 // The hint must be ignored if the sampling frequency is not supported
1336 // by the codec, and applied otherwise.
1337 ASSERT_EQ(configuration->parameters.samplingFrequencyHz ==
1338 sampling_frequency_hz,
1339 std::find(a2dp_info.samplingFrequencyHz.begin(),
1340 a2dp_info.samplingFrequencyHz.end(),
1341 sampling_frequency_hz) !=
1342 a2dp_info.samplingFrequencyHz.end());
1343 }
1344 }
1345 }
1346}
1347
1348/**
1349 * Calling getA2dpConfiguration with valid remote capabilities
1350 * with various hinted sampling bit-depths.
1351 */
1352TEST_P(BluetoothAudioProviderAidl, getA2dpConfiguration_hintBitdepth) {
1353 for (auto& [provider, provider_info] :
1354 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1355 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1356 if (provider == nullptr || !provider_info.has_value() ||
1357 provider_info->codecInfos.empty()) {
1358 continue;
1359 }
1360
1361 // Test with all available codecs in the provider info.
1362 for (auto const& codec_info : provider_info->codecInfos) {
1363 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1364 std::optional<A2dpConfiguration> configuration{};
1365 ::ndk::ScopedAStatus aidl_retval;
1366
1367 for (auto& bitdepth : {0, 1, 16, 24, 32}) {
1368 // Add the hint for the bit depth.
1369 A2dpConfigurationHint hint;
1370 auto& codec_parameters = hint.codecParameters.emplace();
1371 codec_parameters.bitdepth = bitdepth;
1372
1373 aidl_retval = provider->getA2dpConfiguration(
1374 std::vector<A2dpRemoteCapabilities>{
1375 A2dpRemoteCapabilities(/*seid*/ 42, codec_info.id,
1376 a2dp_info.capabilities),
1377 },
1378 hint, &configuration);
1379
1380 ASSERT_TRUE(aidl_retval.isOk());
1381 ASSERT_TRUE(configuration.has_value());
1382
1383 // The hint must be ignored if the bitdepth is not supported
1384 // by the codec, and applied otherwise.
1385 ASSERT_EQ(
1386 configuration->parameters.bitdepth == bitdepth,
1387 std::find(a2dp_info.bitdepth.begin(), a2dp_info.bitdepth.end(),
1388 bitdepth) != a2dp_info.bitdepth.end());
1389 }
1390 }
1391 }
1392}
1393
1394/**
1395 * Calling startSession with an unknown codec id must fail.
1396 */
1397TEST_P(BluetoothAudioProviderAidl, startSession_unknownCodecId) {
1398 for (auto& [provider, provider_info] :
1399 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1400 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1401 if (provider == nullptr || !provider_info.has_value() ||
1402 provider_info->codecInfos.empty()) {
1403 continue;
1404 }
1405
1406 for (auto& codec_id :
1407 {CodecId(CodecId::Core::CVSD),
1408 CodecId(CodecId::Vendor(0xFCB1, 0x42) /*Google Codec #42*/)}) {
1409 A2dpStreamConfiguration a2dp_config;
1410 DataMQDesc data_mq_desc;
1411
1412 a2dp_config.codecId = codec_id;
1413 a2dp_config.configuration = std::vector<uint8_t>{1, 2, 3};
1414
1415 auto aidl_retval =
1416 provider->startSession(audio_port_, AudioConfiguration(a2dp_config),
1417 std::vector<LatencyMode>{}, &data_mq_desc);
1418
1419 EXPECT_FALSE(aidl_retval.isOk());
1420 }
1421 }
1422}
1423
1424/**
1425 * Calling startSession with a known codec and a valid configuration
1426 * must succeed.
1427 */
1428TEST_P(BluetoothAudioProviderAidl, startSession_valid) {
1429 for (auto& [provider, provider_info] :
1430 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1431 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1432 if (provider == nullptr || !provider_info.has_value() ||
1433 provider_info->codecInfos.empty()) {
1434 continue;
1435 }
1436
1437 // Use the first available codec in the provider info for testing.
1438 // To get a valid configuration (the capabilities array in the provider
1439 // info is not a selection), getA2dpConfiguration is used with the
1440 // selected codec parameters as input.
1441 auto const& codec_info = provider_info->codecInfos[0];
1442 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1443 ::ndk::ScopedAStatus aidl_retval;
1444 A2dpRemoteCapabilities remote_capabilities(/*seid*/ 0, codec_info.id,
1445 a2dp_info.capabilities);
1446 std::optional<A2dpConfiguration> configuration;
1447 aidl_retval = provider->getA2dpConfiguration(
1448 std::vector<A2dpRemoteCapabilities>{remote_capabilities},
1449 A2dpConfigurationHint(), &configuration);
1450 ASSERT_TRUE(aidl_retval.isOk());
1451 ASSERT_TRUE(configuration.has_value());
1452
1453 // Build the stream configuration.
1454 A2dpStreamConfiguration a2dp_config;
1455 DataMQDesc data_mq_desc;
1456
1457 a2dp_config.codecId = codec_info.id;
1458 a2dp_config.configuration = configuration->configuration;
1459
1460 aidl_retval =
1461 provider->startSession(audio_port_, AudioConfiguration(a2dp_config),
1462 std::vector<LatencyMode>{}, &data_mq_desc);
1463
1464 EXPECT_TRUE(aidl_retval.isOk());
1465 }
1466}
1467
1468/**
1469 * Calling startSession with a known codec but an invalid configuration
1470 * must fail.
1471 */
1472TEST_P(BluetoothAudioProviderAidl, startSession_invalidConfiguration) {
1473 for (auto& [provider, provider_info] :
1474 {std::pair(a2dp_encoding_provider_, a2dp_encoding_provider_info_),
1475 std::pair(a2dp_decoding_provider_, a2dp_decoding_provider_info_)}) {
1476 if (provider == nullptr || !provider_info.has_value() ||
1477 provider_info->codecInfos.empty()) {
1478 continue;
1479 }
1480
1481 // Use the first available codec in the provider info for testing.
1482 // To get a valid configuration (the capabilities array in the provider
1483 // info is not a selection), getA2dpConfiguration is used with the
1484 // selected codec parameters as input.
1485 ::ndk::ScopedAStatus aidl_retval;
1486 auto const& codec_info = provider_info->codecInfos[0];
1487 auto a2dp_info = codec_info.transport.get<CodecInfo::Transport::a2dp>();
1488 A2dpRemoteCapabilities remote_capabilities(/*seid*/ 0, codec_info.id,
1489 a2dp_info.capabilities);
1490 std::optional<A2dpConfiguration> configuration;
1491 aidl_retval = provider->getA2dpConfiguration(
1492 std::vector<A2dpRemoteCapabilities>{remote_capabilities},
1493 A2dpConfigurationHint(), &configuration);
1494 ASSERT_TRUE(aidl_retval.isOk());
1495 ASSERT_TRUE(configuration.has_value());
1496
1497 // Build the stream configuration but edit the configuration bytes
1498 // to make it invalid.
1499 A2dpStreamConfiguration a2dp_config;
1500 DataMQDesc data_mq_desc;
1501
1502 a2dp_config.codecId = codec_info.id;
1503 a2dp_config.configuration = configuration->configuration;
1504 a2dp_config.configuration.push_back(42);
1505
1506 aidl_retval =
1507 provider->startSession(audio_port_, AudioConfiguration(a2dp_config),
1508 std::vector<LatencyMode>{}, &data_mq_desc);
1509
1510 EXPECT_FALSE(aidl_retval.isOk());
1511 }
1512}
1513
Antoine SOULIER8c90f1f2023-09-26 18:55:17 +00001514/**
Alice Kuoadcceec2022-03-28 13:28:43 +08001515 * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
1516 */
1517class BluetoothAudioProviderA2dpEncodingSoftwareAidl
1518 : public BluetoothAudioProviderFactoryAidl {
1519 public:
1520 virtual void SetUp() override {
1521 BluetoothAudioProviderFactoryAidl::SetUp();
1522 GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
1523 OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
1524 ASSERT_NE(audio_provider_, nullptr);
1525 }
1526
1527 virtual void TearDown() override {
1528 audio_port_ = nullptr;
1529 audio_provider_ = nullptr;
1530 BluetoothAudioProviderFactoryAidl::TearDown();
1531 }
Josh Wu049e2cd2022-01-12 05:42:58 -08001532};
1533
1534/**
1535 * Test whether we can open a provider of type
1536 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001537TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
1538 OpenA2dpEncodingSoftwareProvider) {}
1539
1540/**
1541 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001542 * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped
1543 * with different PCM config
Alice Kuoadcceec2022-03-28 13:28:43 +08001544 */
1545TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
1546 StartAndEndA2dpEncodingSoftwareSessionWithPossiblePcmConfig) {
1547 for (auto sample_rate : a2dp_sample_rates) {
1548 for (auto bits_per_sample : a2dp_bits_per_samples) {
1549 for (auto channel_mode : a2dp_channel_modes) {
1550 PcmConfiguration pcm_config{
1551 .sampleRateHz = sample_rate,
Alice Kuoadcceec2022-03-28 13:28:43 +08001552 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00001553 .bitsPerSample = bits_per_sample,
Alice Kuoadcceec2022-03-28 13:28:43 +08001554 };
1555 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
1556 DataMQDesc mq_desc;
1557 auto aidl_retval = audio_provider_->startSession(
1558 audio_port_, AudioConfiguration(pcm_config), latency_modes,
1559 &mq_desc);
1560 DataMQ data_mq(mq_desc);
1561
1562 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
1563 if (is_codec_config_valid) {
1564 EXPECT_TRUE(data_mq.isValid());
1565 }
1566 EXPECT_TRUE(audio_provider_->endSession().isOk());
1567 }
1568 }
1569 }
1570}
1571
1572/**
Bao Do72399432023-11-09 08:13:05 +00001573 * openProvider HFP_SOFTWARE_ENCODING_DATAPATH
1574 */
1575class BluetoothAudioProviderHfpSoftwareEncodingAidl
1576 : public BluetoothAudioProviderFactoryAidl {
1577 public:
1578 virtual void SetUp() override {
1579 BluetoothAudioProviderFactoryAidl::SetUp();
Bao Dob487a852023-12-25 10:12:09 +08001580 if (GetProviderFactoryInterfaceVersion() <
1581 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
1582 GTEST_SKIP();
1583 }
Bao Do72399432023-11-09 08:13:05 +00001584 GetProviderCapabilitiesHelper(SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
1585 OpenProviderHelper(SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
1586 ASSERT_NE(audio_provider_, nullptr);
1587 }
1588
1589 virtual void TearDown() override {
1590 audio_port_ = nullptr;
1591 audio_provider_ = nullptr;
1592 BluetoothAudioProviderFactoryAidl::TearDown();
1593 }
1594
1595 bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
Bao Do5b2fdab2023-11-20 08:02:55 +00001596 ChannelMode channel_mode, int32_t data_interval_us) {
Bao Do72399432023-11-09 08:13:05 +00001597 PcmConfiguration pcm_config{
1598 .sampleRateHz = sample_rate,
1599 .channelMode = channel_mode,
1600 .bitsPerSample = bits_per_sample,
1601 .dataIntervalUs = data_interval_us,
1602 };
1603 // Checking against provider capability from getProviderCapabilities
1604 // For HFP software, it's
1605 // BluetoothAudioCodecs::GetSoftwarePcmCapabilities();
1606 DataMQDesc mq_desc;
1607 auto aidl_retval = audio_provider_->startSession(
1608 audio_port_, AudioConfiguration(pcm_config), latency_modes, &mq_desc);
1609 DataMQ data_mq(mq_desc);
1610
1611 if (!aidl_retval.isOk()) return false;
1612 if (!data_mq.isValid()) return false;
1613 return true;
1614 }
1615};
1616
1617/**
1618 * Test whether we can open a provider of type
1619 */
1620TEST_P(BluetoothAudioProviderHfpSoftwareEncodingAidl,
1621 OpenHfpSoftwareEncodingProvider) {}
1622
1623/**
1624 * Test whether each provider of type
1625 * SessionType::HFP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
1626 * different PCM config
1627 */
1628TEST_P(BluetoothAudioProviderHfpSoftwareEncodingAidl,
1629 StartAndEndHfpEncodingSoftwareSessionWithPossiblePcmConfig) {
1630 for (auto sample_rate : hfp_sample_rates_) {
1631 for (auto bits_per_sample : hfp_bits_per_samples_) {
1632 for (auto channel_mode : hfp_channel_modes_) {
Bao Do5b2fdab2023-11-20 08:02:55 +00001633 for (auto data_interval_us : hfp_data_interval_us_) {
1634 EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample, channel_mode,
1635 data_interval_us));
Bao Do72399432023-11-09 08:13:05 +00001636 EXPECT_TRUE(audio_provider_->endSession().isOk());
1637 }
1638 }
1639 }
1640 }
1641}
1642
1643/**
1644 * openProvider HFP_SOFTWARE_DECODING_DATAPATH
1645 */
1646class BluetoothAudioProviderHfpSoftwareDecodingAidl
1647 : public BluetoothAudioProviderFactoryAidl {
1648 public:
1649 virtual void SetUp() override {
1650 BluetoothAudioProviderFactoryAidl::SetUp();
Bao Dob487a852023-12-25 10:12:09 +08001651 if (GetProviderFactoryInterfaceVersion() <
1652 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
1653 GTEST_SKIP();
1654 }
Bao Do72399432023-11-09 08:13:05 +00001655 GetProviderCapabilitiesHelper(SessionType::HFP_SOFTWARE_DECODING_DATAPATH);
1656 OpenProviderHelper(SessionType::HFP_SOFTWARE_DECODING_DATAPATH);
1657 ASSERT_NE(audio_provider_, nullptr);
1658 }
1659
1660 virtual void TearDown() override {
1661 audio_port_ = nullptr;
1662 audio_provider_ = nullptr;
1663 BluetoothAudioProviderFactoryAidl::TearDown();
1664 }
1665
1666 bool OpenSession(int32_t sample_rate, int8_t bits_per_sample,
Bao Do5b2fdab2023-11-20 08:02:55 +00001667 ChannelMode channel_mode, int32_t data_interval_us) {
Bao Do72399432023-11-09 08:13:05 +00001668 PcmConfiguration pcm_config{
1669 .sampleRateHz = sample_rate,
1670 .channelMode = channel_mode,
1671 .bitsPerSample = bits_per_sample,
1672 .dataIntervalUs = data_interval_us,
1673 };
1674 DataMQDesc mq_desc;
1675 auto aidl_retval = audio_provider_->startSession(
1676 audio_port_, AudioConfiguration(pcm_config), latency_modes, &mq_desc);
1677 DataMQ data_mq(mq_desc);
1678
1679 if (!aidl_retval.isOk()) return false;
1680 if (!data_mq.isValid()) return false;
1681 return true;
1682 }
1683};
1684
1685/**
1686 * Test whether we can open a provider of type
1687 */
1688TEST_P(BluetoothAudioProviderHfpSoftwareDecodingAidl,
1689 OpenHfpSoftwareDecodingProvider) {}
1690
1691/**
1692 * Test whether each provider of type
1693 * SessionType::HFP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
1694 * different PCM config
1695 */
1696TEST_P(BluetoothAudioProviderHfpSoftwareDecodingAidl,
1697 StartAndEndHfpDecodingSoftwareSessionWithPossiblePcmConfig) {
1698 for (auto sample_rate : hfp_sample_rates_) {
1699 for (auto bits_per_sample : hfp_bits_per_samples_) {
1700 for (auto channel_mode : hfp_channel_modes_) {
Bao Do5b2fdab2023-11-20 08:02:55 +00001701 for (auto data_interval_us : hfp_data_interval_us_) {
1702 EXPECT_TRUE(OpenSession(sample_rate, bits_per_sample, channel_mode,
1703 data_interval_us));
1704 EXPECT_TRUE(audio_provider_->endSession().isOk());
Bao Do72399432023-11-09 08:13:05 +00001705 }
1706 }
1707 }
1708 }
1709}
1710
1711/**
Alice Kuoadcceec2022-03-28 13:28:43 +08001712 * openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH
1713 */
1714class BluetoothAudioProviderA2dpEncodingHardwareAidl
1715 : public BluetoothAudioProviderFactoryAidl {
1716 public:
1717 virtual void SetUp() override {
1718 BluetoothAudioProviderFactoryAidl::SetUp();
1719 GetProviderCapabilitiesHelper(
1720 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1721 OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1722 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1723 audio_provider_ != nullptr);
1724 }
1725
1726 virtual void TearDown() override {
1727 audio_port_ = nullptr;
1728 audio_provider_ = nullptr;
1729 BluetoothAudioProviderFactoryAidl::TearDown();
1730 }
1731
1732 bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
1733};
1734
1735/**
1736 * Test whether we can open a provider of type
1737 */
1738TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1739 OpenA2dpEncodingHardwareProvider) {}
Josh Wu049e2cd2022-01-12 05:42:58 -08001740
1741/**
1742 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001743 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1744 * with SBC hardware encoding config
Josh Wu049e2cd2022-01-12 05:42:58 -08001745 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001746TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1747 StartAndEndA2dpSbcEncodingHardwareSession) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001748 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001749 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001750 }
1751
1752 CodecConfiguration codec_config = {
1753 .codecType = CodecType::SBC,
1754 .encodedAudioBitrate = 328000,
1755 .peerMtu = 1005,
1756 .isScmstEnabled = false,
1757 };
1758 auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
1759
1760 for (auto& codec_specific : sbc_codec_specifics) {
1761 copy_codec_specific(codec_config.config, codec_specific);
1762 DataMQDesc mq_desc;
1763 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001764 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001765
1766 ASSERT_TRUE(aidl_retval.isOk());
1767 EXPECT_TRUE(audio_provider_->endSession().isOk());
1768 }
1769}
1770
1771/**
1772 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001773 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1774 * with AAC hardware encoding config
Josh Wu049e2cd2022-01-12 05:42:58 -08001775 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001776TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1777 StartAndEndA2dpAacEncodingHardwareSession) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001778 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001779 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001780 }
1781
1782 CodecConfiguration codec_config = {
1783 .codecType = CodecType::AAC,
1784 .encodedAudioBitrate = 320000,
1785 .peerMtu = 1005,
1786 .isScmstEnabled = false,
1787 };
1788 auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
1789
1790 for (auto& codec_specific : aac_codec_specifics) {
1791 copy_codec_specific(codec_config.config, codec_specific);
1792 DataMQDesc mq_desc;
1793 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001794 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001795
1796 ASSERT_TRUE(aidl_retval.isOk());
1797 EXPECT_TRUE(audio_provider_->endSession().isOk());
1798 }
1799}
1800
1801/**
1802 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001803 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1804 * with LDAC hardware encoding config
Josh Wu049e2cd2022-01-12 05:42:58 -08001805 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001806TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1807 StartAndEndA2dpLdacEncodingHardwareSession) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001808 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001809 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001810 }
1811
1812 CodecConfiguration codec_config = {
1813 .codecType = CodecType::LDAC,
1814 .encodedAudioBitrate = 990000,
1815 .peerMtu = 1005,
1816 .isScmstEnabled = false,
1817 };
1818 auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
1819
1820 for (auto& codec_specific : ldac_codec_specifics) {
1821 copy_codec_specific(codec_config.config, codec_specific);
1822 DataMQDesc mq_desc;
1823 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001824 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001825
1826 ASSERT_TRUE(aidl_retval.isOk());
1827 EXPECT_TRUE(audio_provider_->endSession().isOk());
1828 }
1829}
1830
1831/**
1832 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001833 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1834 * with Opus hardware encoding config
Josh Wu049e2cd2022-01-12 05:42:58 -08001835 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001836TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
Omer Osmana2587da2022-05-01 03:54:11 +00001837 StartAndEndA2dpOpusEncodingHardwareSession) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001838 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001839 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001840 }
1841
1842 CodecConfiguration codec_config = {
Omer Osmana2587da2022-05-01 03:54:11 +00001843 .codecType = CodecType::OPUS,
Josh Wu049e2cd2022-01-12 05:42:58 -08001844 .encodedAudioBitrate = 990000,
1845 .peerMtu = 1005,
1846 .isScmstEnabled = false,
1847 };
Omer Osmana2587da2022-05-01 03:54:11 +00001848 auto opus_codec_specifics = GetOpusCodecSpecificSupportedList(true);
Josh Wu049e2cd2022-01-12 05:42:58 -08001849
Omer Osmana2587da2022-05-01 03:54:11 +00001850 for (auto& codec_specific : opus_codec_specifics) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001851 copy_codec_specific(codec_config.config, codec_specific);
1852 DataMQDesc mq_desc;
1853 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001854 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001855
1856 ASSERT_TRUE(aidl_retval.isOk());
1857 EXPECT_TRUE(audio_provider_->endSession().isOk());
1858 }
1859}
1860
1861/**
1862 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001863 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1864 * with AptX hardware encoding config
Josh Wu049e2cd2022-01-12 05:42:58 -08001865 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001866TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1867 StartAndEndA2dpAptxEncodingHardwareSession) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001868 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001869 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001870 }
1871
1872 for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
1873 CodecConfiguration codec_config = {
1874 .codecType = codec_type,
1875 .encodedAudioBitrate =
1876 (codec_type == CodecType::APTX ? 352000 : 576000),
1877 .peerMtu = 1005,
1878 .isScmstEnabled = false,
1879 };
1880
1881 auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
1882 (codec_type == CodecType::APTX_HD ? true : false), true);
1883
1884 for (auto& codec_specific : aptx_codec_specifics) {
1885 copy_codec_specific(codec_config.config, codec_specific);
1886 DataMQDesc mq_desc;
1887 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001888 audio_port_, AudioConfiguration(codec_config), latency_modes,
1889 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001890
1891 ASSERT_TRUE(aidl_retval.isOk());
1892 EXPECT_TRUE(audio_provider_->endSession().isOk());
1893 }
1894 }
1895}
1896
1897/**
1898 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08001899 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped
1900 * with an invalid codec config
Josh Wu049e2cd2022-01-12 05:42:58 -08001901 */
Alice Kuoadcceec2022-03-28 13:28:43 +08001902TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
1903 StartAndEndA2dpEncodingHardwareSessionInvalidCodecConfig) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001904 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00001905 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08001906 }
1907 ASSERT_NE(audio_provider_, nullptr);
1908
1909 std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
Sagar Verma62df9102022-12-07 17:56:04 +05301910 for (auto codec_type : ndk::enum_range<CodecType>()) {
Josh Wu049e2cd2022-01-12 05:42:58 -08001911 switch (codec_type) {
1912 case CodecType::SBC:
1913 codec_specifics = GetSbcCodecSpecificSupportedList(false);
1914 break;
1915 case CodecType::AAC:
1916 codec_specifics = GetAacCodecSpecificSupportedList(false);
1917 break;
1918 case CodecType::LDAC:
1919 codec_specifics = GetLdacCodecSpecificSupportedList(false);
1920 break;
1921 case CodecType::APTX:
1922 codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
1923 break;
1924 case CodecType::APTX_HD:
1925 codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
1926 break;
Omer Osmana2587da2022-05-01 03:54:11 +00001927 case CodecType::OPUS:
1928 codec_specifics = GetOpusCodecSpecificSupportedList(false);
Josh Wu049e2cd2022-01-12 05:42:58 -08001929 continue;
1930 case CodecType::APTX_ADAPTIVE:
Sagar Verma62df9102022-12-07 17:56:04 +05301931 case CodecType::APTX_ADAPTIVE_LE:
1932 case CodecType::APTX_ADAPTIVE_LEX:
Omer Osmana2587da2022-05-01 03:54:11 +00001933 case CodecType::LC3:
Josh Wu049e2cd2022-01-12 05:42:58 -08001934 case CodecType::VENDOR:
1935 case CodecType::UNKNOWN:
1936 codec_specifics.clear();
1937 break;
1938 }
1939 if (codec_specifics.empty()) {
1940 continue;
1941 }
1942
1943 CodecConfiguration codec_config = {
1944 .codecType = codec_type,
1945 .encodedAudioBitrate = 328000,
1946 .peerMtu = 1005,
1947 .isScmstEnabled = false,
1948 };
1949 for (auto codec_specific : codec_specifics) {
1950 copy_codec_specific(codec_config.config, codec_specific);
1951 DataMQDesc mq_desc;
1952 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08001953 audio_port_, AudioConfiguration(codec_config), latency_modes,
1954 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08001955
1956 // AIDL call should fail on invalid codec
1957 ASSERT_FALSE(aidl_retval.isOk());
1958 EXPECT_TRUE(audio_provider_->endSession().isOk());
1959 }
1960 }
1961}
1962
1963/**
Bao Do72399432023-11-09 08:13:05 +00001964 * openProvider HFP_HARDWARE_OFFLOAD_DATAPATH
1965 */
1966class BluetoothAudioProviderHfpHardwareAidl
1967 : public BluetoothAudioProviderFactoryAidl {
1968 public:
1969 virtual void SetUp() override {
1970 BluetoothAudioProviderFactoryAidl::SetUp();
Bao Dob487a852023-12-25 10:12:09 +08001971 if (GetProviderFactoryInterfaceVersion() <
1972 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
1973 GTEST_SKIP();
1974 }
Bao Do2fa1ab42024-01-29 17:50:34 +08001975 GetProviderInfoHelper(SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH);
Bao Do72399432023-11-09 08:13:05 +00001976 OpenProviderHelper(SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH);
1977 // Can open or empty capability
1978 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
1979 audio_provider_ != nullptr);
1980 }
1981
1982 virtual void TearDown() override {
1983 audio_port_ = nullptr;
1984 audio_provider_ = nullptr;
1985 BluetoothAudioProviderFactoryAidl::TearDown();
1986 }
1987
1988 bool OpenSession(CodecId codec_id, int connection_handle, bool nrec,
Bao Do5b2fdab2023-11-20 08:02:55 +00001989 bool controller_codec) {
Bao Do72399432023-11-09 08:13:05 +00001990 // Check if can open session with a Hfp configuration
1991 HfpConfiguration hfp_configuration{
1992 .codecId = codec_id,
1993 .connectionHandle = connection_handle,
1994 .nrec = nrec,
1995 .controllerCodec = controller_codec,
1996 };
1997 DataMQDesc mq_desc;
1998 auto aidl_retval = audio_provider_->startSession(
1999 audio_port_, AudioConfiguration(hfp_configuration), latency_modes,
2000 &mq_desc);
2001
2002 // Only check if aidl is ok to start session.
2003 return aidl_retval.isOk();
2004 }
2005};
2006
2007/**
2008 * Test whether we can open a provider of type
2009 */
2010TEST_P(BluetoothAudioProviderHfpHardwareAidl, OpenHfpHardwareProvider) {}
2011
2012/**
2013 * Test whether each provider of type
2014 * SessionType::HFP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
2015 * different HFP config
2016 */
2017TEST_P(BluetoothAudioProviderHfpHardwareAidl,
2018 StartAndEndHfpHardwareSessionWithPossiblePcmConfig) {
2019 // Try to open with a sample configuration
2020 EXPECT_TRUE(OpenSession(CodecId::Core::CVSD, 6, false, true));
2021 EXPECT_TRUE(audio_provider_->endSession().isOk());
2022}
2023
2024/**
Josh Wu049e2cd2022-01-12 05:42:58 -08002025 * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
2026 */
2027class BluetoothAudioProviderHearingAidSoftwareAidl
2028 : public BluetoothAudioProviderFactoryAidl {
2029 public:
2030 virtual void SetUp() override {
2031 BluetoothAudioProviderFactoryAidl::SetUp();
2032 GetProviderCapabilitiesHelper(
2033 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
2034 OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
2035 ASSERT_NE(audio_provider_, nullptr);
2036 }
2037
2038 virtual void TearDown() override {
2039 audio_port_ = nullptr;
2040 audio_provider_ = nullptr;
2041 BluetoothAudioProviderFactoryAidl::TearDown();
2042 }
2043
2044 static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
2045 static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
2046 static constexpr ChannelMode hearing_aid_channel_modes_[] = {
2047 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
2048};
2049
2050/**
2051 * Test whether we can open a provider of type
2052 */
2053TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
2054 OpenHearingAidSoftwareProvider) {}
2055
2056/**
2057 * Test whether each provider of type
2058 * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
2059 * stopped with different PCM config
2060 */
2061TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
2062 StartAndEndHearingAidSessionWithPossiblePcmConfig) {
2063 for (int32_t sample_rate : hearing_aid_sample_rates_) {
2064 for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
2065 for (auto channel_mode : hearing_aid_channel_modes_) {
2066 PcmConfiguration pcm_config{
2067 .sampleRateHz = sample_rate,
Josh Wu049e2cd2022-01-12 05:42:58 -08002068 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00002069 .bitsPerSample = bits_per_sample,
Josh Wu049e2cd2022-01-12 05:42:58 -08002070 };
2071 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
2072 DataMQDesc mq_desc;
2073 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08002074 audio_port_, AudioConfiguration(pcm_config), latency_modes,
2075 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08002076 DataMQ data_mq(mq_desc);
2077
2078 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
2079 if (is_codec_config_valid) {
2080 EXPECT_TRUE(data_mq.isValid());
2081 }
2082 EXPECT_TRUE(audio_provider_->endSession().isOk());
2083 }
2084 }
2085 }
2086}
2087
2088/**
2089 * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
2090 */
2091class BluetoothAudioProviderLeAudioOutputSoftwareAidl
2092 : public BluetoothAudioProviderFactoryAidl {
2093 public:
2094 virtual void SetUp() override {
2095 BluetoothAudioProviderFactoryAidl::SetUp();
2096 GetProviderCapabilitiesHelper(
2097 SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
2098 OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
2099 ASSERT_NE(audio_provider_, nullptr);
2100 }
2101
2102 virtual void TearDown() override {
2103 audio_port_ = nullptr;
2104 audio_provider_ = nullptr;
2105 BluetoothAudioProviderFactoryAidl::TearDown();
2106 }
2107
2108 static constexpr int32_t le_audio_output_sample_rates_[] = {
2109 0, 8000, 16000, 24000, 32000, 44100, 48000,
2110 };
2111 static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
2112 static constexpr ChannelMode le_audio_output_channel_modes_[] = {
2113 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
2114 static constexpr int32_t le_audio_output_data_interval_us_[] = {
2115 0 /* Invalid */, 10000 /* Valid 10ms */};
2116};
2117
2118/**
2119 * Test whether each provider of type
2120 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
2121 * stopped
2122 */
2123TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
2124 OpenLeAudioOutputSoftwareProvider) {}
2125
2126/**
2127 * Test whether each provider of type
2128 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
2129 * stopped with different PCM config
2130 */
2131TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
2132 StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
2133 for (auto sample_rate : le_audio_output_sample_rates_) {
2134 for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
2135 for (auto channel_mode : le_audio_output_channel_modes_) {
2136 for (auto data_interval_us : le_audio_output_data_interval_us_) {
2137 PcmConfiguration pcm_config{
2138 .sampleRateHz = sample_rate,
Josh Wu049e2cd2022-01-12 05:42:58 -08002139 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00002140 .bitsPerSample = bits_per_sample,
Josh Wu049e2cd2022-01-12 05:42:58 -08002141 .dataIntervalUs = data_interval_us,
2142 };
Josh Wu8a1be762022-02-15 09:37:29 -08002143 bool is_codec_config_valid =
2144 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -08002145 DataMQDesc mq_desc;
2146 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08002147 audio_port_, AudioConfiguration(pcm_config), latency_modes,
2148 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08002149 DataMQ data_mq(mq_desc);
2150
2151 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
2152 if (is_codec_config_valid) {
2153 EXPECT_TRUE(data_mq.isValid());
2154 }
2155 EXPECT_TRUE(audio_provider_->endSession().isOk());
2156 }
2157 }
2158 }
2159 }
2160}
2161
2162/**
Alice Kuo04a399a2022-02-16 09:19:56 +08002163 * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
Josh Wu049e2cd2022-01-12 05:42:58 -08002164 */
2165class BluetoothAudioProviderLeAudioInputSoftwareAidl
2166 : public BluetoothAudioProviderFactoryAidl {
2167 public:
2168 virtual void SetUp() override {
2169 BluetoothAudioProviderFactoryAidl::SetUp();
2170 GetProviderCapabilitiesHelper(
2171 SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
2172 OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
2173 ASSERT_NE(audio_provider_, nullptr);
2174 }
2175
2176 virtual void TearDown() override {
2177 audio_port_ = nullptr;
2178 audio_provider_ = nullptr;
2179 BluetoothAudioProviderFactoryAidl::TearDown();
2180 }
2181
2182 static constexpr int32_t le_audio_input_sample_rates_[] = {
2183 0, 8000, 16000, 24000, 32000, 44100, 48000};
2184 static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
2185 static constexpr ChannelMode le_audio_input_channel_modes_[] = {
2186 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
2187 static constexpr int32_t le_audio_input_data_interval_us_[] = {
2188 0 /* Invalid */, 10000 /* Valid 10ms */};
2189};
2190
2191/**
2192 * Test whether each provider of type
Alice Kuo04a399a2022-02-16 09:19:56 +08002193 * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08002194 * stopped
2195 */
2196TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
2197 OpenLeAudioInputSoftwareProvider) {}
2198
2199/**
2200 * Test whether each provider of type
Alice Kuo04a399a2022-02-16 09:19:56 +08002201 * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08002202 * stopped with different PCM config
2203 */
2204TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
2205 StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
2206 for (auto sample_rate : le_audio_input_sample_rates_) {
2207 for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
2208 for (auto channel_mode : le_audio_input_channel_modes_) {
2209 for (auto data_interval_us : le_audio_input_data_interval_us_) {
2210 PcmConfiguration pcm_config{
2211 .sampleRateHz = sample_rate,
Josh Wu049e2cd2022-01-12 05:42:58 -08002212 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00002213 .bitsPerSample = bits_per_sample,
Josh Wu049e2cd2022-01-12 05:42:58 -08002214 .dataIntervalUs = data_interval_us,
2215 };
Josh Wu8a1be762022-02-15 09:37:29 -08002216 bool is_codec_config_valid =
2217 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -08002218 DataMQDesc mq_desc;
2219 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08002220 audio_port_, AudioConfiguration(pcm_config), latency_modes,
2221 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08002222 DataMQ data_mq(mq_desc);
2223
2224 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
2225 if (is_codec_config_valid) {
2226 EXPECT_TRUE(data_mq.isValid());
2227 }
2228 EXPECT_TRUE(audio_provider_->endSession().isOk());
2229 }
2230 }
2231 }
2232 }
2233}
2234
2235/**
Alice Kuo04a399a2022-02-16 09:19:56 +08002236 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
Josh Wu049e2cd2022-01-12 05:42:58 -08002237 */
2238class BluetoothAudioProviderLeAudioOutputHardwareAidl
2239 : public BluetoothAudioProviderFactoryAidl {
2240 public:
2241 virtual void SetUp() override {
2242 BluetoothAudioProviderFactoryAidl::SetUp();
2243 GetProviderCapabilitiesHelper(
2244 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Bao Doc36897d2023-12-06 01:27:54 +00002245 GetProviderInfoHelper(
2246 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Josh Wu049e2cd2022-01-12 05:42:58 -08002247 OpenProviderHelper(
2248 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
2249 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
2250 audio_provider_ != nullptr);
2251 }
2252
2253 virtual void TearDown() override {
2254 audio_port_ = nullptr;
2255 audio_provider_ = nullptr;
2256 BluetoothAudioProviderFactoryAidl::TearDown();
2257 }
2258
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002259 bool IsMultidirectionalCapabilitiesEnabled() {
2260 if (!temp_provider_info_.has_value()) return false;
2261
2262 return temp_provider_info_.value().supportsMultidirectionalCapabilities;
2263 }
2264
2265 bool IsAsymmetricConfigurationAllowed() {
2266 if (!temp_provider_info_.has_value()) return false;
2267 if (temp_provider_info_.value().codecInfos.empty()) return false;
2268
2269 for (auto& codec_info : temp_provider_info_.value().codecInfos) {
2270 if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio) {
2271 return false;
2272 }
2273
2274 auto flags =
2275 codec_info.transport.get<CodecInfo::Transport::leAudio>().flags;
2276
2277 if (!flags) {
2278 continue;
2279 }
2280
2281 if (flags->bitmask &
2282 ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS) {
2283 return true;
2284 }
2285 }
2286
2287 return false;
2288 }
2289
Josh Wu049e2cd2022-01-12 05:42:58 -08002290 bool IsOffloadOutputSupported() {
2291 for (auto& capability : temp_provider_capabilities_) {
2292 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
2293 continue;
2294 }
2295 auto& le_audio_capability =
2296 capability.get<AudioCapabilities::leAudioCapabilities>();
2297 if (le_audio_capability.unicastEncodeCapability.codecType !=
2298 CodecType::UNKNOWN)
2299 return true;
2300 }
2301 return false;
2302 }
2303
Bao Doc36897d2023-12-06 01:27:54 +00002304 bool IsOffloadOutputProviderInfoSupported() {
2305 if (!temp_provider_info_.has_value()) return false;
2306 if (temp_provider_info_.value().codecInfos.empty()) return false;
2307 // Check if all codec info is of LeAudio type
2308 for (auto& codec_info : temp_provider_info_.value().codecInfos) {
2309 if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
2310 return false;
2311 }
2312 return true;
2313 }
2314
2315 std::vector<Lc3Configuration> GetUnicastLc3SupportedListFromProviderInfo() {
2316 std::vector<Lc3Configuration> le_audio_codec_configs;
2317 for (auto& codec_info : temp_provider_info_.value().codecInfos) {
2318 // Only gets LC3 codec information
2319 if (codec_info.id != CodecId::Core::LC3) continue;
2320 // Combine those parameters into one list of Lc3Configuration
2321 auto& transport =
2322 codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
2323 for (int32_t samplingFrequencyHz : transport.samplingFrequencyHz) {
2324 for (int32_t frameDurationUs : transport.frameDurationUs) {
2325 for (int32_t octetsPerFrame : transport.bitdepth) {
2326 Lc3Configuration lc3_config = {
2327 .samplingFrequencyHz = samplingFrequencyHz,
2328 .frameDurationUs = frameDurationUs,
2329 .octetsPerFrame = octetsPerFrame,
2330 };
2331 le_audio_codec_configs.push_back(lc3_config);
2332 }
2333 }
2334 }
2335 }
2336
2337 return le_audio_codec_configs;
2338 }
2339
2340 AudioContext GetAudioContext(int32_t bitmask) {
2341 AudioContext media_audio_context;
2342 media_audio_context.bitmask = bitmask;
2343 return media_audio_context;
2344 }
2345
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002346 LeAudioDeviceCapabilities GetDefaultRemoteSinkCapability() {
Bao Doc36897d2023-12-06 01:27:54 +00002347 // Create a capability
2348 LeAudioDeviceCapabilities capability;
2349
2350 capability.codecId = CodecId::Core::LC3;
2351
2352 auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002353 pref_context_metadata.values =
2354 GetAudioContext(AudioContext::MEDIA | AudioContext::CONVERSATIONAL |
2355 AudioContext::GAME);
Bao Doc36897d2023-12-06 01:27:54 +00002356 capability.metadata = {pref_context_metadata};
2357
2358 auto sampling_rate =
2359 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
2360 sampling_rate.bitmask =
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002361 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000 |
Bao Doc36897d2023-12-06 01:27:54 +00002362 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000;
2363 auto frame_duration =
2364 CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
2365 frame_duration.bitmask =
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002366 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
2367 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
Bao Doc36897d2023-12-06 01:27:54 +00002368 auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
Jakub Tyszkowski1d214222024-01-16 09:44:48 +00002369 octets.min = 0;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002370 octets.max = 120;
Bao Doc36897d2023-12-06 01:27:54 +00002371 auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
2372 frames.value = 2;
2373 capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
2374 octets, frames};
2375 return capability;
2376 }
2377
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002378 LeAudioDeviceCapabilities GetDefaultRemoteSourceCapability() {
2379 // Create a capability
2380 LeAudioDeviceCapabilities capability;
2381
2382 capability.codecId = CodecId::Core::LC3;
2383
2384 auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
2385 pref_context_metadata.values =
2386 GetAudioContext(AudioContext::LIVE_AUDIO |
2387 AudioContext::CONVERSATIONAL | AudioContext::GAME);
2388 capability.metadata = {pref_context_metadata};
2389
2390 auto sampling_rate =
2391 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
2392 sampling_rate.bitmask =
2393 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000 |
2394 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000;
2395 auto frame_duration =
2396 CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
2397 frame_duration.bitmask =
2398 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
2399 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
2400 auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
2401 octets.min = 0;
2402 octets.max = 120;
2403 auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
2404 frames.value = 2;
2405 capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
2406 octets, frames};
2407 return capability;
2408 }
2409
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002410 bool IsAseRequirementSatisfiedWithUnknownChannelCount(
2411 const std::vector<std::optional<AseDirectionRequirement>>&
2412 ase_requirements,
2413 const std::vector<std::optional<AseDirectionConfiguration>>&
2414 ase_configurations) {
2415 /* This is mandatory to match sample freq, allocation however, when in the
2416 * device group there is only one device which supports left and right
2417 * allocation, and channel count is hidden from the BT stack, the BT stack
2418 * will send single requirement but it can receive two configurations if the
2419 * channel count is 1.
2420 */
2421
2422 int num_of_ase_requirements = 0;
2423 for (const auto& ase_req : ase_requirements) {
2424 auto required_allocation_ltv = GetConfigurationLtv(
2425 ase_req->aseConfiguration.codecConfiguration,
2426 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2427 if (required_allocation_ltv == std::nullopt) {
2428 continue;
2429 }
2430 int required_allocation =
2431 required_allocation_ltv
2432 ->get<
2433 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
2434 .bitmask;
2435 num_of_ase_requirements += std::bitset<32>(required_allocation).count();
2436 }
2437
2438 int num_of_satisfied_ase_requirements = 0;
2439 for (const auto& ase_req : ase_requirements) {
2440 if (!ase_req) {
2441 continue;
2442 }
2443 auto required_sample_freq_ltv = GetConfigurationLtv(
2444 ase_req->aseConfiguration.codecConfiguration,
2445 CodecSpecificConfigurationLtv::Tag::samplingFrequency);
2446 auto required_allocation_ltv = GetConfigurationLtv(
2447 ase_req->aseConfiguration.codecConfiguration,
2448 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2449
2450 /* Allocation and sample freq shall be always in the requirement */
2451 if (!required_sample_freq_ltv || !required_allocation_ltv) {
2452 return false;
2453 }
2454
2455 int required_allocation =
2456 required_allocation_ltv
2457 ->get<
2458 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
2459 .bitmask;
2460
2461 for (const auto& ase_conf : ase_configurations) {
2462 if (!ase_conf) {
2463 continue;
2464 }
2465 auto config_sample_freq_ltv = GetConfigurationLtv(
2466 ase_conf->aseConfiguration.codecConfiguration,
2467 CodecSpecificConfigurationLtv::Tag::samplingFrequency);
2468 auto config_allocation_ltv = GetConfigurationLtv(
2469 ase_conf->aseConfiguration.codecConfiguration,
2470 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2471 if (config_sample_freq_ltv == std::nullopt ||
2472 config_allocation_ltv == std::nullopt) {
2473 return false;
2474 }
2475
2476 int configured_allocation = config_allocation_ltv
2477 ->get<CodecSpecificConfigurationLtv::
2478 Tag::audioChannelAllocation>()
2479 .bitmask;
2480
2481 if (config_sample_freq_ltv == required_sample_freq_ltv &&
2482 (required_allocation & configured_allocation)) {
2483 num_of_satisfied_ase_requirements +=
2484 std::bitset<32>(configured_allocation).count();
2485 }
2486 }
2487 }
2488
2489 return (num_of_satisfied_ase_requirements == num_of_ase_requirements);
2490 }
2491
2492 bool IsAseRequirementSatisfied(
2493 const std::vector<std::optional<AseDirectionRequirement>>&
2494 ase_requirements,
2495 const std::vector<std::optional<AseDirectionConfiguration>>&
2496 ase_configurations) {
2497 // This is mandatory to match sample freq, allocation
2498 int num_of_satisfied_ase_requirements = 0;
2499
2500 int required_allocations = 0;
2501 for (const auto& ase_req : ase_requirements) {
2502 auto required_allocation_ltv = GetConfigurationLtv(
2503 ase_req->aseConfiguration.codecConfiguration,
2504 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2505 if (required_allocation_ltv == std::nullopt) {
2506 continue;
2507 }
2508
2509 int allocations =
2510 required_allocation_ltv
2511 ->get<
2512 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
2513 .bitmask;
2514 required_allocations += std::bitset<32>(allocations).count();
2515 }
2516
2517 if (ase_requirements.size() != required_allocations) {
2518 /* If more than one allication is requested in the requirement, then use
2519 * different verifier */
2520 return IsAseRequirementSatisfiedWithUnknownChannelCount(
2521 ase_requirements, ase_configurations);
2522 }
2523
2524 for (const auto& ase_req : ase_requirements) {
2525 if (!ase_req) {
2526 continue;
2527 }
2528 auto required_sample_freq_ltv = GetConfigurationLtv(
2529 ase_req->aseConfiguration.codecConfiguration,
2530 CodecSpecificConfigurationLtv::Tag::samplingFrequency);
2531 auto required_allocation_ltv = GetConfigurationLtv(
2532 ase_req->aseConfiguration.codecConfiguration,
2533 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2534
2535 /* Allocation and sample freq shall be always in the requirement */
2536 if (!required_sample_freq_ltv || !required_allocation_ltv) {
2537 return false;
2538 }
2539
2540 for (const auto& ase_conf : ase_configurations) {
2541 if (!ase_conf) {
2542 continue;
2543 }
2544 auto config_sample_freq_ltv = GetConfigurationLtv(
2545 ase_conf->aseConfiguration.codecConfiguration,
2546 CodecSpecificConfigurationLtv::Tag::samplingFrequency);
2547 auto config_allocation_ltv = GetConfigurationLtv(
2548 ase_conf->aseConfiguration.codecConfiguration,
2549 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
2550 if (config_sample_freq_ltv == std::nullopt ||
2551 config_allocation_ltv == std::nullopt) {
2552 return false;
2553 }
2554
2555 if (config_sample_freq_ltv == required_sample_freq_ltv &&
2556 config_allocation_ltv == required_allocation_ltv) {
2557 num_of_satisfied_ase_requirements++;
2558 break;
2559 }
2560 }
2561 }
2562
2563 return (num_of_satisfied_ase_requirements == ase_requirements.size());
2564 }
2565
Jakub Tyszkowski11178a62024-06-18 10:07:26 +00002566 static void VerifyCodecParameters(
2567 ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
2568 LeAudioAseConfigurationSetting::AseDirectionConfiguration config) {
2569 ASSERT_NE(config.aseConfiguration.codecConfiguration.size(), 0lu);
2570 ASSERT_TRUE(config.qosConfiguration.has_value());
2571
2572 int32_t frame_blocks = 1; // by default 1 if not set
2573 int8_t frame_duration = 0;
2574 int32_t octets_per_frame = 0;
2575 std::bitset<32> allocation_bitmask = 0;
2576
2577 for (auto const& param : config.aseConfiguration.codecConfiguration) {
2578 if (param.getTag() ==
2579 ::aidl::android::hardware::bluetooth::audio::
2580 CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU) {
2581 frame_blocks = param
2582 .get<::aidl::android::hardware::bluetooth::audio::
2583 CodecSpecificConfigurationLtv::Tag::
2584 codecFrameBlocksPerSDU>()
2585 .value;
2586 } else if (param.getTag() ==
2587 ::aidl::android::hardware::bluetooth::audio::
2588 CodecSpecificConfigurationLtv::Tag::frameDuration) {
2589 frame_duration = static_cast<int8_t>(
2590 param.get<::aidl::android::hardware::bluetooth::audio::
2591 CodecSpecificConfigurationLtv::Tag::frameDuration>());
2592 } else if (param.getTag() ==
2593 ::aidl::android::hardware::bluetooth::audio::
2594 CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame) {
2595 octets_per_frame = static_cast<int32_t>(
2596 param
2597 .get<::aidl::android::hardware::bluetooth::audio::
2598 CodecSpecificConfigurationLtv::Tag::
2599 octetsPerCodecFrame>()
2600 .value);
2601 } else if (param.getTag() == ::aidl::android::hardware::bluetooth::audio::
2602 CodecSpecificConfigurationLtv::Tag::
2603 audioChannelAllocation) {
2604 allocation_bitmask = static_cast<int32_t>(
2605 param
2606 .get<::aidl::android::hardware::bluetooth::audio::
2607 CodecSpecificConfigurationLtv::Tag::
2608 audioChannelAllocation>()
2609 .bitmask);
2610 }
2611 }
2612
2613 ASSERT_NE(frame_blocks, 0);
2614 ASSERT_NE(frame_duration, 0);
2615 ASSERT_NE(octets_per_frame, 0);
2616
2617 auto const num_channels_per_cis = allocation_bitmask.count();
2618 ASSERT_NE(num_channels_per_cis, 0);
2619
2620 // Verify if QoS takes the codec frame blocks per SDU into the account
2621 ASSERT_TRUE(config.qosConfiguration->sduIntervalUs >=
2622 frame_blocks * frame_duration);
2623 ASSERT_TRUE(config.qosConfiguration->maxSdu >=
2624 (frame_blocks * num_channels_per_cis * octets_per_frame));
2625 }
2626
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002627 void VerifyIfRequirementsSatisfied(
2628 const std::vector<LeAudioConfigurationRequirement>& requirements,
2629 const std::vector<LeAudioAseConfigurationSetting>& configurations) {
2630 if (requirements.empty() && configurations.empty()) {
2631 return;
2632 }
2633
2634 /* It might happen that vendor lib will provide same configuration for
2635 * multiple contexts and it should be accepted
2636 */
2637
2638 int num_of_requirements = 0;
2639 for (const auto& req : requirements) {
2640 num_of_requirements += std::bitset<32>(req.audioContext.bitmask).count();
2641 }
2642
2643 int num_of_configurations = 0;
2644 for (const auto& conf : configurations) {
2645 num_of_configurations +=
2646 std::bitset<32>(conf.audioContext.bitmask).count();
2647 }
2648
2649 ASSERT_EQ(num_of_requirements, num_of_configurations);
2650
2651 int num_of_satisfied_requirements = 0;
2652 for (const auto& req : requirements) {
2653 for (const auto& conf : configurations) {
2654 if ((req.audioContext.bitmask & conf.audioContext.bitmask) !=
2655 req.audioContext.bitmask) {
2656 continue;
2657 }
2658
Jakub Tyszkowski11178a62024-06-18 10:07:26 +00002659 bool sink_req_satisfied = false;
2660 if (req.sinkAseRequirement) {
2661 ASSERT_TRUE(conf.sinkAseConfiguration.has_value());
2662 sink_req_satisfied = IsAseRequirementSatisfied(
2663 *req.sinkAseRequirement, *conf.sinkAseConfiguration);
2664
2665 ASSERT_NE(conf.sinkAseConfiguration->size(), 0lu);
2666 for (auto const& cfg : conf.sinkAseConfiguration.value()) {
2667 ASSERT_TRUE(cfg.has_value());
2668 VerifyCodecParameters(cfg.value());
2669 }
2670 }
2671
2672 bool source_req_satisfied = false;
2673 if (req.sourceAseRequirement) {
2674 ASSERT_TRUE(conf.sourceAseConfiguration.has_value());
2675 source_req_satisfied = IsAseRequirementSatisfied(
2676 *req.sourceAseRequirement, *conf.sourceAseConfiguration);
2677
2678 ASSERT_NE(conf.sourceAseConfiguration->size(), 0lu);
2679 for (auto const& cfg : conf.sourceAseConfiguration.value()) {
2680 ASSERT_TRUE(cfg.has_value());
2681 VerifyCodecParameters(cfg.value());
2682 }
2683 }
2684
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002685 if (req.sinkAseRequirement && req.sourceAseRequirement) {
2686 if (!conf.sinkAseConfiguration || !conf.sourceAseConfiguration) {
2687 continue;
2688 }
2689
Jakub Tyszkowski11178a62024-06-18 10:07:26 +00002690 if (!sink_req_satisfied || !source_req_satisfied) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002691 continue;
2692 }
2693 num_of_satisfied_requirements +=
2694 std::bitset<32>(req.audioContext.bitmask).count();
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002695 break;
2696 } else if (req.sinkAseRequirement) {
Jakub Tyszkowski11178a62024-06-18 10:07:26 +00002697 if (!sink_req_satisfied) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002698 continue;
2699 }
2700 num_of_satisfied_requirements +=
2701 std::bitset<32>(req.audioContext.bitmask).count();
2702 break;
2703 } else if (req.sourceAseRequirement) {
Jakub Tyszkowski11178a62024-06-18 10:07:26 +00002704 if (!source_req_satisfied) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002705 continue;
2706 }
2707 num_of_satisfied_requirements +=
2708 std::bitset<32>(req.audioContext.bitmask).count();
2709 break;
2710 }
2711 }
2712 }
2713 ASSERT_EQ(num_of_satisfied_requirements, num_of_requirements);
2714 }
2715
2716 LeAudioConfigurationRequirement GetUnicastDefaultRequirement(
2717 int32_t context_bits, bool is_sink_requirement,
2718 bool is_source_requriement,
2719 CodecSpecificConfigurationLtv::SamplingFrequency freq =
2720 CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000) {
Bao Doc36897d2023-12-06 01:27:54 +00002721 // Create a requirements
2722 LeAudioConfigurationRequirement requirement;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002723 requirement.audioContext = GetAudioContext(context_bits);
2724
2725 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
2726 allocation.bitmask =
2727 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
2728 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
Bao Doc36897d2023-12-06 01:27:54 +00002729
2730 auto direction_ase_requriement = AseDirectionRequirement();
2731 direction_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
2732 direction_ase_requriement.aseConfiguration.targetLatency =
2733 LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
2734
Bao Doc36897d2023-12-06 01:27:54 +00002735 direction_ase_requriement.aseConfiguration.codecConfiguration = {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002736 freq, CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation
2737
Bao Doc36897d2023-12-06 01:27:54 +00002738 };
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002739 if (is_sink_requirement)
2740 requirement.sinkAseRequirement = {direction_ase_requriement};
2741
Bao Doc36897d2023-12-06 01:27:54 +00002742 if (is_source_requriement)
2743 requirement.sourceAseRequirement = {direction_ase_requriement};
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002744
Bao Doc36897d2023-12-06 01:27:54 +00002745 return requirement;
2746 }
2747
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002748 LeAudioConfigurationRequirement GetUnicastGameRequirement(bool asymmetric) {
2749 // Create a requirements
2750 LeAudioConfigurationRequirement requirement;
2751 requirement.audioContext = GetAudioContext(AudioContext::GAME);
2752
2753 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
2754 allocation.bitmask =
2755 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
2756 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
2757
2758 auto sink_ase_requriement = AseDirectionRequirement();
2759 sink_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
2760 sink_ase_requriement.aseConfiguration.targetLatency =
2761 LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
2762
2763 sink_ase_requriement.aseConfiguration.codecConfiguration = {
2764 CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
2765 CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
2766
2767 auto source_ase_requriement = AseDirectionRequirement();
2768 source_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
2769 source_ase_requriement.aseConfiguration.targetLatency =
2770 LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
2771
2772 if (asymmetric) {
2773 source_ase_requriement.aseConfiguration.codecConfiguration = {
2774 CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
2775 CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
2776 } else {
2777 source_ase_requriement.aseConfiguration.codecConfiguration = {
2778 CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
2779 CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
2780 }
2781
2782 requirement.sinkAseRequirement = {sink_ase_requriement};
2783 requirement.sourceAseRequirement = {source_ase_requriement};
2784
2785 return requirement;
2786 }
2787
2788 LeAudioAseQosConfigurationRequirement GetQosRequirements(
2789 bool is_sink_requirement, bool is_source_requriement, bool valid = true) {
2790 LeAudioAseQosConfigurationRequirement qosRequirement;
2791
2792 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
2793 allocation.bitmask =
2794 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
2795 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
2796
2797 AseQosDirectionRequirement directionalRequirement = {
2798 .framing = IBluetoothAudioProvider::Framing::UNFRAMED,
2799 .preferredRetransmissionNum = 2,
2800 .maxTransportLatencyMs = 10,
2801 .presentationDelayMinUs = 40000,
2802 .presentationDelayMaxUs = 40000,
2803 .aseConfiguration =
2804 {
2805 .targetLatency = LeAudioAseConfiguration::TargetLatency::
2806 BALANCED_LATENCY_RELIABILITY,
2807 .codecId = CodecId::Core::LC3,
2808 .codecConfiguration =
2809 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
2810 CodecSpecificConfigurationLtv::FrameDuration::US10000,
2811 allocation},
2812 },
2813 };
2814
2815 if (!valid) {
2816 // clear some required values;
2817 directionalRequirement.maxTransportLatencyMs = 0;
2818 directionalRequirement.presentationDelayMaxUs = 0;
2819 }
2820
2821 qosRequirement.sinkAseQosRequirement = directionalRequirement;
2822 if (is_source_requriement && is_sink_requirement) {
2823 qosRequirement.sourceAseQosRequirement = directionalRequirement;
2824 qosRequirement.sinkAseQosRequirement = directionalRequirement;
2825 } else if (is_source_requriement) {
2826 qosRequirement.sourceAseQosRequirement = directionalRequirement;
2827 qosRequirement.sinkAseQosRequirement = std::nullopt;
2828 } else if (is_sink_requirement) {
2829 qosRequirement.sourceAseQosRequirement = std::nullopt;
2830 qosRequirement.sinkAseQosRequirement = directionalRequirement;
2831 }
2832
2833 return qosRequirement;
2834 }
2835
Josh Wu049e2cd2022-01-12 05:42:58 -08002836 std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
2837 bool supported) {
2838 std::vector<Lc3Configuration> le_audio_codec_configs;
2839 if (!supported) {
shihchienc3ab9f5e2022-09-23 08:18:05 +00002840 Lc3Configuration lc3_config{.pcmBitDepth = 0, .samplingFrequencyHz = 0};
Josh Wu049e2cd2022-01-12 05:42:58 -08002841 le_audio_codec_configs.push_back(lc3_config);
2842 return le_audio_codec_configs;
2843 }
2844
2845 // There might be more than one LeAudioCodecCapabilitiesSetting
2846 std::vector<Lc3Capabilities> lc3_capabilities;
2847 for (auto& capability : temp_provider_capabilities_) {
2848 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
2849 continue;
2850 }
2851 auto& le_audio_capability =
2852 capability.get<AudioCapabilities::leAudioCapabilities>();
2853 auto& unicast_capability =
2854 decoding ? le_audio_capability.unicastDecodeCapability
2855 : le_audio_capability.unicastEncodeCapability;
2856 if (unicast_capability.codecType != CodecType::LC3) {
2857 continue;
2858 }
2859 auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
2860 UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
2861 lc3_capabilities.push_back(lc3_capability);
2862 }
2863
2864 // Combine those parameters into one list of LeAudioCodecConfiguration
2865 // This seems horrible, but usually each Lc3Capability only contains a
2866 // single Lc3Configuration, which means every array has a length of 1.
2867 for (auto& lc3_capability : lc3_capabilities) {
2868 for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
2869 for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
2870 for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
2871 Lc3Configuration lc3_config = {
2872 .samplingFrequencyHz = samplingFrequencyHz,
2873 .frameDurationUs = frameDurationUs,
2874 .octetsPerFrame = octetsPerFrame,
2875 };
2876 le_audio_codec_configs.push_back(lc3_config);
2877 }
2878 }
2879 }
2880 }
2881
2882 return le_audio_codec_configs;
2883 }
2884
Sagar Verma62df9102022-12-07 17:56:04 +05302885 static constexpr int32_t apx_adaptive_le_config_codec_modes[] = {0, 1, 2, 3};
2886
2887 std::vector<AptxAdaptiveLeConfiguration>
2888 GetUnicastAptxAdaptiveLeSupportedList(bool decoding, bool supported,
2889 bool is_le_extended) {
2890 std::vector<AptxAdaptiveLeConfiguration> le_audio_codec_configs;
2891 if (!supported) {
2892 AptxAdaptiveLeConfiguration aptx_adaptive_le_config{
2893 .pcmBitDepth = 0, .samplingFrequencyHz = 0};
2894 le_audio_codec_configs.push_back(aptx_adaptive_le_config);
2895 return le_audio_codec_configs;
2896 }
2897
2898 // There might be more than one LeAudioCodecCapabilitiesSetting
2899 std::vector<AptxAdaptiveLeCapabilities> aptx_adaptive_le_capabilities;
2900 for (auto& capability : temp_provider_capabilities_) {
2901 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
2902 continue;
2903 }
2904 auto& le_audio_capability =
2905 capability.get<AudioCapabilities::leAudioCapabilities>();
2906 auto& unicast_capability =
2907 decoding ? le_audio_capability.unicastDecodeCapability
2908 : le_audio_capability.unicastEncodeCapability;
2909 if ((!is_le_extended &&
2910 unicast_capability.codecType != CodecType::APTX_ADAPTIVE_LE) ||
2911 (is_le_extended &&
2912 unicast_capability.codecType != CodecType::APTX_ADAPTIVE_LEX)) {
2913 continue;
2914 }
2915
2916 auto& aptx_adaptive_le_capability =
2917 unicast_capability.leAudioCodecCapabilities
2918 .get<UnicastCapability::LeAudioCodecCapabilities::
2919 aptxAdaptiveLeCapabilities>();
2920
2921 aptx_adaptive_le_capabilities.push_back(aptx_adaptive_le_capability);
2922 }
2923
2924 for (auto& aptx_adaptive_le_capability : aptx_adaptive_le_capabilities) {
2925 for (int32_t samplingFrequencyHz :
2926 aptx_adaptive_le_capability.samplingFrequencyHz) {
2927 for (int32_t frameDurationUs :
2928 aptx_adaptive_le_capability.frameDurationUs) {
2929 for (int32_t octetsPerFrame :
2930 aptx_adaptive_le_capability.octetsPerFrame) {
2931 for (int8_t blocksPerSdu :
2932 aptx_adaptive_le_capability.blocksPerSdu) {
2933 for (int32_t codecMode : apx_adaptive_le_config_codec_modes) {
2934 AptxAdaptiveLeConfiguration aptx_adaptive_le_config = {
2935 .samplingFrequencyHz = samplingFrequencyHz,
2936 .frameDurationUs = frameDurationUs,
2937 .octetsPerFrame = octetsPerFrame,
2938 .blocksPerSdu = blocksPerSdu,
2939 .codecMode = codecMode,
2940 };
2941 le_audio_codec_configs.push_back(aptx_adaptive_le_config);
2942 }
2943 }
2944 }
2945 }
2946 }
2947 }
2948
2949 return le_audio_codec_configs;
2950 }
2951
Josh Wu049e2cd2022-01-12 05:42:58 -08002952 LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
Bao Doc36897d2023-12-06 01:27:54 +00002953 std::vector<int32_t> all_context_bitmasks = {
2954 AudioContext::UNSPECIFIED, AudioContext::CONVERSATIONAL,
2955 AudioContext::MEDIA, AudioContext::GAME,
2956 AudioContext::INSTRUCTIONAL, AudioContext::VOICE_ASSISTANTS,
2957 AudioContext::LIVE_AUDIO, AudioContext::SOUND_EFFECTS,
2958 AudioContext::NOTIFICATIONS, AudioContext::RINGTONE_ALERTS,
2959 AudioContext::ALERTS, AudioContext::EMERGENCY_ALARM,
2960 };
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00002961
2962 AudioContext bidirectional_contexts = {
2963 .bitmask = AudioContext::CONVERSATIONAL | AudioContext::GAME |
2964 AudioContext::VOICE_ASSISTANTS | AudioContext::LIVE_AUDIO,
2965 };
Josh Wu049e2cd2022-01-12 05:42:58 -08002966};
2967
2968/**
2969 * Test whether each provider of type
2970 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
2971 * stopped
2972 */
2973TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
2974 OpenLeAudioOutputHardwareProvider) {}
2975
2976/**
2977 * Test whether each provider of type
2978 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
Bao Doc36897d2023-12-06 01:27:54 +00002979 * stopped with Unicast hardware encoding config taken from provider info
2980 */
2981TEST_P(
2982 BluetoothAudioProviderLeAudioOutputHardwareAidl,
2983 StartAndEndLeAudioOutputSessionWithPossibleUnicastConfigFromProviderInfo) {
Bao Dob487a852023-12-25 10:12:09 +08002984 if (GetProviderFactoryInterfaceVersion() <
2985 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
2986 GTEST_SKIP();
2987 }
Bao Doc36897d2023-12-06 01:27:54 +00002988 if (!IsOffloadOutputProviderInfoSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00002989 GTEST_SKIP();
Bao Doc36897d2023-12-06 01:27:54 +00002990 }
2991
2992 auto lc3_codec_configs = GetUnicastLc3SupportedListFromProviderInfo();
2993 LeAudioConfiguration le_audio_config = {
2994 .codecType = CodecType::LC3,
2995 .peerDelayUs = 0,
2996 };
2997
2998 for (auto& lc3_config : lc3_codec_configs) {
2999 le_audio_config.leAudioCodecConfig
3000 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3001 DataMQDesc mq_desc;
3002 auto aidl_retval = audio_provider_->startSession(
3003 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3004 &mq_desc);
3005
3006 ASSERT_TRUE(aidl_retval.isOk());
3007 EXPECT_TRUE(audio_provider_->endSession().isOk());
3008 }
3009}
3010
3011TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3012 GetEmptyAseConfigurationEmptyCapability) {
Bao Dob487a852023-12-25 10:12:09 +08003013 if (GetProviderFactoryInterfaceVersion() <
3014 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3015 GTEST_SKIP();
3016 }
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003017
3018 if (IsMultidirectionalCapabilitiesEnabled()) {
3019 GTEST_SKIP();
3020 }
3021
3022 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
3023 std::vector<LeAudioConfigurationRequirement> empty_requirement;
3024 std::vector<LeAudioAseConfigurationSetting> configurations;
3025
3026 // Check empty capability for source direction
3027 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3028 std::nullopt, empty_capability, empty_requirement, &configurations);
3029
3030 ASSERT_FALSE(aidl_retval.isOk());
3031
3032 // Check empty capability for sink direction
3033 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3034 empty_capability, std::nullopt, empty_requirement, &configurations);
3035
3036 ASSERT_TRUE(aidl_retval.isOk());
3037 ASSERT_TRUE(configurations.empty());
3038}
3039
3040TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3041 GetEmptyAseConfigurationEmptyCapability_Multidirectiona) {
3042 if (GetProviderFactoryInterfaceVersion() <
3043 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3044 GTEST_SKIP();
3045 }
3046
3047 if (!IsMultidirectionalCapabilitiesEnabled()) {
3048 GTEST_SKIP();
3049 }
3050
Bao Doc36897d2023-12-06 01:27:54 +00003051 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
3052 std::vector<LeAudioConfigurationRequirement> empty_requirement;
3053 std::vector<LeAudioAseConfigurationSetting> configurations;
3054
3055 // Check empty capability for source direction
3056 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3057 std::nullopt, empty_capability, empty_requirement, &configurations);
3058
3059 ASSERT_TRUE(aidl_retval.isOk());
3060 ASSERT_TRUE(configurations.empty());
3061
3062 // Check empty capability for sink direction
3063 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3064 empty_capability, std::nullopt, empty_requirement, &configurations);
3065
3066 ASSERT_TRUE(aidl_retval.isOk());
3067 ASSERT_TRUE(configurations.empty());
3068}
3069
3070TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3071 GetEmptyAseConfigurationMismatchedRequirement) {
Bao Dob487a852023-12-25 10:12:09 +08003072 if (GetProviderFactoryInterfaceVersion() <
3073 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3074 GTEST_SKIP();
3075 }
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003076 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3077 GetDefaultRemoteSinkCapability()};
3078 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3079 GetDefaultRemoteSourceCapability()};
3080
3081 auto not_supported_sampling_rate_by_remote =
3082 CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025;
Bao Doc36897d2023-12-06 01:27:54 +00003083
3084 // Check empty capability for source direction
3085 std::vector<LeAudioAseConfigurationSetting> configurations;
3086 std::vector<LeAudioConfigurationRequirement> source_requirements = {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003087 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /*sink */,
3088 true /* source */,
3089 not_supported_sampling_rate_by_remote)};
Bao Doc36897d2023-12-06 01:27:54 +00003090 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003091 std::nullopt, source_capabilities, source_requirements, &configurations);
Bao Doc36897d2023-12-06 01:27:54 +00003092
3093 ASSERT_TRUE(aidl_retval.isOk());
3094 ASSERT_TRUE(configurations.empty());
3095
3096 // Check empty capability for sink direction
3097 std::vector<LeAudioConfigurationRequirement> sink_requirements = {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003098 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /*sink */,
3099 false /* source */,
3100 not_supported_sampling_rate_by_remote)};
Bao Doc36897d2023-12-06 01:27:54 +00003101 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003102 sink_capabilities, std::nullopt, sink_requirements, &configurations);
Bao Doc36897d2023-12-06 01:27:54 +00003103
3104 ASSERT_TRUE(aidl_retval.isOk());
3105 ASSERT_TRUE(configurations.empty());
3106}
3107
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003108TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl, GetAseConfiguration) {
3109 if (GetProviderFactoryInterfaceVersion() <
3110 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3111 GTEST_SKIP();
3112 }
3113
3114 if (IsMultidirectionalCapabilitiesEnabled()) {
3115 GTEST_SKIP();
3116 }
3117
3118 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3119 GetDefaultRemoteSinkCapability()};
3120 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3121 GetDefaultRemoteSourceCapability()};
3122
3123 // Should not ask for Source on ENCODING session if Multidiretional not
3124 // supported
3125 std::vector<LeAudioAseConfigurationSetting> configurations;
3126 std::vector<LeAudioConfigurationRequirement> source_requirements = {
3127 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3128 true /* source */)};
3129 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3130 std::nullopt, source_capabilities, source_requirements, &configurations);
3131
3132 ASSERT_FALSE(aidl_retval.isOk());
3133 ASSERT_TRUE(configurations.empty());
3134
3135 // Check capability for remote sink direction
3136 std::vector<LeAudioConfigurationRequirement> sink_requirements = {
3137 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3138 false /* source */)};
3139 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3140 sink_capabilities, std::nullopt, sink_requirements, &configurations);
3141
3142 ASSERT_TRUE(aidl_retval.isOk());
3143 ASSERT_FALSE(configurations.empty());
3144 VerifyIfRequirementsSatisfied(sink_requirements, configurations);
3145
3146 // Check multiple capability for remote sink direction
3147 std::vector<LeAudioConfigurationRequirement> multi_sink_requirements = {
3148 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3149 false /* source */),
3150 GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
3151 true /* sink */, false /* source */)};
3152 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3153 sink_capabilities, std::nullopt, multi_sink_requirements,
3154 &configurations);
3155
3156 ASSERT_TRUE(aidl_retval.isOk());
3157 ASSERT_FALSE(configurations.empty());
3158 VerifyIfRequirementsSatisfied(multi_sink_requirements, configurations);
3159
3160 // Check multiple context types in a single requirement.
3161 std::vector<LeAudioConfigurationRequirement> multi_context_sink_requirements =
3162 {GetUnicastDefaultRequirement(
3163 AudioContext::MEDIA | AudioContext::SOUND_EFFECTS, true /* sink */,
3164 false /* source */)};
3165 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3166 sink_capabilities, std::nullopt, multi_context_sink_requirements,
3167 &configurations);
3168
3169 ASSERT_TRUE(aidl_retval.isOk());
3170 ASSERT_FALSE(configurations.empty());
3171 VerifyIfRequirementsSatisfied(multi_sink_requirements, configurations);
3172}
3173
3174TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3175 GetAseConfiguration_Multidirectional) {
3176 if (GetProviderFactoryInterfaceVersion() <
3177 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3178 GTEST_SKIP();
3179 }
3180
3181 if (!IsMultidirectionalCapabilitiesEnabled()) {
3182 GTEST_SKIP();
3183 }
3184
3185 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3186 GetDefaultRemoteSinkCapability()};
3187 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3188 GetDefaultRemoteSourceCapability()};
3189
3190 // Verify source configuration is received
3191 std::vector<LeAudioAseConfigurationSetting> configurations;
3192 std::vector<LeAudioConfigurationRequirement> source_requirements = {
3193 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3194 true /* source */)};
3195 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3196 std::nullopt, source_capabilities, source_requirements, &configurations);
3197
3198 ASSERT_TRUE(aidl_retval.isOk());
3199 ASSERT_FALSE(configurations.empty());
3200 VerifyIfRequirementsSatisfied(source_requirements, configurations);
3201
3202 // Verify sink configuration is received
3203 std::vector<LeAudioConfigurationRequirement> sink_requirements = {
3204 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3205 false /* source */)};
3206 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3207 sink_capabilities, std::nullopt, sink_requirements, &configurations);
3208
3209 ASSERT_TRUE(aidl_retval.isOk());
3210 ASSERT_FALSE(configurations.empty());
3211 VerifyIfRequirementsSatisfied(sink_requirements, configurations);
3212
3213 std::vector<LeAudioConfigurationRequirement> combined_requirements = {
3214 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3215 true /* source */),
3216 GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
3217 true /* sink */, true /* source */),
3218 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3219 false /* source */)};
3220
3221 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3222 sink_capabilities, source_capabilities, combined_requirements,
3223 &configurations);
3224
3225 ASSERT_TRUE(aidl_retval.isOk());
3226 ASSERT_FALSE(configurations.empty());
3227 VerifyIfRequirementsSatisfied(combined_requirements, configurations);
3228}
3229
3230TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3231 GetAsymmetricAseConfiguration_Multidirectional) {
3232 if (GetProviderFactoryInterfaceVersion() <
3233 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3234 GTEST_SKIP();
3235 }
3236
3237 if (!IsMultidirectionalCapabilitiesEnabled()) {
3238 GTEST_SKIP();
3239 }
3240
3241 if (!IsAsymmetricConfigurationAllowed()) {
3242 GTEST_SKIP();
3243 }
3244
3245 std::vector<LeAudioAseConfigurationSetting> configurations;
3246 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3247 GetDefaultRemoteSinkCapability()};
3248 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3249 GetDefaultRemoteSourceCapability()};
3250
3251 std::vector<LeAudioConfigurationRequirement> asymmetric_requirements = {
3252 GetUnicastGameRequirement(true /* Asymmetric */)};
3253
3254 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3255 sink_capabilities, source_capabilities, asymmetric_requirements,
3256 &configurations);
3257
3258 ASSERT_TRUE(aidl_retval.isOk());
3259 ASSERT_FALSE(configurations.empty());
3260 VerifyIfRequirementsSatisfied(asymmetric_requirements, configurations);
3261}
3262
3263TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3264 GetQoSConfiguration_Multidirectional) {
3265 if (GetProviderFactoryInterfaceVersion() <
3266 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3267 GTEST_SKIP();
3268 }
3269
3270 if (!IsMultidirectionalCapabilitiesEnabled()) {
3271 GTEST_SKIP();
3272 }
3273
3274 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3275 allocation.bitmask =
3276 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3277 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3278
3279 LeAudioAseQosConfigurationRequirement requirement =
3280 GetQosRequirements(true, true);
3281
3282 std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
3283 QoSConfigurations;
3284 bool is_supported = false;
3285 for (auto bitmask : all_context_bitmasks) {
3286 requirement.audioContext = GetAudioContext(bitmask);
3287 bool is_bidirectional = bidirectional_contexts.bitmask & bitmask;
3288
3289 if (is_bidirectional) {
3290 requirement.sourceAseQosRequirement = requirement.sinkAseQosRequirement;
3291 } else {
3292 requirement.sourceAseQosRequirement = std::nullopt;
3293 }
3294
3295 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
3296 auto aidl_retval =
3297 audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
3298 if (!aidl_retval.isOk()) {
3299 // If not OK, then it could be not supported, as it is an optional
3300 // feature
3301 ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
3302 }
3303
3304 is_supported = true;
3305 if (result.sinkQosConfiguration.has_value()) {
3306 if (is_bidirectional) {
3307 ASSERT_TRUE(result.sourceQosConfiguration.has_value());
3308 } else {
3309 ASSERT_FALSE(result.sourceQosConfiguration.has_value());
3310 }
3311 QoSConfigurations.push_back(result.sinkQosConfiguration.value());
3312 }
3313 }
3314 if (is_supported) {
3315 // QoS Configurations should not be empty, as we searched for all contexts
3316 ASSERT_FALSE(QoSConfigurations.empty());
3317 }
3318}
3319
3320TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3321 GetQoSConfiguration_InvalidRequirements) {
3322 if (GetProviderFactoryInterfaceVersion() <
3323 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3324 GTEST_SKIP();
3325 }
3326 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3327 allocation.bitmask =
3328 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3329 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3330
3331 LeAudioAseQosConfigurationRequirement invalid_requirement =
3332 GetQosRequirements(true /* sink */, false /* source */,
3333 false /* valid */);
3334
3335 std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
3336 QoSConfigurations;
3337 for (auto bitmask : all_context_bitmasks) {
3338 invalid_requirement.audioContext = GetAudioContext(bitmask);
3339 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
3340 auto aidl_retval = audio_provider_->getLeAudioAseQosConfiguration(
3341 invalid_requirement, &result);
3342 ASSERT_FALSE(aidl_retval.isOk());
3343 }
3344}
3345
Bao Doc36897d2023-12-06 01:27:54 +00003346TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl, GetQoSConfiguration) {
Bao Dob487a852023-12-25 10:12:09 +08003347 if (GetProviderFactoryInterfaceVersion() <
3348 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3349 GTEST_SKIP();
3350 }
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003351 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3352 allocation.bitmask =
3353 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3354 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3355
Bao Doc36897d2023-12-06 01:27:54 +00003356 IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement requirement;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003357 requirement = GetQosRequirements(true /* sink */, false /* source */);
3358
Bao Doc36897d2023-12-06 01:27:54 +00003359 std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
3360 QoSConfigurations;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003361 bool is_supported = false;
Bao Doc36897d2023-12-06 01:27:54 +00003362 for (auto bitmask : all_context_bitmasks) {
Jakub Tyszkowski1d214222024-01-16 09:44:48 +00003363 requirement.audioContext = GetAudioContext(bitmask);
Bao Doc36897d2023-12-06 01:27:54 +00003364 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
3365 auto aidl_retval =
3366 audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003367 if (!aidl_retval.isOk()) {
3368 // If not OK, then it could be not supported, as it is an optional
3369 // feature
3370 ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
3371 } else {
3372 is_supported = true;
3373 if (result.sinkQosConfiguration.has_value()) {
3374 QoSConfigurations.push_back(result.sinkQosConfiguration.value());
3375 }
3376 }
Bao Doc36897d2023-12-06 01:27:54 +00003377 }
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003378
3379 if (is_supported) {
3380 // QoS Configurations should not be empty, as we searched for all contexts
3381 ASSERT_FALSE(QoSConfigurations.empty());
3382 }
3383}
3384
3385TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3386 GetDataPathConfiguration_Multidirectional) {
3387 IBluetoothAudioProvider::StreamConfig sink_requirement;
3388 IBluetoothAudioProvider::StreamConfig source_requirement;
3389 std::vector<IBluetoothAudioProvider::LeAudioDataPathConfiguration>
3390 DataPathConfigurations;
3391
3392 if (!IsMultidirectionalCapabilitiesEnabled()) {
3393 GTEST_SKIP();
3394 }
3395
3396 bool is_supported = false;
3397 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3398 allocation.bitmask =
3399 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3400 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3401
3402 auto streamMap = LeAudioConfiguration::StreamMap();
3403
3404 // Use some mandatory configuration
3405 streamMap.streamHandle = 0x0001;
3406 streamMap.audioChannelAllocation = 0x03;
3407 streamMap.aseConfiguration = {
3408 .targetLatency =
3409 LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY,
3410 .codecId = CodecId::Core::LC3,
3411 .codecConfiguration =
3412 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
3413 CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation},
3414 };
3415
3416 // Bidirectional
3417 sink_requirement.streamMap = {streamMap};
3418 source_requirement.streamMap = {streamMap};
3419
3420 for (auto bitmask : all_context_bitmasks) {
3421 sink_requirement.audioContext = GetAudioContext(bitmask);
3422 source_requirement.audioContext = sink_requirement.audioContext;
3423
3424 IBluetoothAudioProvider::LeAudioDataPathConfigurationPair result;
3425 ::ndk::ScopedAStatus aidl_retval;
3426
3427 bool is_bidirectional = bidirectional_contexts.bitmask & bitmask;
3428 if (is_bidirectional) {
3429 aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
3430 sink_requirement, source_requirement, &result);
3431 } else {
3432 aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
3433 sink_requirement, std::nullopt, &result);
3434 }
3435
3436 if (!aidl_retval.isOk()) {
3437 // If not OK, then it could be not supported, as it is an optional
3438 // feature
3439 ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
3440 } else {
3441 is_supported = true;
3442 if (result.outputConfig.has_value()) {
3443 if (is_bidirectional) {
3444 ASSERT_TRUE(result.inputConfig.has_value());
3445 } else {
3446 ASSERT_TRUE(!result.inputConfig.has_value());
3447 }
3448 DataPathConfigurations.push_back(result.outputConfig.value());
3449 }
3450 }
3451 }
3452
3453 if (is_supported) {
3454 // Datapath Configurations should not be empty, as we searched for all
3455 // contexts
3456 ASSERT_FALSE(DataPathConfigurations.empty());
3457 }
Bao Doc36897d2023-12-06 01:27:54 +00003458}
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003459
3460TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3461 GetDataPathConfiguration) {
Jakub Tyszkowskie77f8722024-01-29 13:21:21 +00003462 if (GetProviderFactoryInterfaceVersion() <
3463 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3464 GTEST_SKIP();
3465 }
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003466 IBluetoothAudioProvider::StreamConfig sink_requirement;
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003467 std::vector<IBluetoothAudioProvider::LeAudioDataPathConfiguration>
3468 DataPathConfigurations;
3469 bool is_supported = false;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003470 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3471 allocation.bitmask =
3472 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3473 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3474
3475 auto streamMap = LeAudioConfiguration::StreamMap();
3476
3477 // Use some mandatory configuration
3478 streamMap.streamHandle = 0x0001;
3479 streamMap.audioChannelAllocation = 0x03;
3480 streamMap.aseConfiguration = {
3481 .targetLatency =
3482 LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY,
3483 .codecId = CodecId::Core::LC3,
3484 .codecConfiguration =
3485 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
3486 CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation},
3487 };
3488
3489 sink_requirement.streamMap = {streamMap};
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003490
3491 for (auto bitmask : all_context_bitmasks) {
Jakub Tyszkowski1d214222024-01-16 09:44:48 +00003492 sink_requirement.audioContext = GetAudioContext(bitmask);
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003493 IBluetoothAudioProvider::LeAudioDataPathConfigurationPair result;
3494 auto aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003495 sink_requirement, std::nullopt, &result);
3496
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003497 if (!aidl_retval.isOk()) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003498 // If not OK, then it could be not supported, as it is an optional
3499 // feature
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003500 ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
3501 } else {
3502 is_supported = true;
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003503 if (result.outputConfig.has_value()) {
3504 DataPathConfigurations.push_back(result.outputConfig.value());
3505 }
Jakub Tyszkowskic8a62242024-01-05 15:25:49 +00003506 }
3507 }
3508
3509 if (is_supported) {
3510 // Datapath Configurations should not be empty, as we searched for all
3511 // contexts
3512 ASSERT_FALSE(DataPathConfigurations.empty());
3513 }
3514}
3515
Bao Doc36897d2023-12-06 01:27:54 +00003516/**
3517 * Test whether each provider of type
3518 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08003519 * stopped with Unicast hardware encoding config
3520 */
3521TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3522 StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
3523 if (!IsOffloadOutputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003524 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08003525 }
3526
3527 auto lc3_codec_configs =
3528 GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
3529 LeAudioConfiguration le_audio_config = {
3530 .codecType = CodecType::LC3,
3531 .peerDelayUs = 0,
3532 };
3533
3534 for (auto& lc3_config : lc3_codec_configs) {
3535 le_audio_config.leAudioCodecConfig
3536 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3537 DataMQDesc mq_desc;
3538 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08003539 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3540 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08003541
3542 ASSERT_TRUE(aidl_retval.isOk());
3543 EXPECT_TRUE(audio_provider_->endSession().isOk());
3544 }
3545}
3546
3547/**
3548 * Test whether each provider of type
3549 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
3550 * stopped with Unicast hardware encoding config
3551 *
Josh Wu049e2cd2022-01-12 05:42:58 -08003552 */
3553TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003554 StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
Josh Wu049e2cd2022-01-12 05:42:58 -08003555 if (!IsOffloadOutputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003556 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08003557 }
3558
3559 auto lc3_codec_configs =
3560 GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
3561 LeAudioConfiguration le_audio_config = {
3562 .codecType = CodecType::LC3,
3563 .peerDelayUs = 0,
3564 };
3565
3566 for (auto& lc3_config : lc3_codec_configs) {
3567 le_audio_config.leAudioCodecConfig
3568 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3569 DataMQDesc mq_desc;
3570 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08003571 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3572 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08003573
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003574 // It is OK to start session with invalid configuration
3575 ASSERT_TRUE(aidl_retval.isOk());
Josh Wu049e2cd2022-01-12 05:42:58 -08003576 EXPECT_TRUE(audio_provider_->endSession().isOk());
3577 }
3578}
3579
Sagar Verma62df9102022-12-07 17:56:04 +05303580static std::vector<uint8_t> vendorMetadata = {0x0B, // Length
3581 0xFF, // Type: Vendor-specific
3582 0x0A, 0x00, // Company_ID
3583 0x01, 0x02, 0x03, 0x04, // Data
3584 0x05, 0x06, 0x07, 0x08};
3585
3586/**
3587 * Test whether each provider of type
3588 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
3589 * stopped with Unicast hardware encoding config
3590 */
3591TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
3592 StartAndEndLeAudioOutputSessionWithAptxAdaptiveLeUnicastConfig) {
3593 if (!IsOffloadOutputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003594 GTEST_SKIP();
Sagar Verma62df9102022-12-07 17:56:04 +05303595 }
3596 for (auto codec_type :
3597 {CodecType::APTX_ADAPTIVE_LE, CodecType::APTX_ADAPTIVE_LEX}) {
3598 bool is_le_extended = (codec_type == CodecType::APTX_ADAPTIVE_LEX);
3599 auto aptx_adaptive_le_codec_configs =
3600 GetUnicastAptxAdaptiveLeSupportedList(false, true, is_le_extended);
3601 LeAudioConfiguration le_audio_config = {
3602 .codecType = codec_type,
3603 .peerDelayUs = 0,
3604 .vendorSpecificMetadata = vendorMetadata,
3605 };
3606
3607 for (auto& aptx_adaptive_le_config : aptx_adaptive_le_codec_configs) {
3608 le_audio_config.leAudioCodecConfig
3609 .set<LeAudioCodecConfiguration::aptxAdaptiveLeConfig>(
3610 aptx_adaptive_le_config);
3611 DataMQDesc mq_desc;
3612 auto aidl_retval = audio_provider_->startSession(
3613 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3614 &mq_desc);
3615
3616 ASSERT_TRUE(aidl_retval.isOk());
3617 EXPECT_TRUE(audio_provider_->endSession().isOk());
3618 }
3619 }
3620}
3621
3622/**
3623 * Test whether each provider of type
3624 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
3625 * stopped with Unicast hardware encoding config
3626 */
3627TEST_P(
3628 BluetoothAudioProviderLeAudioOutputHardwareAidl,
3629 BluetoothAudioProviderLeAudioOutputHardwareAidl_StartAndEndLeAudioOutputSessionWithInvalidAptxAdaptiveLeAudioConfiguration) {
3630 if (!IsOffloadOutputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003631 GTEST_SKIP();
Sagar Verma62df9102022-12-07 17:56:04 +05303632 }
3633
3634 for (auto codec_type :
3635 {CodecType::APTX_ADAPTIVE_LE, CodecType::APTX_ADAPTIVE_LEX}) {
3636 bool is_le_extended = (codec_type == CodecType::APTX_ADAPTIVE_LEX);
3637 auto aptx_adaptive_le_codec_configs =
3638 GetUnicastAptxAdaptiveLeSupportedList(false, true, is_le_extended);
3639 LeAudioConfiguration le_audio_config = {
3640 .codecType = codec_type,
3641 .peerDelayUs = 0,
3642 .vendorSpecificMetadata = vendorMetadata,
3643 };
3644
3645 for (auto& aptx_adaptive_le_config : aptx_adaptive_le_codec_configs) {
3646 le_audio_config.leAudioCodecConfig
3647 .set<LeAudioCodecConfiguration::aptxAdaptiveLeConfig>(
3648 aptx_adaptive_le_config);
3649 DataMQDesc mq_desc;
3650 auto aidl_retval = audio_provider_->startSession(
3651 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3652 &mq_desc);
3653
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003654 // It is OK to start session with invalid configuration
3655 ASSERT_TRUE(aidl_retval.isOk());
Sagar Verma62df9102022-12-07 17:56:04 +05303656 EXPECT_TRUE(audio_provider_->endSession().isOk());
3657 }
3658 }
3659}
3660
Josh Wu049e2cd2022-01-12 05:42:58 -08003661/**
3662 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
3663 */
3664class BluetoothAudioProviderLeAudioInputHardwareAidl
3665 : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
3666 public:
3667 virtual void SetUp() override {
3668 BluetoothAudioProviderFactoryAidl::SetUp();
3669 GetProviderCapabilitiesHelper(
3670 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Bao Doc36897d2023-12-06 01:27:54 +00003671 GetProviderInfoHelper(
3672 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
Josh Wu049e2cd2022-01-12 05:42:58 -08003673 OpenProviderHelper(
3674 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
3675 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
3676 audio_provider_ != nullptr);
3677 }
3678
3679 bool IsOffloadInputSupported() {
3680 for (auto& capability : temp_provider_capabilities_) {
3681 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
3682 continue;
3683 }
3684 auto& le_audio_capability =
3685 capability.get<AudioCapabilities::leAudioCapabilities>();
3686 if (le_audio_capability.unicastDecodeCapability.codecType !=
3687 CodecType::UNKNOWN)
3688 return true;
3689 }
3690 return false;
3691 }
3692
3693 virtual void TearDown() override {
3694 audio_port_ = nullptr;
3695 audio_provider_ = nullptr;
3696 BluetoothAudioProviderFactoryAidl::TearDown();
3697 }
3698};
3699
3700/**
3701 * Test whether each provider of type
Bao Doc36897d2023-12-06 01:27:54 +00003702 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08003703 * stopped
3704 */
3705TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3706 OpenLeAudioInputHardwareProvider) {}
3707
3708/**
3709 * Test whether each provider of type
Bao Doc36897d2023-12-06 01:27:54 +00003710 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
3711 * stopped with Unicast hardware encoding config taken from provider info
3712 */
3713TEST_P(
3714 BluetoothAudioProviderLeAudioInputHardwareAidl,
3715 StartAndEndLeAudioInputSessionWithPossibleUnicastConfigFromProviderInfo) {
3716 if (!IsOffloadOutputProviderInfoSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003717 GTEST_SKIP();
Bao Doc36897d2023-12-06 01:27:54 +00003718 }
3719
3720 auto lc3_codec_configs = GetUnicastLc3SupportedListFromProviderInfo();
3721 LeAudioConfiguration le_audio_config = {
3722 .codecType = CodecType::LC3,
3723 .peerDelayUs = 0,
3724 };
3725
3726 for (auto& lc3_config : lc3_codec_configs) {
3727 le_audio_config.leAudioCodecConfig
3728 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3729 DataMQDesc mq_desc;
3730 auto aidl_retval = audio_provider_->startSession(
3731 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3732 &mq_desc);
3733
3734 ASSERT_TRUE(aidl_retval.isOk());
3735 EXPECT_TRUE(audio_provider_->endSession().isOk());
3736 }
3737}
3738
3739/**
3740 * Test whether each provider of type
3741 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08003742 * stopped with Unicast hardware encoding config
3743 */
3744TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3745 StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
3746 if (!IsOffloadInputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003747 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08003748 }
3749
3750 auto lc3_codec_configs =
3751 GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
3752 LeAudioConfiguration le_audio_config = {
3753 .codecType = CodecType::LC3,
3754 .peerDelayUs = 0,
3755 };
3756
3757 for (auto& lc3_config : lc3_codec_configs) {
3758 le_audio_config.leAudioCodecConfig
3759 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3760 DataMQDesc mq_desc;
3761 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08003762 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3763 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08003764
3765 ASSERT_TRUE(aidl_retval.isOk());
3766 EXPECT_TRUE(audio_provider_->endSession().isOk());
3767 }
3768}
3769
3770/**
3771 * Test whether each provider of type
Bao Doc36897d2023-12-06 01:27:54 +00003772 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
Josh Wu049e2cd2022-01-12 05:42:58 -08003773 * stopped with Unicast hardware encoding config
3774 *
Josh Wu049e2cd2022-01-12 05:42:58 -08003775 */
3776TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003777 StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
Josh Wu049e2cd2022-01-12 05:42:58 -08003778 if (!IsOffloadInputSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00003779 GTEST_SKIP();
Josh Wu049e2cd2022-01-12 05:42:58 -08003780 }
3781
3782 auto lc3_codec_configs =
3783 GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
3784 LeAudioConfiguration le_audio_config = {
3785 .codecType = CodecType::LC3,
3786 .peerDelayUs = 0,
3787 };
3788
3789 for (auto& lc3_config : lc3_codec_configs) {
3790 le_audio_config.leAudioCodecConfig
3791 .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
3792
3793 DataMQDesc mq_desc;
3794 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08003795 audio_port_, AudioConfiguration(le_audio_config), latency_modes,
3796 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08003797
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003798 // It is OK to start with invalid configuration as it might be unknown on
3799 // start
3800 ASSERT_TRUE(aidl_retval.isOk());
Josh Wu049e2cd2022-01-12 05:42:58 -08003801 EXPECT_TRUE(audio_provider_->endSession().isOk());
3802 }
3803}
3804
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00003805TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3806 GetEmptyAseConfigurationEmptyCapability) {
3807 if (GetProviderFactoryInterfaceVersion() <
3808 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3809 GTEST_SKIP();
3810 }
3811
3812 if (IsMultidirectionalCapabilitiesEnabled()) {
3813 GTEST_SKIP();
3814 }
3815
3816 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
3817 std::vector<LeAudioConfigurationRequirement> empty_requirement;
3818 std::vector<LeAudioAseConfigurationSetting> configurations;
3819
3820 // Check success for source direction (Input == DecodingSession == remote
3821 // source)
3822 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3823 std::nullopt, empty_capability, empty_requirement, &configurations);
3824
3825 ASSERT_TRUE(aidl_retval.isOk());
3826 ASSERT_TRUE(configurations.empty());
3827
3828 // Check failure for sink direction
3829 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3830 empty_capability, std::nullopt, empty_requirement, &configurations);
3831
3832 ASSERT_FALSE(aidl_retval.isOk());
3833}
3834
3835TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3836 GetEmptyAseConfigurationEmptyCapability_Multidirectional) {
3837 if (GetProviderFactoryInterfaceVersion() <
3838 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3839 GTEST_SKIP();
3840 }
3841
3842 if (!IsMultidirectionalCapabilitiesEnabled()) {
3843 GTEST_SKIP();
3844 }
3845
3846 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
3847 std::vector<LeAudioConfigurationRequirement> empty_requirement;
3848 std::vector<LeAudioAseConfigurationSetting> configurations;
3849
3850 // Check empty capability for source direction
3851 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3852 std::nullopt, empty_capability, empty_requirement, &configurations);
3853
3854 ASSERT_TRUE(aidl_retval.isOk());
3855 ASSERT_TRUE(configurations.empty());
3856
3857 // Check empty capability for sink direction
3858 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3859 empty_capability, std::nullopt, empty_requirement, &configurations);
3860
3861 ASSERT_TRUE(aidl_retval.isOk());
3862 ASSERT_TRUE(configurations.empty());
3863}
3864
3865TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl, GetAseConfiguration) {
3866 if (GetProviderFactoryInterfaceVersion() <
3867 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3868 GTEST_SKIP();
3869 }
3870
3871 if (IsMultidirectionalCapabilitiesEnabled()) {
3872 GTEST_SKIP();
3873 }
3874
3875 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3876 GetDefaultRemoteSinkCapability()};
3877 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3878 GetDefaultRemoteSourceCapability()};
3879
3880 // Check source configuration is received
3881 std::vector<LeAudioAseConfigurationSetting> configurations;
3882 std::vector<LeAudioConfigurationRequirement> source_requirements = {
3883 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3884 true /* source */)};
3885 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3886 std::nullopt, source_capabilities, source_requirements, &configurations);
3887
3888 ASSERT_TRUE(aidl_retval.isOk());
3889 ASSERT_FALSE(configurations.empty());
3890
3891 // Check error result when requesting sink on DECODING session
3892 std::vector<LeAudioConfigurationRequirement> sink_requirements = {
3893 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3894 false /* source */)};
3895 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3896 sink_capabilities, std::nullopt, sink_requirements, &configurations);
3897
3898 ASSERT_FALSE(aidl_retval.isOk());
3899}
3900
3901TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3902 GetAseConfiguration_Multidirectional) {
3903 if (GetProviderFactoryInterfaceVersion() <
3904 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3905 GTEST_SKIP();
3906 }
3907
3908 if (!IsMultidirectionalCapabilitiesEnabled()) {
3909 GTEST_SKIP();
3910 }
3911
3912 std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
3913 GetDefaultRemoteSinkCapability()};
3914 std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
3915 GetDefaultRemoteSourceCapability()};
3916
3917 // Check source configuration is received
3918 std::vector<LeAudioAseConfigurationSetting> configurations;
3919 std::vector<LeAudioConfigurationRequirement> source_requirements = {
3920 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3921 true /* source */)};
3922 auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3923 std::nullopt, source_capabilities, source_requirements, &configurations);
3924
3925 ASSERT_TRUE(aidl_retval.isOk());
3926 ASSERT_FALSE(configurations.empty());
3927 VerifyIfRequirementsSatisfied(source_requirements, configurations);
3928
3929 // Check empty capability for sink direction
3930 std::vector<LeAudioConfigurationRequirement> sink_requirements = {
3931 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3932 false /* source */)};
3933 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3934 sink_capabilities, std::nullopt, sink_requirements, &configurations);
3935
3936 ASSERT_TRUE(aidl_retval.isOk());
3937 ASSERT_FALSE(configurations.empty());
3938 VerifyIfRequirementsSatisfied(sink_requirements, configurations);
3939
3940 std::vector<LeAudioConfigurationRequirement> combined_requirements = {
3941 GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
3942 true /* source */),
3943 GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
3944 true /* sink */, true /* source */),
3945 GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
3946 false /* source */)};
3947
3948 aidl_retval = audio_provider_->getLeAudioAseConfiguration(
3949 sink_capabilities, source_capabilities, combined_requirements,
3950 &configurations);
3951
3952 ASSERT_TRUE(aidl_retval.isOk());
3953 ASSERT_FALSE(configurations.empty());
3954 VerifyIfRequirementsSatisfied(combined_requirements, configurations);
3955}
3956
3957TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
3958 GetQoSConfiguration_InvalidRequirements) {
3959 if (GetProviderFactoryInterfaceVersion() <
3960 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3961 GTEST_SKIP();
3962 }
3963 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3964 allocation.bitmask =
3965 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3966 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3967
3968 LeAudioAseQosConfigurationRequirement invalid_requirement =
3969 GetQosRequirements(false /* sink */, true /* source */,
3970 false /* valid */);
3971
3972 std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
3973 QoSConfigurations;
3974 for (auto bitmask : all_context_bitmasks) {
3975 invalid_requirement.audioContext = GetAudioContext(bitmask);
3976 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
3977 auto aidl_retval = audio_provider_->getLeAudioAseQosConfiguration(
3978 invalid_requirement, &result);
3979 ASSERT_FALSE(aidl_retval.isOk());
3980 }
3981}
3982
3983TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl, GetQoSConfiguration) {
3984 if (GetProviderFactoryInterfaceVersion() <
3985 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
3986 GTEST_SKIP();
3987 }
3988 auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
3989 allocation.bitmask =
3990 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
3991 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
3992
3993 IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement requirement;
3994 requirement = GetQosRequirements(false /* sink */, true /* source */);
3995
3996 std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
3997 QoSConfigurations;
3998 bool is_supported = false;
3999 for (auto bitmask : all_context_bitmasks) {
4000 requirement.audioContext = GetAudioContext(bitmask);
4001 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
4002 auto aidl_retval =
4003 audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
4004 if (!aidl_retval.isOk()) {
4005 // If not OK, then it could be not supported, as it is an optional
4006 // feature
4007 ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
4008 } else {
4009 is_supported = true;
4010 if (result.sourceQosConfiguration.has_value()) {
4011 QoSConfigurations.push_back(result.sourceQosConfiguration.value());
4012 }
4013 }
4014 }
4015
4016 if (is_supported) {
4017 // QoS Configurations should not be empty, as we searched for all contexts
4018 ASSERT_FALSE(QoSConfigurations.empty());
4019 }
4020}
Josh Wu049e2cd2022-01-12 05:42:58 -08004021/**
4022 * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
4023 */
4024class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
4025 : public BluetoothAudioProviderFactoryAidl {
4026 public:
4027 virtual void SetUp() override {
4028 BluetoothAudioProviderFactoryAidl::SetUp();
4029 GetProviderCapabilitiesHelper(
4030 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
4031 OpenProviderHelper(
4032 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
4033 ASSERT_NE(audio_provider_, nullptr);
4034 }
4035
4036 virtual void TearDown() override {
4037 audio_port_ = nullptr;
4038 audio_provider_ = nullptr;
4039 BluetoothAudioProviderFactoryAidl::TearDown();
4040 }
4041
4042 static constexpr int32_t le_audio_output_sample_rates_[] = {
4043 0, 8000, 16000, 24000, 32000, 44100, 48000,
4044 };
4045 static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
4046 static constexpr ChannelMode le_audio_output_channel_modes_[] = {
4047 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
4048 static constexpr int32_t le_audio_output_data_interval_us_[] = {
4049 0 /* Invalid */, 10000 /* Valid 10ms */};
4050};
4051
4052/**
4053 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004054 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started
4055 * and stopped
Josh Wu049e2cd2022-01-12 05:42:58 -08004056 */
4057TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
Josh Wu3202eab2022-02-17 18:09:05 -08004058 OpenLeAudioOutputSoftwareProvider) {}
Josh Wu049e2cd2022-01-12 05:42:58 -08004059
4060/**
4061 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004062 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started
4063 * and stopped with different PCM config
Josh Wu049e2cd2022-01-12 05:42:58 -08004064 */
4065TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
Josh Wu3202eab2022-02-17 18:09:05 -08004066 StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
Josh Wu049e2cd2022-01-12 05:42:58 -08004067 for (auto sample_rate : le_audio_output_sample_rates_) {
4068 for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
4069 for (auto channel_mode : le_audio_output_channel_modes_) {
4070 for (auto data_interval_us : le_audio_output_data_interval_us_) {
4071 PcmConfiguration pcm_config{
4072 .sampleRateHz = sample_rate,
Josh Wu049e2cd2022-01-12 05:42:58 -08004073 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00004074 .bitsPerSample = bits_per_sample,
Josh Wu049e2cd2022-01-12 05:42:58 -08004075 .dataIntervalUs = data_interval_us,
4076 };
Josh Wu8a1be762022-02-15 09:37:29 -08004077 bool is_codec_config_valid =
4078 IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
Josh Wu049e2cd2022-01-12 05:42:58 -08004079 DataMQDesc mq_desc;
4080 auto aidl_retval = audio_provider_->startSession(
Chen Chenc92270e2022-02-14 18:29:52 -08004081 audio_port_, AudioConfiguration(pcm_config), latency_modes,
4082 &mq_desc);
Josh Wu049e2cd2022-01-12 05:42:58 -08004083 DataMQ data_mq(mq_desc);
4084
4085 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
4086 if (is_codec_config_valid) {
4087 EXPECT_TRUE(data_mq.isValid());
4088 }
4089 EXPECT_TRUE(audio_provider_->endSession().isOk());
4090 }
4091 }
4092 }
4093 }
4094}
4095
Alice Kuo336d90c2022-02-16 09:09:59 +08004096/**
4097 * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
4098 */
4099class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
4100 : public BluetoothAudioProviderFactoryAidl {
4101 public:
4102 virtual void SetUp() override {
4103 BluetoothAudioProviderFactoryAidl::SetUp();
4104 GetProviderCapabilitiesHelper(
4105 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Bao Doc36897d2023-12-06 01:27:54 +00004106 GetProviderInfoHelper(
4107 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
Alice Kuo336d90c2022-02-16 09:09:59 +08004108 OpenProviderHelper(
4109 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
4110 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
4111 audio_provider_ != nullptr);
4112 }
4113
4114 virtual void TearDown() override {
4115 audio_port_ = nullptr;
4116 audio_provider_ = nullptr;
4117 BluetoothAudioProviderFactoryAidl::TearDown();
4118 }
4119
4120 bool IsBroadcastOffloadSupported() {
4121 for (auto& capability : temp_provider_capabilities_) {
4122 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
4123 continue;
4124 }
4125 auto& le_audio_capability =
4126 capability.get<AudioCapabilities::leAudioCapabilities>();
4127 if (le_audio_capability.broadcastCapability.codecType !=
4128 CodecType::UNKNOWN)
4129 return true;
4130 }
4131 return false;
4132 }
4133
Bao Doc36897d2023-12-06 01:27:54 +00004134 bool IsBroadcastOffloadProviderInfoSupported() {
4135 if (!temp_provider_info_.has_value()) return false;
4136 if (temp_provider_info_.value().codecInfos.empty()) return false;
4137 // Check if all codec info is of LeAudio type
4138 for (auto& codec_info : temp_provider_info_.value().codecInfos) {
4139 if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
4140 return false;
4141 }
4142 return true;
4143 }
4144
4145 std::vector<Lc3Configuration> GetBroadcastLc3SupportedListFromProviderInfo() {
4146 std::vector<Lc3Configuration> le_audio_codec_configs;
4147 for (auto& codec_info : temp_provider_info_.value().codecInfos) {
4148 // Only gets LC3 codec information
4149 if (codec_info.id != CodecId::Core::LC3) continue;
4150 // Combine those parameters into one list of Lc3Configuration
4151 auto& transport =
4152 codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
4153 for (int32_t samplingFrequencyHz : transport.samplingFrequencyHz) {
4154 for (int32_t frameDurationUs : transport.frameDurationUs) {
4155 for (int32_t octetsPerFrame : transport.bitdepth) {
4156 Lc3Configuration lc3_config = {
4157 .samplingFrequencyHz = samplingFrequencyHz,
4158 .frameDurationUs = frameDurationUs,
4159 .octetsPerFrame = octetsPerFrame,
4160 };
4161 le_audio_codec_configs.push_back(lc3_config);
4162 }
4163 }
4164 }
4165 }
4166
4167 return le_audio_codec_configs;
4168 }
4169
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004170 AudioContext GetAudioContext(int32_t bitmask) {
4171 AudioContext media_audio_context;
4172 media_audio_context.bitmask = bitmask;
4173 return media_audio_context;
4174 }
4175
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004176 std::optional<CodecSpecificConfigurationLtv::SamplingFrequency>
4177 GetBisSampleFreq(const LeAudioBisConfiguration& bis_conf) {
4178 auto sample_freq_ltv = GetConfigurationLtv(
4179 bis_conf.codecConfiguration,
4180 CodecSpecificConfigurationLtv::Tag::samplingFrequency);
4181 if (!sample_freq_ltv) {
4182 return std::nullopt;
4183 }
4184 return (*sample_freq_ltv)
4185 .get<CodecSpecificConfigurationLtv::samplingFrequency>();
4186 }
4187
4188 std::vector<CodecSpecificConfigurationLtv::SamplingFrequency>
4189 GetSubgroupSampleFreqs(
4190 const LeAudioBroadcastSubgroupConfiguration& subgroup_conf) {
4191 std::vector<CodecSpecificConfigurationLtv::SamplingFrequency> result = {};
4192
4193 for (const auto& bis_conf : subgroup_conf.bisConfigurations) {
4194 auto sample_freq = GetBisSampleFreq(bis_conf.bisConfiguration);
4195 if (sample_freq) {
4196 result.push_back(*sample_freq);
4197 }
4198 }
4199 return result;
4200 }
4201
4202 void VerifyBroadcastConfiguration(
4203 const LeAudioBroadcastConfigurationRequirement& requirements,
4204 const LeAudioBroadcastConfigurationSetting& configuration,
4205 std::vector<CodecSpecificConfigurationLtv::SamplingFrequency>
4206 expectedSampleFreqs = {}) {
4207 std::vector<CodecSpecificConfigurationLtv::SamplingFrequency> sampleFreqs =
4208 {};
4209
4210 int number_of_requested_bises = 0;
4211 for (const auto& subgroup_req :
4212 requirements.subgroupConfigurationRequirements) {
4213 number_of_requested_bises += subgroup_req.bisNumPerSubgroup;
4214 }
4215
4216 if (!expectedSampleFreqs.empty()) {
4217 for (const auto& subgroup_conf : configuration.subgroupsConfigurations) {
4218 auto result = GetSubgroupSampleFreqs(subgroup_conf);
4219 sampleFreqs.insert(sampleFreqs.end(), result.begin(), result.end());
4220 }
4221 }
4222
4223 ASSERT_EQ(number_of_requested_bises, configuration.numBis);
4224 ASSERT_EQ(requirements.subgroupConfigurationRequirements.size(),
4225 configuration.subgroupsConfigurations.size());
4226
4227 if (expectedSampleFreqs.empty()) {
4228 return;
4229 }
4230
4231 std::sort(sampleFreqs.begin(), sampleFreqs.end());
4232 std::sort(expectedSampleFreqs.begin(), expectedSampleFreqs.end());
4233
4234 ASSERT_EQ(sampleFreqs, expectedSampleFreqs);
4235 }
4236
4237 LeAudioDeviceCapabilities GetDefaultBroadcastSinkCapability() {
4238 // Create a capability
4239 LeAudioDeviceCapabilities capability;
4240
4241 capability.codecId = CodecId::Core::LC3;
4242
4243 auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
4244 pref_context_metadata.values =
4245 GetAudioContext(AudioContext::MEDIA | AudioContext::CONVERSATIONAL |
4246 AudioContext::GAME);
4247 capability.metadata = {pref_context_metadata};
4248
4249 auto sampling_rate =
4250 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
4251 sampling_rate.bitmask =
4252 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000 |
Bao Do57861bd2024-05-23 17:02:54 +08004253 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000 |
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004254 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000;
4255 auto frame_duration =
4256 CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
4257 frame_duration.bitmask =
4258 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
4259 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
4260 auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
4261 octets.min = 0;
4262 octets.max = 120;
4263 auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
4264 frames.value = 2;
4265 capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
4266 octets, frames};
4267 return capability;
4268 }
4269
4270 LeAudioBroadcastConfigurationRequirement GetBroadcastRequirement(
4271 bool standard_quality, bool high_quality) {
4272 LeAudioBroadcastConfigurationRequirement requirement;
4273
4274 AudioContext media_audio_context;
4275 media_audio_context.bitmask = AudioContext::MEDIA;
4276
4277 LeAudioBroadcastSubgroupConfigurationRequirement
4278 standard_quality_requirement = {
4279 .audioContext = media_audio_context,
4280 .quality = IBluetoothAudioProvider::BroadcastQuality::STANDARD,
4281 .bisNumPerSubgroup = 2};
4282
4283 LeAudioBroadcastSubgroupConfigurationRequirement high_quality_requirement =
4284 {.audioContext = media_audio_context,
4285 .quality = IBluetoothAudioProvider::BroadcastQuality::HIGH,
4286 .bisNumPerSubgroup = 2};
4287
4288 if (standard_quality) {
4289 requirement.subgroupConfigurationRequirements.push_back(
4290 standard_quality_requirement);
4291 }
4292
4293 if (high_quality) {
4294 requirement.subgroupConfigurationRequirements.push_back(
4295 high_quality_requirement);
4296 }
4297 return requirement;
4298 }
4299
Alice Kuo336d90c2022-02-16 09:09:59 +08004300 std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
4301 std::vector<Lc3Configuration> le_audio_codec_configs;
4302 if (!supported) {
shihchienc3ab9f5e2022-09-23 08:18:05 +00004303 Lc3Configuration lc3_config{.pcmBitDepth = 0, .samplingFrequencyHz = 0};
Alice Kuo336d90c2022-02-16 09:09:59 +08004304 le_audio_codec_configs.push_back(lc3_config);
4305 return le_audio_codec_configs;
4306 }
4307
4308 // There might be more than one LeAudioCodecCapabilitiesSetting
4309 std::vector<Lc3Capabilities> lc3_capabilities;
4310 for (auto& capability : temp_provider_capabilities_) {
4311 if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
4312 continue;
4313 }
4314 auto& le_audio_capability =
4315 capability.get<AudioCapabilities::leAudioCapabilities>();
4316 auto& broadcast_capability = le_audio_capability.broadcastCapability;
4317 if (broadcast_capability.codecType != CodecType::LC3) {
4318 continue;
4319 }
4320 auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
4321 BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
4322 for (int idx = 0; idx < lc3_capability->size(); idx++)
4323 lc3_capabilities.push_back(*lc3_capability->at(idx));
4324 }
4325
4326 // Combine those parameters into one list of LeAudioCodecConfiguration
4327 // This seems horrible, but usually each Lc3Capability only contains a
4328 // single Lc3Configuration, which means every array has a length of 1.
4329 for (auto& lc3_capability : lc3_capabilities) {
4330 for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
4331 for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
4332 for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
4333 Lc3Configuration lc3_config = {
4334 .samplingFrequencyHz = samplingFrequencyHz,
4335 .frameDurationUs = frameDurationUs,
4336 .octetsPerFrame = octetsPerFrame,
4337 };
4338 le_audio_codec_configs.push_back(lc3_config);
4339 }
4340 }
4341 }
4342 }
4343
4344 return le_audio_codec_configs;
4345 }
4346
4347 LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
4348};
4349
4350/**
4351 * Test whether each provider of type
4352 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
4353 * started and stopped
4354 */
4355TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4356 OpenLeAudioOutputHardwareProvider) {}
4357
4358/**
4359 * Test whether each provider of type
4360 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
Bao Doc36897d2023-12-06 01:27:54 +00004361 * started and stopped with broadcast hardware encoding config taken from
4362 * provider info
4363 */
4364TEST_P(
4365 BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4366 StartAndEndLeAudioBroadcastSessionWithPossibleUnicastConfigFromProviderInfo) {
Bao Dob487a852023-12-25 10:12:09 +08004367 if (GetProviderFactoryInterfaceVersion() <
4368 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
4369 GTEST_SKIP();
4370 }
Bao Doc36897d2023-12-06 01:27:54 +00004371 if (!IsBroadcastOffloadProviderInfoSupported()) {
4372 return;
4373 }
4374
4375 auto lc3_codec_configs = GetBroadcastLc3SupportedListFromProviderInfo();
4376 LeAudioBroadcastConfiguration le_audio_broadcast_config = {
4377 .codecType = CodecType::LC3,
4378 .streamMap = {},
4379 };
4380
4381 for (auto& lc3_config : lc3_codec_configs) {
4382 le_audio_broadcast_config.streamMap.resize(1);
4383 le_audio_broadcast_config.streamMap[0]
4384 .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
4385 lc3_config);
4386 le_audio_broadcast_config.streamMap[0].streamHandle = 0x0;
4387 le_audio_broadcast_config.streamMap[0].pcmStreamId = 0x0;
4388 le_audio_broadcast_config.streamMap[0].audioChannelAllocation = 0x1 << 0;
4389
4390 DataMQDesc mq_desc;
4391 auto aidl_retval = audio_provider_->startSession(
4392 audio_port_, AudioConfiguration(le_audio_broadcast_config),
4393 latency_modes, &mq_desc);
4394
4395 ASSERT_TRUE(aidl_retval.isOk());
4396 EXPECT_TRUE(audio_provider_->endSession().isOk());
4397 }
4398}
4399
Bao Do5b2fdab2023-11-20 08:02:55 +00004400TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4401 GetEmptyBroadcastConfigurationEmptyCapability) {
Bao Dob487a852023-12-25 10:12:09 +08004402 if (GetProviderFactoryInterfaceVersion() <
4403 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
4404 GTEST_SKIP();
4405 }
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004406
4407 if (!IsBroadcastOffloadSupported()) {
4408 GTEST_SKIP();
4409 }
4410
Bao Do5b2fdab2023-11-20 08:02:55 +00004411 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
4412 IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
4413 empty_requirement;
4414
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004415 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
Bao Do5b2fdab2023-11-20 08:02:55 +00004416
4417 // Check empty capability for source direction
4418 auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004419 empty_capability, empty_requirement, &configuration);
4420
4421 ASSERT_FALSE(aidl_retval.isOk());
4422}
4423
4424TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4425 GetBroadcastConfigurationEmptyCapability) {
4426 if (GetProviderFactoryInterfaceVersion() <
4427 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
4428 GTEST_SKIP();
4429 }
4430
4431 if (!IsBroadcastOffloadSupported()) {
4432 GTEST_SKIP();
4433 }
4434
4435 std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
4436 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
4437
4438 IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
4439 one_subgroup_requirement =
4440 GetBroadcastRequirement(true /* standard*/, false /* high */);
4441
4442 // Check empty capability for source direction
4443 auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
4444 empty_capability, one_subgroup_requirement, &configuration);
Bao Do5b2fdab2023-11-20 08:02:55 +00004445
4446 ASSERT_TRUE(aidl_retval.isOk());
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004447 ASSERT_NE(configuration.numBis, 0);
4448 ASSERT_FALSE(configuration.subgroupsConfigurations.empty());
4449 VerifyBroadcastConfiguration(one_subgroup_requirement, configuration);
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004450}
4451
4452TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4453 GetBroadcastConfigurationNonEmptyCapability) {
4454 if (GetProviderFactoryInterfaceVersion() <
4455 BluetoothAudioHalVersion::VERSION_AIDL_V4) {
4456 GTEST_SKIP();
4457 }
4458
4459 if (!IsBroadcastOffloadSupported()) {
4460 GTEST_SKIP();
4461 }
4462
4463 std::vector<std::optional<LeAudioDeviceCapabilities>> capability = {
4464 GetDefaultBroadcastSinkCapability()};
4465
4466 IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
4467 requirement =
Bao Do7f89d612024-06-07 16:59:52 +08004468 GetBroadcastRequirement(true /* standard*/, false /* high */);
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004469
4470 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
4471
4472 // Check empty capability for source direction
4473 auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
4474 capability, requirement, &configuration);
4475
4476 ASSERT_TRUE(aidl_retval.isOk());
4477 ASSERT_NE(configuration.numBis, 0);
4478 ASSERT_FALSE(configuration.subgroupsConfigurations.empty());
4479 VerifyBroadcastConfiguration(requirement, configuration);
Bao Do5b2fdab2023-11-20 08:02:55 +00004480}
4481
Bao Doc36897d2023-12-06 01:27:54 +00004482/**
4483 * Test whether each provider of type
4484 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
Alice Kuo336d90c2022-02-16 09:09:59 +08004485 * started and stopped with broadcast hardware encoding config
4486 */
4487TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4488 StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
4489 if (!IsBroadcastOffloadSupported()) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004490 GTEST_SKIP();
Alice Kuo336d90c2022-02-16 09:09:59 +08004491 }
4492
4493 auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
4494 LeAudioBroadcastConfiguration le_audio_broadcast_config = {
4495 .codecType = CodecType::LC3,
4496 .streamMap = {},
4497 };
4498
4499 for (auto& lc3_config : lc3_codec_configs) {
Patty Huangac077ef2022-11-23 14:45:15 +08004500 le_audio_broadcast_config.streamMap.resize(1);
Alice Kuo336d90c2022-02-16 09:09:59 +08004501 le_audio_broadcast_config.streamMap[0]
4502 .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
4503 lc3_config);
Rongxuan Liuc1aea322023-01-26 17:14:54 +00004504 le_audio_broadcast_config.streamMap[0].streamHandle = 0x0;
4505 le_audio_broadcast_config.streamMap[0].pcmStreamId = 0x0;
4506 le_audio_broadcast_config.streamMap[0].audioChannelAllocation = 0x1 << 0;
4507
Alice Kuo336d90c2022-02-16 09:09:59 +08004508 DataMQDesc mq_desc;
4509 auto aidl_retval = audio_provider_->startSession(
Chen Chen60d52e42022-02-16 12:19:12 -08004510 audio_port_, AudioConfiguration(le_audio_broadcast_config),
4511 latency_modes, &mq_desc);
Alice Kuo336d90c2022-02-16 09:09:59 +08004512
4513 ASSERT_TRUE(aidl_retval.isOk());
4514 EXPECT_TRUE(audio_provider_->endSession().isOk());
4515 }
4516}
4517
4518/**
4519 * Test whether each provider of type
4520 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
4521 * started and stopped with Broadcast hardware encoding config
4522 *
4523 * Disabled since offload codec checking is not ready
4524 */
4525TEST_P(
4526 BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4527 DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
4528 if (!IsBroadcastOffloadSupported()) {
Łukasz Rymanowski5a43cb92024-01-17 21:35:44 +00004529 GTEST_SKIP();
Alice Kuo336d90c2022-02-16 09:09:59 +08004530 }
4531
4532 auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
4533 LeAudioBroadcastConfiguration le_audio_broadcast_config = {
4534 .codecType = CodecType::LC3,
4535 .streamMap = {},
4536 };
4537
4538 for (auto& lc3_config : lc3_codec_configs) {
4539 le_audio_broadcast_config.streamMap[0]
4540 .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
4541 lc3_config);
4542 DataMQDesc mq_desc;
4543 auto aidl_retval = audio_provider_->startSession(
Chen Chen60d52e42022-02-16 12:19:12 -08004544 audio_port_, AudioConfiguration(le_audio_broadcast_config),
4545 latency_modes, &mq_desc);
Alice Kuo336d90c2022-02-16 09:09:59 +08004546
4547 // AIDL call should fail on invalid codec
4548 ASSERT_FALSE(aidl_retval.isOk());
4549 EXPECT_TRUE(audio_provider_->endSession().isOk());
4550 }
4551}
4552
Alice Kuoadcceec2022-03-28 13:28:43 +08004553/**
4554 * openProvider A2DP_SOFTWARE_DECODING_DATAPATH
4555 */
4556class BluetoothAudioProviderA2dpDecodingSoftwareAidl
4557 : public BluetoothAudioProviderFactoryAidl {
4558 public:
4559 virtual void SetUp() override {
4560 BluetoothAudioProviderFactoryAidl::SetUp();
4561 GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
4562 OpenProviderHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
4563 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
4564 audio_provider_ != nullptr);
4565 }
4566
4567 virtual void TearDown() override {
4568 audio_port_ = nullptr;
4569 audio_provider_ = nullptr;
4570 BluetoothAudioProviderFactoryAidl::TearDown();
4571 }
4572};
4573
4574/**
4575 * Test whether we can open a provider of type
4576 */
4577TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
4578 OpenA2dpDecodingSoftwareProvider) {}
4579
4580/**
4581 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004582 * SessionType::A2DP_SOFTWARE_DECODING_DATAPATH can be started and stopped
4583 * with different PCM config
Alice Kuoadcceec2022-03-28 13:28:43 +08004584 */
4585TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
4586 StartAndEndA2dpDecodingSoftwareSessionWithPossiblePcmConfig) {
4587 for (auto sample_rate : a2dp_sample_rates) {
4588 for (auto bits_per_sample : a2dp_bits_per_samples) {
4589 for (auto channel_mode : a2dp_channel_modes) {
4590 PcmConfiguration pcm_config{
4591 .sampleRateHz = sample_rate,
Alice Kuoadcceec2022-03-28 13:28:43 +08004592 .channelMode = channel_mode,
shihchienc3ab9f5e2022-09-23 08:18:05 +00004593 .bitsPerSample = bits_per_sample,
Alice Kuoadcceec2022-03-28 13:28:43 +08004594 };
4595 bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
4596 DataMQDesc mq_desc;
4597 auto aidl_retval = audio_provider_->startSession(
4598 audio_port_, AudioConfiguration(pcm_config), latency_modes,
4599 &mq_desc);
4600 DataMQ data_mq(mq_desc);
4601
4602 EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
4603 if (is_codec_config_valid) {
4604 EXPECT_TRUE(data_mq.isValid());
4605 }
4606 EXPECT_TRUE(audio_provider_->endSession().isOk());
4607 }
4608 }
4609 }
4610}
4611
4612/**
4613 * openProvider A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH
4614 */
4615class BluetoothAudioProviderA2dpDecodingHardwareAidl
4616 : public BluetoothAudioProviderFactoryAidl {
4617 public:
4618 virtual void SetUp() override {
4619 BluetoothAudioProviderFactoryAidl::SetUp();
4620 GetProviderCapabilitiesHelper(
4621 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
4622 OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
4623 ASSERT_TRUE(temp_provider_capabilities_.empty() ||
4624 audio_provider_ != nullptr);
4625 }
4626
4627 virtual void TearDown() override {
4628 audio_port_ = nullptr;
4629 audio_provider_ = nullptr;
4630 BluetoothAudioProviderFactoryAidl::TearDown();
4631 }
4632
4633 bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
4634};
4635
4636/**
4637 * Test whether we can open a provider of type
4638 */
4639TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4640 OpenA2dpDecodingHardwareProvider) {}
4641
4642/**
4643 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004644 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4645 * with SBC hardware encoding config
Alice Kuoadcceec2022-03-28 13:28:43 +08004646 */
4647TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4648 StartAndEndA2dpSbcDecodingHardwareSession) {
4649 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004650 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004651 }
4652
4653 CodecConfiguration codec_config = {
4654 .codecType = CodecType::SBC,
4655 .encodedAudioBitrate = 328000,
4656 .peerMtu = 1005,
4657 .isScmstEnabled = false,
4658 };
4659 auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
4660
4661 for (auto& codec_specific : sbc_codec_specifics) {
4662 copy_codec_specific(codec_config.config, codec_specific);
4663 DataMQDesc mq_desc;
4664 auto aidl_retval = audio_provider_->startSession(
4665 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
4666
4667 ASSERT_TRUE(aidl_retval.isOk());
4668 EXPECT_TRUE(audio_provider_->endSession().isOk());
4669 }
4670}
4671
4672/**
4673 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004674 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4675 * with AAC hardware encoding config
Alice Kuoadcceec2022-03-28 13:28:43 +08004676 */
4677TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4678 StartAndEndA2dpAacDecodingHardwareSession) {
4679 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004680 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004681 }
4682
4683 CodecConfiguration codec_config = {
4684 .codecType = CodecType::AAC,
4685 .encodedAudioBitrate = 320000,
4686 .peerMtu = 1005,
4687 .isScmstEnabled = false,
4688 };
4689 auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
4690
4691 for (auto& codec_specific : aac_codec_specifics) {
4692 copy_codec_specific(codec_config.config, codec_specific);
4693 DataMQDesc mq_desc;
4694 auto aidl_retval = audio_provider_->startSession(
4695 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
4696
4697 ASSERT_TRUE(aidl_retval.isOk());
4698 EXPECT_TRUE(audio_provider_->endSession().isOk());
4699 }
4700}
4701
4702/**
4703 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004704 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4705 * with LDAC hardware encoding config
Alice Kuoadcceec2022-03-28 13:28:43 +08004706 */
4707TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4708 StartAndEndA2dpLdacDecodingHardwareSession) {
4709 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004710 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004711 }
4712
4713 CodecConfiguration codec_config = {
4714 .codecType = CodecType::LDAC,
4715 .encodedAudioBitrate = 990000,
4716 .peerMtu = 1005,
4717 .isScmstEnabled = false,
4718 };
4719 auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
4720
4721 for (auto& codec_specific : ldac_codec_specifics) {
4722 copy_codec_specific(codec_config.config, codec_specific);
4723 DataMQDesc mq_desc;
4724 auto aidl_retval = audio_provider_->startSession(
4725 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
4726
4727 ASSERT_TRUE(aidl_retval.isOk());
4728 EXPECT_TRUE(audio_provider_->endSession().isOk());
4729 }
4730}
4731
4732/**
4733 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004734 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4735 * with Opus hardware encoding config
Alice Kuoadcceec2022-03-28 13:28:43 +08004736 */
4737TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
Omer Osmana2587da2022-05-01 03:54:11 +00004738 StartAndEndA2dpOpusDecodingHardwareSession) {
Alice Kuoadcceec2022-03-28 13:28:43 +08004739 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004740 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004741 }
4742
4743 CodecConfiguration codec_config = {
Omer Osmana2587da2022-05-01 03:54:11 +00004744 .codecType = CodecType::OPUS,
Alice Kuoadcceec2022-03-28 13:28:43 +08004745 .encodedAudioBitrate = 990000,
4746 .peerMtu = 1005,
4747 .isScmstEnabled = false,
4748 };
Omer Osmana2587da2022-05-01 03:54:11 +00004749 auto opus_codec_specifics = GetOpusCodecSpecificSupportedList(true);
Alice Kuoadcceec2022-03-28 13:28:43 +08004750
Omer Osmana2587da2022-05-01 03:54:11 +00004751 for (auto& codec_specific : opus_codec_specifics) {
Alice Kuoadcceec2022-03-28 13:28:43 +08004752 copy_codec_specific(codec_config.config, codec_specific);
4753 DataMQDesc mq_desc;
4754 auto aidl_retval = audio_provider_->startSession(
4755 audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
4756
4757 ASSERT_TRUE(aidl_retval.isOk());
4758 EXPECT_TRUE(audio_provider_->endSession().isOk());
4759 }
4760}
4761
4762/**
4763 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004764 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4765 * with AptX hardware encoding config
Alice Kuoadcceec2022-03-28 13:28:43 +08004766 */
4767TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4768 StartAndEndA2dpAptxDecodingHardwareSession) {
4769 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004770 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004771 }
4772
4773 for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
4774 CodecConfiguration codec_config = {
4775 .codecType = codec_type,
4776 .encodedAudioBitrate =
4777 (codec_type == CodecType::APTX ? 352000 : 576000),
4778 .peerMtu = 1005,
4779 .isScmstEnabled = false,
4780 };
4781
4782 auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
4783 (codec_type == CodecType::APTX_HD ? true : false), true);
4784
4785 for (auto& codec_specific : aptx_codec_specifics) {
4786 copy_codec_specific(codec_config.config, codec_specific);
4787 DataMQDesc mq_desc;
4788 auto aidl_retval = audio_provider_->startSession(
4789 audio_port_, AudioConfiguration(codec_config), latency_modes,
4790 &mq_desc);
4791
4792 ASSERT_TRUE(aidl_retval.isOk());
4793 EXPECT_TRUE(audio_provider_->endSession().isOk());
4794 }
4795 }
4796}
4797
4798/**
4799 * Test whether each provider of type
Bao Dob487a852023-12-25 10:12:09 +08004800 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped
4801 * with an invalid codec config
Alice Kuoadcceec2022-03-28 13:28:43 +08004802 */
4803TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
4804 StartAndEndA2dpDecodingHardwareSessionInvalidCodecConfig) {
4805 if (!IsOffloadSupported()) {
Jakub Tyszkowski334bf182024-01-08 13:43:27 +00004806 GTEST_SKIP();
Alice Kuoadcceec2022-03-28 13:28:43 +08004807 }
4808 ASSERT_NE(audio_provider_, nullptr);
4809
4810 std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
Sagar Verma62df9102022-12-07 17:56:04 +05304811 for (auto codec_type : ndk::enum_range<CodecType>()) {
Alice Kuoadcceec2022-03-28 13:28:43 +08004812 switch (codec_type) {
4813 case CodecType::SBC:
4814 codec_specifics = GetSbcCodecSpecificSupportedList(false);
4815 break;
4816 case CodecType::AAC:
4817 codec_specifics = GetAacCodecSpecificSupportedList(false);
4818 break;
4819 case CodecType::LDAC:
4820 codec_specifics = GetLdacCodecSpecificSupportedList(false);
4821 break;
4822 case CodecType::APTX:
4823 codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
4824 break;
4825 case CodecType::APTX_HD:
4826 codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
4827 break;
Omer Osmana2587da2022-05-01 03:54:11 +00004828 case CodecType::OPUS:
4829 codec_specifics = GetOpusCodecSpecificSupportedList(false);
Alice Kuoadcceec2022-03-28 13:28:43 +08004830 continue;
4831 case CodecType::APTX_ADAPTIVE:
Sagar Verma62df9102022-12-07 17:56:04 +05304832 case CodecType::APTX_ADAPTIVE_LE:
4833 case CodecType::APTX_ADAPTIVE_LEX:
Omer Osmana2587da2022-05-01 03:54:11 +00004834 case CodecType::LC3:
Alice Kuoadcceec2022-03-28 13:28:43 +08004835 case CodecType::VENDOR:
4836 case CodecType::UNKNOWN:
4837 codec_specifics.clear();
4838 break;
4839 }
4840 if (codec_specifics.empty()) {
4841 continue;
4842 }
4843
4844 CodecConfiguration codec_config = {
4845 .codecType = codec_type,
4846 .encodedAudioBitrate = 328000,
4847 .peerMtu = 1005,
4848 .isScmstEnabled = false,
4849 };
4850 for (auto codec_specific : codec_specifics) {
4851 copy_codec_specific(codec_config.config, codec_specific);
4852 DataMQDesc mq_desc;
4853 auto aidl_retval = audio_provider_->startSession(
4854 audio_port_, AudioConfiguration(codec_config), latency_modes,
4855 &mq_desc);
4856
4857 // AIDL call should fail on invalid codec
4858 ASSERT_FALSE(aidl_retval.isOk());
4859 EXPECT_TRUE(audio_provider_->endSession().isOk());
4860 }
4861 }
4862}
4863
Josh Wu049e2cd2022-01-12 05:42:58 -08004864GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4865 BluetoothAudioProviderFactoryAidl);
4866INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
4867 testing::ValuesIn(android::getAidlHalInstanceNames(
4868 IBluetoothAudioProviderFactory::descriptor)),
4869 android::PrintInstanceNameToString);
4870
Antoine SOULIER33c4e5a2023-09-28 21:59:19 +00004871GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothAudioProviderAidl);
4872INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderAidl,
4873 testing::ValuesIn(android::getAidlHalInstanceNames(
4874 IBluetoothAudioProviderFactory::descriptor)),
4875 android::PrintInstanceNameToString);
4876
Josh Wu049e2cd2022-01-12 05:42:58 -08004877GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
Alice Kuoadcceec2022-03-28 13:28:43 +08004878 BluetoothAudioProviderA2dpEncodingSoftwareAidl);
4879INSTANTIATE_TEST_SUITE_P(PerInstance,
4880 BluetoothAudioProviderA2dpEncodingSoftwareAidl,
Josh Wu049e2cd2022-01-12 05:42:58 -08004881 testing::ValuesIn(android::getAidlHalInstanceNames(
4882 IBluetoothAudioProviderFactory::descriptor)),
4883 android::PrintInstanceNameToString);
4884
4885GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
Alice Kuoadcceec2022-03-28 13:28:43 +08004886 BluetoothAudioProviderA2dpEncodingHardwareAidl);
4887INSTANTIATE_TEST_SUITE_P(PerInstance,
4888 BluetoothAudioProviderA2dpEncodingHardwareAidl,
Josh Wu049e2cd2022-01-12 05:42:58 -08004889 testing::ValuesIn(android::getAidlHalInstanceNames(
4890 IBluetoothAudioProviderFactory::descriptor)),
4891 android::PrintInstanceNameToString);
4892
4893GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4894 BluetoothAudioProviderHearingAidSoftwareAidl);
4895INSTANTIATE_TEST_SUITE_P(PerInstance,
4896 BluetoothAudioProviderHearingAidSoftwareAidl,
4897 testing::ValuesIn(android::getAidlHalInstanceNames(
4898 IBluetoothAudioProviderFactory::descriptor)),
4899 android::PrintInstanceNameToString);
4900
4901GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4902 BluetoothAudioProviderLeAudioOutputSoftwareAidl);
4903INSTANTIATE_TEST_SUITE_P(PerInstance,
4904 BluetoothAudioProviderLeAudioOutputSoftwareAidl,
4905 testing::ValuesIn(android::getAidlHalInstanceNames(
4906 IBluetoothAudioProviderFactory::descriptor)),
4907 android::PrintInstanceNameToString);
4908
4909GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4910 BluetoothAudioProviderLeAudioInputSoftwareAidl);
4911INSTANTIATE_TEST_SUITE_P(PerInstance,
4912 BluetoothAudioProviderLeAudioInputSoftwareAidl,
4913 testing::ValuesIn(android::getAidlHalInstanceNames(
4914 IBluetoothAudioProviderFactory::descriptor)),
4915 android::PrintInstanceNameToString);
4916
4917GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4918 BluetoothAudioProviderLeAudioOutputHardwareAidl);
4919INSTANTIATE_TEST_SUITE_P(PerInstance,
4920 BluetoothAudioProviderLeAudioOutputHardwareAidl,
4921 testing::ValuesIn(android::getAidlHalInstanceNames(
4922 IBluetoothAudioProviderFactory::descriptor)),
4923 android::PrintInstanceNameToString);
4924
4925GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4926 BluetoothAudioProviderLeAudioInputHardwareAidl);
4927INSTANTIATE_TEST_SUITE_P(PerInstance,
4928 BluetoothAudioProviderLeAudioInputHardwareAidl,
4929 testing::ValuesIn(android::getAidlHalInstanceNames(
4930 IBluetoothAudioProviderFactory::descriptor)),
4931 android::PrintInstanceNameToString);
4932
4933GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4934 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
4935INSTANTIATE_TEST_SUITE_P(PerInstance,
4936 BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
4937 testing::ValuesIn(android::getAidlHalInstanceNames(
4938 IBluetoothAudioProviderFactory::descriptor)),
4939 android::PrintInstanceNameToString);
4940
Alice Kuo336d90c2022-02-16 09:09:59 +08004941GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4942 BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
4943INSTANTIATE_TEST_SUITE_P(PerInstance,
4944 BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
4945 testing::ValuesIn(android::getAidlHalInstanceNames(
4946 IBluetoothAudioProviderFactory::descriptor)),
4947 android::PrintInstanceNameToString);
Josh Wu049e2cd2022-01-12 05:42:58 -08004948
Alice Kuoadcceec2022-03-28 13:28:43 +08004949GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4950 BluetoothAudioProviderA2dpDecodingSoftwareAidl);
4951INSTANTIATE_TEST_SUITE_P(PerInstance,
4952 BluetoothAudioProviderA2dpDecodingSoftwareAidl,
4953 testing::ValuesIn(android::getAidlHalInstanceNames(
4954 IBluetoothAudioProviderFactory::descriptor)),
4955 android::PrintInstanceNameToString);
4956
4957GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4958 BluetoothAudioProviderA2dpDecodingHardwareAidl);
4959INSTANTIATE_TEST_SUITE_P(PerInstance,
4960 BluetoothAudioProviderA2dpDecodingHardwareAidl,
4961 testing::ValuesIn(android::getAidlHalInstanceNames(
4962 IBluetoothAudioProviderFactory::descriptor)),
4963 android::PrintInstanceNameToString);
4964
Bao Do72399432023-11-09 08:13:05 +00004965GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4966 BluetoothAudioProviderHfpHardwareAidl);
4967INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderHfpHardwareAidl,
4968 testing::ValuesIn(android::getAidlHalInstanceNames(
4969 IBluetoothAudioProviderFactory::descriptor)),
4970 android::PrintInstanceNameToString);
4971
4972GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4973 BluetoothAudioProviderHfpSoftwareDecodingAidl);
4974INSTANTIATE_TEST_SUITE_P(PerInstance,
4975 BluetoothAudioProviderHfpSoftwareDecodingAidl,
4976 testing::ValuesIn(android::getAidlHalInstanceNames(
4977 IBluetoothAudioProviderFactory::descriptor)),
4978 android::PrintInstanceNameToString);
4979
4980GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
4981 BluetoothAudioProviderHfpSoftwareEncodingAidl);
4982INSTANTIATE_TEST_SUITE_P(PerInstance,
4983 BluetoothAudioProviderHfpSoftwareEncodingAidl,
4984 testing::ValuesIn(android::getAidlHalInstanceNames(
4985 IBluetoothAudioProviderFactory::descriptor)),
4986 android::PrintInstanceNameToString);
4987
Josh Wu049e2cd2022-01-12 05:42:58 -08004988int main(int argc, char** argv) {
4989 ::testing::InitGoogleTest(&argc, argv);
4990 ABinderProcess_setThreadPoolMaxThreadCount(1);
4991 ABinderProcess_startThreadPool();
4992 return RUN_ALL_TESTS();
4993}