blob: a20c79984787900922e8c42719ec324378ef86d4 [file] [log] [blame]
Phil Burk9a9e6002017-11-17 12:17:37 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Test various AAudio features including AAudioStream_setBufferSizeInFrames().
18
Phil Burk2581ae22017-11-21 15:47:29 -080019#include <condition_variable>
20#include <mutex>
Phil Burk9a9e6002017-11-17 12:17:37 -080021#include <stdio.h>
Phil Burk9a9e6002017-11-17 12:17:37 -080022
23#include <android-base/macros.h>
24#include <aaudio/AAudio.h>
25
26#include <gtest/gtest.h>
Phil Burk2581ae22017-11-21 15:47:29 -080027#include <unistd.h>
28
Phil Burk9a9e6002017-11-17 12:17:37 -080029// Callback function that does nothing.
Phil Burk2581ae22017-11-21 15:47:29 -080030aaudio_data_callback_result_t NoopDataCallbackProc(
Phil Burk9cf23822020-04-17 11:53:35 -070031 AAudioStream * stream,
32 void * /* userData */,
Phil Burk9a9e6002017-11-17 12:17:37 -080033 void *audioData,
34 int32_t numFrames
35) {
Phil Burk9cf23822020-04-17 11:53:35 -070036 int channels = AAudioStream_getChannelCount(stream);
37 int numSamples = channels * numFrames;
38 bool allZeros = true;
39 float * const floatData = reinterpret_cast<float *>(audioData);
40 for (int i = 0; i < numSamples; i++) {
41 allZeros &= (floatData[i] == 0.0f);
42 floatData[i] = 0.0f;
43 }
44 EXPECT_TRUE(allZeros);
Phil Burk9a9e6002017-11-17 12:17:37 -080045 return AAUDIO_CALLBACK_RESULT_CONTINUE;
46}
47
Phil Burk0c15f4f2017-11-28 15:46:15 -080048constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
49
Phil Burk8b4e05e2019-12-17 12:12:09 -080050void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
51 aaudio_sharing_mode_t sharingMode) {
52 AAudioStreamBuilder* aaudioBuilder = nullptr;
53 AAudioStream* aaudioStream = nullptr;
54
55 // Use an AAudioStreamBuilder to contain requested parameters.
56 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
57
58 // Request stream properties.
59 AAudioStreamBuilder_setDataCallback(aaudioBuilder,
60 NoopDataCallbackProc,
61 nullptr);
62 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
63 AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
Phil Burk9cf23822020-04-17 11:53:35 -070064 AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
Phil Burk8b4e05e2019-12-17 12:12:09 -080065
66 // Create an AAudioStream using the Builder.
67 ASSERT_EQ(AAUDIO_OK,
68 AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
69 AAudioStreamBuilder_delete(aaudioBuilder);
70
71 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
72
73 sleep(1);
74
75 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
76
77 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
Phil Burkcc131ba2020-04-17 08:25:30 -070078 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
Phil Burk8b4e05e2019-12-17 12:12:09 -080079
80 // We should be able to call this again without crashing.
81 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
Phil Burkcc131ba2020-04-17 08:25:30 -070082 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
83
84 // We expect these not to crash.
85 AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
86 AAudioStream_setBufferSizeInFrames(aaudioStream, 99999999);
87
88 // We should NOT be able to start or change a stream after it has been released.
89 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStart(aaudioStream));
90 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
91 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestPause(aaudioStream));
92 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
93 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStop(aaudioStream));
94 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
95
96 // Does this crash?
97 EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream));
98 EXPECT_LT(0, AAudioStream_getFramesWritten(aaudioStream));
99
100 // Verify Closing State. Does this crash?
101 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
102 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
103 AAUDIO_STREAM_STATE_UNKNOWN, &state,
104 500 * NANOS_PER_MILLISECOND));
Phil Burk8b4e05e2019-12-17 12:12:09 -0800105 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
106
107 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
108}
109
110TEST(test_various, aaudio_release_close_none) {
111 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
112 AAUDIO_SHARING_MODE_SHARED);
113 // No EXCLUSIVE streams with MODE_NONE.
114}
115
116TEST(test_various, aaudio_release_close_low_shared) {
117 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
118 AAUDIO_SHARING_MODE_SHARED);
119}
120
121TEST(test_various, aaudio_release_close_low_exclusive) {
122 checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
123 AAUDIO_SHARING_MODE_EXCLUSIVE);
124}
125
Phil Burk4fa3b942017-12-13 17:25:24 -0800126enum FunctionToCall {
Phil Burk29112a12020-06-25 07:52:45 -0700127 CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH, CALL_RELEASE
Phil Burk4fa3b942017-12-13 17:25:24 -0800128};
129
130void checkStateTransition(aaudio_performance_mode_t perfMode,
131 aaudio_stream_state_t originalState,
132 FunctionToCall functionToCall,
133 aaudio_result_t expectedResult,
134 aaudio_stream_state_t expectedState) {
Phil Burk0c15f4f2017-11-28 15:46:15 -0800135 AAudioStreamBuilder *aaudioBuilder = nullptr;
136 AAudioStream *aaudioStream = nullptr;
137
Phil Burk4fa3b942017-12-13 17:25:24 -0800138 // Use an AAudioStreamBuilder to contain requested parameters.
Phil Burk0c15f4f2017-11-28 15:46:15 -0800139 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
140
Phil Burk4fa3b942017-12-13 17:25:24 -0800141 // Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -0800142 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk4fa3b942017-12-13 17:25:24 -0800143 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
Phil Burk9cf23822020-04-17 11:53:35 -0700144 AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
Phil Burk0c15f4f2017-11-28 15:46:15 -0800145
Phil Burk4fa3b942017-12-13 17:25:24 -0800146 // Create an AAudioStream using the Builder.
147 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
Phil Burk0c15f4f2017-11-28 15:46:15 -0800148
Phil Burk4fa3b942017-12-13 17:25:24 -0800149 // Verify Open State
Phil Burk0c15f4f2017-11-28 15:46:15 -0800150 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
151 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
152 AAUDIO_STREAM_STATE_UNKNOWN, &state,
153 1000 * NANOS_PER_MILLISECOND));
154 EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, state);
155
Phil Burk4fa3b942017-12-13 17:25:24 -0800156 // Put stream into desired state.
157 aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED;
158 if (originalState != AAUDIO_STREAM_STATE_OPEN) {
Phil Burk0c15f4f2017-11-28 15:46:15 -0800159
Phil Burk4fa3b942017-12-13 17:25:24 -0800160 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
161
162 if (originalState != AAUDIO_STREAM_STATE_STARTING) {
163
164 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
165 AAUDIO_STREAM_STATE_STARTING,
166 &state,
167 1000 * NANOS_PER_MILLISECOND));
168 ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
169
170 if (originalState == AAUDIO_STREAM_STATE_STOPPING) {
171 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
172 } else if (originalState == AAUDIO_STREAM_STATE_STOPPED) {
173 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
174 inputState = AAUDIO_STREAM_STATE_STOPPING;
175 } else if (originalState == AAUDIO_STREAM_STATE_PAUSING) {
176 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
177 } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
178 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
179 inputState = AAUDIO_STREAM_STATE_PAUSING;
Phil Burk29112a12020-06-25 07:52:45 -0700180 } else if (originalState == AAUDIO_STREAM_STATE_FLUSHING) {
181 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
182 // We can only flush() after pause is complete.
183 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
184 AAUDIO_STREAM_STATE_PAUSING,
185 &state,
186 1000 * NANOS_PER_MILLISECOND));
187 ASSERT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
188 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestFlush(aaudioStream));
189 // That will put the stream into the FLUSHING state.
190 // The FLUSHING state will persist until we process functionToCall.
191 // That is because the transition to FLUSHED is caused by the callback,
192 // or by calling write() or waitForStateChange(). But those will not
193 // occur.
194 } else if (originalState == AAUDIO_STREAM_STATE_CLOSING) {
195 ASSERT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
Phil Burk4fa3b942017-12-13 17:25:24 -0800196 }
197 }
198 }
199
Phil Burk29112a12020-06-25 07:52:45 -0700200 // Wait until we get past the transitional state if requested.
Phil Burk4fa3b942017-12-13 17:25:24 -0800201 if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
202 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
203 inputState,
204 &state,
205 1000 * NANOS_PER_MILLISECOND));
206 ASSERT_EQ(originalState, state);
207 }
208
209 aaudio_stream_state_t transitionalState = originalState;
210 switch(functionToCall) {
211 case FunctionToCall::CALL_START:
212 EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
213 transitionalState = AAUDIO_STREAM_STATE_STARTING;
214 break;
215 case FunctionToCall::CALL_STOP:
216 EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
217 transitionalState = AAUDIO_STREAM_STATE_STOPPING;
218 break;
219 case FunctionToCall::CALL_PAUSE:
220 EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
221 transitionalState = AAUDIO_STREAM_STATE_PAUSING;
222 break;
223 case FunctionToCall::CALL_FLUSH:
224 EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
225 transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
226 break;
Phil Burk29112a12020-06-25 07:52:45 -0700227 case FunctionToCall::CALL_RELEASE:
228 EXPECT_EQ(expectedResult, AAudioStream_release(aaudioStream));
229 // Set to UNINITIALIZED so the waitForStateChange() below will
230 // will return immediately with the current state.
231 transitionalState = AAUDIO_STREAM_STATE_UNINITIALIZED;
232 break;
Phil Burk4fa3b942017-12-13 17:25:24 -0800233 }
234
Phil Burk29112a12020-06-25 07:52:45 -0700235 EXPECT_EQ(AAUDIO_OK,
236 AAudioStream_waitForStateChange(aaudioStream,
237 transitionalState,
238 &state,
239 1000 * NANOS_PER_MILLISECOND));
240
Phil Burk4fa3b942017-12-13 17:25:24 -0800241 // We should not change state when a function fails.
242 if (expectedResult != AAUDIO_OK) {
243 ASSERT_EQ(originalState, expectedState);
244 }
245 EXPECT_EQ(expectedState, state);
246 if (state != expectedState) {
247 printf("ERROR - expected %s, actual = %s\n",
248 AAudio_convertStreamStateToText(expectedState),
249 AAudio_convertStreamStateToText(state));
250 fflush(stdout);
251 }
Phil Burk0c15f4f2017-11-28 15:46:15 -0800252
253 AAudioStream_close(aaudioStream);
254 AAudioStreamBuilder_delete(aaudioBuilder);
255}
256
Phil Burk4fa3b942017-12-13 17:25:24 -0800257// TODO Use parameterized tests instead of these individual specific tests.
258
259// OPEN =================================================================
260TEST(test_various, aaudio_state_lowlat_open_start) {
261 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
262 AAUDIO_STREAM_STATE_OPEN,
263 FunctionToCall::CALL_START,
264 AAUDIO_OK,
265 AAUDIO_STREAM_STATE_STARTED);
266}
267
268TEST(test_various, aaudio_state_none_open_start) {
269 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
270 AAUDIO_STREAM_STATE_OPEN,
271 FunctionToCall::CALL_START,
272 AAUDIO_OK,
273 AAUDIO_STREAM_STATE_STARTED);
274}
275
276TEST(test_various, aaudio_state_lowlat_open_stop) {
277 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
278 AAUDIO_STREAM_STATE_OPEN,
279 FunctionToCall::CALL_STOP,
280 AAUDIO_OK,
281 AAUDIO_STREAM_STATE_STOPPED);
282}
283
284TEST(test_various, aaudio_state_none_open_stop) {
285 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
286 AAUDIO_STREAM_STATE_OPEN,
287 FunctionToCall::CALL_STOP,
288 AAUDIO_OK,
289 AAUDIO_STREAM_STATE_STOPPED);
290}
291
292TEST(test_various, aaudio_state_lowlat_open_pause) {
293 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
294 AAUDIO_STREAM_STATE_OPEN,
295 FunctionToCall::CALL_PAUSE,
296 AAUDIO_OK,
297 AAUDIO_STREAM_STATE_PAUSED);
298}
299
300TEST(test_various, aaudio_state_none_open_pause) {
301 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
302 AAUDIO_STREAM_STATE_OPEN,
303 FunctionToCall::CALL_PAUSE,
304 AAUDIO_OK,
305 AAUDIO_STREAM_STATE_PAUSED);
306}
307
308TEST(test_various, aaudio_state_lowlat_open_flush) {
309 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
310 AAUDIO_STREAM_STATE_OPEN,
311 FunctionToCall::CALL_FLUSH,
312 AAUDIO_OK,
313 AAUDIO_STREAM_STATE_FLUSHED);
314}
315
316TEST(test_various, aaudio_state_none_open_flush) {
317 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
318 AAUDIO_STREAM_STATE_OPEN,
319 FunctionToCall::CALL_FLUSH,
320 AAUDIO_OK,
321 AAUDIO_STREAM_STATE_FLUSHED);
322}
323
324
325// STARTED =================================================================
326TEST(test_various, aaudio_state_lowlat_started_start) {
327 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
328 AAUDIO_STREAM_STATE_STARTED,
329 FunctionToCall::CALL_START,
330 AAUDIO_ERROR_INVALID_STATE,
331 AAUDIO_STREAM_STATE_STARTED);
332}
333
334TEST(test_various, aaudio_state_none_started_start) {
335 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
336 AAUDIO_STREAM_STATE_STARTED,
337 FunctionToCall::CALL_START,
338 AAUDIO_ERROR_INVALID_STATE,
339 AAUDIO_STREAM_STATE_STARTED);
340}
341
342TEST(test_various, aaudio_state_lowlat_started_stop) {
343 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
344 AAUDIO_STREAM_STATE_STARTED,
345 FunctionToCall::CALL_STOP,
346 AAUDIO_OK,
347 AAUDIO_STREAM_STATE_STOPPED);
348}
349
350TEST(test_various, aaudio_state_none_started_stop) {
351 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
352 AAUDIO_STREAM_STATE_STARTED,
353 FunctionToCall::CALL_STOP,
354 AAUDIO_OK,
355 AAUDIO_STREAM_STATE_STOPPED);
356}
357
358TEST(test_various, aaudio_state_lowlat_started_pause) {
359 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
360 AAUDIO_STREAM_STATE_STARTED,
361 FunctionToCall::CALL_PAUSE,
362 AAUDIO_OK,
363 AAUDIO_STREAM_STATE_PAUSED);
364}
365
366TEST(test_various, aaudio_state_none_started_pause) {
367 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
368 AAUDIO_STREAM_STATE_STARTED,
369 FunctionToCall::CALL_PAUSE,
370 AAUDIO_OK,
371 AAUDIO_STREAM_STATE_PAUSED);
372}
373
374TEST(test_various, aaudio_state_lowlat_started_flush) {
375 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
376 AAUDIO_STREAM_STATE_STARTED,
377 FunctionToCall::CALL_FLUSH,
378 AAUDIO_ERROR_INVALID_STATE,
379 AAUDIO_STREAM_STATE_STARTED);
380}
381
382TEST(test_various, aaudio_state_none_started_flush) {
383 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
384 AAUDIO_STREAM_STATE_STARTED,
385 FunctionToCall::CALL_FLUSH,
386 AAUDIO_ERROR_INVALID_STATE,
387 AAUDIO_STREAM_STATE_STARTED);
388}
389
390// STOPPED =================================================================
391TEST(test_various, aaudio_state_lowlat_stopped_start) {
392 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
393 AAUDIO_STREAM_STATE_STOPPED,
394 FunctionToCall::CALL_START,
395 AAUDIO_OK,
396 AAUDIO_STREAM_STATE_STARTED);
397}
398
399TEST(test_various, aaudio_state_none_stopped_start) {
400 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
401 AAUDIO_STREAM_STATE_STOPPED,
402 FunctionToCall::CALL_START,
403 AAUDIO_OK,
404 AAUDIO_STREAM_STATE_STARTED);
405}
406
407TEST(test_various, aaudio_state_lowlat_stopped_stop) {
408 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
409 AAUDIO_STREAM_STATE_STOPPED,
410 FunctionToCall::CALL_STOP,
411 AAUDIO_OK,
412 AAUDIO_STREAM_STATE_STOPPED);
413}
414
415TEST(test_various, aaudio_state_none_stopped_stop) {
416 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
417 AAUDIO_STREAM_STATE_STOPPED,
418 FunctionToCall::CALL_STOP,
419 AAUDIO_OK,
420 AAUDIO_STREAM_STATE_STOPPED);
421}
422
423TEST(test_various, aaudio_state_lowlat_stopped_pause) {
424 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
425 AAUDIO_STREAM_STATE_STOPPED,
426 FunctionToCall::CALL_PAUSE,
427 AAUDIO_OK,
428 AAUDIO_STREAM_STATE_PAUSED);
429}
430
431TEST(test_various, aaudio_state_none_stopped_pause) {
432 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
433 AAUDIO_STREAM_STATE_STOPPED,
434 FunctionToCall::CALL_PAUSE,
435 AAUDIO_OK,
436 AAUDIO_STREAM_STATE_PAUSED);
437}
438
439TEST(test_various, aaudio_state_lowlat_stopped_flush) {
440 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
441 AAUDIO_STREAM_STATE_STOPPED,
442 FunctionToCall::CALL_FLUSH,
443 AAUDIO_OK,
444 AAUDIO_STREAM_STATE_FLUSHED);
445}
446
447TEST(test_various, aaudio_state_none_stopped_flush) {
448 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
449 AAUDIO_STREAM_STATE_STOPPED,
450 FunctionToCall::CALL_FLUSH,
451 AAUDIO_OK,
452 AAUDIO_STREAM_STATE_FLUSHED);
453}
454
455// PAUSED =================================================================
456TEST(test_various, aaudio_state_lowlat_paused_start) {
457checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
458 AAUDIO_STREAM_STATE_PAUSED,
459 FunctionToCall::CALL_START,
460 AAUDIO_OK,
461 AAUDIO_STREAM_STATE_STARTED);
462}
463
464TEST(test_various, aaudio_state_none_paused_start) {
465checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
466 AAUDIO_STREAM_STATE_PAUSED,
467 FunctionToCall::CALL_START,
468 AAUDIO_OK,
469 AAUDIO_STREAM_STATE_STARTED);
470}
471
472TEST(test_various, aaudio_state_lowlat_paused_stop) {
473checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
474 AAUDIO_STREAM_STATE_PAUSED,
475 FunctionToCall::CALL_STOP,
476 AAUDIO_OK,
477 AAUDIO_STREAM_STATE_STOPPED);
478}
479
480TEST(test_various, aaudio_state_none_paused_stop) {
481checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
482 AAUDIO_STREAM_STATE_PAUSED,
483 FunctionToCall::CALL_STOP,
484 AAUDIO_OK,
485 AAUDIO_STREAM_STATE_STOPPED);
486}
487
488TEST(test_various, aaudio_state_lowlat_paused_pause) {
489checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
490 AAUDIO_STREAM_STATE_PAUSED,
491 FunctionToCall::CALL_PAUSE,
492 AAUDIO_OK,
493 AAUDIO_STREAM_STATE_PAUSED);
494}
495
496TEST(test_various, aaudio_state_none_paused_pause) {
497checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
498 AAUDIO_STREAM_STATE_PAUSED,
499 FunctionToCall::CALL_PAUSE,
500 AAUDIO_OK,
501 AAUDIO_STREAM_STATE_PAUSED);
502}
503
504TEST(test_various, aaudio_state_lowlat_paused_flush) {
505checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
506 AAUDIO_STREAM_STATE_PAUSED,
507 FunctionToCall::CALL_FLUSH,
508 AAUDIO_OK,
509 AAUDIO_STREAM_STATE_FLUSHED);
510}
511
512TEST(test_various, aaudio_state_none_paused_flush) {
513checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
514 AAUDIO_STREAM_STATE_PAUSED,
515 FunctionToCall::CALL_FLUSH,
516 AAUDIO_OK,
517 AAUDIO_STREAM_STATE_FLUSHED);
518}
519
Phil Burk29112a12020-06-25 07:52:45 -0700520// FLUSHING ================================================================
521TEST(test_various, aaudio_state_lowlat_flushing_start) {
522checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
523 AAUDIO_STREAM_STATE_FLUSHING,
524 FunctionToCall::CALL_START,
525 AAUDIO_OK,
526 AAUDIO_STREAM_STATE_STARTED);
527}
528
529TEST(test_various, aaudio_state_none_flushing_start) {
530checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
531 AAUDIO_STREAM_STATE_FLUSHING,
532 FunctionToCall::CALL_START,
533 AAUDIO_OK,
534 AAUDIO_STREAM_STATE_STARTED);
535}
536
537TEST(test_various, aaudio_state_lowlat_flushing_release) {
538checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
539 AAUDIO_STREAM_STATE_FLUSHING,
540 FunctionToCall::CALL_RELEASE,
541 AAUDIO_OK,
542 AAUDIO_STREAM_STATE_CLOSING);
543}
544
545TEST(test_various, aaudio_state_none_flushing_release) {
546checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
547 AAUDIO_STREAM_STATE_FLUSHING,
548 FunctionToCall::CALL_RELEASE,
549 AAUDIO_OK,
550 AAUDIO_STREAM_STATE_CLOSING);
551}
552
553TEST(test_various, aaudio_state_lowlat_starting_release) {
554checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
555 AAUDIO_STREAM_STATE_STARTING,
556 FunctionToCall::CALL_RELEASE,
557 AAUDIO_OK,
558 AAUDIO_STREAM_STATE_CLOSING);
559}
560
561TEST(test_various, aaudio_state_none_starting_release) {
562checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
563 AAUDIO_STREAM_STATE_STARTING,
564 FunctionToCall::CALL_RELEASE,
565 AAUDIO_OK,
566 AAUDIO_STREAM_STATE_CLOSING);
567}
568
569// CLOSING ================================================================
570TEST(test_various, aaudio_state_lowlat_closing_start) {
571checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
572 AAUDIO_STREAM_STATE_CLOSING,
573 FunctionToCall::CALL_START,
574 AAUDIO_ERROR_INVALID_STATE,
575 AAUDIO_STREAM_STATE_CLOSING);
576}
577
578TEST(test_various, aaudio_state_none_closing_start) {
579checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
580 AAUDIO_STREAM_STATE_CLOSING,
581 FunctionToCall::CALL_START,
582 AAUDIO_ERROR_INVALID_STATE,
583 AAUDIO_STREAM_STATE_CLOSING);
584}
585
586TEST(test_various, aaudio_state_lowlat_closing_stop) {
587checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
588 AAUDIO_STREAM_STATE_CLOSING,
589 FunctionToCall::CALL_STOP,
590 AAUDIO_ERROR_INVALID_STATE,
591 AAUDIO_STREAM_STATE_CLOSING);
592}
593
594TEST(test_various, aaudio_state_none_closing_stop) {
595checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
596 AAUDIO_STREAM_STATE_CLOSING,
597 FunctionToCall::CALL_STOP,
598 AAUDIO_ERROR_INVALID_STATE,
599 AAUDIO_STREAM_STATE_CLOSING);
600}
601
Phil Burk4fa3b942017-12-13 17:25:24 -0800602// ==========================================================================
Phil Burk9a9e6002017-11-17 12:17:37 -0800603TEST(test_various, aaudio_set_buffer_size) {
Phil Burk2581ae22017-11-21 15:47:29 -0800604
Phil Burk9a9e6002017-11-17 12:17:37 -0800605 int32_t bufferCapacity;
606 int32_t framesPerBurst = 0;
607 int32_t actualSize = 0;
608
609 AAudioStreamBuilder *aaudioBuilder = nullptr;
610 AAudioStream *aaudioStream = nullptr;
611
612 // Use an AAudioStreamBuilder to contain requested parameters.
613 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
614
615 // Request stream properties.
Phil Burk2581ae22017-11-21 15:47:29 -0800616 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk9a9e6002017-11-17 12:17:37 -0800617 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
618
619 // Create an AAudioStream using the Builder.
620 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
621
622 // This is the number of frames that are read in one chunk by a DMA controller
623 // or a DSP or a mixer.
624 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
625 bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
626 printf(" bufferCapacity = %d, remainder = %d\n",
627 bufferCapacity, bufferCapacity % framesPerBurst);
628
629 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
Phil Burk6363f4b2020-01-10 14:06:51 -0800630 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800631 EXPECT_LE(actualSize, bufferCapacity);
632
633 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
634 EXPECT_GT(actualSize, framesPerBurst);
635 EXPECT_LE(actualSize, bufferCapacity);
636
637 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
638 EXPECT_GT(actualSize, framesPerBurst);
639 EXPECT_LE(actualSize, bufferCapacity);
640
641 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
642 EXPECT_GT(actualSize, framesPerBurst);
643 EXPECT_LE(actualSize, bufferCapacity);
644
645 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
646 EXPECT_GT(actualSize, framesPerBurst);
647 EXPECT_LE(actualSize, bufferCapacity);
648
649 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
650 EXPECT_GT(actualSize, framesPerBurst);
651 EXPECT_LE(actualSize, bufferCapacity);
652
653 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
654 EXPECT_GT(actualSize, framesPerBurst);
655 EXPECT_LE(actualSize, bufferCapacity);
656
657 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
Phil Burk6363f4b2020-01-10 14:06:51 -0800658 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800659 EXPECT_LE(actualSize, bufferCapacity);
660
661 AAudioStream_close(aaudioStream);
662 AAudioStreamBuilder_delete(aaudioBuilder);
Phil Burk9a9e6002017-11-17 12:17:37 -0800663}
Phil Burk2581ae22017-11-21 15:47:29 -0800664
Phil Burk2581ae22017-11-21 15:47:29 -0800665// ************************************************************
666// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
667
668// Callback function that counts calls.
669aaudio_data_callback_result_t CallbackOnceProc(
670 AAudioStream *stream,
671 void *userData,
672 void *audioData,
673 int32_t numFrames
674) {
675 (void) stream;
676 (void) audioData;
677 (void) numFrames;
678
679 std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
680 (*callbackCountPtr)++;
681
682 return AAUDIO_CALLBACK_RESULT_STOP;
683}
684
685void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
686
687 std::atomic<int32_t> callbackCount{0};
688
689 AAudioStreamBuilder *aaudioBuilder = nullptr;
690 AAudioStream *aaudioStream = nullptr;
691
692 // Use an AAudioStreamBuilder to contain requested parameters.
693 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
694
695 // Request stream properties.
696 AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
697 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
698
699 // Create an AAudioStream using the Builder.
700 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
701 AAudioStreamBuilder_delete(aaudioBuilder);
702
703 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
704
705 sleep(1); // Give callback a chance to run many times.
706
707 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
708
709 EXPECT_EQ(1, callbackCount.load()); // should stop after first call
710
711 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
712}
713
714TEST(test_various, aaudio_callback_once_none) {
715 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
716}
717
718TEST(test_various, aaudio_callback_once_lowlat) {
719 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
720}
721
722// ************************************************************
723struct WakeUpCallbackData {
724 void wakeOther() {
725 // signal waiting test to wake up
726 {
727 std::lock_guard <std::mutex> lock(mutex);
728 finished = true;
729 }
730 conditionVariable.notify_one();
731 }
732
733 void waitForFinished() {
734 std::unique_lock <std::mutex> aLock(mutex);
735 conditionVariable.wait(aLock, [=] { return finished; });
736 }
737
738 // For signalling foreground test when callback finished
739 std::mutex mutex;
740 std::condition_variable conditionVariable;
741 bool finished = false;
742};
743
744// Test to make sure we cannot call recursively into the system from a callback.
745struct DangerousData : public WakeUpCallbackData {
746 aaudio_result_t resultStart = AAUDIO_OK;
747 aaudio_result_t resultStop = AAUDIO_OK;
748 aaudio_result_t resultPause = AAUDIO_OK;
749 aaudio_result_t resultFlush = AAUDIO_OK;
750 aaudio_result_t resultClose = AAUDIO_OK;
751};
752
753// Callback function that tries to call back into the stream.
754aaudio_data_callback_result_t DangerousDataCallbackProc(
755 AAudioStream *stream,
756 void *userData,
757 void *audioData,
758 int32_t numFrames) {
759 (void) audioData;
760 (void) numFrames;
761
762 DangerousData *data = (DangerousData *)userData;
763 data->resultStart = AAudioStream_requestStart(stream);
764 data->resultStop = AAudioStream_requestStop(stream);
765 data->resultPause = AAudioStream_requestPause(stream);
766 data->resultFlush = AAudioStream_requestFlush(stream);
767 data->resultClose = AAudioStream_close(stream);
768
769 data->wakeOther();
770
771 return AAUDIO_CALLBACK_RESULT_STOP;
772}
773
774//int main() { // To fix Android Studio formatting when editing.
775void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
776 DangerousData dangerousData;
777 AAudioStreamBuilder *aaudioBuilder = nullptr;
778 AAudioStream *aaudioStream = nullptr;
779
780 // Use an AAudioStreamBuilder to contain requested parameters.
781 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
782
783 // Request stream properties.
784 AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
785 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
786
787 // Create an AAudioStream using the Builder.
788 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
789 AAudioStreamBuilder_delete(aaudioBuilder);
790
791 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
792
793 dangerousData.waitForFinished();
794
795 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
796
797 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
798 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
799 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
800 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
801 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
802
803 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
804}
805
806//int main() { // To fix Android Studio formatting when editing.
807
808TEST(test_various, aaudio_callback_blockers_none) {
809 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
810}
811
812TEST(test_various, aaudio_callback_blockers_lowlat) {
813 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
814}