• 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 *,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     aaudio_direction_t direction = AAudioStream_getDirection(stream);
37     if (direction == AAUDIO_DIRECTION_INPUT) {
38         return AAUDIO_CALLBACK_RESULT_CONTINUE;
39     }
40     // Check to make sure the buffer is initialized to all zeros.
41     int channels = AAudioStream_getChannelCount(stream);
42     int numSamples = channels * numFrames;
43     bool allZeros = true;
44     float * const floatData = reinterpret_cast<float *>(audioData);
45     for (int i = 0; i < numSamples; i++) {
46         allZeros &= (floatData[i] == 0.0f);
47         floatData[i] = 0.0f;
48     }
49     EXPECT_TRUE(allZeros);
50     return AAUDIO_CALLBACK_RESULT_CONTINUE;
51 }
52 
53 constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
54 
checkReleaseThenClose(aaudio_performance_mode_t perfMode,aaudio_sharing_mode_t sharingMode,aaudio_direction_t direction=AAUDIO_DIRECTION_OUTPUT)55 void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
56         aaudio_sharing_mode_t sharingMode,
57         aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
58     AAudioStreamBuilder* aaudioBuilder = nullptr;
59     AAudioStream* aaudioStream = nullptr;
60 
61     // Use an AAudioStreamBuilder to contain requested parameters.
62     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
63 
64     // Request stream properties.
65     AAudioStreamBuilder_setDataCallback(aaudioBuilder,
66                                         NoopDataCallbackProc,
67                                         nullptr);
68     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
69     AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
70     AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
71     AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
72 
73     // Create an AAudioStream using the Builder.
74     ASSERT_EQ(AAUDIO_OK,
75               AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
76     AAudioStreamBuilder_delete(aaudioBuilder);
77 
78     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
79 
80     sleep(1);
81 
82     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
83 
84     EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
85     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
86 
87     // We should be able to call this again without crashing.
88     EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
89     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
90 
91     // We expect these not to crash.
92     AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
93     AAudioStream_setBufferSizeInFrames(aaudioStream, 99999999);
94 
95     // We should NOT be able to start or change a stream after it has been released.
96     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStart(aaudioStream));
97     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
98     // Pause is only implemented for OUTPUT.
99     if (direction == AAUDIO_DIRECTION_OUTPUT) {
100         EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
101                   AAudioStream_requestPause(aaudioStream));
102     }
103     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
104     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStop(aaudioStream));
105     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
106 
107     // Does this crash?
108     EXPECT_GT(AAudioStream_getFramesRead(aaudioStream), 0);
109     EXPECT_GT(AAudioStream_getFramesWritten(aaudioStream), 0);
110     EXPECT_GT(AAudioStream_getFramesPerBurst(aaudioStream), 0);
111     EXPECT_GE(AAudioStream_getXRunCount(aaudioStream), 0);
112     EXPECT_GT(AAudioStream_getBufferCapacityInFrames(aaudioStream), 0);
113     EXPECT_GT(AAudioStream_getBufferSizeInFrames(aaudioStream), 0);
114 
115     int64_t timestampFrames = 0;
116     int64_t timestampNanos = 0;
117     aaudio_result_t result = AAudioStream_getTimestamp(aaudioStream, CLOCK_MONOTONIC,
118             &timestampFrames, &timestampNanos);
119     EXPECT_TRUE(result == AAUDIO_ERROR_INVALID_STATE || result == AAUDIO_ERROR_UNIMPLEMENTED);
120 
121     // Verify Closing State. Does this crash?
122     aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
123     EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
124                                                          AAUDIO_STREAM_STATE_UNKNOWN, &state,
125                                                          500 * NANOS_PER_MILLISECOND));
126     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
127 
128     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
129 }
130 
TEST(test_various,aaudio_release_close_none_output)131 TEST(test_various, aaudio_release_close_none_output) {
132     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
133             AAUDIO_SHARING_MODE_SHARED,
134             AAUDIO_DIRECTION_OUTPUT);
135     // No EXCLUSIVE streams with MODE_NONE.
136 }
137 
TEST(test_various,aaudio_release_close_none_input)138 TEST(test_various, aaudio_release_close_none_input) {
139     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
140             AAUDIO_SHARING_MODE_SHARED,
141             AAUDIO_DIRECTION_INPUT);
142     // No EXCLUSIVE streams with MODE_NONE.
143 }
144 
TEST(test_various,aaudio_release_close_low_shared_output)145 TEST(test_various, aaudio_release_close_low_shared_output) {
146     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
147             AAUDIO_SHARING_MODE_SHARED,
148             AAUDIO_DIRECTION_OUTPUT);
149 }
150 
TEST(test_various,aaudio_release_close_low_shared_input)151 TEST(test_various, aaudio_release_close_low_shared_input) {
152     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
153             AAUDIO_SHARING_MODE_SHARED,
154             AAUDIO_DIRECTION_INPUT);
155 }
156 
TEST(test_various,aaudio_release_close_low_exclusive_output)157 TEST(test_various, aaudio_release_close_low_exclusive_output) {
158     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
159             AAUDIO_SHARING_MODE_EXCLUSIVE,
160             AAUDIO_DIRECTION_OUTPUT);
161 }
162 
TEST(test_various,aaudio_release_close_low_exclusive_input)163 TEST(test_various, aaudio_release_close_low_exclusive_input) {
164     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
165             AAUDIO_SHARING_MODE_EXCLUSIVE,
166             AAUDIO_DIRECTION_INPUT);
167 }
168 
169 enum FunctionToCall {
170     CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH, CALL_RELEASE
171 };
172 
checkStateTransition(aaudio_performance_mode_t perfMode,aaudio_stream_state_t originalState,FunctionToCall functionToCall,aaudio_result_t expectedResult,aaudio_stream_state_t expectedState)173 void checkStateTransition(aaudio_performance_mode_t perfMode,
174                           aaudio_stream_state_t originalState,
175                           FunctionToCall functionToCall,
176                           aaudio_result_t expectedResult,
177                           aaudio_stream_state_t expectedState) {
178     AAudioStreamBuilder *aaudioBuilder = nullptr;
179     AAudioStream *aaudioStream = nullptr;
180 
181     // Use an AAudioStreamBuilder to contain requested parameters.
182     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
183 
184     // Request stream properties.
185     AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
186     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
187     AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
188 
189     // Create an AAudioStream using the Builder.
190     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
191 
192     // Verify Open State
193     aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
194     EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
195                                                          AAUDIO_STREAM_STATE_UNKNOWN, &state,
196                                                          1000 * NANOS_PER_MILLISECOND));
197     EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
198 
199     // Put stream into desired state.
200     aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED;
201     if (originalState != AAUDIO_STREAM_STATE_OPEN) {
202 
203         ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
204 
205         if (originalState != AAUDIO_STREAM_STATE_STARTING) {
206 
207             ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
208                                                                  AAUDIO_STREAM_STATE_STARTING,
209                                                                  &state,
210                                                                  1000 * NANOS_PER_MILLISECOND));
211             ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
212 
213             if (originalState == AAUDIO_STREAM_STATE_STOPPING) {
214                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
215             } else if (originalState == AAUDIO_STREAM_STATE_STOPPED) {
216                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
217                 inputState = AAUDIO_STREAM_STATE_STOPPING;
218             } else if (originalState == AAUDIO_STREAM_STATE_PAUSING) {
219                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
220             } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
221                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
222                 inputState = AAUDIO_STREAM_STATE_PAUSING;
223             } else if (originalState == AAUDIO_STREAM_STATE_FLUSHING) {
224                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
225                 // We can only flush() after pause is complete.
226                 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
227                                                                  AAUDIO_STREAM_STATE_PAUSING,
228                                                                  &state,
229                                                                  1000 * NANOS_PER_MILLISECOND));
230                 ASSERT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
231                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestFlush(aaudioStream));
232                 // That will put the stream into the FLUSHING state.
233                 // The FLUSHING state will persist until we process functionToCall.
234                 // That is because the transition to FLUSHED is caused by the callback,
235                 // or by calling write() or waitForStateChange(). But those will not
236                 // occur.
237             } else if (originalState == AAUDIO_STREAM_STATE_CLOSING) {
238                 ASSERT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
239             }
240         }
241     }
242 
243     // Wait until we get past the transitional state if requested.
244     if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
245         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
246                                                              inputState,
247                                                              &state,
248                                                              1000 * NANOS_PER_MILLISECOND));
249         ASSERT_EQ(originalState, state);
250     }
251 
252     aaudio_stream_state_t transitionalState = originalState;
253     switch(functionToCall) {
254         case FunctionToCall::CALL_START:
255             EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
256             transitionalState = AAUDIO_STREAM_STATE_STARTING;
257             break;
258         case FunctionToCall::CALL_STOP:
259             EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
260             transitionalState = AAUDIO_STREAM_STATE_STOPPING;
261             break;
262         case FunctionToCall::CALL_PAUSE:
263             EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
264             transitionalState = AAUDIO_STREAM_STATE_PAUSING;
265             break;
266         case FunctionToCall::CALL_FLUSH:
267             EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
268             transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
269             break;
270         case FunctionToCall::CALL_RELEASE:
271             EXPECT_EQ(expectedResult, AAudioStream_release(aaudioStream));
272             // Set to UNINITIALIZED so the waitForStateChange() below will
273             // will return immediately with the current state.
274             transitionalState = AAUDIO_STREAM_STATE_UNINITIALIZED;
275             break;
276     }
277 
278     EXPECT_EQ(AAUDIO_OK,
279             AAudioStream_waitForStateChange(aaudioStream,
280                     transitionalState,
281                     &state,
282                     1000 * NANOS_PER_MILLISECOND));
283 
284     // We should not change state when a function fails.
285     if (expectedResult != AAUDIO_OK) {
286         ASSERT_EQ(originalState, expectedState);
287     }
288     EXPECT_EQ(expectedState, state);
289     if (state != expectedState) {
290         printf("ERROR - expected %s, actual = %s\n",
291                 AAudio_convertStreamStateToText(expectedState),
292                 AAudio_convertStreamStateToText(state));
293         fflush(stdout);
294     }
295 
296     AAudioStream_close(aaudioStream);
297     AAudioStreamBuilder_delete(aaudioBuilder);
298 }
299 
300 // TODO Use parameterized tests instead of these individual specific tests.
301 
302 // OPEN =================================================================
TEST(test_various,aaudio_state_lowlat_open_start)303 TEST(test_various, aaudio_state_lowlat_open_start) {
304     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
305             AAUDIO_STREAM_STATE_OPEN,
306             FunctionToCall::CALL_START,
307             AAUDIO_OK,
308             AAUDIO_STREAM_STATE_STARTED);
309 }
310 
TEST(test_various,aaudio_state_none_open_start)311 TEST(test_various, aaudio_state_none_open_start) {
312     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
313             AAUDIO_STREAM_STATE_OPEN,
314             FunctionToCall::CALL_START,
315             AAUDIO_OK,
316             AAUDIO_STREAM_STATE_STARTED);
317 }
318 
TEST(test_various,aaudio_state_lowlat_open_stop)319 TEST(test_various, aaudio_state_lowlat_open_stop) {
320     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
321             AAUDIO_STREAM_STATE_OPEN,
322             FunctionToCall::CALL_STOP,
323             AAUDIO_OK,
324             AAUDIO_STREAM_STATE_STOPPED);
325 }
326 
TEST(test_various,aaudio_state_none_open_stop)327 TEST(test_various, aaudio_state_none_open_stop) {
328     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
329             AAUDIO_STREAM_STATE_OPEN,
330             FunctionToCall::CALL_STOP,
331             AAUDIO_OK,
332             AAUDIO_STREAM_STATE_STOPPED);
333 }
334 
TEST(test_various,aaudio_state_lowlat_open_pause)335 TEST(test_various, aaudio_state_lowlat_open_pause) {
336     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
337             AAUDIO_STREAM_STATE_OPEN,
338             FunctionToCall::CALL_PAUSE,
339             AAUDIO_OK,
340             AAUDIO_STREAM_STATE_PAUSED);
341 }
342 
TEST(test_various,aaudio_state_none_open_pause)343 TEST(test_various, aaudio_state_none_open_pause) {
344     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
345             AAUDIO_STREAM_STATE_OPEN,
346             FunctionToCall::CALL_PAUSE,
347             AAUDIO_OK,
348             AAUDIO_STREAM_STATE_PAUSED);
349 }
350 
TEST(test_various,aaudio_state_lowlat_open_flush)351 TEST(test_various, aaudio_state_lowlat_open_flush) {
352     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
353             AAUDIO_STREAM_STATE_OPEN,
354             FunctionToCall::CALL_FLUSH,
355             AAUDIO_OK,
356             AAUDIO_STREAM_STATE_FLUSHED);
357 }
358 
TEST(test_various,aaudio_state_none_open_flush)359 TEST(test_various, aaudio_state_none_open_flush) {
360     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
361             AAUDIO_STREAM_STATE_OPEN,
362             FunctionToCall::CALL_FLUSH,
363             AAUDIO_OK,
364             AAUDIO_STREAM_STATE_FLUSHED);
365 }
366 
367 
368 // STARTED =================================================================
TEST(test_various,aaudio_state_lowlat_started_start)369 TEST(test_various, aaudio_state_lowlat_started_start) {
370     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
371             AAUDIO_STREAM_STATE_STARTED,
372             FunctionToCall::CALL_START,
373             AAUDIO_ERROR_INVALID_STATE,
374             AAUDIO_STREAM_STATE_STARTED);
375 }
376 
TEST(test_various,aaudio_state_none_started_start)377 TEST(test_various, aaudio_state_none_started_start) {
378     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
379             AAUDIO_STREAM_STATE_STARTED,
380             FunctionToCall::CALL_START,
381             AAUDIO_ERROR_INVALID_STATE,
382             AAUDIO_STREAM_STATE_STARTED);
383 }
384 
TEST(test_various,aaudio_state_lowlat_started_stop)385 TEST(test_various, aaudio_state_lowlat_started_stop) {
386     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
387             AAUDIO_STREAM_STATE_STARTED,
388             FunctionToCall::CALL_STOP,
389             AAUDIO_OK,
390             AAUDIO_STREAM_STATE_STOPPED);
391 }
392 
TEST(test_various,aaudio_state_none_started_stop)393 TEST(test_various, aaudio_state_none_started_stop) {
394     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
395             AAUDIO_STREAM_STATE_STARTED,
396             FunctionToCall::CALL_STOP,
397             AAUDIO_OK,
398             AAUDIO_STREAM_STATE_STOPPED);
399 }
400 
TEST(test_various,aaudio_state_lowlat_started_pause)401 TEST(test_various, aaudio_state_lowlat_started_pause) {
402     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
403             AAUDIO_STREAM_STATE_STARTED,
404             FunctionToCall::CALL_PAUSE,
405             AAUDIO_OK,
406             AAUDIO_STREAM_STATE_PAUSED);
407 }
408 
TEST(test_various,aaudio_state_none_started_pause)409 TEST(test_various, aaudio_state_none_started_pause) {
410     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
411             AAUDIO_STREAM_STATE_STARTED,
412             FunctionToCall::CALL_PAUSE,
413             AAUDIO_OK,
414             AAUDIO_STREAM_STATE_PAUSED);
415 }
416 
TEST(test_various,aaudio_state_lowlat_started_flush)417 TEST(test_various, aaudio_state_lowlat_started_flush) {
418     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
419             AAUDIO_STREAM_STATE_STARTED,
420             FunctionToCall::CALL_FLUSH,
421             AAUDIO_ERROR_INVALID_STATE,
422             AAUDIO_STREAM_STATE_STARTED);
423 }
424 
TEST(test_various,aaudio_state_none_started_flush)425 TEST(test_various, aaudio_state_none_started_flush) {
426     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
427             AAUDIO_STREAM_STATE_STARTED,
428             FunctionToCall::CALL_FLUSH,
429             AAUDIO_ERROR_INVALID_STATE,
430             AAUDIO_STREAM_STATE_STARTED);
431 }
432 
433 // STOPPED =================================================================
TEST(test_various,aaudio_state_lowlat_stopped_start)434 TEST(test_various, aaudio_state_lowlat_stopped_start) {
435     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
436             AAUDIO_STREAM_STATE_STOPPED,
437             FunctionToCall::CALL_START,
438             AAUDIO_OK,
439             AAUDIO_STREAM_STATE_STARTED);
440 }
441 
TEST(test_various,aaudio_state_none_stopped_start)442 TEST(test_various, aaudio_state_none_stopped_start) {
443     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
444             AAUDIO_STREAM_STATE_STOPPED,
445             FunctionToCall::CALL_START,
446             AAUDIO_OK,
447             AAUDIO_STREAM_STATE_STARTED);
448 }
449 
TEST(test_various,aaudio_state_lowlat_stopped_stop)450 TEST(test_various, aaudio_state_lowlat_stopped_stop) {
451     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
452             AAUDIO_STREAM_STATE_STOPPED,
453             FunctionToCall::CALL_STOP,
454             AAUDIO_OK,
455             AAUDIO_STREAM_STATE_STOPPED);
456 }
457 
TEST(test_various,aaudio_state_none_stopped_stop)458 TEST(test_various, aaudio_state_none_stopped_stop) {
459     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
460             AAUDIO_STREAM_STATE_STOPPED,
461             FunctionToCall::CALL_STOP,
462             AAUDIO_OK,
463             AAUDIO_STREAM_STATE_STOPPED);
464 }
465 
TEST(test_various,aaudio_state_lowlat_stopped_pause)466 TEST(test_various, aaudio_state_lowlat_stopped_pause) {
467     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
468             AAUDIO_STREAM_STATE_STOPPED,
469             FunctionToCall::CALL_PAUSE,
470             AAUDIO_OK,
471             AAUDIO_STREAM_STATE_PAUSED);
472 }
473 
TEST(test_various,aaudio_state_none_stopped_pause)474 TEST(test_various, aaudio_state_none_stopped_pause) {
475     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
476             AAUDIO_STREAM_STATE_STOPPED,
477             FunctionToCall::CALL_PAUSE,
478             AAUDIO_OK,
479             AAUDIO_STREAM_STATE_PAUSED);
480 }
481 
TEST(test_various,aaudio_state_lowlat_stopped_flush)482 TEST(test_various, aaudio_state_lowlat_stopped_flush) {
483     checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
484             AAUDIO_STREAM_STATE_STOPPED,
485             FunctionToCall::CALL_FLUSH,
486             AAUDIO_OK,
487             AAUDIO_STREAM_STATE_FLUSHED);
488 }
489 
TEST(test_various,aaudio_state_none_stopped_flush)490 TEST(test_various, aaudio_state_none_stopped_flush) {
491     checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
492             AAUDIO_STREAM_STATE_STOPPED,
493             FunctionToCall::CALL_FLUSH,
494             AAUDIO_OK,
495             AAUDIO_STREAM_STATE_FLUSHED);
496 }
497 
498 // PAUSED =================================================================
TEST(test_various,aaudio_state_lowlat_paused_start)499 TEST(test_various, aaudio_state_lowlat_paused_start) {
500 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
501         AAUDIO_STREAM_STATE_PAUSED,
502         FunctionToCall::CALL_START,
503         AAUDIO_OK,
504         AAUDIO_STREAM_STATE_STARTED);
505 }
506 
TEST(test_various,aaudio_state_none_paused_start)507 TEST(test_various, aaudio_state_none_paused_start) {
508 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
509         AAUDIO_STREAM_STATE_PAUSED,
510         FunctionToCall::CALL_START,
511         AAUDIO_OK,
512         AAUDIO_STREAM_STATE_STARTED);
513 }
514 
TEST(test_various,aaudio_state_lowlat_paused_stop)515 TEST(test_various, aaudio_state_lowlat_paused_stop) {
516 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
517         AAUDIO_STREAM_STATE_PAUSED,
518         FunctionToCall::CALL_STOP,
519         AAUDIO_OK,
520         AAUDIO_STREAM_STATE_STOPPED);
521 }
522 
TEST(test_various,aaudio_state_none_paused_stop)523 TEST(test_various, aaudio_state_none_paused_stop) {
524 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
525         AAUDIO_STREAM_STATE_PAUSED,
526         FunctionToCall::CALL_STOP,
527         AAUDIO_OK,
528         AAUDIO_STREAM_STATE_STOPPED);
529 }
530 
TEST(test_various,aaudio_state_lowlat_paused_pause)531 TEST(test_various, aaudio_state_lowlat_paused_pause) {
532 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
533         AAUDIO_STREAM_STATE_PAUSED,
534         FunctionToCall::CALL_PAUSE,
535         AAUDIO_OK,
536         AAUDIO_STREAM_STATE_PAUSED);
537 }
538 
TEST(test_various,aaudio_state_none_paused_pause)539 TEST(test_various, aaudio_state_none_paused_pause) {
540 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
541         AAUDIO_STREAM_STATE_PAUSED,
542         FunctionToCall::CALL_PAUSE,
543         AAUDIO_OK,
544         AAUDIO_STREAM_STATE_PAUSED);
545 }
546 
TEST(test_various,aaudio_state_lowlat_paused_flush)547 TEST(test_various, aaudio_state_lowlat_paused_flush) {
548 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
549         AAUDIO_STREAM_STATE_PAUSED,
550         FunctionToCall::CALL_FLUSH,
551         AAUDIO_OK,
552         AAUDIO_STREAM_STATE_FLUSHED);
553 }
554 
TEST(test_various,aaudio_state_none_paused_flush)555 TEST(test_various, aaudio_state_none_paused_flush) {
556 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
557         AAUDIO_STREAM_STATE_PAUSED,
558         FunctionToCall::CALL_FLUSH,
559         AAUDIO_OK,
560         AAUDIO_STREAM_STATE_FLUSHED);
561 }
562 
563 // FLUSHING ================================================================
TEST(test_various,aaudio_state_lowlat_flushing_start)564 TEST(test_various, aaudio_state_lowlat_flushing_start) {
565 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
566         AAUDIO_STREAM_STATE_FLUSHING,
567         FunctionToCall::CALL_START,
568         AAUDIO_OK,
569         AAUDIO_STREAM_STATE_STARTED);
570 }
571 
TEST(test_various,aaudio_state_none_flushing_start)572 TEST(test_various, aaudio_state_none_flushing_start) {
573 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
574         AAUDIO_STREAM_STATE_FLUSHING,
575         FunctionToCall::CALL_START,
576         AAUDIO_OK,
577         AAUDIO_STREAM_STATE_STARTED);
578 }
579 
TEST(test_various,aaudio_state_lowlat_flushing_release)580 TEST(test_various, aaudio_state_lowlat_flushing_release) {
581 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
582         AAUDIO_STREAM_STATE_FLUSHING,
583         FunctionToCall::CALL_RELEASE,
584         AAUDIO_OK,
585         AAUDIO_STREAM_STATE_CLOSING);
586 }
587 
TEST(test_various,aaudio_state_none_flushing_release)588 TEST(test_various, aaudio_state_none_flushing_release) {
589 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
590         AAUDIO_STREAM_STATE_FLUSHING,
591         FunctionToCall::CALL_RELEASE,
592         AAUDIO_OK,
593         AAUDIO_STREAM_STATE_CLOSING);
594 }
595 
TEST(test_various,aaudio_state_lowlat_starting_release)596 TEST(test_various, aaudio_state_lowlat_starting_release) {
597 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
598         AAUDIO_STREAM_STATE_STARTING,
599         FunctionToCall::CALL_RELEASE,
600         AAUDIO_OK,
601         AAUDIO_STREAM_STATE_CLOSING);
602 }
603 
TEST(test_various,aaudio_state_none_starting_release)604 TEST(test_various, aaudio_state_none_starting_release) {
605 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
606         AAUDIO_STREAM_STATE_STARTING,
607         FunctionToCall::CALL_RELEASE,
608         AAUDIO_OK,
609         AAUDIO_STREAM_STATE_CLOSING);
610 }
611 
612 // CLOSING ================================================================
TEST(test_various,aaudio_state_lowlat_closing_start)613 TEST(test_various, aaudio_state_lowlat_closing_start) {
614 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
615         AAUDIO_STREAM_STATE_CLOSING,
616         FunctionToCall::CALL_START,
617         AAUDIO_ERROR_INVALID_STATE,
618         AAUDIO_STREAM_STATE_CLOSING);
619 }
620 
TEST(test_various,aaudio_state_none_closing_start)621 TEST(test_various, aaudio_state_none_closing_start) {
622 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
623         AAUDIO_STREAM_STATE_CLOSING,
624         FunctionToCall::CALL_START,
625         AAUDIO_ERROR_INVALID_STATE,
626         AAUDIO_STREAM_STATE_CLOSING);
627 }
628 
TEST(test_various,aaudio_state_lowlat_closing_stop)629 TEST(test_various, aaudio_state_lowlat_closing_stop) {
630 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
631         AAUDIO_STREAM_STATE_CLOSING,
632         FunctionToCall::CALL_STOP,
633         AAUDIO_ERROR_INVALID_STATE,
634         AAUDIO_STREAM_STATE_CLOSING);
635 }
636 
TEST(test_various,aaudio_state_none_closing_stop)637 TEST(test_various, aaudio_state_none_closing_stop) {
638 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
639         AAUDIO_STREAM_STATE_CLOSING,
640         FunctionToCall::CALL_STOP,
641         AAUDIO_ERROR_INVALID_STATE,
642         AAUDIO_STREAM_STATE_CLOSING);
643 }
644 
645 // ==========================================================================
TEST(test_various,aaudio_set_buffer_size)646 TEST(test_various, aaudio_set_buffer_size) {
647 
648     int32_t bufferCapacity;
649     int32_t framesPerBurst = 0;
650     int32_t actualSize = 0;
651 
652     AAudioStreamBuilder *aaudioBuilder = nullptr;
653     AAudioStream *aaudioStream = nullptr;
654 
655     // Use an AAudioStreamBuilder to contain requested parameters.
656     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
657 
658     // Request stream properties.
659     AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
660     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
661 
662     // Create an AAudioStream using the Builder.
663     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
664 
665     // This is the number of frames that are read in one chunk by a DMA controller
666     // or a DSP or a mixer.
667     framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
668     bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
669     printf("          bufferCapacity = %d, remainder = %d\n",
670            bufferCapacity, bufferCapacity % framesPerBurst);
671 
672     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
673     EXPECT_GE(actualSize, 0); // 0 is legal in R
674     EXPECT_LE(actualSize, bufferCapacity);
675 
676     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
677     EXPECT_GT(actualSize, framesPerBurst);
678     EXPECT_LE(actualSize, bufferCapacity);
679 
680     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
681     EXPECT_GT(actualSize, framesPerBurst);
682     EXPECT_LE(actualSize, bufferCapacity);
683 
684     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
685     EXPECT_GT(actualSize, framesPerBurst);
686     EXPECT_LE(actualSize, bufferCapacity);
687 
688     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
689     EXPECT_GT(actualSize, framesPerBurst);
690     EXPECT_LE(actualSize, bufferCapacity);
691 
692     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
693     EXPECT_GT(actualSize, framesPerBurst);
694     EXPECT_LE(actualSize, bufferCapacity);
695 
696     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
697     EXPECT_GT(actualSize, framesPerBurst);
698     EXPECT_LE(actualSize, bufferCapacity);
699 
700     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
701     EXPECT_GE(actualSize, 0); // 0 is legal in R
702     EXPECT_LE(actualSize, bufferCapacity);
703 
704     AAudioStream_close(aaudioStream);
705     AAudioStreamBuilder_delete(aaudioBuilder);
706 }
707 
708 // ************************************************************
709 // Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
710 
711 // Callback function that counts calls.
CallbackOnceProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)712 aaudio_data_callback_result_t CallbackOnceProc(
713         AAudioStream *stream,
714         void *userData,
715         void *audioData,
716         int32_t numFrames
717 ) {
718     (void) stream;
719     (void) audioData;
720     (void) numFrames;
721 
722     std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
723     (*callbackCountPtr)++;
724 
725     return AAUDIO_CALLBACK_RESULT_STOP;
726 }
727 
checkCallbackOnce(aaudio_performance_mode_t perfMode)728 void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
729 
730     std::atomic<int32_t>   callbackCount{0};
731 
732     AAudioStreamBuilder *aaudioBuilder = nullptr;
733     AAudioStream *aaudioStream = nullptr;
734 
735     // Use an AAudioStreamBuilder to contain requested parameters.
736     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
737 
738     // Request stream properties.
739     AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
740     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
741 
742     // Create an AAudioStream using the Builder.
743     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
744     AAudioStreamBuilder_delete(aaudioBuilder);
745 
746     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
747 
748     sleep(1); // Give callback a chance to run many times.
749 
750     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
751 
752     EXPECT_EQ(1, callbackCount.load()); // should stop after first call
753 
754     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
755 }
756 
TEST(test_various,aaudio_callback_once_none)757 TEST(test_various, aaudio_callback_once_none) {
758     checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
759 }
760 
TEST(test_various,aaudio_callback_once_lowlat)761 TEST(test_various, aaudio_callback_once_lowlat) {
762     checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
763 }
764 
765 // ************************************************************
766 struct WakeUpCallbackData {
wakeOtherWakeUpCallbackData767     void wakeOther() {
768         // signal waiting test to wake up
769         {
770             std::lock_guard <std::mutex> lock(mutex);
771             finished = true;
772         }
773         conditionVariable.notify_one();
774     }
775 
waitForFinishedWakeUpCallbackData776     void waitForFinished() {
777         std::unique_lock <std::mutex> aLock(mutex);
778         conditionVariable.wait(aLock, [=] { return finished; });
779     }
780 
781     // For signalling foreground test when callback finished
782     std::mutex              mutex;
783     std::condition_variable conditionVariable;
784     bool                    finished = false;
785 };
786 
787 // Test to make sure we cannot call recursively into the system from a callback.
788 struct DangerousData : public WakeUpCallbackData {
789     aaudio_result_t resultStart = AAUDIO_OK;
790     aaudio_result_t resultStop = AAUDIO_OK;
791     aaudio_result_t resultPause = AAUDIO_OK;
792     aaudio_result_t resultFlush = AAUDIO_OK;
793     aaudio_result_t resultClose = AAUDIO_OK;
794 };
795 
796 // Callback function that tries to call back into the stream.
DangerousDataCallbackProc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)797 aaudio_data_callback_result_t DangerousDataCallbackProc(
798         AAudioStream *stream,
799         void *userData,
800         void *audioData,
801         int32_t numFrames) {
802     (void) audioData;
803     (void) numFrames;
804 
805     DangerousData *data = (DangerousData *)userData;
806     data->resultStart = AAudioStream_requestStart(stream);
807     data->resultStop = AAudioStream_requestStop(stream);
808     data->resultPause = AAudioStream_requestPause(stream);
809     data->resultFlush = AAudioStream_requestFlush(stream);
810     data->resultClose = AAudioStream_close(stream);
811 
812     data->wakeOther();
813 
814     return AAUDIO_CALLBACK_RESULT_STOP;
815 }
816 
817 //int main() { // To fix Android Studio formatting when editing.
checkDangerousCallback(aaudio_performance_mode_t perfMode)818 void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
819     DangerousData        dangerousData;
820     AAudioStreamBuilder *aaudioBuilder = nullptr;
821     AAudioStream        *aaudioStream = nullptr;
822 
823     // Use an AAudioStreamBuilder to contain requested parameters.
824     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
825 
826     // Request stream properties.
827     AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
828     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
829 
830     // Create an AAudioStream using the Builder.
831     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
832     AAudioStreamBuilder_delete(aaudioBuilder);
833 
834     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
835 
836     dangerousData.waitForFinished();
837 
838     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
839 
840     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
841     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
842     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
843     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
844     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
845 
846     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
847 }
848 
849 //int main() { // To fix Android Studio formatting when editing.
850 
TEST(test_various,aaudio_callback_blockers_none)851 TEST(test_various, aaudio_callback_blockers_none) {
852     checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
853 }
854 
TEST(test_various,aaudio_callback_blockers_lowlat)855 TEST(test_various, aaudio_callback_blockers_lowlat) {
856     checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
857 }
858