blob: dc19985d57110ffdd8ee24813173a7f3c1bc650e [file] [log] [blame]
Phil Burk9a9e6002017-11-17 12:17:37 -08001/*
2 * Copyright (C) 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// Test various AAudio features including AAudioStream_setBufferSizeInFrames().
18
Phil Burk2581ae22017-11-21 15:47:29 -080019#include <condition_variable>
20#include <mutex>
Phil Burk9a9e6002017-11-17 12:17:37 -080021#include <stdio.h>
Phil Burk9a9e6002017-11-17 12:17:37 -080022
23#include <android-base/macros.h>
24#include <aaudio/AAudio.h>
25
26#include <gtest/gtest.h>
Phil Burk2581ae22017-11-21 15:47:29 -080027#include <unistd.h>
28
Phil Burk9a9e6002017-11-17 12:17:37 -080029
30// Callback function that does nothing.
Phil Burk2581ae22017-11-21 15:47:29 -080031aaudio_data_callback_result_t NoopDataCallbackProc(
Phil Burk9a9e6002017-11-17 12:17:37 -080032 AAudioStream *stream,
33 void *userData,
34 void *audioData,
35 int32_t numFrames
36) {
37 (void) stream;
38 (void) userData;
39 (void) audioData;
40 (void) numFrames;
41 return AAUDIO_CALLBACK_RESULT_CONTINUE;
42}
43
44// Test AAudioStream_setBufferSizeInFrames()
45
Phil Burk0c15f4f2017-11-28 15:46:15 -080046constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
47
48//int foo() { // To fix Android Studio formatting when editing.
49TEST(test_various, aaudio_stop_when_open) {
50 AAudioStreamBuilder *aaudioBuilder = nullptr;
51 AAudioStream *aaudioStream = nullptr;
52
53// Use an AAudioStreamBuilder to contain requested parameters.
54 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
55
56// Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -080057 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk0c15f4f2017-11-28 15:46:15 -080058 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
59
60// Create an AAudioStream using the Builder.
61 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
62
63
64 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
65 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
66 AAUDIO_STREAM_STATE_UNKNOWN, &state,
67 1000 * NANOS_PER_MILLISECOND));
68 EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
69
70 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
71
72 state = AAUDIO_STREAM_STATE_UNKNOWN;
73 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
74 AAUDIO_STREAM_STATE_UNKNOWN, &state, 0));
75 EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
76
77 AAudioStream_close(aaudioStream);
78 AAudioStreamBuilder_delete(aaudioBuilder);
79}
80
81//int boo() { // To fix Android Studio formatting when editing.
82TEST(test_various, aaudio_flush_when_started) {
83 AAudioStreamBuilder *aaudioBuilder = nullptr;
84 AAudioStream *aaudioStream = nullptr;
85
86// Use an AAudioStreamBuilder to contain requested parameters.
87 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
88
89// Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -080090 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk0c15f4f2017-11-28 15:46:15 -080091 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
92
93// Create an AAudioStream using the Builder.
94 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
95 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
96
97 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
98 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
99 AAUDIO_STREAM_STATE_STARTING, &state,
100 1000 * NANOS_PER_MILLISECOND));
101 EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
102
103 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestFlush(aaudioStream));
104
105 state = AAUDIO_STREAM_STATE_UNKNOWN;
106 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
107 AAUDIO_STREAM_STATE_UNKNOWN, &state, 0));
108 EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
109
110 AAudioStream_close(aaudioStream);
111 AAudioStreamBuilder_delete(aaudioBuilder);
112}
113
Phil Burk9a9e6002017-11-17 12:17:37 -0800114//int main() { // To fix Android Studio formatting when editing.
115TEST(test_various, aaudio_set_buffer_size) {
Phil Burk2581ae22017-11-21 15:47:29 -0800116
Phil Burk9a9e6002017-11-17 12:17:37 -0800117 int32_t bufferCapacity;
118 int32_t framesPerBurst = 0;
119 int32_t actualSize = 0;
120
121 AAudioStreamBuilder *aaudioBuilder = nullptr;
122 AAudioStream *aaudioStream = nullptr;
123
124 // Use an AAudioStreamBuilder to contain requested parameters.
125 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
126
127 // Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -0800128 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk9a9e6002017-11-17 12:17:37 -0800129 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
130
131 // Create an AAudioStream using the Builder.
132 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
133
134 // This is the number of frames that are read in one chunk by a DMA controller
135 // or a DSP or a mixer.
136 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
137 bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
138 printf(" bufferCapacity = %d, remainder = %d\n",
139 bufferCapacity, bufferCapacity % framesPerBurst);
140
141 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
142 EXPECT_GT(actualSize, 0);
143 EXPECT_LE(actualSize, bufferCapacity);
144
145 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
146 EXPECT_GT(actualSize, framesPerBurst);
147 EXPECT_LE(actualSize, bufferCapacity);
148
149 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
150 EXPECT_GT(actualSize, framesPerBurst);
151 EXPECT_LE(actualSize, bufferCapacity);
152
153 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
154 EXPECT_GT(actualSize, framesPerBurst);
155 EXPECT_LE(actualSize, bufferCapacity);
156
157 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
158 EXPECT_GT(actualSize, framesPerBurst);
159 EXPECT_LE(actualSize, bufferCapacity);
160
161 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
162 EXPECT_GT(actualSize, framesPerBurst);
163 EXPECT_LE(actualSize, bufferCapacity);
164
165 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
166 EXPECT_GT(actualSize, framesPerBurst);
167 EXPECT_LE(actualSize, bufferCapacity);
168
169 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
170 EXPECT_GT(actualSize, 0);
171 EXPECT_LE(actualSize, bufferCapacity);
172
173 AAudioStream_close(aaudioStream);
174 AAudioStreamBuilder_delete(aaudioBuilder);
Phil Burk9a9e6002017-11-17 12:17:37 -0800175}
Phil Burk2581ae22017-11-21 15:47:29 -0800176
177
178// ************************************************************
179// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
180
181// Callback function that counts calls.
182aaudio_data_callback_result_t CallbackOnceProc(
183 AAudioStream *stream,
184 void *userData,
185 void *audioData,
186 int32_t numFrames
187) {
188 (void) stream;
189 (void) audioData;
190 (void) numFrames;
191
192 std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
193 (*callbackCountPtr)++;
194
195 return AAUDIO_CALLBACK_RESULT_STOP;
196}
197
198void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
199
200 std::atomic<int32_t> callbackCount{0};
201
202 AAudioStreamBuilder *aaudioBuilder = nullptr;
203 AAudioStream *aaudioStream = nullptr;
204
205 // Use an AAudioStreamBuilder to contain requested parameters.
206 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
207
208 // Request stream properties.
209 AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
210 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
211
212 // Create an AAudioStream using the Builder.
213 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
214 AAudioStreamBuilder_delete(aaudioBuilder);
215
216 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
217
218 sleep(1); // Give callback a chance to run many times.
219
220 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
221
222 EXPECT_EQ(1, callbackCount.load()); // should stop after first call
223
224 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
225}
226
227TEST(test_various, aaudio_callback_once_none) {
228 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
229}
230
231TEST(test_various, aaudio_callback_once_lowlat) {
232 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
233}
234
235// ************************************************************
236struct WakeUpCallbackData {
237 void wakeOther() {
238 // signal waiting test to wake up
239 {
240 std::lock_guard <std::mutex> lock(mutex);
241 finished = true;
242 }
243 conditionVariable.notify_one();
244 }
245
246 void waitForFinished() {
247 std::unique_lock <std::mutex> aLock(mutex);
248 conditionVariable.wait(aLock, [=] { return finished; });
249 }
250
251 // For signalling foreground test when callback finished
252 std::mutex mutex;
253 std::condition_variable conditionVariable;
254 bool finished = false;
255};
256
257// Test to make sure we cannot call recursively into the system from a callback.
258struct DangerousData : public WakeUpCallbackData {
259 aaudio_result_t resultStart = AAUDIO_OK;
260 aaudio_result_t resultStop = AAUDIO_OK;
261 aaudio_result_t resultPause = AAUDIO_OK;
262 aaudio_result_t resultFlush = AAUDIO_OK;
263 aaudio_result_t resultClose = AAUDIO_OK;
264};
265
266// Callback function that tries to call back into the stream.
267aaudio_data_callback_result_t DangerousDataCallbackProc(
268 AAudioStream *stream,
269 void *userData,
270 void *audioData,
271 int32_t numFrames) {
272 (void) audioData;
273 (void) numFrames;
274
275 DangerousData *data = (DangerousData *)userData;
276 data->resultStart = AAudioStream_requestStart(stream);
277 data->resultStop = AAudioStream_requestStop(stream);
278 data->resultPause = AAudioStream_requestPause(stream);
279 data->resultFlush = AAudioStream_requestFlush(stream);
280 data->resultClose = AAudioStream_close(stream);
281
282 data->wakeOther();
283
284 return AAUDIO_CALLBACK_RESULT_STOP;
285}
286
287//int main() { // To fix Android Studio formatting when editing.
288void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
289 DangerousData dangerousData;
290 AAudioStreamBuilder *aaudioBuilder = nullptr;
291 AAudioStream *aaudioStream = nullptr;
292
293 // Use an AAudioStreamBuilder to contain requested parameters.
294 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
295
296 // Request stream properties.
297 AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
298 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
299
300 // Create an AAudioStream using the Builder.
301 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
302 AAudioStreamBuilder_delete(aaudioBuilder);
303
304 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
305
306 dangerousData.waitForFinished();
307
308 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
309
310 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
311 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
312 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
313 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
314 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
315
316 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
317}
318
319//int main() { // To fix Android Studio formatting when editing.
320
321TEST(test_various, aaudio_callback_blockers_none) {
322 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
323}
324
325TEST(test_various, aaudio_callback_blockers_lowlat) {
326 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
327}