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