1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Test various AAudio features including AAudioStream_setBufferSizeInFrames(). 18 19 #include <condition_variable> 20 #include <mutex> 21 #include <stdio.h> 22 23 #include <android-base/macros.h> 24 #include <aaudio/AAudio.h> 25 26 #include <gtest/gtest.h> 27 #include <unistd.h> 28 29 // Callback function that does nothing. 30 aaudio_data_callback_result_t NoopDataCallbackProc( 31 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 45 constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000; 46 47 enum FunctionToCall { 48 CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH 49 }; 50 51 void 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) { 56 AAudioStreamBuilder *aaudioBuilder = nullptr; 57 AAudioStream *aaudioStream = nullptr; 58 59 // Use an AAudioStreamBuilder to contain requested parameters. 60 ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder)); 61 62 // Request stream properties. 63 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr); 64 AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode); 65 66 // Create an AAudioStream using the Builder. 67 ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream)); 68 69 // Verify Open State 70 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 76 // Put stream into desired state. 77 aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_UNINITIALIZED; 78 if (originalState != AAUDIO_STREAM_STATE_OPEN) { 79 80 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 133 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream, 134 transitionalState, 135 &state, 136 1000 * NANOS_PER_MILLISECOND)); 137 // 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 } 148 149 AAudioStream_close(aaudioStream); 150 AAudioStreamBuilder_delete(aaudioBuilder); 151 } 152 153 // TODO Use parameterized tests instead of these individual specific tests. 154 155 // OPEN ================================================================= 156 TEST(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 164 TEST(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 172 TEST(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 180 TEST(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 188 TEST(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 196 TEST(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 204 TEST(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 212 TEST(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 ================================================================= 222 TEST(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 230 TEST(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 238 TEST(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 246 TEST(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 254 TEST(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 262 TEST(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 270 TEST(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 278 TEST(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 ================================================================= 287 TEST(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 295 TEST(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 303 TEST(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 311 TEST(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 319 TEST(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 327 TEST(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 335 TEST(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 343 TEST(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 ================================================================= 352 TEST(test_various, aaudio_state_lowlat_paused_start) { 353 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, 354 AAUDIO_STREAM_STATE_PAUSED, 355 FunctionToCall::CALL_START, 356 AAUDIO_OK, 357 AAUDIO_STREAM_STATE_STARTED); 358 } 359 360 TEST(test_various, aaudio_state_none_paused_start) { 361 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE, 362 AAUDIO_STREAM_STATE_PAUSED, 363 FunctionToCall::CALL_START, 364 AAUDIO_OK, 365 AAUDIO_STREAM_STATE_STARTED); 366 } 367 368 TEST(test_various, aaudio_state_lowlat_paused_stop) { 369 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, 370 AAUDIO_STREAM_STATE_PAUSED, 371 FunctionToCall::CALL_STOP, 372 AAUDIO_OK, 373 AAUDIO_STREAM_STATE_STOPPED); 374 } 375 376 TEST(test_various, aaudio_state_none_paused_stop) { 377 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE, 378 AAUDIO_STREAM_STATE_PAUSED, 379 FunctionToCall::CALL_STOP, 380 AAUDIO_OK, 381 AAUDIO_STREAM_STATE_STOPPED); 382 } 383 384 TEST(test_various, aaudio_state_lowlat_paused_pause) { 385 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, 386 AAUDIO_STREAM_STATE_PAUSED, 387 FunctionToCall::CALL_PAUSE, 388 AAUDIO_OK, 389 AAUDIO_STREAM_STATE_PAUSED); 390 } 391 392 TEST(test_various, aaudio_state_none_paused_pause) { 393 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE, 394 AAUDIO_STREAM_STATE_PAUSED, 395 FunctionToCall::CALL_PAUSE, 396 AAUDIO_OK, 397 AAUDIO_STREAM_STATE_PAUSED); 398 } 399 400 TEST(test_various, aaudio_state_lowlat_paused_flush) { 401 checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, 402 AAUDIO_STREAM_STATE_PAUSED, 403 FunctionToCall::CALL_FLUSH, 404 AAUDIO_OK, 405 AAUDIO_STREAM_STATE_FLUSHED); 406 } 407 408 TEST(test_various, aaudio_state_none_paused_flush) { 409 checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE, 410 AAUDIO_STREAM_STATE_PAUSED, 411 FunctionToCall::CALL_FLUSH, 412 AAUDIO_OK, 413 AAUDIO_STREAM_STATE_FLUSHED); 414 } 415 416 // ========================================================================== 417 TEST(test_various, aaudio_set_buffer_size) { 418 419 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. 430 AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr); 431 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); 444 EXPECT_GT(actualSize, 0); 445 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); 472 EXPECT_GT(actualSize, 0); 473 EXPECT_LE(actualSize, bufferCapacity); 474 475 AAudioStream_close(aaudioStream); 476 AAudioStreamBuilder_delete(aaudioBuilder); 477 } 478 479 // ************************************************************ 480 // Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works. 481 482 // Callback function that counts calls. 483 aaudio_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 499 void 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 528 TEST(test_various, aaudio_callback_once_none) { 529 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE); 530 } 531 532 TEST(test_various, aaudio_callback_once_lowlat) { 533 checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); 534 } 535 536 // ************************************************************ 537 struct 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. 559 struct 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. 568 aaudio_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. 589 void 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 622 TEST(test_various, aaudio_callback_blockers_none) { 623 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE); 624 } 625 626 TEST(test_various, aaudio_callback_blockers_lowlat) { 627 checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); 628 } 629