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