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 <aaudio/AAudio.h>
21 #include <android/log.h>
22 #include <gtest/gtest.h>
23 
24 // Creates a builder, the caller takes ownership
create_stream_builder(AAudioStreamBuilder ** aaudioBuilder)25 static void create_stream_builder(AAudioStreamBuilder** aaudioBuilder) {
26     aaudio_result_t result = AAudio_createStreamBuilder(aaudioBuilder);
27     ASSERT_EQ(AAUDIO_OK, result);
28     ASSERT_NE(nullptr, *aaudioBuilder);
29 }
30 
31 enum class Expect { FAIL, SUCCEED, NOT_CRASH };
32 
33 // Tries to open an audio stream using a primed Builder.
34 // Takes ownership of the Builder.
try_opening_audio_stream(AAudioStreamBuilder * aaudioBuilder,Expect expect)35 static void try_opening_audio_stream(AAudioStreamBuilder *aaudioBuilder, Expect expect) {
36     // Create an AAudioStream using the Builder.
37     AAudioStream *aaudioStream = nullptr;
38     aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
39     if (expect == Expect::FAIL) {
40         ASSERT_NE(AAUDIO_OK, result);
41         ASSERT_EQ(nullptr, aaudioStream);
42     } else if (expect == Expect::SUCCEED) {
43         ASSERT_EQ(AAUDIO_OK, result);
44         ASSERT_NE(nullptr, aaudioStream);
45     } else { // NOT_CRASH
46         ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
47                 || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
48     }
49 
50     // Cleanup
51     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
52     if (aaudioStream != nullptr) {
53         ASSERT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
54     }
55 }
56 
57 // Test creating a default stream with specific devices
runtest_aaudio_devices(int32_t deviceId,Expect expect)58 static void runtest_aaudio_devices(int32_t deviceId, Expect expect) {
59     AAudioStreamBuilder *aaudioBuilder = nullptr;
60     create_stream_builder(&aaudioBuilder);
61     AAudioStreamBuilder_setDeviceId(aaudioBuilder, deviceId);
62     try_opening_audio_stream(aaudioBuilder, expect);
63 }
64 
TEST(test_aaudio,aaudio_stream_device_unspecified)65 TEST(test_aaudio, aaudio_stream_device_unspecified) {
66     runtest_aaudio_devices(AAUDIO_UNSPECIFIED, Expect::NOT_CRASH);
67 }
68 
69 /* FIXME - why can we open this device? What is an illegal deviceId?
70 TEST(test_aaudio, aaudio_stream_device_absurd) {
71     runtest_aaudio_devices(19736459, true);
72 }
73 */
74 /* FIXME review
75 TEST(test_aaudio, aaudio_stream_device_reasonable) {
76     runtest_aaudio_devices(1, false);
77 }
78 */
79 
80 /* FIXME - why can we open this device? What is an illegal deviceId?
81 TEST(test_aaudio, aaudio_stream_device_negative) {
82     runtest_aaudio_devices(-765, true);
83 }
84 */
85 
86 // Test creating a default stream with everything unspecified.
TEST(test_aaudio,aaudio_stream_unspecified)87 TEST(test_aaudio, aaudio_stream_unspecified) {
88     AAudioStreamBuilder *aaudioBuilder = nullptr;
89     create_stream_builder(&aaudioBuilder);
90 
91     // Create an AAudioStream using the Builder.
92     AAudioStream *aaudioStream = nullptr;
93     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
94     ASSERT_NE(nullptr, aaudioStream);
95 
96     // Cleanup
97     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
98     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
99 }
100 
101 class AAudioStreamBuilderSamplingRateTest : public ::testing::TestWithParam<int32_t> {
102   public:
getTestName(const::testing::TestParamInfo<int32_t> & info)103     static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
104         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
105     }
106   protected:
isValidSamplingRate(int32_t sr)107     static bool isValidSamplingRate(int32_t sr) {
108         return sr == AAUDIO_UNSPECIFIED || (sr >= 8000 && sr <= 1000000);
109     }
110 };
111 
TEST_P(AAudioStreamBuilderSamplingRateTest,openStream)112 TEST_P(AAudioStreamBuilderSamplingRateTest, openStream) {
113     AAudioStreamBuilder *aaudioBuilder = nullptr;
114     create_stream_builder(&aaudioBuilder);
115     AAudioStreamBuilder_setSampleRate(aaudioBuilder, GetParam());
116     try_opening_audio_stream(
117             aaudioBuilder, isValidSamplingRate(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
118 }
119 
120 INSTANTIATE_TEST_CASE_P(SR, AAudioStreamBuilderSamplingRateTest,
121         ::testing::Values(
122                 // Commonly used values
123                 AAUDIO_UNSPECIFIED, 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000,
124                 176400, 192000, 384000,
125                 // Odd values
126                 AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED + 1, 1234, 10000000),
127         &AAudioStreamBuilderSamplingRateTest::getTestName);
128 
129 class AAudioStreamBuilderChannelCountTest : public ::testing::TestWithParam<int32_t> {
130   public:
getTestName(const::testing::TestParamInfo<int32_t> & info)131     static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
132         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
133     }
134   protected:
isValidChannelCount(int32_t cc)135     static bool isValidChannelCount(int32_t cc) {
136         return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= 8);
137     }
138 };
139 
TEST_P(AAudioStreamBuilderChannelCountTest,openStream)140 TEST_P(AAudioStreamBuilderChannelCountTest, openStream) {
141     AAudioStreamBuilder *aaudioBuilder = nullptr;
142     create_stream_builder(&aaudioBuilder);
143     AAudioStreamBuilder_setChannelCount(aaudioBuilder, GetParam());
144     try_opening_audio_stream(
145             aaudioBuilder, isValidChannelCount(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
146 }
147 
148 INSTANTIATE_TEST_CASE_P(CC, AAudioStreamBuilderChannelCountTest,
149         ::testing::Values(
150                 // Reasonable values
151                 AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8,
152                 // Odd values
153                 AAUDIO_UNSPECIFIED - 1, 9, 100, 1000000, 10000000),
154         &AAudioStreamBuilderChannelCountTest::getTestName);
155 
156 class AAudioStreamBuilderFormatTest : public ::testing::TestWithParam<aaudio_format_t> {
157   public:
getTestName(const::testing::TestParamInfo<aaudio_format_t> & info)158     static std::string getTestName(const ::testing::TestParamInfo<aaudio_format_t>& info) {
159         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
160     }
161   protected:
isValidFormat(aaudio_format_t f)162     static bool isValidFormat(aaudio_format_t f) {
163         switch (f) {
164             case AAUDIO_FORMAT_UNSPECIFIED:
165             case AAUDIO_FORMAT_PCM_I16:
166             case AAUDIO_FORMAT_PCM_FLOAT:
167                 return true;
168         }
169         return false;
170     }
171 };
172 
TEST_P(AAudioStreamBuilderFormatTest,openStream)173 TEST_P(AAudioStreamBuilderFormatTest, openStream) {
174     AAudioStreamBuilder *aaudioBuilder = nullptr;
175     create_stream_builder(&aaudioBuilder);
176     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
177     try_opening_audio_stream(
178             aaudioBuilder, isValidFormat(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
179 }
180 
181 INSTANTIATE_TEST_CASE_P(F, AAudioStreamBuilderFormatTest,
182         ::testing::Values(
183                 // Reasonable values
184                 AAUDIO_FORMAT_UNSPECIFIED, AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
185                 // Odd values
186                 AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_INVALID - 1, 100, 1000000, 10000000),
187         &AAudioStreamBuilderFormatTest::getTestName);
188 
189 class AAudioStreamBuilderSharingModeTest : public ::testing::TestWithParam<aaudio_sharing_mode_t> {
190   public:
getTestName(const::testing::TestParamInfo<aaudio_sharing_mode_t> & info)191     static std::string getTestName(const ::testing::TestParamInfo<aaudio_sharing_mode_t>& info) {
192         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
193     }
194   protected:
isValidSharingMode(aaudio_sharing_mode_t f)195     static bool isValidSharingMode(aaudio_sharing_mode_t f) {
196         return f == AAUDIO_SHARING_MODE_SHARED || f == AAUDIO_SHARING_MODE_EXCLUSIVE;
197     }
198 };
199 
TEST_P(AAudioStreamBuilderSharingModeTest,openStream)200 TEST_P(AAudioStreamBuilderSharingModeTest, openStream) {
201     AAudioStreamBuilder *aaudioBuilder = nullptr;
202     create_stream_builder(&aaudioBuilder);
203     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
204     try_opening_audio_stream(
205             aaudioBuilder, isValidSharingMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
206 }
207 
208 INSTANTIATE_TEST_CASE_P(SM, AAudioStreamBuilderSharingModeTest,
209         ::testing::Values(
210                 // Reasonable values
211                 AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE,
212                 // Odd values
213                 -1, 100, 1000000, 10000000),
214         &AAudioStreamBuilderSharingModeTest::getTestName);
215 
216 class AAudioStreamBuilderDirectionTest : public ::testing::TestWithParam<aaudio_direction_t> {
217   public:
getTestName(const::testing::TestParamInfo<aaudio_direction_t> & info)218     static std::string getTestName(const ::testing::TestParamInfo<aaudio_direction_t>& info) {
219         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
220     }
221   protected:
isValidSharingMode(aaudio_direction_t f)222     static bool isValidSharingMode(aaudio_direction_t f) {
223         return f == AAUDIO_DIRECTION_OUTPUT || f == AAUDIO_DIRECTION_INPUT;
224     }
225 };
226 
TEST_P(AAudioStreamBuilderDirectionTest,openStream)227 TEST_P(AAudioStreamBuilderDirectionTest, openStream) {
228     AAudioStreamBuilder *aaudioBuilder = nullptr;
229     create_stream_builder(&aaudioBuilder);
230     AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
231     try_opening_audio_stream(
232             aaudioBuilder, isValidSharingMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
233 }
234 
235 INSTANTIATE_TEST_CASE_P(SD, AAudioStreamBuilderDirectionTest,
236         ::testing::Values(
237                 // Reasonable values
238                 AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT,
239                 // Odd values
240                 -1, 100, 1000000, 10000000),
241         &AAudioStreamBuilderDirectionTest::getTestName);
242 
243 class AAudioStreamBuilderBufferCapacityTest : public ::testing::TestWithParam<int32_t> {
244   public:
getTestName(const::testing::TestParamInfo<int32_t> & info)245     static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
246         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
247     }
248   protected:
249     // There is no hard defined limit, the actual maximum capacity depends
250     // on the implementation.
isValidCapacity(int32_t bc)251     static bool isValidCapacity(int32_t bc) {
252         return bc == AAUDIO_UNSPECIFIED || bc >= 0;
253     }
254 };
255 
TEST_P(AAudioStreamBuilderBufferCapacityTest,openStream)256 TEST_P(AAudioStreamBuilderBufferCapacityTest, openStream) {
257     AAudioStreamBuilder *aaudioBuilder = nullptr;
258     create_stream_builder(&aaudioBuilder);
259     AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, GetParam());
260     try_opening_audio_stream(
261             aaudioBuilder, isValidCapacity(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
262 }
263 
264 INSTANTIATE_TEST_CASE_P(BC, AAudioStreamBuilderBufferCapacityTest,
265         ::testing::Values(
266                 // Reasonable values that should not fail
267                 AAUDIO_UNSPECIFIED, 8 * 192, 2 * 1024,
268                 // Odd values
269                 AAUDIO_UNSPECIFIED - 1),
270         &AAudioStreamBuilderBufferCapacityTest::getTestName);
271 
272 class AAudioStreamBuilderPerfModeTest : public ::testing::TestWithParam<aaudio_performance_mode_t> {
273   public:
getTestName(const::testing::TestParamInfo<aaudio_performance_mode_t> & info)274     static std::string getTestName(const ::testing::TestParamInfo<aaudio_performance_mode_t>& info) {
275         return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
276     }
277   protected:
isValidPerfMode(aaudio_performance_mode_t pm)278     static bool isValidPerfMode(aaudio_performance_mode_t pm) {
279         switch (pm) {
280             case AAUDIO_PERFORMANCE_MODE_NONE:
281             case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
282             case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
283                 return true;
284         }
285         return false;
286     }
287 };
288 
TEST_P(AAudioStreamBuilderPerfModeTest,openStream)289 TEST_P(AAudioStreamBuilderPerfModeTest, openStream) {
290     AAudioStreamBuilder *aaudioBuilder = nullptr;
291     create_stream_builder(&aaudioBuilder);
292     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, GetParam());
293     try_opening_audio_stream(
294             aaudioBuilder, isValidPerfMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
295 }
296 
297 INSTANTIATE_TEST_CASE_P(PM, AAudioStreamBuilderPerfModeTest,
298         ::testing::Values(
299                 // Reasonable values
300                 AAUDIO_PERFORMANCE_MODE_NONE,
301                 AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
302                 AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
303                 // Odd values
304                 AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED, 100, 1000000, 10000000),
305         &AAudioStreamBuilderPerfModeTest::getTestName);
306