1 /*
2 * Copyright 2017 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 #define LOG_NDEBUG 0
18 #define LOG_TAG "AAudioTest"
19
20 #include <cstring>
21 #include <sstream>
22 #include <utility>
23
24 #include <aaudio/AAudio.h>
25 #include <android/log.h>
26 #include <android-base/properties.h>
27 #include <gtest/gtest.h>
28 #include <system/audio.h> /* FCC_LIMIT */
29
30 #include "utils.h"
31
32 /**
33 * See https://source.android.com/devices/tech/perf/low-ram
34 * for more details.
35 *
36 * @return true if running on low memory device
37 */
isLowRamDevice()38 static bool isLowRamDevice() {
39 return android::base::GetBoolProperty("ro.config.low_ram", false);
40 }
41
42 // Creates a builder, the caller takes ownership
create_stream_builder(AAudioStreamBuilder ** aaudioBuilder)43 static void create_stream_builder(AAudioStreamBuilder** aaudioBuilder) {
44 aaudio_result_t result = AAudio_createStreamBuilder(aaudioBuilder);
45 ASSERT_EQ(AAUDIO_OK, result);
46 ASSERT_NE(nullptr, *aaudioBuilder);
47 }
48
49 enum class Expect { FAIL, SUCCEED, NOT_CRASH };
50
51 // Tries to open an audio stream using a primed Builder.
52 // Takes ownership of the Builder.
try_opening_audio_stream(AAudioStreamBuilder * aaudioBuilder,Expect expect)53 static void try_opening_audio_stream(AAudioStreamBuilder *aaudioBuilder, Expect expect) {
54 // Create an AAudioStream using the Builder.
55 AAudioStream *aaudioStream = nullptr;
56 int64_t beforeTimeNanos = getNanoseconds();
57 aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
58 if (expect == Expect::FAIL) {
59 ASSERT_NE(AAUDIO_OK, result);
60 ASSERT_EQ(nullptr, aaudioStream);
61 } else if (expect == Expect::SUCCEED) {
62 ASSERT_EQ(AAUDIO_OK, result);
63 ASSERT_NE(nullptr, aaudioStream);
64 } else { // NOT_CRASH
65 ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
66 || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
67 }
68
69 // The stream should be open within one second.
70 static const int64_t kNanosPerSecond = 1e9;
71 ASSERT_LT(getNanoseconds() - beforeTimeNanos, kNanosPerSecond)
72 << "It took more than one second to open stream";
73
74 // Cleanup
75 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
76 if (aaudioStream != nullptr) {
77 beforeTimeNanos = getNanoseconds();
78 ASSERT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
79 // The stream should be closed within one second.
80 ASSERT_LT(getNanoseconds() - beforeTimeNanos, kNanosPerSecond)
81 << "It took more than one second to close stream";
82 }
83 }
84
85 // Test creating a default stream with specific devices
runtest_aaudio_devices(int32_t deviceId,Expect expect)86 static void runtest_aaudio_devices(int32_t deviceId, Expect expect) {
87 AAudioStreamBuilder *aaudioBuilder = nullptr;
88 create_stream_builder(&aaudioBuilder);
89 AAudioStreamBuilder_setDeviceId(aaudioBuilder, deviceId);
90 try_opening_audio_stream(aaudioBuilder, expect);
91 }
92
TEST(test_aaudio,aaudio_stream_device_unspecified)93 TEST(test_aaudio, aaudio_stream_device_unspecified) {
94 runtest_aaudio_devices(AAUDIO_UNSPECIFIED, Expect::NOT_CRASH);
95 }
96
97 /* FIXME - why can we open this device? What is an illegal deviceId?
98 TEST(test_aaudio, aaudio_stream_device_absurd) {
99 runtest_aaudio_devices(19736459, true);
100 }
101 */
102 /* FIXME review
103 TEST(test_aaudio, aaudio_stream_device_reasonable) {
104 runtest_aaudio_devices(1, false);
105 }
106 */
107
108 /* FIXME - why can we open this device? What is an illegal deviceId?
109 TEST(test_aaudio, aaudio_stream_device_negative) {
110 runtest_aaudio_devices(-765, true);
111 }
112 */
113
114 // Test creating a default stream with everything unspecified.
TEST(test_aaudio,aaudio_stream_unspecified)115 TEST(test_aaudio, aaudio_stream_unspecified) {
116 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
117 AAudioStreamBuilder *aaudioBuilder = nullptr;
118 create_stream_builder(&aaudioBuilder);
119
120 // Create an AAudioStream using the Builder.
121 AAudioStream *aaudioStream = nullptr;
122 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
123 ASSERT_NE(nullptr, aaudioStream);
124
125 // Cleanup
126 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
127 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
128 }
129
130 class AAudioStreamBuilderSamplingRateTest : public ::testing::TestWithParam<int32_t> {
131 public:
getTestName(const::testing::TestParamInfo<int32_t> & info)132 static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
133 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
134 }
135 protected:
isValidSamplingRate(int32_t sr)136 static bool isValidSamplingRate(int32_t sr) {
137 return sr == AAUDIO_UNSPECIFIED || (sr >= 8000 && sr <= 1000000);
138 }
139 };
140
TEST_P(AAudioStreamBuilderSamplingRateTest,openStream)141 TEST_P(AAudioStreamBuilderSamplingRateTest, openStream) {
142 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
143 const int32_t sampleRate = GetParam();
144 const bool isSampleRateValid = isValidSamplingRate(sampleRate);
145 // Opening a stream with a high sample rates can fail because the required buffer size
146 // is bigger than the heap size. This is a limitation in AudioFlinger. b/112528380
147 if (isSampleRateValid && isLowRamDevice() && (sampleRate > 192000)) {
148 return; // skip this test
149 }
150 AAudioStreamBuilder *aaudioBuilder = nullptr;
151 create_stream_builder(&aaudioBuilder);
152 AAudioStreamBuilder_setSampleRate(aaudioBuilder, sampleRate);
153 try_opening_audio_stream(
154 aaudioBuilder, isSampleRateValid ? Expect::SUCCEED : Expect::FAIL);
155 }
156
157 INSTANTIATE_TEST_CASE_P(SR, AAudioStreamBuilderSamplingRateTest,
158 ::testing::Values(
159 // Commonly used values
160 AAUDIO_UNSPECIFIED, 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000,
161 176400, 192000, 384000,
162 // Odd values
163 AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED + 1, 1234, 10000000),
164 &AAudioStreamBuilderSamplingRateTest::getTestName);
165
166 class AAudioStreamBuilderChannelCountTest : public ::testing::TestWithParam<int32_t> {
167 public:
getTestName(const::testing::TestParamInfo<int32_t> & info)168 static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
169 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
170 }
171 protected:
isValidChannelCount(int32_t cc)172 static bool isValidChannelCount(int32_t cc) {
173 return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= FCC_LIMIT);
174 }
175 };
176
TEST_P(AAudioStreamBuilderChannelCountTest,openStream)177 TEST_P(AAudioStreamBuilderChannelCountTest, openStream) {
178 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
179 AAudioStreamBuilder *aaudioBuilder = nullptr;
180 create_stream_builder(&aaudioBuilder);
181 AAudioStreamBuilder_setChannelCount(aaudioBuilder, GetParam());
182 try_opening_audio_stream(
183 aaudioBuilder, isValidChannelCount(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
184 }
185
186 INSTANTIATE_TEST_CASE_P(CC, AAudioStreamBuilderChannelCountTest,
187 ::testing::Values(
188 // Reasonable values that should work OK.
189 AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8, FCC_LIMIT,
190 // These values should fail.
191 AAUDIO_UNSPECIFIED - 1, (FCC_LIMIT + 1), 1000, 1000000),
192 &AAudioStreamBuilderChannelCountTest::getTestName);
193
194 class AAudioStreamBuilderFormatTest : public ::testing::TestWithParam<aaudio_format_t> {
195 public:
getTestName(const::testing::TestParamInfo<aaudio_format_t> & info)196 static std::string getTestName(const ::testing::TestParamInfo<aaudio_format_t>& info) {
197 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
198 }
199 protected:
isValidFormat(aaudio_format_t f)200 static bool isValidFormat(aaudio_format_t f) {
201 switch (f) {
202 case AAUDIO_FORMAT_UNSPECIFIED:
203 case AAUDIO_FORMAT_PCM_I16:
204 case AAUDIO_FORMAT_PCM_FLOAT:
205 return true;
206 }
207 return false;
208 }
209 };
210
TEST_P(AAudioStreamBuilderFormatTest,openStream)211 TEST_P(AAudioStreamBuilderFormatTest, openStream) {
212 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
213 AAudioStreamBuilder *aaudioBuilder = nullptr;
214 create_stream_builder(&aaudioBuilder);
215 AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
216 try_opening_audio_stream(
217 aaudioBuilder, isValidFormat(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
218 }
219
220 INSTANTIATE_TEST_CASE_P(F, AAudioStreamBuilderFormatTest,
221 ::testing::Values(
222 // Reasonable values
223 AAUDIO_FORMAT_UNSPECIFIED, AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
224 // Odd values
225 AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_INVALID - 1, 100, 1000000, 10000000),
226 &AAudioStreamBuilderFormatTest::getTestName);
227
228 class AAudioStreamBuilderSharingModeTest : public ::testing::TestWithParam<aaudio_sharing_mode_t> {
229 public:
getTestName(const::testing::TestParamInfo<aaudio_sharing_mode_t> & info)230 static std::string getTestName(const ::testing::TestParamInfo<aaudio_sharing_mode_t>& info) {
231 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
232 }
233 protected:
isValidSharingMode(aaudio_sharing_mode_t f)234 static bool isValidSharingMode(aaudio_sharing_mode_t f) {
235 return f == AAUDIO_SHARING_MODE_SHARED || f == AAUDIO_SHARING_MODE_EXCLUSIVE;
236 }
237 };
238
TEST_P(AAudioStreamBuilderSharingModeTest,openStream)239 TEST_P(AAudioStreamBuilderSharingModeTest, openStream) {
240 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
241 AAudioStreamBuilder *aaudioBuilder = nullptr;
242 create_stream_builder(&aaudioBuilder);
243 AAudioStreamBuilder_setSharingMode(aaudioBuilder, GetParam());
244 try_opening_audio_stream(
245 aaudioBuilder, isValidSharingMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
246 }
247
248 INSTANTIATE_TEST_CASE_P(SM, AAudioStreamBuilderSharingModeTest,
249 ::testing::Values(
250 // Reasonable values
251 AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE,
252 // Odd values
253 -1, 100, 1000000, 10000000),
254 &AAudioStreamBuilderSharingModeTest::getTestName);
255
256 class AAudioStreamBuilderDirectionTest : public ::testing::TestWithParam<aaudio_direction_t> {
257 public:
getTestName(const::testing::TestParamInfo<aaudio_direction_t> & info)258 static std::string getTestName(const ::testing::TestParamInfo<aaudio_direction_t>& info) {
259 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
260 }
261 protected:
isValidDirection(aaudio_direction_t f)262 static bool isValidDirection(aaudio_direction_t f) {
263 return f == AAUDIO_DIRECTION_OUTPUT || f == AAUDIO_DIRECTION_INPUT;
264 }
265 };
266
TEST_P(AAudioStreamBuilderDirectionTest,openStream)267 TEST_P(AAudioStreamBuilderDirectionTest, openStream) {
268 if (GetParam() == AAUDIO_DIRECTION_OUTPUT
269 && !deviceSupportsFeature(FEATURE_PLAYBACK)) return;
270 if (GetParam() == AAUDIO_DIRECTION_INPUT
271 && !deviceSupportsFeature(FEATURE_RECORDING)) return;
272 AAudioStreamBuilder *aaudioBuilder = nullptr;
273 create_stream_builder(&aaudioBuilder);
274 AAudioStreamBuilder_setDirection(aaudioBuilder, GetParam());
275 try_opening_audio_stream(
276 aaudioBuilder, isValidDirection(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
277 }
278
279 INSTANTIATE_TEST_CASE_P(SD, AAudioStreamBuilderDirectionTest,
280 ::testing::Values(
281 // Reasonable values
282 AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT,
283 // Odd values
284 -1, 100, 1000000, 10000000),
285 &AAudioStreamBuilderDirectionTest::getTestName);
286
287 class AAudioStreamBuilderBufferCapacityTest : public ::testing::TestWithParam<int32_t> {
288 public:
getTestName(const::testing::TestParamInfo<int32_t> & info)289 static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
290 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
291 }
292 protected:
293 // There is no hard defined limit, the actual maximum capacity depends
294 // on the implementation.
isValidCapacity(int32_t bc)295 static bool isValidCapacity(int32_t bc) {
296 return bc == AAUDIO_UNSPECIFIED || bc >= 0;
297 }
298 };
299
TEST_P(AAudioStreamBuilderBufferCapacityTest,openStream)300 TEST_P(AAudioStreamBuilderBufferCapacityTest, openStream) {
301 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
302 AAudioStreamBuilder *aaudioBuilder = nullptr;
303 create_stream_builder(&aaudioBuilder);
304 AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, GetParam());
305 try_opening_audio_stream(
306 aaudioBuilder, isValidCapacity(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
307 }
308
309 INSTANTIATE_TEST_CASE_P(BC, AAudioStreamBuilderBufferCapacityTest,
310 ::testing::Values(
311 // Reasonable values that should not fail
312 AAUDIO_UNSPECIFIED, 8 * 192, 2 * 1024,
313 // Odd values
314 AAUDIO_UNSPECIFIED - 1),
315 &AAudioStreamBuilderBufferCapacityTest::getTestName);
316
317 class AAudioStreamBuilderPerfModeTest : public ::testing::TestWithParam<aaudio_performance_mode_t> {
318 public:
getTestName(const::testing::TestParamInfo<aaudio_performance_mode_t> & info)319 static std::string getTestName(const ::testing::TestParamInfo<aaudio_performance_mode_t>& info) {
320 return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
321 }
322 protected:
isValidPerfMode(aaudio_performance_mode_t pm)323 static bool isValidPerfMode(aaudio_performance_mode_t pm) {
324 switch (pm) {
325 case AAUDIO_PERFORMANCE_MODE_NONE:
326 case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
327 case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
328 return true;
329 }
330 return false;
331 }
332 };
333
TEST_P(AAudioStreamBuilderPerfModeTest,openStream)334 TEST_P(AAudioStreamBuilderPerfModeTest, openStream) {
335 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
336 AAudioStreamBuilder *aaudioBuilder = nullptr;
337 create_stream_builder(&aaudioBuilder);
338 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, GetParam());
339 try_opening_audio_stream(
340 aaudioBuilder, isValidPerfMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
341 }
342
343 INSTANTIATE_TEST_CASE_P(PM, AAudioStreamBuilderPerfModeTest,
344 ::testing::Values(
345 // Reasonable values
346 AAUDIO_PERFORMANCE_MODE_NONE,
347 AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
348 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
349 // Odd values
350 AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED, 100, 1000000, 10000000),
351 &AAudioStreamBuilderPerfModeTest::getTestName);
352
353 class AAudioStreamBuilderChannelMaskTest : public ::testing::TestWithParam<aaudio_channel_mask_t> {
354 public:
getTestName(const::testing::TestParamInfo<aaudio_channel_mask_t> & info)355 static std::string getTestName(const ::testing::TestParamInfo<aaudio_channel_mask_t>& info) {
356 std::stringstream ss;
357 ss << "0x" << std::hex << info.param;
358 return ss.str();
359 }
360 protected:
361
isValidChannelMask(aaudio_channel_mask_t channelMask,bool isInput)362 static bool isValidChannelMask(aaudio_channel_mask_t channelMask, bool isInput) {
363 if (channelMask == AAUDIO_UNSPECIFIED) {
364 return true;
365 }
366
367 if (__builtin_popcount(channelMask) > FCC_LIMIT) {
368 return false;
369 }
370
371 if (isInput) {
372 switch (channelMask) {
373 case AAUDIO_CHANNEL_MONO:
374 case AAUDIO_CHANNEL_STEREO:
375 case AAUDIO_CHANNEL_FRONT_BACK:
376 case AAUDIO_CHANNEL_2POINT0POINT2:
377 case AAUDIO_CHANNEL_2POINT1POINT2:
378 case AAUDIO_CHANNEL_3POINT0POINT2:
379 case AAUDIO_CHANNEL_3POINT1POINT2:
380 case AAUDIO_CHANNEL_5POINT1:
381 return true;
382 }
383 return false;
384 } else {
385 switch (channelMask) {
386 case AAUDIO_CHANNEL_MONO:
387 case AAUDIO_CHANNEL_STEREO:
388 case AAUDIO_CHANNEL_2POINT1:
389 case AAUDIO_CHANNEL_TRI:
390 case AAUDIO_CHANNEL_TRI_BACK:
391 case AAUDIO_CHANNEL_3POINT1:
392 case AAUDIO_CHANNEL_2POINT0POINT2:
393 case AAUDIO_CHANNEL_2POINT1POINT2:
394 case AAUDIO_CHANNEL_3POINT0POINT2:
395 case AAUDIO_CHANNEL_3POINT1POINT2:
396 case AAUDIO_CHANNEL_QUAD:
397 case AAUDIO_CHANNEL_QUAD_SIDE:
398 case AAUDIO_CHANNEL_SURROUND:
399 case AAUDIO_CHANNEL_PENTA:
400 case AAUDIO_CHANNEL_5POINT1:
401 case AAUDIO_CHANNEL_5POINT1_SIDE:
402 case AAUDIO_CHANNEL_5POINT1POINT2:
403 case AAUDIO_CHANNEL_5POINT1POINT4:
404 case AAUDIO_CHANNEL_6POINT1:
405 case AAUDIO_CHANNEL_7POINT1:
406 case AAUDIO_CHANNEL_7POINT1POINT2:
407 case AAUDIO_CHANNEL_7POINT1POINT4:
408 case AAUDIO_CHANNEL_9POINT1POINT4:
409 case AAUDIO_CHANNEL_9POINT1POINT6:
410 return true;
411 }
412 return false;
413 }
414 }
415
416 void testChannelMask(aaudio_channel_mask_t channelMask, aaudio_direction_t direction);
417 };
418
testChannelMask(aaudio_channel_mask_t channelMask,aaudio_direction_t direction)419 void AAudioStreamBuilderChannelMaskTest::testChannelMask(aaudio_channel_mask_t channelMask,
420 aaudio_direction_t direction) {
421 AAudioStreamBuilder *aaudioBuilder = nullptr;
422 create_stream_builder(&aaudioBuilder);
423 AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
424 AAudioStreamBuilder_setChannelMask(aaudioBuilder, channelMask);
425 const Expect expect =
426 isValidChannelMask(channelMask, direction) ? Expect::SUCCEED : Expect::FAIL;
427 AAudioStream *aaudioStream = nullptr;
428 aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
429 if (expect == Expect::FAIL) {
430 ASSERT_NE(AAUDIO_OK, result);
431 ASSERT_EQ(nullptr, aaudioStream);
432 } else if (expect == Expect::SUCCEED) {
433 ASSERT_EQ(AAUDIO_OK, result);
434 ASSERT_NE(nullptr, aaudioStream);
435 ASSERT_NE(0, AAudioStream_getChannelCount(aaudioStream));
436 ASSERT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getChannelMask(aaudioStream));
437 ASSERT_NE(AAUDIO_CHANNEL_INVALID, AAudioStream_getChannelMask(aaudioStream));
438 } else { // NOT_CRASH
439 ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
440 || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
441 }
442
443 // Cleanup
444 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
445 if (aaudioStream != nullptr) {
446 ASSERT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
447 }
448 }
449
TEST_P(AAudioStreamBuilderChannelMaskTest,openInputStream)450 TEST_P(AAudioStreamBuilderChannelMaskTest, openInputStream) {
451 if (!deviceSupportsFeature(FEATURE_RECORDING)) {
452 return;
453 }
454 testChannelMask(GetParam(), AAUDIO_DIRECTION_INPUT);
455 }
456
TEST_P(AAudioStreamBuilderChannelMaskTest,openOutputStream)457 TEST_P(AAudioStreamBuilderChannelMaskTest, openOutputStream) {
458 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) {
459 return;
460 }
461 testChannelMask(GetParam(), AAUDIO_DIRECTION_OUTPUT);
462 }
463
464 INSTANTIATE_TEST_CASE_P(
465 CM, AAudioStreamBuilderChannelMaskTest,
466 ::testing::Values(
467 // UNSPECIFIED is valid channel mask
468 AAUDIO_UNSPECIFIED,
469 AAUDIO_CHANNEL_INVALID,
470 // Channel mask listed in audio.h
471 // AAUDIO_CHANNEL_FRONT_LEFT,
472 AAUDIO_CHANNEL_FRONT_RIGHT,
473 AAUDIO_CHANNEL_FRONT_CENTER,
474 AAUDIO_CHANNEL_LOW_FREQUENCY,
475 AAUDIO_CHANNEL_BACK_LEFT,
476 AAUDIO_CHANNEL_BACK_RIGHT,
477 AAUDIO_CHANNEL_FRONT_LEFT_OF_CENTER,
478 AAUDIO_CHANNEL_FRONT_RIGHT_OF_CENTER,
479 AAUDIO_CHANNEL_BACK_CENTER,
480 AAUDIO_CHANNEL_SIDE_LEFT,
481 AAUDIO_CHANNEL_SIDE_RIGHT,
482 AAUDIO_CHANNEL_TOP_CENTER,
483 AAUDIO_CHANNEL_TOP_FRONT_LEFT,
484 AAUDIO_CHANNEL_TOP_FRONT_CENTER,
485 AAUDIO_CHANNEL_TOP_FRONT_RIGHT,
486 AAUDIO_CHANNEL_TOP_BACK_LEFT,
487 AAUDIO_CHANNEL_TOP_BACK_CENTER,
488 AAUDIO_CHANNEL_TOP_BACK_RIGHT,
489 AAUDIO_CHANNEL_TOP_SIDE_LEFT,
490 AAUDIO_CHANNEL_TOP_SIDE_RIGHT,
491 AAUDIO_CHANNEL_BOTTOM_FRONT_LEFT,
492 AAUDIO_CHANNEL_BOTTOM_FRONT_CENTER,
493 AAUDIO_CHANNEL_BOTTOM_FRONT_RIGHT,
494 AAUDIO_CHANNEL_LOW_FREQUENCY_2,
495 AAUDIO_CHANNEL_FRONT_WIDE_LEFT,
496 AAUDIO_CHANNEL_FRONT_WIDE_RIGHT,
497 AAUDIO_CHANNEL_MONO,
498 AAUDIO_CHANNEL_STEREO,
499 AAUDIO_CHANNEL_2POINT1,
500 AAUDIO_CHANNEL_TRI,
501 AAUDIO_CHANNEL_TRI_BACK,
502 AAUDIO_CHANNEL_3POINT1,
503 AAUDIO_CHANNEL_2POINT0POINT2,
504 AAUDIO_CHANNEL_2POINT1POINT2,
505 AAUDIO_CHANNEL_3POINT0POINT2,
506 AAUDIO_CHANNEL_3POINT1POINT2,
507 AAUDIO_CHANNEL_QUAD,
508 AAUDIO_CHANNEL_QUAD_SIDE,
509 AAUDIO_CHANNEL_SURROUND,
510 AAUDIO_CHANNEL_PENTA,
511 AAUDIO_CHANNEL_5POINT1,
512 AAUDIO_CHANNEL_5POINT1_SIDE,
513 AAUDIO_CHANNEL_6POINT1,
514 AAUDIO_CHANNEL_7POINT1,
515 AAUDIO_CHANNEL_5POINT1POINT2,
516 AAUDIO_CHANNEL_5POINT1POINT4,
517 AAUDIO_CHANNEL_7POINT1POINT2,
518 AAUDIO_CHANNEL_7POINT1POINT4,
519 AAUDIO_CHANNEL_9POINT1POINT4,
520 AAUDIO_CHANNEL_9POINT1POINT6,
521 AAUDIO_CHANNEL_FRONT_BACK,
522 // Odd value
523 0x20000000,
524 0x30000000,
525 0x40000005),
526 &AAudioStreamBuilderChannelMaskTest::getTestName);
527
528 using ChannelMaskAndCountParams = std::pair<aaudio_direction_t, aaudio_channel_mask_t>;
529 class AAudioStreamBuilderChannelMaskAndCountTest :
530 public ::testing::TestWithParam<ChannelMaskAndCountParams> {
531 public:
getTestName(const::testing::TestParamInfo<ChannelMaskAndCountParams> & info)532 static std::string getTestName(
533 const ::testing::TestParamInfo<ChannelMaskAndCountParams>& info) {
534 std::stringstream ss;
535 ss << (info.param.first == AAUDIO_DIRECTION_INPUT ? "INPUT_0x" : "OUTPUT_0x")
536 << std::hex << info.param.second;
537 return ss.str();
538 }
539
540 protected:
541 void testSetChannelMaskAndCount(aaudio_direction_t direction,
542 aaudio_channel_mask_t channelMask,
543 int32_t channelCount,
544 bool channelMaskFirst);
545 };
546
testSetChannelMaskAndCount(aaudio_direction_t direction,aaudio_channel_mask_t channelMask,int32_t channelCount,bool setChannelMaskFirst)547 void AAudioStreamBuilderChannelMaskAndCountTest::testSetChannelMaskAndCount(
548 aaudio_direction_t direction, aaudio_channel_mask_t channelMask,
549 int32_t channelCount, bool setChannelMaskFirst) {
550 AAudioStreamBuilder *aaudioBuilder = nullptr;
551 create_stream_builder(&aaudioBuilder);
552 AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
553 if (setChannelMaskFirst) {
554 AAudioStreamBuilder_setChannelMask(aaudioBuilder, channelMask);
555 AAudioStreamBuilder_setChannelCount(aaudioBuilder, channelCount);
556 } else {
557 AAudioStreamBuilder_setChannelCount(aaudioBuilder, channelCount);
558 AAudioStreamBuilder_setChannelMask(aaudioBuilder, channelMask);
559 }
560 AAudioStream *aaudioStream = nullptr;
561 aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
562 ASSERT_EQ(AAUDIO_OK, result);
563 ASSERT_NE(nullptr, aaudioStream);
564 if (setChannelMaskFirst) {
565 ASSERT_EQ(channelCount, AAudioStream_getChannelCount(aaudioStream));
566 ASSERT_EQ(AAUDIO_UNSPECIFIED, AAudioStream_getChannelMask(aaudioStream));
567 } else {
568 // If channel mask is unspecified, stereo will be returned.
569 ASSERT_EQ(channelMask == AAUDIO_UNSPECIFIED ? AAUDIO_CHANNEL_STEREO : channelMask,
570 AAudioStream_getChannelMask(aaudioStream));
571 ASSERT_EQ(channelMask == AAUDIO_UNSPECIFIED ? 2 : __builtin_popcount(channelMask),
572 AAudioStream_getChannelCount(aaudioStream));
573 }
574 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
575 if (aaudioStream != nullptr) {
576 ASSERT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
577 }
578 }
579
TEST_P(AAudioStreamBuilderChannelMaskAndCountTest,channelMaskAndCount)580 TEST_P(AAudioStreamBuilderChannelMaskAndCountTest, channelMaskAndCount) {
581 const aaudio_direction_t direction = GetParam().first;
582 if ((direction == AAUDIO_DIRECTION_OUTPUT && !deviceSupportsFeature(FEATURE_PLAYBACK)) ||
583 (direction == AAUDIO_DIRECTION_INPUT && !deviceSupportsFeature(FEATURE_RECORDING))) {
584 return;
585 }
586 const aaudio_channel_mask_t channelMask = GetParam().second;
587
588 testSetChannelMaskAndCount(direction, channelMask,
589 2 /*channelCount*/, true /*setChannelMaskFirst*/);
590 testSetChannelMaskAndCount(direction, channelMask,
591 2 /*channelCount*/, false /*setChannelMaskFirst*/);
592
593 testSetChannelMaskAndCount(direction, AAUDIO_CHANNEL_5POINT1,
594 2 /*channelCount*/, true /*setChannelMaskFirst*/);
595 testSetChannelMaskAndCount(direction, AAUDIO_CHANNEL_5POINT1,
596 2 /*channelCount*/, false /*setChannelMaskFirst*/);
597 }
598
599 INSTANTIATE_TEST_CASE_P(CMC, AAudioStreamBuilderChannelMaskAndCountTest,
600 ::testing::Values(
601 std::make_pair(AAUDIO_DIRECTION_OUTPUT, AAUDIO_CHANNEL_MONO),
602 std::make_pair(AAUDIO_DIRECTION_OUTPUT, AAUDIO_CHANNEL_5POINT1),
603 std::make_pair(AAUDIO_DIRECTION_OUTPUT, AAUDIO_UNSPECIFIED),
604 std::make_pair(AAUDIO_DIRECTION_INPUT, AAUDIO_CHANNEL_MONO),
605 std::make_pair(AAUDIO_DIRECTION_INPUT, AAUDIO_CHANNEL_5POINT1),
606 std::make_pair(AAUDIO_DIRECTION_INPUT, AAUDIO_UNSPECIFIED)),
607 &AAudioStreamBuilderChannelMaskAndCountTest::getTestName);
608
609 using CommonCombinationTestParams = std::tuple<aaudio_direction_t,
610 aaudio_sharing_mode_t,
611 aaudio_performance_mode_t,
612 int32_t /*sample rate*/,
613 aaudio_format_t,
614 aaudio_channel_mask_t>;
615 enum {
616 PARAM_DIRECTION = 0,
617 PARAM_SHARING_MODE,
618 PARAM_PERFORMANCE_MODE,
619 PARAM_SAMPLE_RATE,
620 PARAM_FORMAT,
621 PARAM_CHANNEL_MASK
622 };
623 class AAudioStreamBuilderCommonCombinationTest :
624 public ::testing::TestWithParam<CommonCombinationTestParams> {
625 public:
getTestName(const::testing::TestParamInfo<CommonCombinationTestParams> & info)626 static std::string getTestName(
627 const ::testing::TestParamInfo<CommonCombinationTestParams>& info) {
628 std::stringstream ss;
629 ss << (std::get<PARAM_DIRECTION>(info.param) == AAUDIO_DIRECTION_INPUT ? "INPUT_"
630 : "OUTPUT_")
631 << sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param)) << "_"
632 << performanceModeToString(std::get<PARAM_PERFORMANCE_MODE>(info.param)) << "_"
633 << "sampleRate_" << std::get<PARAM_SAMPLE_RATE>(info.param) << "_"
634 << "format_0x" << std::hex << std::get<PARAM_FORMAT>(info.param) << "_"
635 << "channelMask_0x" << std::get<PARAM_CHANNEL_MASK>(info.param) << "";
636 return ss.str();
637 }
638 };
639
TEST_P(AAudioStreamBuilderCommonCombinationTest,openStream)640 TEST_P(AAudioStreamBuilderCommonCombinationTest, openStream) {
641 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
642 AAudioStreamBuilder *aaudioBuilder = nullptr;
643 create_stream_builder(&aaudioBuilder);
644 const auto param = GetParam();
645 AAudioStreamBuilder_setDirection(aaudioBuilder, std::get<PARAM_DIRECTION>(param));
646 AAudioStreamBuilder_setSharingMode(aaudioBuilder, std::get<PARAM_SHARING_MODE>(param));
647 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, std::get<PARAM_PERFORMANCE_MODE>(param));
648 AAudioStreamBuilder_setSampleRate(aaudioBuilder, std::get<PARAM_SAMPLE_RATE>(param));
649 AAudioStreamBuilder_setFormat(aaudioBuilder, std::get<PARAM_FORMAT>(param));
650 AAudioStreamBuilder_setChannelMask(aaudioBuilder, std::get<PARAM_CHANNEL_MASK>(param));
651 // All the test parameters all reasonable values with different combination. In that case,
652 // it is expected that the opening will be successful.
653 try_opening_audio_stream(aaudioBuilder, Expect::SUCCEED);
654 }
655
656 INSTANTIATE_TEST_CASE_P(CommonComb, AAudioStreamBuilderCommonCombinationTest,
657 ::testing::Combine(
658 ::testing::Values(AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT),
659 ::testing::Values(AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE),
660 ::testing::Values(
661 AAUDIO_PERFORMANCE_MODE_NONE,
662 AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
663 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY),
664 ::testing::Values(// Sample rate
665 AAUDIO_UNSPECIFIED, 8000, 16000, 44100, 48000, 96000, 192000),
666 ::testing::Values(
667 AAUDIO_UNSPECIFIED,
668 AAUDIO_FORMAT_PCM_I16,
669 AAUDIO_FORMAT_PCM_FLOAT),
670 ::testing::Values(AAUDIO_CHANNEL_MONO, AAUDIO_CHANNEL_STEREO)),
671 &AAudioStreamBuilderCommonCombinationTest::getTestName);
672