• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getInputPreset()256     aaudio_input_preset_t getInputPreset() const {
257         return mInputPreset;
258     }
259 
getAllowedCapturePolicy()260     aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const {
261         return mAllowedCapturePolicy;
262     }
263 
getSessionId()264     int32_t getSessionId() const {
265         return mSessionId;
266     }
267 
isPrivacySensitive()268     bool isPrivacySensitive() const {
269         return mIsPrivacySensitive;
270     }
271 
272     /**
273      * This is only valid after setSamplesPerFrame() and setFormat() have been called.
274      */
getBytesPerFrame()275     int32_t getBytesPerFrame() const {
276         return mSamplesPerFrame * getBytesPerSample();
277     }
278 
279     /**
280      * This is only valid after setFormat() has been called.
281      */
getBytesPerSample()282     int32_t getBytesPerSample() const {
283         return audio_bytes_per_sample(mFormat);
284     }
285 
286     /**
287      * This is only valid after setSamplesPerFrame() and setDeviceFormat() have been called.
288      */
getBytesPerDeviceFrame()289     int32_t getBytesPerDeviceFrame() const {
290         return getSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat());
291     }
292 
293     virtual int64_t getFramesWritten() = 0;
294 
295     virtual int64_t getFramesRead() = 0;
296 
getDataCallbackProc()297     AAudioStream_dataCallback getDataCallbackProc() const {
298         return mDataCallbackProc;
299     }
300 
getErrorCallbackProc()301     AAudioStream_errorCallback getErrorCallbackProc() const {
302         return mErrorCallbackProc;
303     }
304 
305     aaudio_data_callback_result_t maybeCallDataCallback(void *audioData, int32_t numFrames);
306 
307     void maybeCallErrorCallback(aaudio_result_t result);
308 
getDataCallbackUserData()309     void *getDataCallbackUserData() const {
310         return mDataCallbackUserData;
311     }
312 
getErrorCallbackUserData()313     void *getErrorCallbackUserData() const {
314         return mErrorCallbackUserData;
315     }
316 
getFramesPerDataCallback()317     int32_t getFramesPerDataCallback() const {
318         return mFramesPerDataCallback;
319     }
320 
321     /**
322      * @return true if data callback has been specified
323      */
isDataCallbackSet()324     bool isDataCallbackSet() const {
325         return mDataCallbackProc != nullptr;
326     }
327 
328     /**
329      * @return true if data callback has been specified and stream is running
330      */
isDataCallbackActive()331     bool isDataCallbackActive() const {
332         return isDataCallbackSet() && isActive();
333     }
334 
335     /**
336      * @return true if called from the same thread as the callback
337      */
338     bool collidesWithCallback() const;
339 
340     // Implement AudioDeviceCallback
onAudioDeviceUpdate(audio_io_handle_t audioIo,audio_port_handle_t deviceId)341     void onAudioDeviceUpdate(audio_io_handle_t audioIo,
342             audio_port_handle_t deviceId) override {};
343 
344     // ============== I/O ===========================
345     // 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)346     virtual aaudio_result_t write(const void *buffer __unused,
347                              int32_t numFrames __unused,
348                              int64_t timeoutNanoseconds __unused) {
349         return AAUDIO_ERROR_UNIMPLEMENTED;
350     }
351 
read(void * buffer __unused,int32_t numFrames __unused,int64_t timeoutNanoseconds __unused)352     virtual aaudio_result_t read(void *buffer __unused,
353                             int32_t numFrames __unused,
354                             int64_t timeoutNanoseconds __unused) {
355         return AAUDIO_ERROR_UNIMPLEMENTED;
356     }
357 
358     // This is used by the AudioManager to duck and mute the stream when changing audio focus.
359     void setDuckAndMuteVolume(float duckAndMuteVolume);
360 
getDuckAndMuteVolume()361     float getDuckAndMuteVolume() const {
362         return mDuckAndMuteVolume;
363     }
364 
365     // Implement this in the output subclasses.
doSetVolume()366     virtual android::status_t doSetVolume() { return android::NO_ERROR; }
367 
368 #if AAUDIO_USE_VOLUME_SHAPER
369     virtual ::android::binder::Status applyVolumeShaper(
370             const ::android::media::VolumeShaper::Configuration& configuration __unused,
371             const ::android::media::VolumeShaper::Operation& operation __unused);
372 #endif
373 
374     /**
375      * Register this stream's PlayerBase with the AudioManager if needed.
376      * Only register output streams.
377      * This should only be called for client streams and not for streams
378      * that run in the service.
379      */
registerPlayerBase()380     void registerPlayerBase() {
381         if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
382             mPlayerBase->registerWithAudioManager(this);
383         }
384     }
385 
386     /**
387      * Unregister this stream's PlayerBase with the AudioManager.
388      * This will only unregister if already registered.
389      */
unregisterPlayerBase()390     void unregisterPlayerBase() {
391         mPlayerBase->unregisterWithAudioManager();
392     }
393 
394     aaudio_result_t systemStart();
395 
396     aaudio_result_t systemPause();
397 
398     aaudio_result_t safeFlush();
399 
400     /**
401      * This is called when an app calls AAudioStream_requestStop();
402      * It prevents calls from a callback.
403      */
404     aaudio_result_t systemStopFromApp();
405 
406     /**
407      * This is called internally when an app callback returns AAUDIO_CALLBACK_RESULT_STOP.
408      */
409     aaudio_result_t systemStopInternal();
410 
411     /**
412      * Safely RELEASE a stream after taking mStreamLock and checking
413      * to make sure we are not being called from a callback.
414      * @return AAUDIO_OK or a negative error
415      */
416     aaudio_result_t safeRelease();
417 
418     /**
419      * Safely RELEASE and CLOSE a stream after taking mStreamLock and checking
420      * to make sure we are not being called from a callback.
421      * @return AAUDIO_OK or a negative error
422      */
423     aaudio_result_t safeReleaseClose();
424 
425     aaudio_result_t safeReleaseCloseInternal();
426 
427 protected:
428 
429     // PlayerBase allows the system to control the stream volume.
430     class MyPlayerBase : public android::PlayerBase {
431     public:
MyPlayerBase()432         MyPlayerBase() {};
433 
434         virtual ~MyPlayerBase() = default;
435 
436         /**
437          * Register for volume changes and remote control.
438          */
439         void registerWithAudioManager(const android::sp<AudioStream>& parent);
440 
441         /**
442          * UnRegister.
443          */
444         void unregisterWithAudioManager();
445 
446         /**
447          * Just calls unregisterWithAudioManager().
448          */
449         void destroy() override;
450 
451         // Just a stub. The ability to start audio through PlayerBase is being deprecated.
playerStart()452         android::status_t playerStart() override {
453             return android::NO_ERROR;
454         }
455 
456         // Just a stub. The ability to pause audio through PlayerBase is being deprecated.
playerPause()457         android::status_t playerPause() override {
458             return android::NO_ERROR;
459         }
460 
461         // Just a stub. The ability to stop audio through PlayerBase is being deprecated.
playerStop()462         android::status_t playerStop() override {
463             return android::NO_ERROR;
464         }
465 
466         android::status_t playerSetVolume() override;
467 
468 #if AAUDIO_USE_VOLUME_SHAPER
469         ::android::binder::Status applyVolumeShaper();
470 #endif
471 
getResult()472         aaudio_result_t getResult() {
473             return mResult;
474         }
475 
476         // Returns the playerIId if registered, -1 otherwise.
getPlayerIId()477         int32_t getPlayerIId() const {
478             return mPIId;
479         }
480 
481     private:
482         // Use a weak pointer so the AudioStream can be deleted.
483         std::mutex               mParentLock;
484         android::wp<AudioStream> mParent GUARDED_BY(mParentLock);
485         aaudio_result_t          mResult = AAUDIO_OK;
486         bool                     mRegistered = false;
487     };
488 
489     /**
490      * This should not be called after the open() call.
491      * TODO for multiple setters: assert(mState == AAUDIO_STREAM_STATE_UNINITIALIZED)
492      */
setSampleRate(int32_t sampleRate)493     void setSampleRate(int32_t sampleRate) {
494         mSampleRate = sampleRate;
495     }
496 
497     // This should not be called after the open() call.
setSamplesPerFrame(int32_t samplesPerFrame)498     void setSamplesPerFrame(int32_t samplesPerFrame) {
499         mSamplesPerFrame = samplesPerFrame;
500     }
501 
502     // This should not be called after the open() call.
setFramesPerBurst(int32_t framesPerBurst)503     void setFramesPerBurst(int32_t framesPerBurst) {
504         mFramesPerBurst = framesPerBurst;
505     }
506 
507     // This should not be called after the open() call.
setBufferCapacity(int32_t bufferCapacity)508     void setBufferCapacity(int32_t bufferCapacity) {
509         mBufferCapacity = bufferCapacity;
510     }
511 
512     // This should not be called after the open() call.
setSharingMode(aaudio_sharing_mode_t sharingMode)513     void setSharingMode(aaudio_sharing_mode_t sharingMode) {
514         mSharingMode = sharingMode;
515     }
516 
517     // This should not be called after the open() call.
setFormat(audio_format_t format)518     void setFormat(audio_format_t format) {
519         mFormat = format;
520     }
521 
522     // This should not be called after the open() call.
setDeviceFormat(audio_format_t format)523     void setDeviceFormat(audio_format_t format) {
524         mDeviceFormat = format;
525     }
526 
getDeviceFormat()527     audio_format_t getDeviceFormat() const {
528         return mDeviceFormat;
529     }
530 
531     void setState(aaudio_stream_state_t state);
532 
setDeviceId(int32_t deviceId)533     void setDeviceId(int32_t deviceId) {
534         mDeviceId = deviceId;
535     }
536 
537     // This should not be called after the open() call.
setSessionId(int32_t sessionId)538     void setSessionId(int32_t sessionId) {
539         mSessionId = sessionId;
540     }
541 
542     aaudio_result_t createThread_l(int64_t periodNanoseconds,
543                                            aaudio_audio_thread_proc_t threadProc,
544                                            void *threadArg)
545                                            REQUIRES(mStreamLock);
546 
547     aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock);
548 
549     std::atomic<bool>    mCallbackEnabled{false};
550 
551     float                mDuckAndMuteVolume = 1.0f;
552 
553 protected:
554 
555     /**
556      * Either convert the data from device format to app format and return a pointer
557      * to the conversion buffer,
558      * OR just pass back the original pointer.
559      *
560      * Note that this is only used for the INPUT path.
561      *
562      * @param audioData
563      * @param numFrames
564      * @return original pointer or the conversion buffer
565      */
maybeConvertDeviceData(const void * audioData,int32_t numFrames)566     virtual const void * maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
567         return audioData;
568     }
569 
setPeriodNanoseconds(int64_t periodNanoseconds)570     void setPeriodNanoseconds(int64_t periodNanoseconds) {
571         mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release);
572     }
573 
getPeriodNanoseconds()574     int64_t getPeriodNanoseconds() {
575         return mPeriodNanoseconds.load(std::memory_order_acquire);
576     }
577 
578     /**
579      * This should not be called after the open() call.
580      */
setUsage(aaudio_usage_t usage)581     void setUsage(aaudio_usage_t usage) {
582         mUsage = usage;
583     }
584 
585     /**
586      * This should not be called after the open() call.
587      */
setContentType(aaudio_content_type_t contentType)588     void setContentType(aaudio_content_type_t contentType) {
589         mContentType = contentType;
590     }
591 
592     /**
593      * This should not be called after the open() call.
594      */
setInputPreset(aaudio_input_preset_t inputPreset)595     void setInputPreset(aaudio_input_preset_t inputPreset) {
596         mInputPreset = inputPreset;
597     }
598 
599     /**
600      * This should not be called after the open() call.
601      */
setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy)602     void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) {
603         mAllowedCapturePolicy = policy;
604     }
605 
606     /**
607      * This should not be called after the open() call.
608      */
setPrivacySensitive(bool privacySensitive)609     void setPrivacySensitive(bool privacySensitive) {
610         mIsPrivacySensitive = privacySensitive;
611     }
612 
613     std::string mMetricsId; // set once during open()
614 
615     std::mutex                 mStreamLock;
616 
617 private:
618 
619     aaudio_result_t safeStop_l() REQUIRES(mStreamLock);
620 
621     /**
622      * Release then close the stream.
623      */
releaseCloseFinal_l()624     void releaseCloseFinal_l() REQUIRES(mStreamLock) {
625         if (getState() != AAUDIO_STREAM_STATE_CLOSING) { // not already released?
626             // Ignore result and keep closing.
627             (void) release_l();
628         }
629         close_l();
630     }
631 
632     const android::sp<MyPlayerBase>   mPlayerBase;
633 
634     // These do not change after open().
635     int32_t                     mSamplesPerFrame = AAUDIO_UNSPECIFIED;
636     int32_t                     mSampleRate = AAUDIO_UNSPECIFIED;
637     int32_t                     mDeviceId = AAUDIO_UNSPECIFIED;
638     aaudio_sharing_mode_t       mSharingMode = AAUDIO_SHARING_MODE_SHARED;
639     bool                        mSharingModeMatchRequired = false; // must match sharing mode requested
640     audio_format_t              mFormat = AUDIO_FORMAT_DEFAULT;
641     aaudio_stream_state_t       mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
642     aaudio_performance_mode_t   mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
643     int32_t                     mFramesPerBurst = 0;
644     int32_t                     mBufferCapacity = 0;
645 
646     aaudio_usage_t              mUsage           = AAUDIO_UNSPECIFIED;
647     aaudio_content_type_t       mContentType     = AAUDIO_UNSPECIFIED;
648     aaudio_input_preset_t       mInputPreset     = AAUDIO_UNSPECIFIED;
649     aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
650     bool                        mIsPrivacySensitive = false;
651 
652     int32_t                     mSessionId = AAUDIO_UNSPECIFIED;
653 
654     // Sometimes the hardware is operating with a different format from the app.
655     // Then we require conversion in AAudio.
656     audio_format_t              mDeviceFormat = AUDIO_FORMAT_INVALID;
657 
658     // callback ----------------------------------
659 
660     AAudioStream_dataCallback   mDataCallbackProc = nullptr;  // external callback functions
661     void                       *mDataCallbackUserData = nullptr;
662     int32_t                     mFramesPerDataCallback = AAUDIO_UNSPECIFIED; // frames
663     std::atomic<pid_t>          mDataCallbackThread{CALLBACK_THREAD_NONE};
664 
665     AAudioStream_errorCallback  mErrorCallbackProc = nullptr;
666     void                       *mErrorCallbackUserData = nullptr;
667     std::atomic<pid_t>          mErrorCallbackThread{CALLBACK_THREAD_NONE};
668 
669     // background thread ----------------------------------
670     // Use mHasThread to prevent joining twice, which has undefined behavior.
671     bool                        mHasThread GUARDED_BY(mStreamLock) = false;
672     pthread_t                   mThread  GUARDED_BY(mStreamLock) = {};
673 
674     // These are set by the application thread and then read by the audio pthread.
675     std::atomic<int64_t>        mPeriodNanoseconds; // for tuning SCHED_FIFO threads
676     // TODO make atomic?
677     aaudio_audio_thread_proc_t  mThreadProc = nullptr;
678     void                       *mThreadArg = nullptr;
679     aaudio_result_t             mThreadRegistrationResult = AAUDIO_OK;
680 
681     const aaudio_stream_id_t    mStreamId;
682 
683 };
684 
685 } /* namespace aaudio */
686 
687 #endif /* AAUDIO_AUDIOSTREAM_H */
688