• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
19 #include <condition_variable>
20 #include <mutex>
21 #include <stdio.h>
22 
23 #include <android-base/macros.h>
24 #include <aaudio/AAudio.h>
25 
26 #include <gtest/gtest.h>
27 #include <unistd.h>
28 
29 // Callback function that does nothing.
NoopDataCallbackProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)30 aaudio_data_callback_result_t NoopDataCallbackProc(
31         AAudioStream *stream,
32         void *userData,
33         void *audioData,
34         int32_t numFrames
35 ) {
36     (void) stream;
37     (void) userData;
38     (void) audioData;
39     (void) numFrames;
40     return AAUDIO_CALLBACK_RESULT_CONTINUE;
41 }
42 
43 // Test AAudioStream_setBufferSizeInFrames()
44 
45 constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
46 
47 enum FunctionToCall {
48     CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
49 };
50 
checkStateTransition(aaudio_performance_mode_t perfMode,aaudio_stream_state_t originalState,FunctionToCall functionToCall,aaudio_result_t expectedResult,aaudio_stream_state_t expectedState)51 void checkStateTransition(aaudio_performance_mode_t perfMode,
52                           aaudio_stream_state_t originalState,
53                           FunctionToCall functionToCall,
54                           aaudio_result_t expectedResult,
55                           aaudio_stream_state_t expectedState) {
56     AAudioStreamBuilder *aaudioBuilder = nullptr;
57     AAudioStream *aaudioStream = nullptr;
58 
59     // Use an AAudioStreamBuilder to contain requested parameters.
60     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
61 
62     // Request stream properties.
63     AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
64     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
65 
66     // Create an AAudioStream using the Builder.
67     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
68 
69     // Verify Open State
70     aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
71     EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
72                                                          AAUDIO_STREAM_STATE_UNKNOWN, &state,
73                                                          1000 * NANOS_PER_MILLISECOND));
74     EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
75 
76     // Put stream into desired state.
77     aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED;
78     if (originalState != AAUDIO_STREAM_STATE_OPEN) {
79 
80         ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
81 
82         if (originalState != AAUDIO_STREAM_STATE_STARTING) {
83 
84             ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
85                                                                  AAUDIO_STREAM_STATE_STARTING,
86                                                                  &state,
87                                                                  1000 * NANOS_PER_MILLISECOND));
88             ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
89 
90             if (originalState == AAUDIO_STREAM_STATE_STOPPING) {
91                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
92             } else if (originalState == AAUDIO_STREAM_STATE_STOPPED) {
93                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
94                 inputState = AAUDIO_STREAM_STATE_STOPPING;
95             } else if (originalState == AAUDIO_STREAM_STATE_PAUSING) {
96                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
97             } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
98                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
99                 inputState = AAUDIO_STREAM_STATE_PAUSING;
100             }
101         }
102     }
103 
104     // Wait until past transitional state.
105     if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
106         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
107                                                              inputState,
108                                                              &state,
109                                                              1000 * NANOS_PER_MILLISECOND));
110         ASSERT_EQ(originalState, state);
111     }
112 
113     aaudio_stream_state_t transitionalState = originalState;
114     switch(functionToCall) {
115         case FunctionToCall::CALL_START:
116             EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
117             transitionalState = AAUDIO_STREAM_STATE_STARTING;
118             break;
119         case FunctionToCall::CALL_STOP:
120             EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
121             transitionalState = AAUDIO_STREAM_STATE_STOPPING;
122             break;
123         case FunctionToCall::CALL_PAUSE:
124             EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
125             transitionalState = AAUDIO_STREAM_STATE_PAUSING;
126             break;
127         case FunctionToCall::CALL_FLUSH:
128             EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
129             transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
130             break;
131     }
132 
133     EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
134                                                          transitionalState,
135                                                          &state,
136                                                          1000 * NANOS_PER_MILLISECOND));
137     // We should not change state when a function fails.
138     if (expectedResult != AAUDIO_OK) {
139         ASSERT_EQ(originalState, expectedState);
140     }
141     EXPECT_EQ(expectedState, state);
142     if (state != expectedState) {
143         printf("ERROR - expected %s, actual = %s\n",
144                 AAudio_convertStreamStateToText(expectedState),
145                 AAudio_convertStreamStateToText(state));
146         fflush(stdout);
147     }
148 
149     AAudioStream_close(aaudioStream);
150     AAudioStreamBuilder_delete(aaudioBuilder);
151 }
152 
153 // TODO Use parameterized tests instead of these individual specific tests.
154 
155 // OPEN =================================================================
TEST(test_various,aaudio_state_lowlat_open_start)156 TEST(test_various, aaudio_state_lowlat_open_start) {
157     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
158             AAUDIO_STREAM_STATE_OPEN,
159             FunctionToCall::CALL_START,
160             AAUDIO_OK,
161             AAUDIO_STREAM_STATE_STARTED);
162 }
163 
TEST(test_various,aaudio_state_none_open_start)164 TEST(test_various, aaudio_state_none_open_start) {
165     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
166             AAUDIO_STREAM_STATE_OPEN,
167             FunctionToCall::CALL_START,
168             AAUDIO_OK,
169             AAUDIO_STREAM_STATE_STARTED);
170 }
171 
TEST(test_various,aaudio_state_lowlat_open_stop)172 TEST(test_various, aaudio_state_lowlat_open_stop) {
173     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
174             AAUDIO_STREAM_STATE_OPEN,
175             FunctionToCall::CALL_STOP,
176             AAUDIO_OK,
177             AAUDIO_STREAM_STATE_STOPPED);
178 }
179 
TEST(test_various,aaudio_state_none_open_stop)180 TEST(test_various, aaudio_state_none_open_stop) {
181     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
182             AAUDIO_STREAM_STATE_OPEN,
183             FunctionToCall::CALL_STOP,
184             AAUDIO_OK,
185             AAUDIO_STREAM_STATE_STOPPED);
186 }
187 
TEST(test_various,aaudio_state_lowlat_open_pause)188 TEST(test_various, aaudio_state_lowlat_open_pause) {
189     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
190             AAUDIO_STREAM_STATE_OPEN,
191             FunctionToCall::CALL_PAUSE,
192             AAUDIO_OK,
193             AAUDIO_STREAM_STATE_PAUSED);
194 }
195 
TEST(test_various,aaudio_state_none_open_pause)196 TEST(test_various, aaudio_state_none_open_pause) {
197     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
198             AAUDIO_STREAM_STATE_OPEN,
199             FunctionToCall::CALL_PAUSE,
200             AAUDIO_OK,
201             AAUDIO_STREAM_STATE_PAUSED);
202 }
203 
TEST(test_various,aaudio_state_lowlat_open_flush)204 TEST(test_various, aaudio_state_lowlat_open_flush) {
205     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
206             AAUDIO_STREAM_STATE_OPEN,
207             FunctionToCall::CALL_FLUSH,
208             AAUDIO_OK,
209             AAUDIO_STREAM_STATE_FLUSHED);
210 }
211 
TEST(test_various,aaudio_state_none_open_flush)212 TEST(test_various, aaudio_state_none_open_flush) {
213     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
214             AAUDIO_STREAM_STATE_OPEN,
215             FunctionToCall::CALL_FLUSH,
216             AAUDIO_OK,
217             AAUDIO_STREAM_STATE_FLUSHED);
218 }
219 
220 
221 // STARTED =================================================================
TEST(test_various,aaudio_state_lowlat_started_start)222 TEST(test_various, aaudio_state_lowlat_started_start) {
223     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
224             AAUDIO_STREAM_STATE_STARTED,
225             FunctionToCall::CALL_START,
226             AAUDIO_ERROR_INVALID_STATE,
227             AAUDIO_STREAM_STATE_STARTED);
228 }
229 
TEST(test_various,aaudio_state_none_started_start)230 TEST(test_various, aaudio_state_none_started_start) {
231     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
232             AAUDIO_STREAM_STATE_STARTED,
233             FunctionToCall::CALL_START,
234             AAUDIO_ERROR_INVALID_STATE,
235             AAUDIO_STREAM_STATE_STARTED);
236 }
237 
TEST(test_various,aaudio_state_lowlat_started_stop)238 TEST(test_various, aaudio_state_lowlat_started_stop) {
239     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
240             AAUDIO_STREAM_STATE_STARTED,
241             FunctionToCall::CALL_STOP,
242             AAUDIO_OK,
243             AAUDIO_STREAM_STATE_STOPPED);
244 }
245 
TEST(test_various,aaudio_state_none_started_stop)246 TEST(test_various, aaudio_state_none_started_stop) {
247     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
248             AAUDIO_STREAM_STATE_STARTED,
249             FunctionToCall::CALL_STOP,
250             AAUDIO_OK,
251             AAUDIO_STREAM_STATE_STOPPED);
252 }
253 
TEST(test_various,aaudio_state_lowlat_started_pause)254 TEST(test_various, aaudio_state_lowlat_started_pause) {
255     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
256             AAUDIO_STREAM_STATE_STARTED,
257             FunctionToCall::CALL_PAUSE,
258             AAUDIO_OK,
259             AAUDIO_STREAM_STATE_PAUSED);
260 }
261 
TEST(test_various,aaudio_state_none_started_pause)262 TEST(test_various, aaudio_state_none_started_pause) {
263     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
264             AAUDIO_STREAM_STATE_STARTED,
265             FunctionToCall::CALL_PAUSE,
266             AAUDIO_OK,
267             AAUDIO_STREAM_STATE_PAUSED);
268 }
269 
TEST(test_various,aaudio_state_lowlat_started_flush)270 TEST(test_various, aaudio_state_lowlat_started_flush) {
271     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
272             AAUDIO_STREAM_STATE_STARTED,
273             FunctionToCall::CALL_FLUSH,
274             AAUDIO_ERROR_INVALID_STATE,
275             AAUDIO_STREAM_STATE_STARTED);
276 }
277 
TEST(test_various,aaudio_state_none_started_flush)278 TEST(test_various, aaudio_state_none_started_flush) {
279     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
280             AAUDIO_STREAM_STATE_STARTED,
281             FunctionToCall::CALL_FLUSH,
282             AAUDIO_ERROR_INVALID_STATE,
283             AAUDIO_STREAM_STATE_STARTED);
284 }
285 
286 // STOPPED =================================================================
TEST(test_various,aaudio_state_lowlat_stopped_start)287 TEST(test_various, aaudio_state_lowlat_stopped_start) {
288     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
289             AAUDIO_STREAM_STATE_STOPPED,
290             FunctionToCall::CALL_START,
291             AAUDIO_OK,
292             AAUDIO_STREAM_STATE_STARTED);
293 }
294 
TEST(test_various,aaudio_state_none_stopped_start)295 TEST(test_various, aaudio_state_none_stopped_start) {
296     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
297             AAUDIO_STREAM_STATE_STOPPED,
298             FunctionToCall::CALL_START,
299             AAUDIO_OK,
300             AAUDIO_STREAM_STATE_STARTED);
301 }
302 
TEST(test_various,aaudio_state_lowlat_stopped_stop)303 TEST(test_various, aaudio_state_lowlat_stopped_stop) {
304     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
305             AAUDIO_STREAM_STATE_STOPPED,
306             FunctionToCall::CALL_STOP,
307             AAUDIO_OK,
308             AAUDIO_STREAM_STATE_STOPPED);
309 }
310 
TEST(test_various,aaudio_state_none_stopped_stop)311 TEST(test_various, aaudio_state_none_stopped_stop) {
312     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
313             AAUDIO_STREAM_STATE_STOPPED,
314             FunctionToCall::CALL_STOP,
315             AAUDIO_OK,
316             AAUDIO_STREAM_STATE_STOPPED);
317 }
318 
TEST(test_various,aaudio_state_lowlat_stopped_pause)319 TEST(test_various, aaudio_state_lowlat_stopped_pause) {
320     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
321             AAUDIO_STREAM_STATE_STOPPED,
322             FunctionToCall::CALL_PAUSE,
323             AAUDIO_OK,
324             AAUDIO_STREAM_STATE_PAUSED);
325 }
326 
TEST(test_various,aaudio_state_none_stopped_pause)327 TEST(test_various, aaudio_state_none_stopped_pause) {
328     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
329             AAUDIO_STREAM_STATE_STOPPED,
330             FunctionToCall::CALL_PAUSE,
331             AAUDIO_OK,
332             AAUDIO_STREAM_STATE_PAUSED);
333 }
334 
TEST(test_various,aaudio_state_lowlat_stopped_flush)335 TEST(test_various, aaudio_state_lowlat_stopped_flush) {
336     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
337             AAUDIO_STREAM_STATE_STOPPED,
338             FunctionToCall::CALL_FLUSH,
339             AAUDIO_OK,
340             AAUDIO_STREAM_STATE_FLUSHED);
341 }
342 
TEST(test_various,aaudio_state_none_stopped_flush)343 TEST(test_various, aaudio_state_none_stopped_flush) {
344     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
345             AAUDIO_STREAM_STATE_STOPPED,
346             FunctionToCall::CALL_FLUSH,
347             AAUDIO_OK,
348             AAUDIO_STREAM_STATE_FLUSHED);
349 }
350 
351 // PAUSED =================================================================
TEST(test_various,aaudio_state_lowlat_paused_start)352 TEST(test_various, aaudio_state_lowlat_paused_start) {
353 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
354         AAUDIO_STREAM_STATE_PAUSED,
355         FunctionToCall::CALL_START,
356         AAUDIO_OK,
357         AAUDIO_STREAM_STATE_STARTED);
358 }
359 
TEST(test_various,aaudio_state_none_paused_start)360 TEST(test_various, aaudio_state_none_paused_start) {
361 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
362         AAUDIO_STREAM_STATE_PAUSED,
363         FunctionToCall::CALL_START,
364         AAUDIO_OK,
365         AAUDIO_STREAM_STATE_STARTED);
366 }
367 
TEST(test_various,aaudio_state_lowlat_paused_stop)368 TEST(test_various, aaudio_state_lowlat_paused_stop) {
369 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
370         AAUDIO_STREAM_STATE_PAUSED,
371         FunctionToCall::CALL_STOP,
372         AAUDIO_OK,
373         AAUDIO_STREAM_STATE_STOPPED);
374 }
375 
TEST(test_various,aaudio_state_none_paused_stop)376 TEST(test_various, aaudio_state_none_paused_stop) {
377 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
378         AAUDIO_STREAM_STATE_PAUSED,
379         FunctionToCall::CALL_STOP,
380         AAUDIO_OK,
381         AAUDIO_STREAM_STATE_STOPPED);
382 }
383 
TEST(test_various,aaudio_state_lowlat_paused_pause)384 TEST(test_various, aaudio_state_lowlat_paused_pause) {
385 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
386         AAUDIO_STREAM_STATE_PAUSED,
387         FunctionToCall::CALL_PAUSE,
388         AAUDIO_OK,
389         AAUDIO_STREAM_STATE_PAUSED);
390 }
391 
TEST(test_various,aaudio_state_none_paused_pause)392 TEST(test_various, aaudio_state_none_paused_pause) {
393 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
394         AAUDIO_STREAM_STATE_PAUSED,
395         FunctionToCall::CALL_PAUSE,
396         AAUDIO_OK,
397         AAUDIO_STREAM_STATE_PAUSED);
398 }
399 
TEST(test_various,aaudio_state_lowlat_paused_flush)400 TEST(test_various, aaudio_state_lowlat_paused_flush) {
401 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
402         AAUDIO_STREAM_STATE_PAUSED,
403         FunctionToCall::CALL_FLUSH,
404         AAUDIO_OK,
405         AAUDIO_STREAM_STATE_FLUSHED);
406 }
407 
TEST(test_various,aaudio_state_none_paused_flush)408 TEST(test_various, aaudio_state_none_paused_flush) {
409 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
410         AAUDIO_STREAM_STATE_PAUSED,
411         FunctionToCall::CALL_FLUSH,
412         AAUDIO_OK,
413         AAUDIO_STREAM_STATE_FLUSHED);
414 }
415 
416 // ==========================================================================
TEST(test_various,aaudio_set_buffer_size)417 TEST(test_various, aaudio_set_buffer_size) {
418 
419     int32_t bufferCapacity;
420     int32_t framesPerBurst = 0;
421     int32_t actualSize = 0;
422 
423     AAudioStreamBuilder *aaudioBuilder = nullptr;
424     AAudioStream *aaudioStream = nullptr;
425 
426     // Use an AAudioStreamBuilder to contain requested parameters.
427     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
428 
429     // Request stream properties.
430     AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
431     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
432 
433     // Create an AAudioStream using the Builder.
434     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
435 
436     // This is the number of frames that are read in one chunk by a DMA controller
437     // or a DSP or a mixer.
438     framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
439     bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
440     printf("          bufferCapacity = %d, remainder = %d\n",
441            bufferCapacity, bufferCapacity % framesPerBurst);
442 
443     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
444     EXPECT_GT(actualSize, 0);
445     EXPECT_LE(actualSize, bufferCapacity);
446 
447     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
448     EXPECT_GT(actualSize, framesPerBurst);
449     EXPECT_LE(actualSize, bufferCapacity);
450 
451     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
452     EXPECT_GT(actualSize, framesPerBurst);
453     EXPECT_LE(actualSize, bufferCapacity);
454 
455     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
456     EXPECT_GT(actualSize, framesPerBurst);
457     EXPECT_LE(actualSize, bufferCapacity);
458 
459     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
460     EXPECT_GT(actualSize, framesPerBurst);
461     EXPECT_LE(actualSize, bufferCapacity);
462 
463     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
464     EXPECT_GT(actualSize, framesPerBurst);
465     EXPECT_LE(actualSize, bufferCapacity);
466 
467     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
468     EXPECT_GT(actualSize, framesPerBurst);
469     EXPECT_LE(actualSize, bufferCapacity);
470 
471     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
472     EXPECT_GT(actualSize, 0);
473     EXPECT_LE(actualSize, bufferCapacity);
474 
475     AAudioStream_close(aaudioStream);
476     AAudioStreamBuilder_delete(aaudioBuilder);
477 }
478 
479 // ************************************************************
480 // Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
481 
482 // Callback function that counts calls.
CallbackOnceProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)483 aaudio_data_callback_result_t CallbackOnceProc(
484         AAudioStream *stream,
485         void *userData,
486         void *audioData,
487         int32_t numFrames
488 ) {
489     (void) stream;
490     (void) audioData;
491     (void) numFrames;
492 
493     std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
494     (*callbackCountPtr)++;
495 
496     return AAUDIO_CALLBACK_RESULT_STOP;
497 }
498 
checkCallbackOnce(aaudio_performance_mode_t perfMode)499 void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
500 
501     std::atomic<int32_t>   callbackCount{0};
502 
503     AAudioStreamBuilder *aaudioBuilder = nullptr;
504     AAudioStream *aaudioStream = nullptr;
505 
506     // Use an AAudioStreamBuilder to contain requested parameters.
507     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
508 
509     // Request stream properties.
510     AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
511     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
512 
513     // Create an AAudioStream using the Builder.
514     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
515     AAudioStreamBuilder_delete(aaudioBuilder);
516 
517     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
518 
519     sleep(1); // Give callback a chance to run many times.
520 
521     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
522 
523     EXPECT_EQ(1, callbackCount.load()); // should stop after first call
524 
525     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
526 }
527 
TEST(test_various,aaudio_callback_once_none)528 TEST(test_various, aaudio_callback_once_none) {
529     checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
530 }
531 
TEST(test_various,aaudio_callback_once_lowlat)532 TEST(test_various, aaudio_callback_once_lowlat) {
533     checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
534 }
535 
536 // ************************************************************
537 struct WakeUpCallbackData {
wakeOtherWakeUpCallbackData538     void wakeOther() {
539         // signal waiting test to wake up
540         {
541             std::lock_guard <std::mutex> lock(mutex);
542             finished = true;
543         }
544         conditionVariable.notify_one();
545     }
546 
waitForFinishedWakeUpCallbackData547     void waitForFinished() {
548         std::unique_lock <std::mutex> aLock(mutex);
549         conditionVariable.wait(aLock, [=] { return finished; });
550     }
551 
552     // For signalling foreground test when callback finished
553     std::mutex              mutex;
554     std::condition_variable conditionVariable;
555     bool                    finished = false;
556 };
557 
558 // Test to make sure we cannot call recursively into the system from a callback.
559 struct DangerousData : public WakeUpCallbackData {
560     aaudio_result_t resultStart = AAUDIO_OK;
561     aaudio_result_t resultStop = AAUDIO_OK;
562     aaudio_result_t resultPause = AAUDIO_OK;
563     aaudio_result_t resultFlush = AAUDIO_OK;
564     aaudio_result_t resultClose = AAUDIO_OK;
565 };
566 
567 // Callback function that tries to call back into the stream.
DangerousDataCallbackProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)568 aaudio_data_callback_result_t DangerousDataCallbackProc(
569         AAudioStream *stream,
570         void *userData,
571         void *audioData,
572         int32_t numFrames) {
573     (void) audioData;
574     (void) numFrames;
575 
576     DangerousData *data = (DangerousData *)userData;
577     data->resultStart = AAudioStream_requestStart(stream);
578     data->resultStop = AAudioStream_requestStop(stream);
579     data->resultPause = AAudioStream_requestPause(stream);
580     data->resultFlush = AAudioStream_requestFlush(stream);
581     data->resultClose = AAudioStream_close(stream);
582 
583     data->wakeOther();
584 
585     return AAUDIO_CALLBACK_RESULT_STOP;
586 }
587 
588 //int main() { // To fix Android Studio formatting when editing.
checkDangerousCallback(aaudio_performance_mode_t perfMode)589 void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
590     DangerousData        dangerousData;
591     AAudioStreamBuilder *aaudioBuilder = nullptr;
592     AAudioStream        *aaudioStream = nullptr;
593 
594     // Use an AAudioStreamBuilder to contain requested parameters.
595     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
596 
597     // Request stream properties.
598     AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
599     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
600 
601     // Create an AAudioStream using the Builder.
602     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
603     AAudioStreamBuilder_delete(aaudioBuilder);
604 
605     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
606 
607     dangerousData.waitForFinished();
608 
609     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
610 
611     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
612     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
613     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
614     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
615     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
616 
617     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
618 }
619 
620 //int main() { // To fix Android Studio formatting when editing.
621 
TEST(test_various,aaudio_callback_blockers_none)622 TEST(test_various, aaudio_callback_blockers_none) {
623     checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
624 }
625 
TEST(test_various,aaudio_callback_blockers_lowlat)626 TEST(test_various, aaudio_callback_blockers_lowlat) {
627     checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
628 }
629