blob: fd8c8dca0a3481d4a8579c332f205dd35be63ddd [file] [log] [blame]
Cheney Niad05f3e2018-11-08 16:41:02 +08001/*
2 * Copyright 2019 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
17#include <gtest/gtest.h>
18
19#include "client_interface.h"
20
21namespace {
22
23using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
24using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
25using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
26using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
27using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
28using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
29using ::android::hardware::bluetooth::audio::V2_0::CodecType;
30using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
31using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
32using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
33using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
34using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
35using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
36using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
37using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
38
39using ::bluetooth::audio::AudioCapabilities;
40using ::bluetooth::audio::AudioConfiguration;
41using ::bluetooth::audio::BitsPerSample;
42using ::bluetooth::audio::BluetoothAudioClientInterface;
43using ::bluetooth::audio::BluetoothAudioStatus;
44using ::bluetooth::audio::ChannelMode;
45using ::bluetooth::audio::PcmParameters;
46using ::bluetooth::audio::SampleRate;
47using ::bluetooth::audio::SessionType;
48using ::testing::Test;
49
50constexpr SampleRate kSampleRates[9] = {
51 SampleRate::RATE_UNKNOWN, SampleRate::RATE_44100, SampleRate::RATE_48000,
52 SampleRate::RATE_88200, SampleRate::RATE_96000, SampleRate::RATE_176400,
53 SampleRate::RATE_192000, SampleRate::RATE_16000, SampleRate::RATE_24000};
54constexpr BitsPerSample kBitsPerSamples[4] = {
55 BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24,
56 BitsPerSample::BITS_32};
57constexpr ChannelMode kChannelModes[3] = {
58 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
59constexpr uint16_t kPeerMtus[5] = {660, 663, 883, 1005, 1500};
60
61class TestTransport : public bluetooth::audio::IBluetoothTransportInstance {
62 private:
63 static constexpr uint64_t kRemoteDelayReportMs = 200;
64
65 public:
66 TestTransport(SessionType session_type)
67 : bluetooth::audio::IBluetoothTransportInstance(session_type, {}){};
Yi Kong183eace2019-03-29 15:42:58 -070068 bluetooth::audio::BluetoothAudioCtrlAck StartRequest() override {
Cheney Niad05f3e2018-11-08 16:41:02 +080069 return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
70 }
Yi Kong183eace2019-03-29 15:42:58 -070071 bluetooth::audio::BluetoothAudioCtrlAck SuspendRequest() override {
Cheney Niad05f3e2018-11-08 16:41:02 +080072 return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
73 }
Yi Kong183eace2019-03-29 15:42:58 -070074 void StopRequest() override {}
Cheney Niad05f3e2018-11-08 16:41:02 +080075 bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
76 uint64_t* total_bytes_readed,
Yi Kong183eace2019-03-29 15:42:58 -070077 timespec* data_position) override {
Cheney Niad05f3e2018-11-08 16:41:02 +080078 if (remote_delay_report_ns) {
79 *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
80 }
81 if (total_bytes_readed) {
82 *total_bytes_readed = 0;
83 }
84 if (data_position) {
85 clock_gettime(CLOCK_MONOTONIC, data_position);
86 }
87 return true;
88 }
Yi Kong183eace2019-03-29 15:42:58 -070089 void MetadataChanged(
90 const source_metadata_t& source_metadata __unused) override {}
91 void ResetPresentationPosition() override{};
92 void LogBytesRead(size_t bytes_readed __unused) override{};
Cheney Niad05f3e2018-11-08 16:41:02 +080093};
94
95class BluetoothAudioClientInterfaceTest : public Test {
96 protected:
97 TestTransport* test_transport_;
98 BluetoothAudioClientInterface* clientif_;
99
100 static constexpr int kClientIfReturnSuccess = 0;
101
Yi Kong183eace2019-03-29 15:42:58 -0700102 void SetUp() override {}
Cheney Niad05f3e2018-11-08 16:41:02 +0800103
Yi Kong183eace2019-03-29 15:42:58 -0700104 void TearDown() override {
Cheney Niad05f3e2018-11-08 16:41:02 +0800105 clientif_ = nullptr;
106 test_transport_ = nullptr;
107 }
108
109 bool IsSoftwarePcmParametersSupported(const PcmParameters& pcm_config) {
110 const std::vector<AudioCapabilities>& capabilities =
111 clientif_->GetAudioCapabilities();
112 PcmParameters pcm_capabilities = capabilities[0].pcmCapabilities();
113 bool is_pcm_config_valid =
114 (pcm_config.sampleRate != SampleRate::RATE_UNKNOWN &&
115 pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
116 pcm_config.channelMode != ChannelMode::UNKNOWN);
117 bool is_pcm_config_supported =
118 (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
119 pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
120 pcm_config.channelMode & pcm_capabilities.channelMode);
121 return (is_pcm_config_valid && is_pcm_config_supported);
122 }
123
124 bool IsOffloadCodecConfigurationSupported(
125 const CodecConfiguration& codec_config) {
126 CodecCapabilities codec_capability = {};
127 for (auto audio_capability : clientif_->GetAudioCapabilities()) {
128 if (audio_capability.codecCapabilities().codecType ==
129 codec_config.codecType) {
130 codec_capability = audio_capability.codecCapabilities();
131 }
132 }
133 if (codec_capability.codecType != codec_config.codecType) {
134 // codec is unsupported
135 return false;
136 }
137 bool is_codec_config_supported = false;
138 switch (codec_config.codecType) {
139 case CodecType::SBC: {
140 SbcParameters sbc_config = codec_config.config.sbcConfig();
141 SbcParameters sbc_capability =
142 codec_capability.capabilities.sbcCapabilities();
143 is_codec_config_supported =
144 (sbc_config.sampleRate & sbc_capability.sampleRate &&
145 sbc_config.channelMode & sbc_capability.channelMode &&
146 sbc_config.blockLength & sbc_capability.blockLength &&
147 sbc_config.numSubbands & sbc_capability.numSubbands &&
148 sbc_config.allocMethod & sbc_capability.allocMethod &&
149 sbc_config.bitsPerSample & sbc_capability.bitsPerSample &&
150 (sbc_capability.minBitpool <= sbc_config.minBitpool &&
151 sbc_config.minBitpool <= sbc_config.maxBitpool &&
152 sbc_config.maxBitpool <= sbc_capability.maxBitpool));
153 return is_codec_config_supported;
154 }
155 case CodecType::AAC: {
156 AacParameters aac_config = codec_config.config.aacConfig();
157 AacParameters aac_capability =
158 codec_capability.capabilities.aacCapabilities();
159 is_codec_config_supported =
160 (aac_config.objectType & aac_capability.objectType &&
161 aac_config.sampleRate & aac_capability.sampleRate &&
162 aac_config.channelMode & aac_capability.channelMode &&
163 (aac_config.variableBitRateEnabled ==
164 AacVariableBitRate::DISABLED ||
165 aac_capability.variableBitRateEnabled ==
166 AacVariableBitRate::ENABLED) &&
167 aac_config.bitsPerSample & aac_capability.bitsPerSample);
168 return is_codec_config_supported;
169 }
170 case CodecType::LDAC: {
171 LdacParameters ldac_config = codec_config.config.ldacConfig();
172 LdacParameters ldac_capability =
173 codec_capability.capabilities.ldacCapabilities();
174 is_codec_config_supported =
175 (ldac_config.sampleRate & ldac_capability.sampleRate &&
176 ldac_config.channelMode & ldac_capability.channelMode &&
177 ldac_config.bitsPerSample & ldac_capability.bitsPerSample);
178 return is_codec_config_supported;
179 }
180 case CodecType::APTX:
181 [[fallthrough]];
182 case CodecType::APTX_HD: {
183 AptxParameters aptx_config = codec_config.config.aptxConfig();
184 AptxParameters aptx_capability =
185 codec_capability.capabilities.aptxCapabilities();
186 is_codec_config_supported =
187 (aptx_config.sampleRate & aptx_capability.sampleRate &&
188 aptx_config.channelMode & aptx_capability.channelMode &&
189 aptx_config.bitsPerSample & aptx_capability.bitsPerSample);
190 return is_codec_config_supported;
191 }
192 case CodecType::UNKNOWN:
193 return false;
194 }
195 }
196};
197
198} // namespace
199
200TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpSoftwareSession) {
201 test_transport_ =
202 new TestTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
203 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
204 AudioConfiguration audio_config = {};
205 PcmParameters pcm_config = {};
206 for (auto sample_rate : kSampleRates) {
207 pcm_config.sampleRate = sample_rate;
208 for (auto bits_per_sample : kBitsPerSamples) {
209 pcm_config.bitsPerSample = bits_per_sample;
210 for (auto channel_mode : kChannelModes) {
211 pcm_config.channelMode = channel_mode;
212 audio_config.pcmConfig(pcm_config);
213 clientif_->UpdateAudioConfig(audio_config);
214 if (IsSoftwarePcmParametersSupported(pcm_config)) {
215 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
216 } else {
217 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
218 }
219 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
220 } // ChannelMode
221 } // BitsPerSampple
222 } // SampleRate
223}
224
225TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) {
226 test_transport_ =
227 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
228 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
229 AudioConfiguration audio_config = {};
230 CodecConfiguration codec_config = {};
231 SbcBlockLength block_lengths[4] = {
232 SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8,
233 SbcBlockLength::BLOCKS_12, SbcBlockLength::BLOCKS_16};
234 SbcNumSubbands num_subbands[2] = {SbcNumSubbands::SUBBAND_4,
235 SbcNumSubbands::SUBBAND_8};
236 SbcAllocMethod alloc_methods[2] = {SbcAllocMethod::ALLOC_MD_S,
237 SbcAllocMethod::ALLOC_MD_L};
238 for (auto sample_rate : kSampleRates) {
239 for (auto bits_per_sample : kBitsPerSamples) {
240 for (auto channel_mode : kChannelModes) {
241 for (auto peer_mtu : kPeerMtus) {
242 for (auto block_length : block_lengths) {
243 for (auto num_subband : num_subbands) {
244 for (auto alloc_method : alloc_methods) {
245 codec_config.codecType = CodecType::SBC;
246 codec_config.peerMtu = peer_mtu;
247 codec_config.isScmstEnabled = false;
248 // A2DP_SBC_DEFAULT_BITRATE
249 codec_config.encodedAudioBitrate = 328000;
250 SbcParameters sbc = {
251 .sampleRate = sample_rate,
252 .channelMode = (channel_mode == ChannelMode::MONO
253 ? SbcChannelMode::MONO
254 : SbcChannelMode::JOINT_STEREO),
255 .blockLength = block_length,
256 .numSubbands = num_subband,
257 .allocMethod = alloc_method,
258 .bitsPerSample = bits_per_sample,
259 .minBitpool = 2,
260 .maxBitpool = 53};
261 codec_config.config.sbcConfig(sbc);
262 audio_config.codecConfig(codec_config);
263 clientif_->UpdateAudioConfig(audio_config);
264 if (IsOffloadCodecConfigurationSupported(codec_config)) {
265 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
266 } else {
267 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
268 }
269 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
270 } // SbcAllocMethod
271 } // SbcNumSubbands
272 } // SbcBlockLength
273 } // peerMtu
274 } // ChannelMode
275 } // BitsPerSampple
276 } // SampleRate
277}
278
279TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) {
280 test_transport_ =
281 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
282 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
283 AudioConfiguration audio_config = {};
284 CodecConfiguration codec_config = {};
285 AacObjectType object_types[4] = {
286 AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC,
287 AacObjectType::MPEG4_LTP, AacObjectType::MPEG4_SCALABLE};
288 AacVariableBitRate variable_bitrates[2] = {AacVariableBitRate::DISABLED,
289 AacVariableBitRate::ENABLED};
290 for (auto sample_rate : kSampleRates) {
291 for (auto bits_per_sample : kBitsPerSamples) {
292 for (auto channel_mode : kChannelModes) {
293 for (auto peer_mtu : kPeerMtus) {
294 for (auto object_type : object_types) {
295 for (auto variable_bitrate : variable_bitrates) {
296 codec_config.codecType = CodecType::AAC;
297 codec_config.peerMtu = peer_mtu;
298 codec_config.isScmstEnabled = false;
299 // A2DP_AAC_DEFAULT_BITRATE
300 codec_config.encodedAudioBitrate = 320000;
301 AacParameters aac = {.objectType = object_type,
302 .sampleRate = sample_rate,
303 .channelMode = channel_mode,
304 .variableBitRateEnabled = variable_bitrate,
305 .bitsPerSample = bits_per_sample};
306 codec_config.config.aacConfig(aac);
307 audio_config.codecConfig(codec_config);
308 clientif_->UpdateAudioConfig(audio_config);
309 if (IsOffloadCodecConfigurationSupported(codec_config)) {
310 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
311 } else {
312 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
313 }
314 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
315 } // AacVariableBitRate
316 } // AacObjectType
317 } // peerMtu
318 } // ChannelMode
319 } // BitsPerSampple
320 } // SampleRate
321}
322
323TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) {
324 test_transport_ =
325 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
326 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
327 AudioConfiguration audio_config = {};
328 CodecConfiguration codec_config = {};
329 LdacQualityIndex quality_indexes[4] = {
330 LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
331 LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
332 for (auto sample_rate : kSampleRates) {
333 for (auto bits_per_sample : kBitsPerSamples) {
334 for (auto channel_mode : kChannelModes) {
335 for (auto peer_mtu : kPeerMtus) {
336 for (auto quality_index : quality_indexes) {
337 codec_config.codecType = CodecType::LDAC;
338 codec_config.peerMtu = peer_mtu;
339 codec_config.isScmstEnabled = false;
340 codec_config.encodedAudioBitrate = 990000;
341 LdacParameters ldac = {
342 .sampleRate = sample_rate,
343 .channelMode = (channel_mode == ChannelMode::MONO
344 ? LdacChannelMode::MONO
345 : LdacChannelMode::STEREO),
346 .qualityIndex = quality_index,
347 .bitsPerSample = bits_per_sample};
348 codec_config.config.ldacConfig(ldac);
349 audio_config.codecConfig(codec_config);
350 clientif_->UpdateAudioConfig(audio_config);
351 if (IsOffloadCodecConfigurationSupported(codec_config)) {
352 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
353 } else {
354 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
355 }
356 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
357 } // LdacQualityIndex
358 } // peerMtu
359 } // ChannelMode
360 } // BitsPerSampple
361 } // SampleRate
362}
363
364TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxSession) {
365 test_transport_ =
366 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
367 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
368 AudioConfiguration audio_config = {};
369 CodecConfiguration codec_config = {};
370 for (auto sample_rate : kSampleRates) {
371 for (auto bits_per_sample : kBitsPerSamples) {
372 for (auto channel_mode : kChannelModes) {
373 for (auto peer_mtu : kPeerMtus) {
374 codec_config.codecType = CodecType::APTX;
375 codec_config.peerMtu = peer_mtu;
376 codec_config.isScmstEnabled = false;
377 codec_config.encodedAudioBitrate = 352000;
378 AptxParameters aptx = {.sampleRate = sample_rate,
379 .channelMode = channel_mode,
380 .bitsPerSample = bits_per_sample};
381 codec_config.config.aptxConfig(aptx);
382 audio_config.codecConfig(codec_config);
383 clientif_->UpdateAudioConfig(audio_config);
384 if (IsOffloadCodecConfigurationSupported(codec_config)) {
385 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
386 } else {
387 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
388 }
389 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
390 } // peerMtu
391 } // ChannelMode
392 } // BitsPerSampple
393 } // SampleRate
394}
395
396TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxHdSession) {
397 test_transport_ =
398 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
399 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
400 AudioConfiguration audio_config = {};
401 CodecConfiguration codec_config = {};
402 for (auto sample_rate : kSampleRates) {
403 for (auto bits_per_sample : kBitsPerSamples) {
404 for (auto channel_mode : kChannelModes) {
405 for (auto peer_mtu : kPeerMtus) {
406 codec_config.codecType = CodecType::APTX_HD;
407 codec_config.peerMtu = peer_mtu;
408 codec_config.isScmstEnabled = false;
409 codec_config.encodedAudioBitrate = 576000;
410 AptxParameters aptx = {.sampleRate = sample_rate,
411 .channelMode = channel_mode,
412 .bitsPerSample = bits_per_sample};
413 codec_config.config.aptxConfig(aptx);
414 audio_config.codecConfig(codec_config);
415 clientif_->UpdateAudioConfig(audio_config);
416 if (IsOffloadCodecConfigurationSupported(codec_config)) {
417 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
418 } else {
419 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
420 }
421 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
422 } // peerMtu
423 } // ChannelMode
424 } // BitsPerSampple
425 } // SampleRate
426}
427
428TEST_F(BluetoothAudioClientInterfaceTest,
429 StartAndEndA2dpOffloadUnknownSession) {
430 test_transport_ =
431 new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
432 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
433 AudioConfiguration audio_config = {};
434 CodecConfiguration codec_config = {};
435 codec_config.codecType = CodecType::UNKNOWN;
436 codec_config.peerMtu = 1005;
437 codec_config.isScmstEnabled = false;
438 codec_config.encodedAudioBitrate = 328000;
439 codec_config.config = {};
440 audio_config.codecConfig(codec_config);
441 clientif_->UpdateAudioConfig(audio_config);
442 if (IsOffloadCodecConfigurationSupported(codec_config)) {
443 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
444 } else {
445 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
446 }
447 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
448}
449
450TEST_F(BluetoothAudioClientInterfaceTest,
451 StartAndEndHearingAidSoftwareSession) {
452 test_transport_ =
453 new TestTransport(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
454 clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
455 AudioConfiguration audio_config = {};
456 PcmParameters pcm_config = {};
457 for (auto sample_rate : kSampleRates) {
458 pcm_config.sampleRate = sample_rate;
459 for (auto bits_per_sample : kBitsPerSamples) {
460 pcm_config.bitsPerSample = bits_per_sample;
461 for (auto channel_mode : kChannelModes) {
462 pcm_config.channelMode = channel_mode;
463 audio_config.pcmConfig(pcm_config);
464 clientif_->UpdateAudioConfig(audio_config);
465 if (IsSoftwarePcmParametersSupported(pcm_config)) {
466 EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
467 } else {
468 EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
469 }
470 EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
471 } // ChannelMode
472 } // BitsPerSampple
473 } // SampleRate
474}