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