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