blob: 1c2661518bf2393a323932d006436fefe013b8be [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 {
127 CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
128};
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;
180 }
181 }
182 }
183
184 // Wait until past transitional state.
185 if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
186 ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
187 inputState,
188 &state,
189 1000 * NANOS_PER_MILLISECOND));
190 ASSERT_EQ(originalState, state);
191 }
192
193 aaudio_stream_state_t transitionalState = originalState;
194 switch(functionToCall) {
195 case FunctionToCall::CALL_START:
196 EXPECT_EQ(expectedResult, AAudioStream_requestStart(aaudioStream));
197 transitionalState = AAUDIO_STREAM_STATE_STARTING;
198 break;
199 case FunctionToCall::CALL_STOP:
200 EXPECT_EQ(expectedResult, AAudioStream_requestStop(aaudioStream));
201 transitionalState = AAUDIO_STREAM_STATE_STOPPING;
202 break;
203 case FunctionToCall::CALL_PAUSE:
204 EXPECT_EQ(expectedResult, AAudioStream_requestPause(aaudioStream));
205 transitionalState = AAUDIO_STREAM_STATE_PAUSING;
206 break;
207 case FunctionToCall::CALL_FLUSH:
208 EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
209 transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
210 break;
211 }
212
Phil Burk0c15f4f2017-11-28 15:46:15 -0800213 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
Phil Burk4fa3b942017-12-13 17:25:24 -0800214 transitionalState,
215 &state,
Phil Burk0c15f4f2017-11-28 15:46:15 -0800216 1000 * NANOS_PER_MILLISECOND));
Phil Burk4fa3b942017-12-13 17:25:24 -0800217 // We should not change state when a function fails.
218 if (expectedResult != AAUDIO_OK) {
219 ASSERT_EQ(originalState, expectedState);
220 }
221 EXPECT_EQ(expectedState, state);
222 if (state != expectedState) {
223 printf("ERROR - expected %s, actual = %s\n",
224 AAudio_convertStreamStateToText(expectedState),
225 AAudio_convertStreamStateToText(state));
226 fflush(stdout);
227 }
Phil Burk0c15f4f2017-11-28 15:46:15 -0800228
229 AAudioStream_close(aaudioStream);
230 AAudioStreamBuilder_delete(aaudioBuilder);
231}
232
Phil Burk4fa3b942017-12-13 17:25:24 -0800233// TODO Use parameterized tests instead of these individual specific tests.
234
235// OPEN =================================================================
236TEST(test_various, aaudio_state_lowlat_open_start) {
237 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
238 AAUDIO_STREAM_STATE_OPEN,
239 FunctionToCall::CALL_START,
240 AAUDIO_OK,
241 AAUDIO_STREAM_STATE_STARTED);
242}
243
244TEST(test_various, aaudio_state_none_open_start) {
245 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
246 AAUDIO_STREAM_STATE_OPEN,
247 FunctionToCall::CALL_START,
248 AAUDIO_OK,
249 AAUDIO_STREAM_STATE_STARTED);
250}
251
252TEST(test_various, aaudio_state_lowlat_open_stop) {
253 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
254 AAUDIO_STREAM_STATE_OPEN,
255 FunctionToCall::CALL_STOP,
256 AAUDIO_OK,
257 AAUDIO_STREAM_STATE_STOPPED);
258}
259
260TEST(test_various, aaudio_state_none_open_stop) {
261 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
262 AAUDIO_STREAM_STATE_OPEN,
263 FunctionToCall::CALL_STOP,
264 AAUDIO_OK,
265 AAUDIO_STREAM_STATE_STOPPED);
266}
267
268TEST(test_various, aaudio_state_lowlat_open_pause) {
269 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
270 AAUDIO_STREAM_STATE_OPEN,
271 FunctionToCall::CALL_PAUSE,
272 AAUDIO_OK,
273 AAUDIO_STREAM_STATE_PAUSED);
274}
275
276TEST(test_various, aaudio_state_none_open_pause) {
277 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
278 AAUDIO_STREAM_STATE_OPEN,
279 FunctionToCall::CALL_PAUSE,
280 AAUDIO_OK,
281 AAUDIO_STREAM_STATE_PAUSED);
282}
283
284TEST(test_various, aaudio_state_lowlat_open_flush) {
285 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
286 AAUDIO_STREAM_STATE_OPEN,
287 FunctionToCall::CALL_FLUSH,
288 AAUDIO_OK,
289 AAUDIO_STREAM_STATE_FLUSHED);
290}
291
292TEST(test_various, aaudio_state_none_open_flush) {
293 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
294 AAUDIO_STREAM_STATE_OPEN,
295 FunctionToCall::CALL_FLUSH,
296 AAUDIO_OK,
297 AAUDIO_STREAM_STATE_FLUSHED);
298}
299
300
301// STARTED =================================================================
302TEST(test_various, aaudio_state_lowlat_started_start) {
303 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
304 AAUDIO_STREAM_STATE_STARTED,
305 FunctionToCall::CALL_START,
306 AAUDIO_ERROR_INVALID_STATE,
307 AAUDIO_STREAM_STATE_STARTED);
308}
309
310TEST(test_various, aaudio_state_none_started_start) {
311 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
312 AAUDIO_STREAM_STATE_STARTED,
313 FunctionToCall::CALL_START,
314 AAUDIO_ERROR_INVALID_STATE,
315 AAUDIO_STREAM_STATE_STARTED);
316}
317
318TEST(test_various, aaudio_state_lowlat_started_stop) {
319 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
320 AAUDIO_STREAM_STATE_STARTED,
321 FunctionToCall::CALL_STOP,
322 AAUDIO_OK,
323 AAUDIO_STREAM_STATE_STOPPED);
324}
325
326TEST(test_various, aaudio_state_none_started_stop) {
327 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
328 AAUDIO_STREAM_STATE_STARTED,
329 FunctionToCall::CALL_STOP,
330 AAUDIO_OK,
331 AAUDIO_STREAM_STATE_STOPPED);
332}
333
334TEST(test_various, aaudio_state_lowlat_started_pause) {
335 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
336 AAUDIO_STREAM_STATE_STARTED,
337 FunctionToCall::CALL_PAUSE,
338 AAUDIO_OK,
339 AAUDIO_STREAM_STATE_PAUSED);
340}
341
342TEST(test_various, aaudio_state_none_started_pause) {
343 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
344 AAUDIO_STREAM_STATE_STARTED,
345 FunctionToCall::CALL_PAUSE,
346 AAUDIO_OK,
347 AAUDIO_STREAM_STATE_PAUSED);
348}
349
350TEST(test_various, aaudio_state_lowlat_started_flush) {
351 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
352 AAUDIO_STREAM_STATE_STARTED,
353 FunctionToCall::CALL_FLUSH,
354 AAUDIO_ERROR_INVALID_STATE,
355 AAUDIO_STREAM_STATE_STARTED);
356}
357
358TEST(test_various, aaudio_state_none_started_flush) {
359 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
360 AAUDIO_STREAM_STATE_STARTED,
361 FunctionToCall::CALL_FLUSH,
362 AAUDIO_ERROR_INVALID_STATE,
363 AAUDIO_STREAM_STATE_STARTED);
364}
365
366// STOPPED =================================================================
367TEST(test_various, aaudio_state_lowlat_stopped_start) {
368 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
369 AAUDIO_STREAM_STATE_STOPPED,
370 FunctionToCall::CALL_START,
371 AAUDIO_OK,
372 AAUDIO_STREAM_STATE_STARTED);
373}
374
375TEST(test_various, aaudio_state_none_stopped_start) {
376 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
377 AAUDIO_STREAM_STATE_STOPPED,
378 FunctionToCall::CALL_START,
379 AAUDIO_OK,
380 AAUDIO_STREAM_STATE_STARTED);
381}
382
383TEST(test_various, aaudio_state_lowlat_stopped_stop) {
384 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
385 AAUDIO_STREAM_STATE_STOPPED,
386 FunctionToCall::CALL_STOP,
387 AAUDIO_OK,
388 AAUDIO_STREAM_STATE_STOPPED);
389}
390
391TEST(test_various, aaudio_state_none_stopped_stop) {
392 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
393 AAUDIO_STREAM_STATE_STOPPED,
394 FunctionToCall::CALL_STOP,
395 AAUDIO_OK,
396 AAUDIO_STREAM_STATE_STOPPED);
397}
398
399TEST(test_various, aaudio_state_lowlat_stopped_pause) {
400 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
401 AAUDIO_STREAM_STATE_STOPPED,
402 FunctionToCall::CALL_PAUSE,
403 AAUDIO_OK,
404 AAUDIO_STREAM_STATE_PAUSED);
405}
406
407TEST(test_various, aaudio_state_none_stopped_pause) {
408 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
409 AAUDIO_STREAM_STATE_STOPPED,
410 FunctionToCall::CALL_PAUSE,
411 AAUDIO_OK,
412 AAUDIO_STREAM_STATE_PAUSED);
413}
414
415TEST(test_various, aaudio_state_lowlat_stopped_flush) {
416 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
417 AAUDIO_STREAM_STATE_STOPPED,
418 FunctionToCall::CALL_FLUSH,
419 AAUDIO_OK,
420 AAUDIO_STREAM_STATE_FLUSHED);
421}
422
423TEST(test_various, aaudio_state_none_stopped_flush) {
424 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
425 AAUDIO_STREAM_STATE_STOPPED,
426 FunctionToCall::CALL_FLUSH,
427 AAUDIO_OK,
428 AAUDIO_STREAM_STATE_FLUSHED);
429}
430
431// PAUSED =================================================================
432TEST(test_various, aaudio_state_lowlat_paused_start) {
433checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
434 AAUDIO_STREAM_STATE_PAUSED,
435 FunctionToCall::CALL_START,
436 AAUDIO_OK,
437 AAUDIO_STREAM_STATE_STARTED);
438}
439
440TEST(test_various, aaudio_state_none_paused_start) {
441checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
442 AAUDIO_STREAM_STATE_PAUSED,
443 FunctionToCall::CALL_START,
444 AAUDIO_OK,
445 AAUDIO_STREAM_STATE_STARTED);
446}
447
448TEST(test_various, aaudio_state_lowlat_paused_stop) {
449checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
450 AAUDIO_STREAM_STATE_PAUSED,
451 FunctionToCall::CALL_STOP,
452 AAUDIO_OK,
453 AAUDIO_STREAM_STATE_STOPPED);
454}
455
456TEST(test_various, aaudio_state_none_paused_stop) {
457checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
458 AAUDIO_STREAM_STATE_PAUSED,
459 FunctionToCall::CALL_STOP,
460 AAUDIO_OK,
461 AAUDIO_STREAM_STATE_STOPPED);
462}
463
464TEST(test_various, aaudio_state_lowlat_paused_pause) {
465checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
466 AAUDIO_STREAM_STATE_PAUSED,
467 FunctionToCall::CALL_PAUSE,
468 AAUDIO_OK,
469 AAUDIO_STREAM_STATE_PAUSED);
470}
471
472TEST(test_various, aaudio_state_none_paused_pause) {
473checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
474 AAUDIO_STREAM_STATE_PAUSED,
475 FunctionToCall::CALL_PAUSE,
476 AAUDIO_OK,
477 AAUDIO_STREAM_STATE_PAUSED);
478}
479
480TEST(test_various, aaudio_state_lowlat_paused_flush) {
481checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
482 AAUDIO_STREAM_STATE_PAUSED,
483 FunctionToCall::CALL_FLUSH,
484 AAUDIO_OK,
485 AAUDIO_STREAM_STATE_FLUSHED);
486}
487
488TEST(test_various, aaudio_state_none_paused_flush) {
489checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
490 AAUDIO_STREAM_STATE_PAUSED,
491 FunctionToCall::CALL_FLUSH,
492 AAUDIO_OK,
493 AAUDIO_STREAM_STATE_FLUSHED);
494}
495
496// ==========================================================================
Phil Burk9a9e6002017-11-17 12:17:37 -0800497TEST(test_various, aaudio_set_buffer_size) {
Phil Burk2581ae22017-11-21 15:47:29 -0800498
Phil Burk9a9e6002017-11-17 12:17:37 -0800499 int32_t bufferCapacity;
500 int32_t framesPerBurst = 0;
501 int32_t actualSize = 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.
Phil Burk2581ae22017-11-21 15:47:29 -0800510 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
Phil Burk9a9e6002017-11-17 12:17:37 -0800511 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
512
513 // Create an AAudioStream using the Builder.
514 EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
515
516 // This is the number of frames that are read in one chunk by a DMA controller
517 // or a DSP or a mixer.
518 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
519 bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
520 printf(" bufferCapacity = %d, remainder = %d\n",
521 bufferCapacity, bufferCapacity % framesPerBurst);
522
523 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
Phil Burk6363f4b2020-01-10 14:06:51 -0800524 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800525 EXPECT_LE(actualSize, bufferCapacity);
526
527 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
528 EXPECT_GT(actualSize, framesPerBurst);
529 EXPECT_LE(actualSize, bufferCapacity);
530
531 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity - 1);
532 EXPECT_GT(actualSize, framesPerBurst);
533 EXPECT_LE(actualSize, bufferCapacity);
534
535 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity);
536 EXPECT_GT(actualSize, framesPerBurst);
537 EXPECT_LE(actualSize, bufferCapacity);
538
539 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, bufferCapacity + 1);
540 EXPECT_GT(actualSize, framesPerBurst);
541 EXPECT_LE(actualSize, bufferCapacity);
542
543 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 1234567);
544 EXPECT_GT(actualSize, framesPerBurst);
545 EXPECT_LE(actualSize, bufferCapacity);
546
547 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MAX);
548 EXPECT_GT(actualSize, framesPerBurst);
549 EXPECT_LE(actualSize, bufferCapacity);
550
551 actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
Phil Burk6363f4b2020-01-10 14:06:51 -0800552 EXPECT_GE(actualSize, 0); // 0 is legal in R
Phil Burk9a9e6002017-11-17 12:17:37 -0800553 EXPECT_LE(actualSize, bufferCapacity);
554
555 AAudioStream_close(aaudioStream);
556 AAudioStreamBuilder_delete(aaudioBuilder);
Phil Burk9a9e6002017-11-17 12:17:37 -0800557}
Phil Burk2581ae22017-11-21 15:47:29 -0800558
Phil Burk2581ae22017-11-21 15:47:29 -0800559// ************************************************************
560// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
561
562// Callback function that counts calls.
563aaudio_data_callback_result_t CallbackOnceProc(
564 AAudioStream *stream,
565 void *userData,
566 void *audioData,
567 int32_t numFrames
568) {
569 (void) stream;
570 (void) audioData;
571 (void) numFrames;
572
573 std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
574 (*callbackCountPtr)++;
575
576 return AAUDIO_CALLBACK_RESULT_STOP;
577}
578
579void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
580
581 std::atomic<int32_t> callbackCount{0};
582
583 AAudioStreamBuilder *aaudioBuilder = nullptr;
584 AAudioStream *aaudioStream = nullptr;
585
586 // Use an AAudioStreamBuilder to contain requested parameters.
587 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
588
589 // Request stream properties.
590 AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
591 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
592
593 // Create an AAudioStream using the Builder.
594 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
595 AAudioStreamBuilder_delete(aaudioBuilder);
596
597 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
598
599 sleep(1); // Give callback a chance to run many times.
600
601 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
602
603 EXPECT_EQ(1, callbackCount.load()); // should stop after first call
604
605 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
606}
607
608TEST(test_various, aaudio_callback_once_none) {
609 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
610}
611
612TEST(test_various, aaudio_callback_once_lowlat) {
613 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
614}
615
616// ************************************************************
617struct WakeUpCallbackData {
618 void wakeOther() {
619 // signal waiting test to wake up
620 {
621 std::lock_guard <std::mutex> lock(mutex);
622 finished = true;
623 }
624 conditionVariable.notify_one();
625 }
626
627 void waitForFinished() {
628 std::unique_lock <std::mutex> aLock(mutex);
629 conditionVariable.wait(aLock, [=] { return finished; });
630 }
631
632 // For signalling foreground test when callback finished
633 std::mutex mutex;
634 std::condition_variable conditionVariable;
635 bool finished = false;
636};
637
638// Test to make sure we cannot call recursively into the system from a callback.
639struct DangerousData : public WakeUpCallbackData {
640 aaudio_result_t resultStart = AAUDIO_OK;
641 aaudio_result_t resultStop = AAUDIO_OK;
642 aaudio_result_t resultPause = AAUDIO_OK;
643 aaudio_result_t resultFlush = AAUDIO_OK;
644 aaudio_result_t resultClose = AAUDIO_OK;
645};
646
647// Callback function that tries to call back into the stream.
648aaudio_data_callback_result_t DangerousDataCallbackProc(
649 AAudioStream *stream,
650 void *userData,
651 void *audioData,
652 int32_t numFrames) {
653 (void) audioData;
654 (void) numFrames;
655
656 DangerousData *data = (DangerousData *)userData;
657 data->resultStart = AAudioStream_requestStart(stream);
658 data->resultStop = AAudioStream_requestStop(stream);
659 data->resultPause = AAudioStream_requestPause(stream);
660 data->resultFlush = AAudioStream_requestFlush(stream);
661 data->resultClose = AAudioStream_close(stream);
662
663 data->wakeOther();
664
665 return AAUDIO_CALLBACK_RESULT_STOP;
666}
667
668//int main() { // To fix Android Studio formatting when editing.
669void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
670 DangerousData dangerousData;
671 AAudioStreamBuilder *aaudioBuilder = nullptr;
672 AAudioStream *aaudioStream = nullptr;
673
674 // Use an AAudioStreamBuilder to contain requested parameters.
675 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
676
677 // Request stream properties.
678 AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
679 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
680
681 // Create an AAudioStream using the Builder.
682 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
683 AAudioStreamBuilder_delete(aaudioBuilder);
684
685 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
686
687 dangerousData.waitForFinished();
688
689 EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
690
691 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
692 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
693 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
694 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
695 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
696
697 EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
698}
699
700//int main() { // To fix Android Studio formatting when editing.
701
702TEST(test_various, aaudio_callback_blockers_none) {
703 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
704}
705
706TEST(test_various, aaudio_callback_blockers_lowlat) {
707 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
708}