blob: 41693e884b2a147c016213bf3153a049e5b720aa [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// Callback function that does nothing.
Phil Burk2581ae22017-11-21 15:47:29 -080030aaudio_data_callback_result_t NoopDataCallbackProc(
Phil Burk9cf23822020-04-17 11:53:35 -070031 AAudioStream * stream,
32 void * /* userData */,
Phil Burk9a9e6002017-11-17 12:17:37 -080033 void *audioData,
34 int32_t numFrames
35) {
Phil Burk9cf23822020-04-17 11:53:35 -070036 int channels = AAudioStream_getChannelCount(stream);
37 int numSamples = channels * numFrames;
38 bool allZeros = true;
39 float * const floatData = reinterpret_cast<float *>(audioData);
40 for (int i = 0; i < numSamples; i++) {
41 allZeros &= (floatData[i] == 0.0f);
42 floatData[i] = 0.0f;
43 }
44 EXPECT_TRUE(allZeros);
Phil Burk9a9e6002017-11-17 12:17:37 -080045 return AAUDIO_CALLBACK_RESULT_CONTINUE;
46}
47
Phil Burk0c15f4f2017-11-28 15:46:15 -080048constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
49
Phil Burk8b4e05e2019-12-17 12:12:09 -080050void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
51 aaudio_sharing_mode_t sharingMode) {
52 AAudioStreamBuilder* aaudioBuilder = nullptr;
53 AAudioStream* aaudioStream = nullptr;
54
55 // Use an AAudioStreamBuilder to contain requested parameters.
56 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
57
58 // Request stream properties.
59 AAudioStreamBuilder_setDataCallback(aaudioBuilder,
60 NoopDataCallbackProc,
61 nullptr);
62 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
63 AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
Phil Burk9cf23822020-04-17 11:53:35 -070064 AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
Phil Burk8b4e05e2019-12-17 12:12:09 -080065
66 // Create an AAudioStream using the Builder.
67 ASSERT_EQ(AAUDIO_OK,
68 AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
69 AAudioStreamBuilder_delete(aaudioBuilder);
70
71 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
72
73 sleep(1);
74
75 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
76
77 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
78 aaudio_stream_state_t state = AAudioStream_getState(aaudioStream);
79 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
80
81 // We should be able to call this again without crashing.
82 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
83 state = AAudioStream_getState(aaudioStream);
84 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
85
86 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
87}
88
89TEST(test_various, aaudio_release_close_none) {
90 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
91 AAUDIO_SHARING_MODE_SHARED);
92 // No EXCLUSIVE streams with MODE_NONE.
93}
94
95TEST(test_various, aaudio_release_close_low_shared) {
96 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
97 AAUDIO_SHARING_MODE_SHARED);
98}
99
100TEST(test_various, aaudio_release_close_low_exclusive) {
101 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
102 AAUDIO_SHARING_MODE_EXCLUSIVE);
103}
104
Phil Burk4fa3b942017-12-13 17:25:24 -0800105enum FunctionToCall {
106 CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
107};
108
109void checkStateTransition(aaudio_performance_mode_t perfMode,
110 aaudio_stream_state_t originalState,
111 FunctionToCall functionToCall,
112 aaudio_result_t expectedResult,
113 aaudio_stream_state_t expectedState) {
Phil Burk0c15f4f2017-11-28 15:46:15 -0800114 AAudioStreamBuilder *aaudioBuilder = nullptr;
115 AAudioStream *aaudioStream = nullptr;
116
Phil Burk4fa3b942017-12-13 17:25:24 -0800117 // Use an AAudioStreamBuilder to contain requested parameters.
Phil Burk0c15f4f2017-11-28 15:46:15 -0800118 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
119
Phil Burk4fa3b942017-12-13 17:25:24 -0800120 // Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -0800121 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk4fa3b942017-12-13 17:25:24 -0800122 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
Phil Burk9cf23822020-04-17 11:53:35 -0700123 AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
Phil Burk0c15f4f2017-11-28 15:46:15 -0800124
Phil Burk4fa3b942017-12-13 17:25:24 -0800125 // Create an AAudioStream using the Builder.
126 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
Phil Burk0c15f4f2017-11-28 15:46:15 -0800127
Phil Burk4fa3b942017-12-13 17:25:24 -0800128 // Verify Open State
Phil Burk0c15f4f2017-11-28 15:46:15 -0800129 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
130 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
131 AAUDIO_STREAM_STATE_UNKNOWN, &state,
132 1000 * NANOS_PER_MILLISECOND));
133 EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
134
Phil Burk4fa3b942017-12-13 17:25:24 -0800135 // Put stream into desired state.
136 aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED;
137 if (originalState != AAUDIO_STREAM_STATE_OPEN) {
Phil Burk0c15f4f2017-11-28 15:46:15 -0800138
Phil Burk4fa3b942017-12-13 17:25:24 -0800139 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
140
141 if (originalState != AAUDIO_STREAM_STATE_STARTING) {
142
143 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
144 AAUDIO_STREAM_STATE_STARTING,
145 &state,
146 1000 * NANOS_PER_MILLISECOND));
147 ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
148
149 if (originalState == AAUDIO_STREAM_STATE_STOPPING) {
150 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
151 } else if (originalState == AAUDIO_STREAM_STATE_STOPPED) {
152 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
153 inputState = AAUDIO_STREAM_STATE_STOPPING;
154 } else if (originalState == AAUDIO_STREAM_STATE_PAUSING) {
155 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
156 } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
157 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
158 inputState = AAUDIO_STREAM_STATE_PAUSING;
159 }
160 }
161 }
162
163 // Wait until past transitional state.
164 if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
165 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
166 inputState,
167 &state,
168 1000 * NANOS_PER_MILLISECOND));
169 ASSERT_EQ(originalState, state);
170 }
171
172 aaudio_stream_state_t transitionalState = originalState;
173 switch(functionToCall) {
174 case FunctionToCall::CALL_START:
175 EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
176 transitionalState = AAUDIO_STREAM_STATE_STARTING;
177 break;
178 case FunctionToCall::CALL_STOP:
179 EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
180 transitionalState = AAUDIO_STREAM_STATE_STOPPING;
181 break;
182 case FunctionToCall::CALL_PAUSE:
183 EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
184 transitionalState = AAUDIO_STREAM_STATE_PAUSING;
185 break;
186 case FunctionToCall::CALL_FLUSH:
187 EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
188 transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
189 break;
190 }
191
Phil Burk0c15f4f2017-11-28 15:46:15 -0800192 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
Phil Burk4fa3b942017-12-13 17:25:24 -0800193 transitionalState,
194 &state,
Phil Burk0c15f4f2017-11-28 15:46:15 -0800195 1000 * NANOS_PER_MILLISECOND));
Phil Burk4fa3b942017-12-13 17:25:24 -0800196 // We should not change state when a function fails.
197 if (expectedResult != AAUDIO_OK) {
198 ASSERT_EQ(originalState, expectedState);
199 }
200 EXPECT_EQ(expectedState, state);
201 if (state != expectedState) {
202 printf("ERROR - expected %s, actual = %s\n",
203 AAudio_convertStreamStateToText(expectedState),
204 AAudio_convertStreamStateToText(state));
205 fflush(stdout);
206 }
Phil Burk0c15f4f2017-11-28 15:46:15 -0800207
208 AAudioStream_close(aaudioStream);
209 AAudioStreamBuilder_delete(aaudioBuilder);
210}
211
Phil Burk4fa3b942017-12-13 17:25:24 -0800212// TODO Use parameterized tests instead of these individual specific tests.
213
214// OPEN =================================================================
215TEST(test_various, aaudio_state_lowlat_open_start) {
216 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
217 AAUDIO_STREAM_STATE_OPEN,
218 FunctionToCall::CALL_START,
219 AAUDIO_OK,
220 AAUDIO_STREAM_STATE_STARTED);
221}
222
223TEST(test_various, aaudio_state_none_open_start) {
224 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
225 AAUDIO_STREAM_STATE_OPEN,
226 FunctionToCall::CALL_START,
227 AAUDIO_OK,
228 AAUDIO_STREAM_STATE_STARTED);
229}
230
231TEST(test_various, aaudio_state_lowlat_open_stop) {
232 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
233 AAUDIO_STREAM_STATE_OPEN,
234 FunctionToCall::CALL_STOP,
235 AAUDIO_OK,
236 AAUDIO_STREAM_STATE_STOPPED);
237}
238
239TEST(test_various, aaudio_state_none_open_stop) {
240 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
241 AAUDIO_STREAM_STATE_OPEN,
242 FunctionToCall::CALL_STOP,
243 AAUDIO_OK,
244 AAUDIO_STREAM_STATE_STOPPED);
245}
246
247TEST(test_various, aaudio_state_lowlat_open_pause) {
248 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
249 AAUDIO_STREAM_STATE_OPEN,
250 FunctionToCall::CALL_PAUSE,
251 AAUDIO_OK,
252 AAUDIO_STREAM_STATE_PAUSED);
253}
254
255TEST(test_various, aaudio_state_none_open_pause) {
256 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
257 AAUDIO_STREAM_STATE_OPEN,
258 FunctionToCall::CALL_PAUSE,
259 AAUDIO_OK,
260 AAUDIO_STREAM_STATE_PAUSED);
261}
262
263TEST(test_various, aaudio_state_lowlat_open_flush) {
264 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
265 AAUDIO_STREAM_STATE_OPEN,
266 FunctionToCall::CALL_FLUSH,
267 AAUDIO_OK,
268 AAUDIO_STREAM_STATE_FLUSHED);
269}
270
271TEST(test_various, aaudio_state_none_open_flush) {
272 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
273 AAUDIO_STREAM_STATE_OPEN,
274 FunctionToCall::CALL_FLUSH,
275 AAUDIO_OK,
276 AAUDIO_STREAM_STATE_FLUSHED);
277}
278
279
280// STARTED =================================================================
281TEST(test_various, aaudio_state_lowlat_started_start) {
282 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
283 AAUDIO_STREAM_STATE_STARTED,
284 FunctionToCall::CALL_START,
285 AAUDIO_ERROR_INVALID_STATE,
286 AAUDIO_STREAM_STATE_STARTED);
287}
288
289TEST(test_various, aaudio_state_none_started_start) {
290 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
291 AAUDIO_STREAM_STATE_STARTED,
292 FunctionToCall::CALL_START,
293 AAUDIO_ERROR_INVALID_STATE,
294 AAUDIO_STREAM_STATE_STARTED);
295}
296
297TEST(test_various, aaudio_state_lowlat_started_stop) {
298 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
299 AAUDIO_STREAM_STATE_STARTED,
300 FunctionToCall::CALL_STOP,
301 AAUDIO_OK,
302 AAUDIO_STREAM_STATE_STOPPED);
303}
304
305TEST(test_various, aaudio_state_none_started_stop) {
306 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
307 AAUDIO_STREAM_STATE_STARTED,
308 FunctionToCall::CALL_STOP,
309 AAUDIO_OK,
310 AAUDIO_STREAM_STATE_STOPPED);
311}
312
313TEST(test_various, aaudio_state_lowlat_started_pause) {
314 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
315 AAUDIO_STREAM_STATE_STARTED,
316 FunctionToCall::CALL_PAUSE,
317 AAUDIO_OK,
318 AAUDIO_STREAM_STATE_PAUSED);
319}
320
321TEST(test_various, aaudio_state_none_started_pause) {
322 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
323 AAUDIO_STREAM_STATE_STARTED,
324 FunctionToCall::CALL_PAUSE,
325 AAUDIO_OK,
326 AAUDIO_STREAM_STATE_PAUSED);
327}
328
329TEST(test_various, aaudio_state_lowlat_started_flush) {
330 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
331 AAUDIO_STREAM_STATE_STARTED,
332 FunctionToCall::CALL_FLUSH,
333 AAUDIO_ERROR_INVALID_STATE,
334 AAUDIO_STREAM_STATE_STARTED);
335}
336
337TEST(test_various, aaudio_state_none_started_flush) {
338 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
339 AAUDIO_STREAM_STATE_STARTED,
340 FunctionToCall::CALL_FLUSH,
341 AAUDIO_ERROR_INVALID_STATE,
342 AAUDIO_STREAM_STATE_STARTED);
343}
344
345// STOPPED =================================================================
346TEST(test_various, aaudio_state_lowlat_stopped_start) {
347 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
348 AAUDIO_STREAM_STATE_STOPPED,
349 FunctionToCall::CALL_START,
350 AAUDIO_OK,
351 AAUDIO_STREAM_STATE_STARTED);
352}
353
354TEST(test_various, aaudio_state_none_stopped_start) {
355 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
356 AAUDIO_STREAM_STATE_STOPPED,
357 FunctionToCall::CALL_START,
358 AAUDIO_OK,
359 AAUDIO_STREAM_STATE_STARTED);
360}
361
362TEST(test_various, aaudio_state_lowlat_stopped_stop) {
363 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
364 AAUDIO_STREAM_STATE_STOPPED,
365 FunctionToCall::CALL_STOP,
366 AAUDIO_OK,
367 AAUDIO_STREAM_STATE_STOPPED);
368}
369
370TEST(test_various, aaudio_state_none_stopped_stop) {
371 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
372 AAUDIO_STREAM_STATE_STOPPED,
373 FunctionToCall::CALL_STOP,
374 AAUDIO_OK,
375 AAUDIO_STREAM_STATE_STOPPED);
376}
377
378TEST(test_various, aaudio_state_lowlat_stopped_pause) {
379 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
380 AAUDIO_STREAM_STATE_STOPPED,
381 FunctionToCall::CALL_PAUSE,
382 AAUDIO_OK,
383 AAUDIO_STREAM_STATE_PAUSED);
384}
385
386TEST(test_various, aaudio_state_none_stopped_pause) {
387 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
388 AAUDIO_STREAM_STATE_STOPPED,
389 FunctionToCall::CALL_PAUSE,
390 AAUDIO_OK,
391 AAUDIO_STREAM_STATE_PAUSED);
392}
393
394TEST(test_various, aaudio_state_lowlat_stopped_flush) {
395 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
396 AAUDIO_STREAM_STATE_STOPPED,
397 FunctionToCall::CALL_FLUSH,
398 AAUDIO_OK,
399 AAUDIO_STREAM_STATE_FLUSHED);
400}
401
402TEST(test_various, aaudio_state_none_stopped_flush) {
403 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
404 AAUDIO_STREAM_STATE_STOPPED,
405 FunctionToCall::CALL_FLUSH,
406 AAUDIO_OK,
407 AAUDIO_STREAM_STATE_FLUSHED);
408}
409
410// PAUSED =================================================================
411TEST(test_various, aaudio_state_lowlat_paused_start) {
412checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
413 AAUDIO_STREAM_STATE_PAUSED,
414 FunctionToCall::CALL_START,
415 AAUDIO_OK,
416 AAUDIO_STREAM_STATE_STARTED);
417}
418
419TEST(test_various, aaudio_state_none_paused_start) {
420checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
421 AAUDIO_STREAM_STATE_PAUSED,
422 FunctionToCall::CALL_START,
423 AAUDIO_OK,
424 AAUDIO_STREAM_STATE_STARTED);
425}
426
427TEST(test_various, aaudio_state_lowlat_paused_stop) {
428checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
429 AAUDIO_STREAM_STATE_PAUSED,
430 FunctionToCall::CALL_STOP,
431 AAUDIO_OK,
432 AAUDIO_STREAM_STATE_STOPPED);
433}
434
435TEST(test_various, aaudio_state_none_paused_stop) {
436checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
437 AAUDIO_STREAM_STATE_PAUSED,
438 FunctionToCall::CALL_STOP,
439 AAUDIO_OK,
440 AAUDIO_STREAM_STATE_STOPPED);
441}
442
443TEST(test_various, aaudio_state_lowlat_paused_pause) {
444checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
445 AAUDIO_STREAM_STATE_PAUSED,
446 FunctionToCall::CALL_PAUSE,
447 AAUDIO_OK,
448 AAUDIO_STREAM_STATE_PAUSED);
449}
450
451TEST(test_various, aaudio_state_none_paused_pause) {
452checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
453 AAUDIO_STREAM_STATE_PAUSED,
454 FunctionToCall::CALL_PAUSE,
455 AAUDIO_OK,
456 AAUDIO_STREAM_STATE_PAUSED);
457}
458
459TEST(test_various, aaudio_state_lowlat_paused_flush) {
460checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
461 AAUDIO_STREAM_STATE_PAUSED,
462 FunctionToCall::CALL_FLUSH,
463 AAUDIO_OK,
464 AAUDIO_STREAM_STATE_FLUSHED);
465}
466
467TEST(test_various, aaudio_state_none_paused_flush) {
468checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
469 AAUDIO_STREAM_STATE_PAUSED,
470 FunctionToCall::CALL_FLUSH,
471 AAUDIO_OK,
472 AAUDIO_STREAM_STATE_FLUSHED);
473}
474
475// ==========================================================================
Phil Burk9a9e6002017-11-17 12:17:37 -0800476TEST(test_various, aaudio_set_buffer_size) {
Phil Burk2581ae22017-11-21 15:47:29 -0800477
Phil Burk9a9e6002017-11-17 12:17:37 -0800478 int32_t bufferCapacity;
479 int32_t framesPerBurst = 0;
480 int32_t actualSize = 0;
481
482 AAudioStreamBuilder *aaudioBuilder = nullptr;
483 AAudioStream *aaudioStream = nullptr;
484
485 // Use an AAudioStreamBuilder to contain requested parameters.
486 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
487
488 // Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -0800489 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk9a9e6002017-11-17 12:17:37 -0800490 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
491
492 // Create an AAudioStream using the Builder.
493 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
494
495 // This is the number of frames that are read in one chunk by a DMA controller
496 // or a DSP or a mixer.
497 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
498 bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
499 printf(" bufferCapacity = %d, remainder = %d\n",
500 bufferCapacity, bufferCapacity % framesPerBurst);
501
502 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
Phil Burk6363f4b2020-01-10 14:06:51 -0800503 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800504 EXPECT_LE(actualSize, bufferCapacity);
505
506 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
507 EXPECT_GT(actualSize, framesPerBurst);
508 EXPECT_LE(actualSize, bufferCapacity);
509
510 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
511 EXPECT_GT(actualSize, framesPerBurst);
512 EXPECT_LE(actualSize, bufferCapacity);
513
514 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
515 EXPECT_GT(actualSize, framesPerBurst);
516 EXPECT_LE(actualSize, bufferCapacity);
517
518 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
519 EXPECT_GT(actualSize, framesPerBurst);
520 EXPECT_LE(actualSize, bufferCapacity);
521
522 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
523 EXPECT_GT(actualSize, framesPerBurst);
524 EXPECT_LE(actualSize, bufferCapacity);
525
526 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
527 EXPECT_GT(actualSize, framesPerBurst);
528 EXPECT_LE(actualSize, bufferCapacity);
529
530 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
Phil Burk6363f4b2020-01-10 14:06:51 -0800531 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800532 EXPECT_LE(actualSize, bufferCapacity);
533
534 AAudioStream_close(aaudioStream);
535 AAudioStreamBuilder_delete(aaudioBuilder);
Phil Burk9a9e6002017-11-17 12:17:37 -0800536}
Phil Burk2581ae22017-11-21 15:47:29 -0800537
Phil Burk2581ae22017-11-21 15:47:29 -0800538// ************************************************************
539// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
540
541// Callback function that counts calls.
542aaudio_data_callback_result_t CallbackOnceProc(
543 AAudioStream *stream,
544 void *userData,
545 void *audioData,
546 int32_t numFrames
547) {
548 (void) stream;
549 (void) audioData;
550 (void) numFrames;
551
552 std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
553 (*callbackCountPtr)++;
554
555 return AAUDIO_CALLBACK_RESULT_STOP;
556}
557
558void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
559
560 std::atomic<int32_t> callbackCount{0};
561
562 AAudioStreamBuilder *aaudioBuilder = nullptr;
563 AAudioStream *aaudioStream = nullptr;
564
565 // Use an AAudioStreamBuilder to contain requested parameters.
566 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
567
568 // Request stream properties.
569 AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
570 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
571
572 // Create an AAudioStream using the Builder.
573 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
574 AAudioStreamBuilder_delete(aaudioBuilder);
575
576 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
577
578 sleep(1); // Give callback a chance to run many times.
579
580 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
581
582 EXPECT_EQ(1, callbackCount.load()); // should stop after first call
583
584 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
585}
586
587TEST(test_various, aaudio_callback_once_none) {
588 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
589}
590
591TEST(test_various, aaudio_callback_once_lowlat) {
592 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
593}
594
595// ************************************************************
596struct WakeUpCallbackData {
597 void wakeOther() {
598 // signal waiting test to wake up
599 {
600 std::lock_guard <std::mutex> lock(mutex);
601 finished = true;
602 }
603 conditionVariable.notify_one();
604 }
605
606 void waitForFinished() {
607 std::unique_lock <std::mutex> aLock(mutex);
608 conditionVariable.wait(aLock, [=] { return finished; });
609 }
610
611 // For signalling foreground test when callback finished
612 std::mutex mutex;
613 std::condition_variable conditionVariable;
614 bool finished = false;
615};
616
617// Test to make sure we cannot call recursively into the system from a callback.
618struct DangerousData : public WakeUpCallbackData {
619 aaudio_result_t resultStart = AAUDIO_OK;
620 aaudio_result_t resultStop = AAUDIO_OK;
621 aaudio_result_t resultPause = AAUDIO_OK;
622 aaudio_result_t resultFlush = AAUDIO_OK;
623 aaudio_result_t resultClose = AAUDIO_OK;
624};
625
626// Callback function that tries to call back into the stream.
627aaudio_data_callback_result_t DangerousDataCallbackProc(
628 AAudioStream *stream,
629 void *userData,
630 void *audioData,
631 int32_t numFrames) {
632 (void) audioData;
633 (void) numFrames;
634
635 DangerousData *data = (DangerousData *)userData;
636 data->resultStart = AAudioStream_requestStart(stream);
637 data->resultStop = AAudioStream_requestStop(stream);
638 data->resultPause = AAudioStream_requestPause(stream);
639 data->resultFlush = AAudioStream_requestFlush(stream);
640 data->resultClose = AAudioStream_close(stream);
641
642 data->wakeOther();
643
644 return AAUDIO_CALLBACK_RESULT_STOP;
645}
646
647//int main() { // To fix Android Studio formatting when editing.
648void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
649 DangerousData dangerousData;
650 AAudioStreamBuilder *aaudioBuilder = nullptr;
651 AAudioStream *aaudioStream = nullptr;
652
653 // Use an AAudioStreamBuilder to contain requested parameters.
654 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
655
656 // Request stream properties.
657 AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
658 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
659
660 // Create an AAudioStream using the Builder.
661 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
662 AAudioStreamBuilder_delete(aaudioBuilder);
663
664 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
665
666 dangerousData.waitForFinished();
667
668 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
669
670 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
671 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
672 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
673 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
674 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
675
676 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
677}
678
679//int main() { // To fix Android Studio formatting when editing.
680
681TEST(test_various, aaudio_callback_blockers_none) {
682 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
683}
684
685TEST(test_various, aaudio_callback_blockers_lowlat) {
686 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
687}