• 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 #include <cassert>
18 #include <stdint.h>
19 #include <stdlib.h>
20 
21 #include "aaudio/AAudioLoader.h"
22 #include "aaudio/AudioStreamAAudio.h"
23 #include "common/OboeDebug.h"
24 #include "oboe/AudioClock.h"
25 #include "oboe/Utilities.h"
26 #include "AAudioExtensions.h"
27 
28 #ifdef __ANDROID__
29 #include <sys/system_properties.h>
30 #include <common/QuirksManager.h>
31 
32 #endif
33 
34 #ifndef OBOE_FIX_FORCE_STARTING_TO_STARTED
35 // Workaround state problems in AAudio
36 // TODO Which versions does this occur in? Verify fixed in Q.
37 #define OBOE_FIX_FORCE_STARTING_TO_STARTED 1
38 #endif // OBOE_FIX_FORCE_STARTING_TO_STARTED
39 
40 using namespace oboe;
41 AAudioLoader *AudioStreamAAudio::mLibLoader = nullptr;
42 
43 // 'C' wrapper for the data callback method
oboe_aaudio_data_callback_proc(AAudioStream * stream,void * userData,void * audioData,int32_t numFrames)44 static aaudio_data_callback_result_t oboe_aaudio_data_callback_proc(
45         AAudioStream *stream,
46         void *userData,
47         void *audioData,
48         int32_t numFrames) {
49 
50     AudioStreamAAudio *oboeStream = reinterpret_cast<AudioStreamAAudio*>(userData);
51     if (oboeStream != nullptr) {
52         return static_cast<aaudio_data_callback_result_t>(
53                 oboeStream->callOnAudioReady(stream, audioData, numFrames));
54 
55     } else {
56         return static_cast<aaudio_data_callback_result_t>(DataCallbackResult::Stop);
57     }
58 }
59 
60 // This runs in its own thread.
61 // Only one of these threads will be launched from internalErrorCallback().
62 // It calls app error callbacks from a static function in case the stream gets deleted.
oboe_aaudio_error_thread_proc_common(AudioStreamAAudio * oboeStream,Result error)63 static void oboe_aaudio_error_thread_proc_common(AudioStreamAAudio *oboeStream,
64                                           Result error) {
65 #if 0
66     LOGE("%s() sleep for 5 seconds", __func__);
67     usleep(5*1000*1000);
68     LOGD("%s() - woke up -------------------------", __func__);
69 #endif
70     AudioStreamErrorCallback *errorCallback = oboeStream->getErrorCallback();
71     if (errorCallback == nullptr) return; // should be impossible
72     bool isErrorHandled = errorCallback->onError(oboeStream, error);
73 
74     if (!isErrorHandled) {
75         oboeStream->requestStop();
76         errorCallback->onErrorBeforeClose(oboeStream, error);
77         oboeStream->close();
78         // Warning, oboeStream may get deleted by this callback.
79         errorCallback->onErrorAfterClose(oboeStream, error);
80     }
81 }
82 
83 // Callback thread for raw pointers.
oboe_aaudio_error_thread_proc(AudioStreamAAudio * oboeStream,Result error)84 static void oboe_aaudio_error_thread_proc(AudioStreamAAudio *oboeStream,
85                                           Result error) {
86     LOGD("%s(,%d) - entering >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", __func__, error);
87     oboe_aaudio_error_thread_proc_common(oboeStream, error);
88     LOGD("%s() - exiting <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", __func__);
89 }
90 
91 // Callback thread for shared pointers.
oboe_aaudio_error_thread_proc_shared(std::shared_ptr<AudioStream> sharedStream,Result error)92 static void oboe_aaudio_error_thread_proc_shared(std::shared_ptr<AudioStream> sharedStream,
93                                           Result error) {
94     LOGD("%s(,%d) - entering >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", __func__, error);
95     // Hold the shared pointer while we use the raw pointer.
96     AudioStreamAAudio *oboeStream = reinterpret_cast<AudioStreamAAudio*>(sharedStream.get());
97     oboe_aaudio_error_thread_proc_common(oboeStream, error);
98     LOGD("%s() - exiting <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", __func__);
99 }
100 
oboe_aaudio_presentation_thread_proc_common(AudioStreamAAudio * oboeStream)101 static void oboe_aaudio_presentation_thread_proc_common(AudioStreamAAudio *oboeStream) {
102     auto presentationCallback = oboeStream->getPresentationCallback();
103     if (presentationCallback == nullptr) return; // should be impossible
104     presentationCallback->onPresentationEnded(oboeStream);
105 }
106 
107 // Callback thread for raw pointers
oboe_aaudio_presentation_thread_proc(AudioStreamAAudio * oboeStream)108 static void oboe_aaudio_presentation_thread_proc(AudioStreamAAudio *oboeStream) {
109     LOGD("%s() - entering >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", __func__);
110     oboe_aaudio_presentation_thread_proc_common(oboeStream);
111     LOGD("%s() - exiting <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", __func__);
112 }
113 
114 // Callback thread for shared pointers
oboe_aaudio_presentation_end_thread_proc_shared(std::shared_ptr<AudioStream> sharedStream)115 static void oboe_aaudio_presentation_end_thread_proc_shared(
116         std::shared_ptr<AudioStream> sharedStream) {
117     LOGD("%s() - entering >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", __func__);
118     AudioStreamAAudio *oboeStream = reinterpret_cast<AudioStreamAAudio*>(sharedStream.get());
119     oboe_aaudio_presentation_thread_proc_common(oboeStream);
120     LOGD("%s() - exiting <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", __func__);
121 }
122 
123 namespace oboe {
124 
125 /*
126  * Create a stream that uses Oboe Audio API.
127  */
AudioStreamAAudio(const AudioStreamBuilder & builder)128 AudioStreamAAudio::AudioStreamAAudio(const AudioStreamBuilder &builder)
129     : AudioStream(builder)
130     , mAAudioStream(nullptr) {
131     mCallbackThreadEnabled.store(false);
132     mLibLoader = AAudioLoader::getInstance();
133 }
134 
isSupported()135 bool AudioStreamAAudio::isSupported() {
136     mLibLoader = AAudioLoader::getInstance();
137     int openResult = mLibLoader->open();
138     return openResult == 0;
139 }
140 
141 // Static method for the error callback.
142 // We use a method so we can access protected methods on the stream.
143 // Launch a thread to handle the error.
144 // That other thread can safely stop, close and delete the stream.
internalErrorCallback(AAudioStream * stream,void * userData,aaudio_result_t error)145 void AudioStreamAAudio::internalErrorCallback(
146         AAudioStream *stream,
147         void *userData,
148         aaudio_result_t error) {
149     oboe::Result oboeResult = static_cast<Result>(error);
150     AudioStreamAAudio *oboeStream = reinterpret_cast<AudioStreamAAudio*>(userData);
151 
152     // Coerce the error code if needed to workaround a regression in RQ1A that caused
153     // the wrong code to be passed when headsets plugged in. See b/173928197.
154     if (OboeGlobals::areWorkaroundsEnabled()
155             && getSdkVersion() == __ANDROID_API_R__
156             && oboeResult == oboe::Result::ErrorTimeout) {
157         oboeResult = oboe::Result::ErrorDisconnected;
158         LOGD("%s() ErrorTimeout changed to ErrorDisconnected to fix b/173928197", __func__);
159     }
160 
161     oboeStream->mErrorCallbackResult = oboeResult;
162 
163     // Prevents deletion of the stream if the app is using AudioStreamBuilder::openStream(shared_ptr)
164     std::shared_ptr<AudioStream> sharedStream = oboeStream->lockWeakThis();
165 
166     // These checks should be enough because we assume that the stream close()
167     // will join() any active callback threads and will not allow new callbacks.
168     if (oboeStream->wasErrorCallbackCalled()) { // block extra error callbacks
169         LOGE("%s() multiple error callbacks called!", __func__);
170     } else if (stream != oboeStream->getUnderlyingStream()) {
171         LOGW("%s() stream already closed or closing", __func__); // might happen if there are bugs
172     } else if (sharedStream) {
173         // Handle error on a separate thread using shared pointer.
174         std::thread t(oboe_aaudio_error_thread_proc_shared, sharedStream, oboeResult);
175         t.detach();
176     } else {
177         // Handle error on a separate thread.
178         std::thread t(oboe_aaudio_error_thread_proc, oboeStream, oboeResult);
179         t.detach();
180     }
181 }
182 
beginPerformanceHintInCallback()183 void AudioStreamAAudio::beginPerformanceHintInCallback() {
184     if (isPerformanceHintEnabled()) {
185         if (!mAdpfOpenAttempted) {
186             int64_t targetDurationNanos = (mFramesPerBurst * 1e9) / getSampleRate();
187             // This has to be called from the callback thread so we get the right TID.
188             int adpfResult = mAdpfWrapper.open(gettid(), targetDurationNanos);
189             if (adpfResult < 0) {
190                 LOGW("WARNING ADPF not supported, %d\n", adpfResult);
191             } else {
192                 LOGD("ADPF is now active\n");
193             }
194             mAdpfOpenAttempted = true;
195         }
196         mAdpfWrapper.onBeginCallback();
197     } else if (!isPerformanceHintEnabled() && mAdpfOpenAttempted) {
198         LOGD("ADPF closed\n");
199         mAdpfWrapper.close();
200         mAdpfOpenAttempted = false;
201     }
202 }
203 
endPerformanceHintInCallback(int32_t numFrames)204 void AudioStreamAAudio::endPerformanceHintInCallback(int32_t numFrames) {
205     if (mAdpfWrapper.isOpen()) {
206         // Scale the measured duration based on numFrames so it is normalized to a full burst.
207         double durationScaler = static_cast<double>(mFramesPerBurst) / numFrames;
208         // Skip this callback if numFrames is very small.
209         // This can happen when buffers wrap around, particularly when doing sample rate conversion.
210         if (durationScaler < 2.0) {
211             mAdpfWrapper.onEndCallback(durationScaler);
212         }
213     }
214 }
215 
logUnsupportedAttributes()216 void AudioStreamAAudio::logUnsupportedAttributes() {
217     int sdkVersion = getSdkVersion();
218 
219     // These attributes are not supported pre Android "P"
220     if (sdkVersion < __ANDROID_API_P__) {
221         if (mUsage != Usage::Media) {
222             LOGW("Usage [AudioStreamBuilder::setUsage()] "
223                  "is not supported on AAudio streams running on pre-Android P versions.");
224         }
225 
226         if (mContentType != ContentType::Music) {
227             LOGW("ContentType [AudioStreamBuilder::setContentType()] "
228                  "is not supported on AAudio streams running on pre-Android P versions.");
229         }
230 
231         if (mSessionId != SessionId::None) {
232             LOGW("SessionId [AudioStreamBuilder::setSessionId()] "
233                  "is not supported on AAudio streams running on pre-Android P versions.");
234         }
235     }
236 }
237 
open()238 Result AudioStreamAAudio::open() {
239     Result result = Result::OK;
240 
241     if (mAAudioStream != nullptr) {
242         return Result::ErrorInvalidState;
243     }
244 
245     result = AudioStream::open();
246     if (result != Result::OK) {
247         return result;
248     }
249 
250     AAudioStreamBuilder *aaudioBuilder;
251     result = static_cast<Result>(mLibLoader->createStreamBuilder(&aaudioBuilder));
252     if (result != Result::OK) {
253         return result;
254     }
255 
256     // Do not set INPUT capacity below 4096 because that prevents us from getting a FAST track
257     // when using the Legacy data path.
258     // If the app requests > 4096 then we allow it but we are less likely to get LowLatency.
259     // See internal bug b/80308183 for more details.
260     // Fixed in Q but let's still clip the capacity because high input capacity
261     // does not increase latency.
262     int32_t capacity = mBufferCapacityInFrames;
263     constexpr int kCapacityRequiredForFastLegacyTrack = 4096; // matches value in AudioFinger
264     if (OboeGlobals::areWorkaroundsEnabled()
265             && mDirection == oboe::Direction::Input
266             && capacity != oboe::Unspecified
267             && capacity < kCapacityRequiredForFastLegacyTrack
268             && mPerformanceMode == oboe::PerformanceMode::LowLatency) {
269         capacity = kCapacityRequiredForFastLegacyTrack;
270         LOGD("AudioStreamAAudio.open() capacity changed from %d to %d for lower latency",
271              static_cast<int>(mBufferCapacityInFrames), capacity);
272     }
273     mLibLoader->builder_setBufferCapacityInFrames(aaudioBuilder, capacity);
274 
275     if (mLibLoader->builder_setSessionId != nullptr) {
276         mLibLoader->builder_setSessionId(aaudioBuilder,
277                                          static_cast<aaudio_session_id_t>(mSessionId));
278         // Output effects do not support PerformanceMode::LowLatency.
279         if (OboeGlobals::areWorkaroundsEnabled()
280                 && mSessionId != SessionId::None
281                 && mDirection == oboe::Direction::Output
282                 && mPerformanceMode == PerformanceMode::LowLatency) {
283                     mPerformanceMode = PerformanceMode::None;
284                     LOGD("AudioStreamAAudio.open() performance mode changed to None when session "
285                          "id is requested");
286         }
287     }
288 
289     // Channel mask was added in SC_V2. Given the corresponding channel count of selected channel
290     // mask may be different from selected channel count, the last set value will be respected.
291     // If channel count is set after channel mask, the previously set channel mask will be cleared.
292     // If channel mask is set after channel count, the channel count will be automatically
293     // calculated from selected channel mask. In that case, only set channel mask when the API
294     // is available and the channel mask is specified.
295     if (mLibLoader->builder_setChannelMask != nullptr && mChannelMask != ChannelMask::Unspecified) {
296         mLibLoader->builder_setChannelMask(aaudioBuilder,
297                                            static_cast<aaudio_channel_mask_t>(mChannelMask));
298     } else {
299         mLibLoader->builder_setChannelCount(aaudioBuilder, mChannelCount);
300     }
301     mLibLoader->builder_setDeviceId(aaudioBuilder, mDeviceId);
302     mLibLoader->builder_setDirection(aaudioBuilder, static_cast<aaudio_direction_t>(mDirection));
303     mLibLoader->builder_setFormat(aaudioBuilder, static_cast<aaudio_format_t>(mFormat));
304     mLibLoader->builder_setSampleRate(aaudioBuilder, mSampleRate);
305     mLibLoader->builder_setSharingMode(aaudioBuilder,
306                                        static_cast<aaudio_sharing_mode_t>(mSharingMode));
307     mLibLoader->builder_setPerformanceMode(aaudioBuilder,
308                                            static_cast<aaudio_performance_mode_t>(mPerformanceMode));
309 
310     // These were added in P so we have to check for the function pointer.
311     if (mLibLoader->builder_setUsage != nullptr) {
312         mLibLoader->builder_setUsage(aaudioBuilder,
313                                      static_cast<aaudio_usage_t>(mUsage));
314     }
315 
316     if (mLibLoader->builder_setContentType != nullptr) {
317         mLibLoader->builder_setContentType(aaudioBuilder,
318                                            static_cast<aaudio_content_type_t>(mContentType));
319     }
320 
321     if (mLibLoader->builder_setInputPreset != nullptr) {
322         aaudio_input_preset_t inputPreset = mInputPreset;
323         if (getSdkVersion() <= __ANDROID_API_P__ && inputPreset == InputPreset::VoicePerformance) {
324             LOGD("InputPreset::VoicePerformance not supported before Q. Using VoiceRecognition.");
325             inputPreset = InputPreset::VoiceRecognition; // most similar preset
326         }
327         mLibLoader->builder_setInputPreset(aaudioBuilder,
328                                            static_cast<aaudio_input_preset_t>(inputPreset));
329     }
330 
331     // These were added in S so we have to check for the function pointer.
332     if (mLibLoader->builder_setPackageName != nullptr && !mPackageName.empty()) {
333         mLibLoader->builder_setPackageName(aaudioBuilder,
334                                            mPackageName.c_str());
335     }
336 
337     if (mLibLoader->builder_setAttributionTag != nullptr && !mAttributionTag.empty()) {
338         mLibLoader->builder_setAttributionTag(aaudioBuilder,
339                                            mAttributionTag.c_str());
340     }
341 
342     // This was added in Q so we have to check for the function pointer.
343     if (mLibLoader->builder_setAllowedCapturePolicy != nullptr && mDirection == oboe::Direction::Output) {
344         mLibLoader->builder_setAllowedCapturePolicy(aaudioBuilder,
345                                            static_cast<aaudio_allowed_capture_policy_t>(mAllowedCapturePolicy));
346     }
347 
348     if (mLibLoader->builder_setPrivacySensitive != nullptr && mDirection == oboe::Direction::Input
349             && mPrivacySensitiveMode != PrivacySensitiveMode::Unspecified) {
350         mLibLoader->builder_setPrivacySensitive(aaudioBuilder,
351                 mPrivacySensitiveMode == PrivacySensitiveMode::Enabled);
352     }
353 
354     if (mLibLoader->builder_setIsContentSpatialized != nullptr) {
355         mLibLoader->builder_setIsContentSpatialized(aaudioBuilder, mIsContentSpatialized);
356     }
357 
358     if (mLibLoader->builder_setSpatializationBehavior != nullptr) {
359         // Override Unspecified as Never to reduce latency.
360         if (mSpatializationBehavior == SpatializationBehavior::Unspecified) {
361             mSpatializationBehavior = SpatializationBehavior::Never;
362         }
363         mLibLoader->builder_setSpatializationBehavior(aaudioBuilder,
364                 static_cast<aaudio_spatialization_behavior_t>(mSpatializationBehavior));
365     } else {
366         mSpatializationBehavior = SpatializationBehavior::Never;
367     }
368 
369     if (isDataCallbackSpecified()) {
370         mLibLoader->builder_setDataCallback(aaudioBuilder, oboe_aaudio_data_callback_proc, this);
371         mLibLoader->builder_setFramesPerDataCallback(aaudioBuilder, getFramesPerDataCallback());
372 
373         if (!isErrorCallbackSpecified()) {
374             // The app did not specify a callback so we should specify
375             // our own so the stream gets closed and stopped.
376             mErrorCallback = &mDefaultErrorCallback;
377         }
378         mLibLoader->builder_setErrorCallback(aaudioBuilder, internalErrorCallback, this);
379     }
380     // Else if the data callback is not being used then the write method will return an error
381     // and the app can stop and close the stream.
382 
383     if (isPresentationCallbackSpecified() &&
384         mLibLoader->builder_setPresentationEndCallback != nullptr) {
385         mLibLoader->builder_setPresentationEndCallback(aaudioBuilder,
386                                                        internalPresentationEndCallback,
387                                                        this);
388     }
389 
390     // ============= OPEN THE STREAM ================
391     {
392         AAudioStream *stream = nullptr;
393         result = static_cast<Result>(mLibLoader->builder_openStream(aaudioBuilder, &stream));
394         mAAudioStream.store(stream);
395     }
396     if (result != Result::OK) {
397         // Warn developer because ErrorInternal is not very informative.
398         if (result == Result::ErrorInternal && mDirection == Direction::Input) {
399             LOGW("AudioStreamAAudio.open() may have failed due to lack of "
400                  "audio recording permission.");
401         }
402         goto error2;
403     }
404 
405     // Query and cache the stream properties
406     mDeviceId = mLibLoader->stream_getDeviceId(mAAudioStream);
407     mChannelCount = mLibLoader->stream_getChannelCount(mAAudioStream);
408     mSampleRate = mLibLoader->stream_getSampleRate(mAAudioStream);
409     mFormat = static_cast<AudioFormat>(mLibLoader->stream_getFormat(mAAudioStream));
410     mSharingMode = static_cast<SharingMode>(mLibLoader->stream_getSharingMode(mAAudioStream));
411     mPerformanceMode = static_cast<PerformanceMode>(
412             mLibLoader->stream_getPerformanceMode(mAAudioStream));
413     mBufferCapacityInFrames = mLibLoader->stream_getBufferCapacity(mAAudioStream);
414     mBufferSizeInFrames = mLibLoader->stream_getBufferSize(mAAudioStream);
415     mFramesPerBurst = mLibLoader->stream_getFramesPerBurst(mAAudioStream);
416 
417     // These were added in P so we have to check for the function pointer.
418     if (mLibLoader->stream_getUsage != nullptr) {
419         mUsage = static_cast<Usage>(mLibLoader->stream_getUsage(mAAudioStream));
420     }
421     if (mLibLoader->stream_getContentType != nullptr) {
422         mContentType = static_cast<ContentType>(mLibLoader->stream_getContentType(mAAudioStream));
423     }
424     if (mLibLoader->stream_getInputPreset != nullptr) {
425         mInputPreset = static_cast<InputPreset>(mLibLoader->stream_getInputPreset(mAAudioStream));
426     }
427     if (mLibLoader->stream_getSessionId != nullptr) {
428         mSessionId = static_cast<SessionId>(mLibLoader->stream_getSessionId(mAAudioStream));
429     } else {
430         mSessionId = SessionId::None;
431     }
432 
433     // This was added in Q so we have to check for the function pointer.
434     if (mLibLoader->stream_getAllowedCapturePolicy != nullptr && mDirection == oboe::Direction::Output) {
435         mAllowedCapturePolicy = static_cast<AllowedCapturePolicy>(mLibLoader->stream_getAllowedCapturePolicy(mAAudioStream));
436     } else {
437         mAllowedCapturePolicy = AllowedCapturePolicy::Unspecified;
438     }
439 
440     if (mLibLoader->stream_isPrivacySensitive != nullptr && mDirection == oboe::Direction::Input) {
441         bool isPrivacySensitive = mLibLoader->stream_isPrivacySensitive(mAAudioStream);
442         mPrivacySensitiveMode = isPrivacySensitive ? PrivacySensitiveMode::Enabled :
443                 PrivacySensitiveMode::Disabled;
444     } else {
445         mPrivacySensitiveMode = PrivacySensitiveMode::Unspecified;
446     }
447 
448     if (mLibLoader->stream_getChannelMask != nullptr) {
449         mChannelMask = static_cast<ChannelMask>(mLibLoader->stream_getChannelMask(mAAudioStream));
450     }
451 
452     if (mLibLoader->stream_isContentSpatialized != nullptr) {
453         mIsContentSpatialized = mLibLoader->stream_isContentSpatialized(mAAudioStream);
454     }
455 
456     if (mLibLoader->stream_getSpatializationBehavior != nullptr) {
457         mSpatializationBehavior = static_cast<SpatializationBehavior>(
458                 mLibLoader->stream_getSpatializationBehavior(mAAudioStream));
459     }
460 
461     if (mLibLoader->stream_getHardwareChannelCount != nullptr) {
462         mHardwareChannelCount = mLibLoader->stream_getHardwareChannelCount(mAAudioStream);
463     }
464     if (mLibLoader->stream_getHardwareSampleRate != nullptr) {
465         mHardwareSampleRate = mLibLoader->stream_getHardwareSampleRate(mAAudioStream);
466     }
467     if (mLibLoader->stream_getHardwareFormat != nullptr) {
468         mHardwareFormat = static_cast<AudioFormat>(mLibLoader->stream_getHardwareFormat(mAAudioStream));
469     }
470 
471     LOGD("AudioStreamAAudio.open() format=%d, sampleRate=%d, capacity = %d",
472             static_cast<int>(mFormat), static_cast<int>(mSampleRate),
473             static_cast<int>(mBufferCapacityInFrames));
474 
475     calculateDefaultDelayBeforeCloseMillis();
476 
477 error2:
478     mLibLoader->builder_delete(aaudioBuilder);
479     if (static_cast<int>(result) > 0) {
480         // Possibly due to b/267531411
481         LOGW("AudioStreamAAudio.open: AAudioStream_Open() returned positive error = %d",
482              static_cast<int>(result));
483         if (OboeGlobals::areWorkaroundsEnabled()) {
484             result = Result::ErrorInternal; // Coerce to negative error.
485         }
486     } else {
487         LOGD("AudioStreamAAudio.open: AAudioStream_Open() returned %s = %d",
488              mLibLoader->convertResultToText(static_cast<aaudio_result_t>(result)),
489              static_cast<int>(result));
490     }
491     return result;
492 }
493 
release()494 Result AudioStreamAAudio::release() {
495     if (getSdkVersion() < __ANDROID_API_R__) {
496         return Result::ErrorUnimplemented;
497     }
498 
499     // AAudioStream_release() is buggy on Android R.
500     if (OboeGlobals::areWorkaroundsEnabled() && getSdkVersion() == __ANDROID_API_R__) {
501         LOGW("Skipping release() on Android R");
502         return Result::ErrorUnimplemented;
503     }
504 
505     std::lock_guard<std::mutex> lock(mLock);
506     AAudioStream *stream = mAAudioStream.load();
507     if (stream != nullptr) {
508         if (OboeGlobals::areWorkaroundsEnabled()) {
509             // Make sure we are really stopped. Do it under mLock
510             // so another thread cannot call requestStart() right before the close.
511             requestStop_l(stream);
512         }
513         return static_cast<Result>(mLibLoader->stream_release(stream));
514     } else {
515         return Result::ErrorClosed;
516     }
517 }
518 
close()519 Result AudioStreamAAudio::close() {
520     // Prevent two threads from closing the stream at the same time and crashing.
521     // This could occur, for example, if an application called close() at the same
522     // time that an onError callback was being executed because of a disconnect.
523     std::lock_guard<std::mutex> lock(mLock);
524 
525     AudioStream::close();
526 
527     AAudioStream *stream = nullptr;
528     {
529         // Wait for any methods using mAAudioStream to finish.
530         std::unique_lock<std::shared_mutex> lock2(mAAudioStreamLock);
531         // Closing will delete *mAAudioStream so we need to null out the pointer atomically.
532         stream = mAAudioStream.exchange(nullptr);
533     }
534     if (stream != nullptr) {
535         if (OboeGlobals::areWorkaroundsEnabled()) {
536             // Make sure we are really stopped. Do it under mLock
537             // so another thread cannot call requestStart() right before the close.
538             requestStop_l(stream);
539             sleepBeforeClose();
540         }
541         return static_cast<Result>(mLibLoader->stream_close(stream));
542     } else {
543         return Result::ErrorClosed;
544     }
545 }
546 
oboe_stop_thread_proc(AudioStream * oboeStream)547 static void oboe_stop_thread_proc(AudioStream *oboeStream) {
548     if (oboeStream != nullptr) {
549         oboeStream->requestStop();
550     }
551 }
552 
launchStopThread()553 void AudioStreamAAudio::launchStopThread() {
554     // Prevent multiple stop threads from being launched.
555     if (mStopThreadAllowed.exchange(false)) {
556         // Stop this stream on a separate thread
557         std::thread t(oboe_stop_thread_proc, this);
558         t.detach();
559     }
560 }
561 
callOnAudioReady(AAudioStream *,void * audioData,int32_t numFrames)562 DataCallbackResult AudioStreamAAudio::callOnAudioReady(AAudioStream * /*stream*/,
563                                                                  void *audioData,
564                                                                  int32_t numFrames) {
565     DataCallbackResult result = fireDataCallback(audioData, numFrames);
566     if (result == DataCallbackResult::Continue) {
567         return result;
568     } else {
569         if (result == DataCallbackResult::Stop) {
570             LOGD("Oboe callback returned DataCallbackResult::Stop");
571         } else {
572             LOGE("Oboe callback returned unexpected value. Error: %d", static_cast<int>(result));
573         }
574 
575         // Returning Stop caused various problems before S. See #1230
576         if (OboeGlobals::areWorkaroundsEnabled() && getSdkVersion() <= __ANDROID_API_R__) {
577             launchStopThread();
578             return DataCallbackResult::Continue;
579         } else {
580             return DataCallbackResult::Stop; // OK >= API_S
581         }
582     }
583 }
584 
requestStart()585 Result AudioStreamAAudio::requestStart() {
586     std::lock_guard<std::mutex> lock(mLock);
587     AAudioStream *stream = mAAudioStream.load();
588     if (stream != nullptr) {
589         // Avoid state machine errors in O_MR1.
590         if (getSdkVersion() <= __ANDROID_API_O_MR1__) {
591             StreamState state = static_cast<StreamState>(mLibLoader->stream_getState(stream));
592             if (state == StreamState::Starting || state == StreamState::Started) {
593                 // WARNING: On P, AAudio is returning ErrorInvalidState for Output and OK for Input.
594                 return Result::OK;
595             }
596         }
597         if (isDataCallbackSpecified()) {
598             setDataCallbackEnabled(true);
599         }
600         mStopThreadAllowed = true;
601         closePerformanceHint();
602         return static_cast<Result>(mLibLoader->stream_requestStart(stream));
603     } else {
604         return Result::ErrorClosed;
605     }
606 }
607 
requestPause()608 Result AudioStreamAAudio::requestPause() {
609     std::lock_guard<std::mutex> lock(mLock);
610     AAudioStream *stream = mAAudioStream.load();
611     if (stream != nullptr) {
612         // Avoid state machine errors in O_MR1.
613         if (getSdkVersion() <= __ANDROID_API_O_MR1__) {
614             StreamState state = static_cast<StreamState>(mLibLoader->stream_getState(stream));
615             if (state == StreamState::Pausing || state == StreamState::Paused) {
616                 return Result::OK;
617             }
618         }
619         return static_cast<Result>(mLibLoader->stream_requestPause(stream));
620     } else {
621         return Result::ErrorClosed;
622     }
623 }
624 
requestFlush()625 Result AudioStreamAAudio::requestFlush() {
626     std::lock_guard<std::mutex> lock(mLock);
627     AAudioStream *stream = mAAudioStream.load();
628     if (stream != nullptr) {
629         // Avoid state machine errors in O_MR1.
630         if (getSdkVersion() <= __ANDROID_API_O_MR1__) {
631             StreamState state = static_cast<StreamState>(mLibLoader->stream_getState(stream));
632             if (state == StreamState::Flushing || state == StreamState::Flushed) {
633                 return Result::OK;
634             }
635         }
636         return static_cast<Result>(mLibLoader->stream_requestFlush(stream));
637     } else {
638         return Result::ErrorClosed;
639     }
640 }
641 
requestStop()642 Result AudioStreamAAudio::requestStop() {
643     std::lock_guard<std::mutex> lock(mLock);
644     AAudioStream *stream = mAAudioStream.load();
645     if (stream != nullptr) {
646         return requestStop_l(stream);
647     } else {
648         return Result::ErrorClosed;
649     }
650 }
651 
652 // Call under mLock
requestStop_l(AAudioStream * stream)653 Result AudioStreamAAudio::requestStop_l(AAudioStream *stream) {
654     // Avoid state machine errors in O_MR1.
655     if (getSdkVersion() <= __ANDROID_API_O_MR1__) {
656         StreamState state = static_cast<StreamState>(mLibLoader->stream_getState(stream));
657         if (state == StreamState::Stopping || state == StreamState::Stopped) {
658             return Result::OK;
659         }
660     }
661     return static_cast<Result>(mLibLoader->stream_requestStop(stream));
662 }
663 
write(const void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)664 ResultWithValue<int32_t>   AudioStreamAAudio::write(const void *buffer,
665                                      int32_t numFrames,
666                                      int64_t timeoutNanoseconds) {
667     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
668     AAudioStream *stream = mAAudioStream.load();
669     if (stream != nullptr) {
670         int32_t result = mLibLoader->stream_write(mAAudioStream, buffer,
671                                                   numFrames, timeoutNanoseconds);
672         return ResultWithValue<int32_t>::createBasedOnSign(result);
673     } else {
674         return ResultWithValue<int32_t>(Result::ErrorClosed);
675     }
676 }
677 
read(void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)678 ResultWithValue<int32_t>   AudioStreamAAudio::read(void *buffer,
679                                  int32_t numFrames,
680                                  int64_t timeoutNanoseconds) {
681     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
682     AAudioStream *stream = mAAudioStream.load();
683     if (stream != nullptr) {
684         int32_t result = mLibLoader->stream_read(mAAudioStream, buffer,
685                                                  numFrames, timeoutNanoseconds);
686         return ResultWithValue<int32_t>::createBasedOnSign(result);
687     } else {
688         return ResultWithValue<int32_t>(Result::ErrorClosed);
689     }
690 }
691 
692 
693 // AAudioStream_waitForStateChange() can crash if it is waiting on a stream and that stream
694 // is closed from another thread.  We do not want to lock the stream for the duration of the call.
695 // So we call AAudioStream_waitForStateChange() with a timeout of zero so that it will not block.
696 // Then we can do our own sleep with the lock unlocked.
waitForStateChange(StreamState currentState,StreamState * nextState,int64_t timeoutNanoseconds)697 Result AudioStreamAAudio::waitForStateChange(StreamState currentState,
698                                         StreamState *nextState,
699                                         int64_t timeoutNanoseconds) {
700     Result oboeResult = Result::ErrorTimeout;
701     int64_t sleepTimeNanos = 20 * kNanosPerMillisecond; // arbitrary
702     aaudio_stream_state_t currentAAudioState = static_cast<aaudio_stream_state_t>(currentState);
703 
704     aaudio_result_t result = AAUDIO_OK;
705     int64_t timeLeftNanos = timeoutNanoseconds;
706 
707     mLock.lock();
708     while (true) {
709         // Do we still have an AAudio stream? If not then stream must have been closed.
710         AAudioStream *stream = mAAudioStream.load();
711         if (stream == nullptr) {
712             if (nextState != nullptr) {
713                 *nextState = StreamState::Closed;
714             }
715             oboeResult = Result::ErrorClosed;
716             break;
717         }
718 
719         // Update and query state change with no blocking.
720         aaudio_stream_state_t aaudioNextState;
721         result = mLibLoader->stream_waitForStateChange(
722                 mAAudioStream,
723                 currentAAudioState,
724                 &aaudioNextState,
725                 0); // timeout=0 for non-blocking
726         // AAudio will return AAUDIO_ERROR_TIMEOUT if timeout=0 and the state does not change.
727         if (result != AAUDIO_OK && result != AAUDIO_ERROR_TIMEOUT) {
728             oboeResult = static_cast<Result>(result);
729             break;
730         }
731 #if OBOE_FIX_FORCE_STARTING_TO_STARTED
732         if (OboeGlobals::areWorkaroundsEnabled()
733             && aaudioNextState == static_cast<aaudio_stream_state_t >(StreamState::Starting)) {
734             aaudioNextState = static_cast<aaudio_stream_state_t >(StreamState::Started);
735         }
736 #endif // OBOE_FIX_FORCE_STARTING_TO_STARTED
737         if (nextState != nullptr) {
738             *nextState = static_cast<StreamState>(aaudioNextState);
739         }
740         if (currentAAudioState != aaudioNextState) { // state changed?
741             oboeResult = Result::OK;
742             break;
743         }
744 
745         // Did we timeout or did user ask for non-blocking?
746         if (timeLeftNanos <= 0) {
747             break;
748         }
749 
750         // No change yet so sleep.
751         mLock.unlock(); // Don't sleep while locked.
752         if (sleepTimeNanos > timeLeftNanos) {
753             sleepTimeNanos = timeLeftNanos; // last little bit
754         }
755         AudioClock::sleepForNanos(sleepTimeNanos);
756         timeLeftNanos -= sleepTimeNanos;
757         mLock.lock();
758     }
759 
760     mLock.unlock();
761     return oboeResult;
762 }
763 
setBufferSizeInFrames(int32_t requestedFrames)764 ResultWithValue<int32_t> AudioStreamAAudio::setBufferSizeInFrames(int32_t requestedFrames) {
765     int32_t adjustedFrames = requestedFrames;
766     if (adjustedFrames > mBufferCapacityInFrames) {
767         adjustedFrames = mBufferCapacityInFrames;
768     }
769     // This calls getBufferSize() so avoid recursive lock.
770     adjustedFrames = QuirksManager::getInstance().clipBufferSize(*this, adjustedFrames);
771 
772     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
773     AAudioStream *stream = mAAudioStream.load();
774     if (stream != nullptr) {
775         int32_t newBufferSize = mLibLoader->stream_setBufferSize(mAAudioStream, adjustedFrames);
776         // Cache the result if it's valid
777         if (newBufferSize > 0) mBufferSizeInFrames = newBufferSize;
778         return ResultWithValue<int32_t>::createBasedOnSign(newBufferSize);
779     } else {
780         return ResultWithValue<int32_t>(Result::ErrorClosed);
781     }
782 }
783 
getState()784 StreamState AudioStreamAAudio::getState() {
785     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
786     AAudioStream *stream = mAAudioStream.load();
787     if (stream != nullptr) {
788         aaudio_stream_state_t aaudioState = mLibLoader->stream_getState(stream);
789 #if OBOE_FIX_FORCE_STARTING_TO_STARTED
790         if (OboeGlobals::areWorkaroundsEnabled()
791             && aaudioState == AAUDIO_STREAM_STATE_STARTING) {
792             aaudioState = AAUDIO_STREAM_STATE_STARTED;
793         }
794 #endif // OBOE_FIX_FORCE_STARTING_TO_STARTED
795         return static_cast<StreamState>(aaudioState);
796     } else {
797         return StreamState::Closed;
798     }
799 }
800 
getBufferSizeInFrames()801 int32_t AudioStreamAAudio::getBufferSizeInFrames() {
802     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
803     AAudioStream *stream = mAAudioStream.load();
804     if (stream != nullptr) {
805         mBufferSizeInFrames = mLibLoader->stream_getBufferSize(stream);
806     }
807     return mBufferSizeInFrames;
808 }
809 
updateFramesRead()810 void AudioStreamAAudio::updateFramesRead() {
811     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
812     AAudioStream *stream = mAAudioStream.load();
813 // Set to 1 for debugging race condition #1180 with mAAudioStream.
814 // See also DEBUG_CLOSE_RACE in OboeTester.
815 // This was left in the code so that we could test the fix again easily in the future.
816 // We could not trigger the race condition without adding these get calls and the sleeps.
817 #define DEBUG_CLOSE_RACE 0
818 #if DEBUG_CLOSE_RACE
819     // This is used when testing race conditions with close().
820     // See DEBUG_CLOSE_RACE in OboeTester
821     AudioClock::sleepForNanos(400 * kNanosPerMillisecond);
822 #endif // DEBUG_CLOSE_RACE
823     if (stream != nullptr) {
824         mFramesRead = mLibLoader->stream_getFramesRead(stream);
825     }
826 }
827 
updateFramesWritten()828 void AudioStreamAAudio::updateFramesWritten() {
829     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
830     AAudioStream *stream = mAAudioStream.load();
831     if (stream != nullptr) {
832         mFramesWritten = mLibLoader->stream_getFramesWritten(stream);
833     }
834 }
835 
getXRunCount()836 ResultWithValue<int32_t> AudioStreamAAudio::getXRunCount() {
837     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
838     AAudioStream *stream = mAAudioStream.load();
839     if (stream != nullptr) {
840         return ResultWithValue<int32_t>::createBasedOnSign(mLibLoader->stream_getXRunCount(stream));
841     } else {
842         return ResultWithValue<int32_t>(Result::ErrorNull);
843     }
844 }
845 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)846 Result AudioStreamAAudio::getTimestamp(clockid_t clockId,
847                                    int64_t *framePosition,
848                                    int64_t *timeNanoseconds) {
849     if (getState() != StreamState::Started) {
850         return Result::ErrorInvalidState;
851     }
852     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
853     AAudioStream *stream = mAAudioStream.load();
854     if (stream != nullptr) {
855         return static_cast<Result>(mLibLoader->stream_getTimestamp(stream, clockId,
856                                                framePosition, timeNanoseconds));
857     } else {
858         return Result::ErrorNull;
859     }
860 }
861 
calculateLatencyMillis()862 ResultWithValue<double> AudioStreamAAudio::calculateLatencyMillis() {
863     // Get the time that a known audio frame was presented.
864     int64_t hardwareFrameIndex;
865     int64_t hardwareFrameHardwareTime;
866     auto result = getTimestamp(CLOCK_MONOTONIC,
867                                &hardwareFrameIndex,
868                                &hardwareFrameHardwareTime);
869     if (result != oboe::Result::OK) {
870         return ResultWithValue<double>(static_cast<Result>(result));
871     }
872 
873     // Get counter closest to the app.
874     bool isOutput = (getDirection() == oboe::Direction::Output);
875     int64_t appFrameIndex = isOutput ? getFramesWritten() : getFramesRead();
876 
877     // Assume that the next frame will be processed at the current time
878     using namespace std::chrono;
879     int64_t appFrameAppTime =
880             duration_cast<nanoseconds>(steady_clock::now().time_since_epoch()).count();
881 
882     // Calculate the number of frames between app and hardware
883     int64_t frameIndexDelta = appFrameIndex - hardwareFrameIndex;
884 
885     // Calculate the time which the next frame will be or was presented
886     int64_t frameTimeDelta = (frameIndexDelta * oboe::kNanosPerSecond) / getSampleRate();
887     int64_t appFrameHardwareTime = hardwareFrameHardwareTime + frameTimeDelta;
888 
889     // The current latency is the difference in time between when the current frame is at
890     // the app and when it is at the hardware.
891     double latencyNanos = static_cast<double>(isOutput
892                           ? (appFrameHardwareTime - appFrameAppTime) // hardware is later
893                           : (appFrameAppTime - appFrameHardwareTime)); // hardware is earlier
894     double latencyMillis = latencyNanos / kNanosPerMillisecond;
895 
896     return ResultWithValue<double>(latencyMillis);
897 }
898 
isMMapUsed()899 bool AudioStreamAAudio::isMMapUsed() {
900     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
901     AAudioStream *stream = mAAudioStream.load();
902     if (stream != nullptr) {
903         return AAudioExtensions::getInstance().isMMapUsed(stream);
904     } else {
905         return false;
906     }
907 }
908 
909 // static
910 // Static method for the presentation end callback.
911 // We use a method so we can access protected methods on the stream.
912 // Launch a thread to handle the error.
913 // That other thread can safely stop, close and delete the stream.
internalPresentationEndCallback(AAudioStream * stream,void * userData)914 void AudioStreamAAudio::internalPresentationEndCallback(AAudioStream *stream, void *userData) {
915     AudioStreamAAudio *oboeStream = reinterpret_cast<AudioStreamAAudio*>(userData);
916 
917     // Prevents deletion of the stream if the app is using AudioStreamBuilder::openStream(shared_ptr)
918     std::shared_ptr<AudioStream> sharedStream = oboeStream->lockWeakThis();
919 
920     if (stream != oboeStream->getUnderlyingStream()) {
921         LOGW("%s() stream already closed or closing", __func__); // might happen if there are bugs
922     } else if (sharedStream) {
923         // Handle error on a separate thread using shared pointer.
924         std::thread t(oboe_aaudio_presentation_end_thread_proc_shared, sharedStream);
925         t.detach();
926     } else {
927         // Handle error on a separate thread.
928         std::thread t(oboe_aaudio_presentation_thread_proc, oboeStream);
929         t.detach();
930     }
931 }
932 
setOffloadDelayPadding(int32_t delayInFrames,int32_t paddingInFrames)933 Result AudioStreamAAudio::setOffloadDelayPadding(
934         int32_t delayInFrames, int32_t paddingInFrames) {
935     if (mLibLoader->stream_setOffloadDelayPadding == nullptr) {
936         return Result::ErrorUnimplemented;
937     }
938     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
939     AAudioStream *stream = mAAudioStream.load();
940     if (stream == nullptr) {
941         return Result::ErrorClosed;
942     }
943     return static_cast<Result>(
944             mLibLoader->stream_setOffloadDelayPadding(stream, delayInFrames, paddingInFrames));
945 }
946 
getOffloadDelay()947 ResultWithValue<int32_t> AudioStreamAAudio::getOffloadDelay() {
948     if (mLibLoader->stream_getOffloadDelay == nullptr) {
949         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
950     }
951     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
952     AAudioStream *stream = mAAudioStream.load();
953     if (stream == nullptr) {
954         return Result::ErrorClosed;
955     }
956     return ResultWithValue<int32_t>::createBasedOnSign(mLibLoader->stream_getOffloadDelay(stream));
957 }
958 
getOffloadPadding()959 ResultWithValue<int32_t> AudioStreamAAudio::getOffloadPadding() {
960     if (mLibLoader->stream_getOffloadPadding == nullptr) {
961         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
962     }
963     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
964     AAudioStream *stream = mAAudioStream.load();
965     if (stream == nullptr) {
966         return ResultWithValue<int32_t>(Result::ErrorClosed);
967     }
968     return ResultWithValue<int32_t>::createBasedOnSign(
969             mLibLoader->stream_getOffloadPadding(stream));
970 }
971 
setOffloadEndOfStream()972 Result AudioStreamAAudio::setOffloadEndOfStream() {
973     if (mLibLoader->stream_setOffloadEndOfStream == nullptr) {
974         return Result::ErrorUnimplemented;
975     }
976     std::shared_lock<std::shared_mutex> lock(mAAudioStreamLock);
977     AAudioStream *stream = mAAudioStream.load();
978     if (stream == nullptr) {
979         return ResultWithValue<int32_t>(Result::ErrorClosed);
980     }
981     return static_cast<Result>(mLibLoader->stream_setOffloadEndOfStream(stream));
982 }
983 
984 } // namespace oboe
985