1 /* 2 * Copyright 2016 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 #ifndef AAUDIO_AUDIOSTREAM_H 18 #define AAUDIO_AUDIOSTREAM_H 19 20 #include <atomic> 21 #include <mutex> 22 #include <stdint.h> 23 24 #include <android-base/thread_annotations.h> 25 #include <binder/IServiceManager.h> 26 #include <binder/Status.h> 27 #include <utils/StrongPointer.h> 28 29 #include <aaudio/AAudio.h> 30 #include <media/AudioSystem.h> 31 #include <media/PlayerBase.h> 32 #include <media/VolumeShaper.h> 33 34 #include "utility/AAudioUtilities.h" 35 #include "utility/MonotonicCounter.h" 36 37 // Cannot get android::media::VolumeShaper to compile! 38 #define AAUDIO_USE_VOLUME_SHAPER 0 39 40 namespace aaudio { 41 42 typedef void *(*aaudio_audio_thread_proc_t)(void *); 43 typedef uint32_t aaudio_stream_id_t; 44 45 class AudioStreamBuilder; 46 47 constexpr pid_t CALLBACK_THREAD_NONE = 0; 48 49 /** 50 * AAudio audio stream. 51 */ 52 // By extending AudioDeviceCallback, we also inherit from RefBase. 53 class AudioStream : public android::AudioSystem::AudioDeviceCallback { 54 public: 55 56 AudioStream(); 57 58 virtual ~AudioStream(); 59 60 protected: 61 62 /** 63 * Check the state to see if Pause is currently legal. 64 * 65 * @param result pointer to return code 66 * @return true if OK to continue, if false then return result 67 */ 68 bool checkPauseStateTransition(aaudio_result_t *result); 69 isFlushSupported()70 virtual bool isFlushSupported() const { 71 // Only implement FLUSH for OUTPUT streams. 72 return false; 73 } 74 isPauseSupported()75 virtual bool isPauseSupported() const { 76 // Only implement PAUSE for OUTPUT streams. 77 return false; 78 } 79 80 /* Asynchronous requests. 81 * Use waitForStateChange() to wait for completion. 82 */ 83 virtual aaudio_result_t requestStart_l() REQUIRES(mStreamLock) = 0; 84 requestPause_l()85 virtual aaudio_result_t requestPause_l() REQUIRES(mStreamLock) { 86 // Only implement this for OUTPUT streams. 87 return AAUDIO_ERROR_UNIMPLEMENTED; 88 } 89 requestFlush_l()90 virtual aaudio_result_t requestFlush_l() REQUIRES(mStreamLock) { 91 // Only implement this for OUTPUT streams. 92 return AAUDIO_ERROR_UNIMPLEMENTED; 93 } 94 95 virtual aaudio_result_t requestStop_l() REQUIRES(mStreamLock) = 0; 96 97 public: 98 virtual aaudio_result_t getTimestamp(clockid_t clockId, 99 int64_t *framePosition, 100 int64_t *timeNanoseconds) = 0; 101 102 /** 103 * Update state machine.() 104 * @return 105 */ 106 virtual aaudio_result_t updateStateMachine() = 0; 107 108 // =========== End ABSTRACT methods =========================== 109 110 virtual aaudio_result_t waitForStateChange(aaudio_stream_state_t currentState, 111 aaudio_stream_state_t *nextState, 112 int64_t timeoutNanoseconds); 113 114 /** 115 * Open the stream using the parameters in the builder. 116 * Allocate the necessary resources. 117 */ 118 virtual aaudio_result_t open(const AudioStreamBuilder& builder); 119 120 // log to MediaMetrics 121 virtual void logOpenActual(); 122 void logReleaseBufferState(); 123 124 /* Note about naming for "release" and "close" related methods. 125 * 126 * These names are intended to match the public AAudio API. 127 * The original AAudio API had an AAudioStream_close() function that 128 * released the hardware and deleted the stream. That made it difficult 129 * because apps want to release the HW ASAP but are not in a rush to delete 130 * the stream object. So in R we added an AAudioStream_release() function 131 * that just released the hardware. 132 * The AAudioStream_close() method releases if needed and then closes. 133 */ 134 135 protected: 136 /** 137 * Free any hardware or system resources from the open() call. 138 * It is safe to call release_l() multiple times. 139 */ release_l()140 virtual aaudio_result_t release_l() REQUIRES(mStreamLock) { 141 setState(AAUDIO_STREAM_STATE_CLOSING); 142 return AAUDIO_OK; 143 } 144 145 /** 146 * Free any resources not already freed by release_l(). 147 * Assume release_l() already called. 148 */ 149 virtual void close_l() REQUIRES(mStreamLock); 150 151 public: 152 // This is only used to identify a stream in the logs without 153 // revealing any pointers. getId()154 aaudio_stream_id_t getId() { 155 return mStreamId; 156 } 157 158 virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0; 159 createThread(int64_t periodNanoseconds,aaudio_audio_thread_proc_t threadProc,void * threadArg)160 aaudio_result_t createThread(int64_t periodNanoseconds, 161 aaudio_audio_thread_proc_t threadProc, 162 void *threadArg) 163 EXCLUDES(mStreamLock) { 164 std::lock_guard<std::mutex> lock(mStreamLock); 165 return createThread_l(periodNanoseconds, threadProc, threadArg); 166 } 167 168 aaudio_result_t joinThread(void **returnArg); 169 registerThread()170 virtual aaudio_result_t registerThread() { 171 return AAUDIO_OK; 172 } 173 unregisterThread()174 virtual aaudio_result_t unregisterThread() { 175 return AAUDIO_OK; 176 } 177 178 /** 179 * Internal function used to call the audio thread passed by the user. 180 * It is unfortunately public because it needs to be called by a static 'C' function. 181 */ 182 void* wrapUserThread(); 183 184 // ============== Queries =========================== 185 getState()186 aaudio_stream_state_t getState() const { 187 return mState; 188 } 189 getBufferSize()190 virtual int32_t getBufferSize() const { 191 return AAUDIO_ERROR_UNIMPLEMENTED; 192 } 193 getBufferCapacity()194 virtual int32_t getBufferCapacity() const { 195 return mBufferCapacity; 196 } 197 getFramesPerBurst()198 virtual int32_t getFramesPerBurst() const { 199 return mFramesPerBurst; 200 } 201 getXRunCount()202 virtual int32_t getXRunCount() const { 203 return AAUDIO_ERROR_UNIMPLEMENTED; 204 } 205 isActive()206 bool isActive() const { 207 return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED; 208 } 209 isMMap()210 virtual bool isMMap() { 211 return false; 212 } 213 getSampleRate()214 aaudio_result_t getSampleRate() const { 215 return mSampleRate; 216 } 217 getFormat()218 audio_format_t getFormat() const { 219 return mFormat; 220 } 221 getSamplesPerFrame()222 aaudio_result_t getSamplesPerFrame() const { 223 return mSamplesPerFrame; 224 } 225 getPerformanceMode()226 virtual int32_t getPerformanceMode() const { 227 return mPerformanceMode; 228 } 229 setPerformanceMode(aaudio_performance_mode_t performanceMode)230 void setPerformanceMode(aaudio_performance_mode_t performanceMode) { 231 mPerformanceMode = performanceMode; 232 } 233 getDeviceId()234 int32_t getDeviceId() const { 235 return mDeviceId; 236 } 237 getSharingMode()238 aaudio_sharing_mode_t getSharingMode() const { 239 return mSharingMode; 240 } 241 isSharingModeMatchRequired()242 bool isSharingModeMatchRequired() const { 243 return mSharingModeMatchRequired; 244 } 245 246 virtual aaudio_direction_t getDirection() const = 0; 247 getUsage()248 aaudio_usage_t getUsage() const { 249 return mUsage; 250 } 251 getContentType()252 aaudio_content_type_t getContentType() const { 253 return mContentType; 254 } 255 getSpatializationBehavior()256 aaudio_spatialization_behavior_t getSpatializationBehavior() const { 257 return mSpatializationBehavior; 258 } 259 isContentSpatialized()260 bool isContentSpatialized() const { 261 return mIsContentSpatialized; 262 } 263 getInputPreset()264 aaudio_input_preset_t getInputPreset() const { 265 return mInputPreset; 266 } 267 getAllowedCapturePolicy()268 aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const { 269 return mAllowedCapturePolicy; 270 } 271 getSessionId()272 int32_t getSessionId() const { 273 return mSessionId; 274 } 275 isPrivacySensitive()276 bool isPrivacySensitive() const { 277 return mIsPrivacySensitive; 278 } 279 280 /** 281 * This is only valid after setChannelMask() and setFormat() 282 * have been called. 283 */ getBytesPerFrame()284 int32_t getBytesPerFrame() const { 285 return mSamplesPerFrame * getBytesPerSample(); 286 } 287 288 /** 289 * This is only valid after setFormat() has been called. 290 */ getBytesPerSample()291 int32_t getBytesPerSample() const { 292 return audio_bytes_per_sample(mFormat); 293 } 294 295 /** 296 * This is only valid after setChannelMask() and setDeviceFormat() have been called. 297 */ getBytesPerDeviceFrame()298 int32_t getBytesPerDeviceFrame() const { 299 return getSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat()); 300 } 301 302 virtual int64_t getFramesWritten() = 0; 303 304 virtual int64_t getFramesRead() = 0; 305 getDataCallbackProc()306 AAudioStream_dataCallback getDataCallbackProc() const { 307 return mDataCallbackProc; 308 } 309 getErrorCallbackProc()310 AAudioStream_errorCallback getErrorCallbackProc() const { 311 return mErrorCallbackProc; 312 } 313 314 aaudio_data_callback_result_t maybeCallDataCallback(void *audioData, int32_t numFrames); 315 316 void maybeCallErrorCallback(aaudio_result_t result); 317 getDataCallbackUserData()318 void *getDataCallbackUserData() const { 319 return mDataCallbackUserData; 320 } 321 getErrorCallbackUserData()322 void *getErrorCallbackUserData() const { 323 return mErrorCallbackUserData; 324 } 325 getFramesPerDataCallback()326 int32_t getFramesPerDataCallback() const { 327 return mFramesPerDataCallback; 328 } 329 getChannelMask()330 aaudio_channel_mask_t getChannelMask() const { 331 return mChannelMask; 332 } 333 setChannelMask(aaudio_channel_mask_t channelMask)334 void setChannelMask(aaudio_channel_mask_t channelMask) { 335 mChannelMask = channelMask; 336 mSamplesPerFrame = AAudioConvert_channelMaskToCount(channelMask); 337 } 338 339 /** 340 * @return true if data callback has been specified 341 */ isDataCallbackSet()342 bool isDataCallbackSet() const { 343 return mDataCallbackProc != nullptr; 344 } 345 346 /** 347 * @return true if data callback has been specified and stream is running 348 */ isDataCallbackActive()349 bool isDataCallbackActive() const { 350 return isDataCallbackSet() && isActive(); 351 } 352 353 /** 354 * @return true if called from the same thread as the callback 355 */ 356 bool collidesWithCallback() const; 357 358 // Implement AudioDeviceCallback onAudioDeviceUpdate(audio_io_handle_t audioIo,audio_port_handle_t deviceId)359 void onAudioDeviceUpdate(audio_io_handle_t audioIo, 360 audio_port_handle_t deviceId) override {}; 361 362 // ============== I/O =========================== 363 // A Stream will only implement read() or write() depending on its direction. write(const void * buffer __unused,int32_t numFrames __unused,int64_t timeoutNanoseconds __unused)364 virtual aaudio_result_t write(const void *buffer __unused, 365 int32_t numFrames __unused, 366 int64_t timeoutNanoseconds __unused) { 367 return AAUDIO_ERROR_UNIMPLEMENTED; 368 } 369 read(void * buffer __unused,int32_t numFrames __unused,int64_t timeoutNanoseconds __unused)370 virtual aaudio_result_t read(void *buffer __unused, 371 int32_t numFrames __unused, 372 int64_t timeoutNanoseconds __unused) { 373 return AAUDIO_ERROR_UNIMPLEMENTED; 374 } 375 376 // This is used by the AudioManager to duck and mute the stream when changing audio focus. 377 void setDuckAndMuteVolume(float duckAndMuteVolume); 378 getDuckAndMuteVolume()379 float getDuckAndMuteVolume() const { 380 return mDuckAndMuteVolume; 381 } 382 383 // Implement this in the output subclasses. doSetVolume()384 virtual android::status_t doSetVolume() { return android::NO_ERROR; } 385 386 #if AAUDIO_USE_VOLUME_SHAPER 387 virtual ::android::binder::Status applyVolumeShaper( 388 const ::android::media::VolumeShaper::Configuration& configuration __unused, 389 const ::android::media::VolumeShaper::Operation& operation __unused); 390 #endif 391 392 /** 393 * Register this stream's PlayerBase with the AudioManager if needed. 394 * Only register output streams. 395 * This should only be called for client streams and not for streams 396 * that run in the service. 397 */ registerPlayerBase()398 void registerPlayerBase() { 399 if (getDirection() == AAUDIO_DIRECTION_OUTPUT) { 400 mPlayerBase->registerWithAudioManager(this); 401 } 402 } 403 404 /** 405 * Unregister this stream's PlayerBase with the AudioManager. 406 * This will only unregister if already registered. 407 */ unregisterPlayerBase()408 void unregisterPlayerBase() { 409 mPlayerBase->unregisterWithAudioManager(); 410 } 411 412 aaudio_result_t systemStart(); 413 414 aaudio_result_t systemPause(); 415 416 aaudio_result_t safeFlush(); 417 418 /** 419 * This is called when an app calls AAudioStream_requestStop(); 420 * It prevents calls from a callback. 421 */ 422 aaudio_result_t systemStopFromApp(); 423 424 /** 425 * This is called internally when an app callback returns AAUDIO_CALLBACK_RESULT_STOP. 426 */ 427 aaudio_result_t systemStopInternal(); 428 429 /** 430 * Safely RELEASE a stream after taking mStreamLock and checking 431 * to make sure we are not being called from a callback. 432 * @return AAUDIO_OK or a negative error 433 */ 434 aaudio_result_t safeRelease(); 435 436 /** 437 * Safely RELEASE and CLOSE a stream after taking mStreamLock and checking 438 * to make sure we are not being called from a callback. 439 * @return AAUDIO_OK or a negative error 440 */ 441 aaudio_result_t safeReleaseClose(); 442 443 aaudio_result_t safeReleaseCloseInternal(); 444 445 protected: 446 447 // PlayerBase allows the system to control the stream volume. 448 class MyPlayerBase : public android::PlayerBase { 449 public: MyPlayerBase()450 MyPlayerBase() {}; 451 452 virtual ~MyPlayerBase() = default; 453 454 /** 455 * Register for volume changes and remote control. 456 */ 457 void registerWithAudioManager(const android::sp<AudioStream>& parent); 458 459 /** 460 * UnRegister. 461 */ 462 void unregisterWithAudioManager(); 463 464 /** 465 * Just calls unregisterWithAudioManager(). 466 */ 467 void destroy() override; 468 469 // Just a stub. The ability to start audio through PlayerBase is being deprecated. playerStart()470 android::status_t playerStart() override { 471 return android::NO_ERROR; 472 } 473 474 // Just a stub. The ability to pause audio through PlayerBase is being deprecated. playerPause()475 android::status_t playerPause() override { 476 return android::NO_ERROR; 477 } 478 479 // Just a stub. The ability to stop audio through PlayerBase is being deprecated. playerStop()480 android::status_t playerStop() override { 481 return android::NO_ERROR; 482 } 483 484 android::status_t playerSetVolume() override; 485 486 #if AAUDIO_USE_VOLUME_SHAPER 487 ::android::binder::Status applyVolumeShaper(); 488 #endif 489 getResult()490 aaudio_result_t getResult() { 491 return mResult; 492 } 493 494 // Returns the playerIId if registered, -1 otherwise. getPlayerIId()495 int32_t getPlayerIId() const { 496 return mPIId; 497 } 498 499 private: 500 // Use a weak pointer so the AudioStream can be deleted. 501 std::mutex mParentLock; 502 android::wp<AudioStream> mParent GUARDED_BY(mParentLock); 503 aaudio_result_t mResult = AAUDIO_OK; 504 bool mRegistered = false; 505 }; 506 507 /** 508 * This should not be called after the open() call. 509 * TODO for multiple setters: assert(mState == AAUDIO_STREAM_STATE_UNINITIALIZED) 510 */ setSampleRate(int32_t sampleRate)511 void setSampleRate(int32_t sampleRate) { 512 mSampleRate = sampleRate; 513 } 514 515 // This should not be called after the open() call. setFramesPerBurst(int32_t framesPerBurst)516 void setFramesPerBurst(int32_t framesPerBurst) { 517 mFramesPerBurst = framesPerBurst; 518 } 519 520 // This should not be called after the open() call. setBufferCapacity(int32_t bufferCapacity)521 void setBufferCapacity(int32_t bufferCapacity) { 522 mBufferCapacity = bufferCapacity; 523 } 524 525 // This should not be called after the open() call. setSharingMode(aaudio_sharing_mode_t sharingMode)526 void setSharingMode(aaudio_sharing_mode_t sharingMode) { 527 mSharingMode = sharingMode; 528 } 529 530 // This should not be called after the open() call. setFormat(audio_format_t format)531 void setFormat(audio_format_t format) { 532 mFormat = format; 533 } 534 535 // This should not be called after the open() call. setDeviceFormat(audio_format_t format)536 void setDeviceFormat(audio_format_t format) { 537 mDeviceFormat = format; 538 } 539 getDeviceFormat()540 audio_format_t getDeviceFormat() const { 541 return mDeviceFormat; 542 } 543 544 void setState(aaudio_stream_state_t state); 545 setDeviceId(int32_t deviceId)546 void setDeviceId(int32_t deviceId) { 547 mDeviceId = deviceId; 548 } 549 550 // This should not be called after the open() call. setSessionId(int32_t sessionId)551 void setSessionId(int32_t sessionId) { 552 mSessionId = sessionId; 553 } 554 555 aaudio_result_t createThread_l(int64_t periodNanoseconds, 556 aaudio_audio_thread_proc_t threadProc, 557 void *threadArg) 558 REQUIRES(mStreamLock); 559 560 aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock); 561 562 std::atomic<bool> mCallbackEnabled{false}; 563 564 float mDuckAndMuteVolume = 1.0f; 565 566 protected: 567 568 /** 569 * Either convert the data from device format to app format and return a pointer 570 * to the conversion buffer, 571 * OR just pass back the original pointer. 572 * 573 * Note that this is only used for the INPUT path. 574 * 575 * @param audioData 576 * @param numFrames 577 * @return original pointer or the conversion buffer 578 */ maybeConvertDeviceData(const void * audioData,int32_t numFrames)579 virtual const void * maybeConvertDeviceData(const void *audioData, int32_t numFrames) { 580 return audioData; 581 } 582 setPeriodNanoseconds(int64_t periodNanoseconds)583 void setPeriodNanoseconds(int64_t periodNanoseconds) { 584 mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release); 585 } 586 getPeriodNanoseconds()587 int64_t getPeriodNanoseconds() { 588 return mPeriodNanoseconds.load(std::memory_order_acquire); 589 } 590 591 /** 592 * This should not be called after the open() call. 593 */ setUsage(aaudio_usage_t usage)594 void setUsage(aaudio_usage_t usage) { 595 mUsage = usage; 596 } 597 598 /** 599 * This should not be called after the open() call. 600 */ setContentType(aaudio_content_type_t contentType)601 void setContentType(aaudio_content_type_t contentType) { 602 mContentType = contentType; 603 } 604 setSpatializationBehavior(aaudio_spatialization_behavior_t spatializationBehavior)605 void setSpatializationBehavior(aaudio_spatialization_behavior_t spatializationBehavior) { 606 mSpatializationBehavior = spatializationBehavior; 607 } 608 setIsContentSpatialized(bool isContentSpatialized)609 void setIsContentSpatialized(bool isContentSpatialized) { 610 mIsContentSpatialized = isContentSpatialized; 611 } 612 613 /** 614 * This should not be called after the open() call. 615 */ setInputPreset(aaudio_input_preset_t inputPreset)616 void setInputPreset(aaudio_input_preset_t inputPreset) { 617 mInputPreset = inputPreset; 618 } 619 620 /** 621 * This should not be called after the open() call. 622 */ setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy)623 void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) { 624 mAllowedCapturePolicy = policy; 625 } 626 627 /** 628 * This should not be called after the open() call. 629 */ setPrivacySensitive(bool privacySensitive)630 void setPrivacySensitive(bool privacySensitive) { 631 mIsPrivacySensitive = privacySensitive; 632 } 633 634 std::string mMetricsId; // set once during open() 635 636 std::mutex mStreamLock; 637 638 private: 639 640 aaudio_result_t safeStop_l() REQUIRES(mStreamLock); 641 642 /** 643 * Release then close the stream. 644 */ releaseCloseFinal_l()645 void releaseCloseFinal_l() REQUIRES(mStreamLock) { 646 if (getState() != AAUDIO_STREAM_STATE_CLOSING) { // not already released? 647 // Ignore result and keep closing. 648 (void) release_l(); 649 } 650 close_l(); 651 } 652 653 const android::sp<MyPlayerBase> mPlayerBase; 654 655 // These do not change after open(). 656 int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED; 657 aaudio_channel_mask_t mChannelMask = AAUDIO_UNSPECIFIED; 658 int32_t mSampleRate = AAUDIO_UNSPECIFIED; 659 int32_t mDeviceId = AAUDIO_UNSPECIFIED; 660 aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED; 661 bool mSharingModeMatchRequired = false; // must match sharing mode requested 662 audio_format_t mFormat = AUDIO_FORMAT_DEFAULT; 663 aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED; 664 aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; 665 int32_t mFramesPerBurst = 0; 666 int32_t mBufferCapacity = 0; 667 668 aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED; 669 aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED; 670 aaudio_spatialization_behavior_t mSpatializationBehavior = AAUDIO_UNSPECIFIED; 671 bool mIsContentSpatialized = false; 672 aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED; 673 aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL; 674 bool mIsPrivacySensitive = false; 675 676 int32_t mSessionId = AAUDIO_UNSPECIFIED; 677 678 // Sometimes the hardware is operating with a different format from the app. 679 // Then we require conversion in AAudio. 680 audio_format_t mDeviceFormat = AUDIO_FORMAT_INVALID; 681 682 // callback ---------------------------------- 683 684 AAudioStream_dataCallback mDataCallbackProc = nullptr; // external callback functions 685 void *mDataCallbackUserData = nullptr; 686 int32_t mFramesPerDataCallback = AAUDIO_UNSPECIFIED; // frames 687 std::atomic<pid_t> mDataCallbackThread{CALLBACK_THREAD_NONE}; 688 689 AAudioStream_errorCallback mErrorCallbackProc = nullptr; 690 void *mErrorCallbackUserData = nullptr; 691 std::atomic<pid_t> mErrorCallbackThread{CALLBACK_THREAD_NONE}; 692 693 // background thread ---------------------------------- 694 // Use mHasThread to prevent joining twice, which has undefined behavior. 695 bool mHasThread GUARDED_BY(mStreamLock) = false; 696 pthread_t mThread GUARDED_BY(mStreamLock) = {}; 697 698 // These are set by the application thread and then read by the audio pthread. 699 std::atomic<int64_t> mPeriodNanoseconds; // for tuning SCHED_FIFO threads 700 // TODO make atomic? 701 aaudio_audio_thread_proc_t mThreadProc = nullptr; 702 void *mThreadArg = nullptr; 703 aaudio_result_t mThreadRegistrationResult = AAUDIO_OK; 704 705 const aaudio_stream_id_t mStreamId; 706 707 }; 708 709 } /* namespace aaudio */ 710 711 #endif /* AAUDIO_AUDIOSTREAM_H */ 712