xref: /aosp_15_r20/external/oboe/src/opensles/AudioStreamOpenSLES.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1*05767d91SRobert Wu /* Copyright 2015 The Android Open Source Project
2*05767d91SRobert Wu  *
3*05767d91SRobert Wu  * Licensed under the Apache License, Version 2.0 (the "License");
4*05767d91SRobert Wu  * you may not use this file except in compliance with the License.
5*05767d91SRobert Wu  * You may obtain a copy of the License at
6*05767d91SRobert Wu  *
7*05767d91SRobert Wu  *      http://www.apache.org/licenses/LICENSE-2.0
8*05767d91SRobert Wu  *
9*05767d91SRobert Wu  * Unless required by applicable law or agreed to in writing, software
10*05767d91SRobert Wu  * distributed under the License is distributed on an "AS IS" BASIS,
11*05767d91SRobert Wu  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*05767d91SRobert Wu  * See the License for the specific language governing permissions and
13*05767d91SRobert Wu  * limitations under the License.
14*05767d91SRobert Wu  */
15*05767d91SRobert Wu #include <sys/types.h>
16*05767d91SRobert Wu #include <cassert>
17*05767d91SRobert Wu #include <android/log.h>
18*05767d91SRobert Wu 
19*05767d91SRobert Wu #include <SLES/OpenSLES.h>
20*05767d91SRobert Wu #include <SLES/OpenSLES_Android.h>
21*05767d91SRobert Wu #include <oboe/AudioStream.h>
22*05767d91SRobert Wu #include <common/AudioClock.h>
23*05767d91SRobert Wu 
24*05767d91SRobert Wu #include "common/OboeDebug.h"
25*05767d91SRobert Wu #include "oboe/AudioStreamBuilder.h"
26*05767d91SRobert Wu #include "AudioStreamOpenSLES.h"
27*05767d91SRobert Wu #include "OpenSLESUtilities.h"
28*05767d91SRobert Wu 
29*05767d91SRobert Wu using namespace oboe;
30*05767d91SRobert Wu 
AudioStreamOpenSLES(const AudioStreamBuilder & builder)31*05767d91SRobert Wu AudioStreamOpenSLES::AudioStreamOpenSLES(const AudioStreamBuilder &builder)
32*05767d91SRobert Wu     : AudioStreamBuffered(builder) {
33*05767d91SRobert Wu     // OpenSL ES does not support device IDs. So overwrite value from builder.
34*05767d91SRobert Wu     mDeviceId = kUnspecified;
35*05767d91SRobert Wu     // OpenSL ES does not support session IDs. So overwrite value from builder.
36*05767d91SRobert Wu     mSessionId = SessionId::None;
37*05767d91SRobert Wu }
38*05767d91SRobert Wu 
39*05767d91SRobert Wu static constexpr int32_t   kHighLatencyBufferSizeMillis = 20; // typical Android period
40*05767d91SRobert Wu static constexpr SLuint32  kAudioChannelCountMax = 30; // TODO Why 30?
41*05767d91SRobert Wu static constexpr SLuint32  SL_ANDROID_UNKNOWN_CHANNELMASK  = 0; // Matches name used internally.
42*05767d91SRobert Wu 
channelCountToChannelMaskDefault(int channelCount) const43*05767d91SRobert Wu SLuint32 AudioStreamOpenSLES::channelCountToChannelMaskDefault(int channelCount) const {
44*05767d91SRobert Wu     if (channelCount > kAudioChannelCountMax) {
45*05767d91SRobert Wu         return SL_ANDROID_UNKNOWN_CHANNELMASK;
46*05767d91SRobert Wu     }
47*05767d91SRobert Wu 
48*05767d91SRobert Wu     SLuint32 bitfield = (1 << channelCount) - 1;
49*05767d91SRobert Wu 
50*05767d91SRobert Wu     // Check for OS at run-time.
51*05767d91SRobert Wu     if(getSdkVersion() >= __ANDROID_API_N__) {
52*05767d91SRobert Wu         return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
53*05767d91SRobert Wu     }
54*05767d91SRobert Wu 
55*05767d91SRobert Wu     // Indexed channels masks were added in N.
56*05767d91SRobert Wu     // For before N, the best we can do is use a positional channel mask.
57*05767d91SRobert Wu     return bitfield;
58*05767d91SRobert Wu }
59*05767d91SRobert Wu 
s_isLittleEndian()60*05767d91SRobert Wu static bool s_isLittleEndian() {
61*05767d91SRobert Wu     static uint32_t value = 1;
62*05767d91SRobert Wu     return (*reinterpret_cast<uint8_t *>(&value) == 1);  // Does address point to LSB?
63*05767d91SRobert Wu }
64*05767d91SRobert Wu 
getDefaultByteOrder()65*05767d91SRobert Wu SLuint32 AudioStreamOpenSLES::getDefaultByteOrder() {
66*05767d91SRobert Wu     return s_isLittleEndian() ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
67*05767d91SRobert Wu }
68*05767d91SRobert Wu 
open()69*05767d91SRobert Wu Result AudioStreamOpenSLES::open() {
70*05767d91SRobert Wu 
71*05767d91SRobert Wu     LOGI("AudioStreamOpenSLES::open() chans=%d, rate=%d", mChannelCount, mSampleRate);
72*05767d91SRobert Wu 
73*05767d91SRobert Wu     // OpenSL ES only supports I16 and Float
74*05767d91SRobert Wu     if (mFormat != AudioFormat::I16 && mFormat != AudioFormat::Float) {
75*05767d91SRobert Wu         LOGW("%s() Android's OpenSL ES implementation only supports I16 and Float. Format: %s",
76*05767d91SRobert Wu              __func__, oboe::convertToText(mFormat));
77*05767d91SRobert Wu         return Result::ErrorInvalidFormat;
78*05767d91SRobert Wu     }
79*05767d91SRobert Wu 
80*05767d91SRobert Wu     SLresult result = EngineOpenSLES::getInstance().open();
81*05767d91SRobert Wu     if (SL_RESULT_SUCCESS != result) {
82*05767d91SRobert Wu         return Result::ErrorInternal;
83*05767d91SRobert Wu     }
84*05767d91SRobert Wu 
85*05767d91SRobert Wu     Result oboeResult = AudioStreamBuffered::open();
86*05767d91SRobert Wu     if (oboeResult != Result::OK) {
87*05767d91SRobert Wu         EngineOpenSLES::getInstance().close();
88*05767d91SRobert Wu         return oboeResult;
89*05767d91SRobert Wu     }
90*05767d91SRobert Wu     // Convert to defaults if UNSPECIFIED
91*05767d91SRobert Wu     if (mSampleRate == kUnspecified) {
92*05767d91SRobert Wu         mSampleRate = DefaultStreamValues::SampleRate;
93*05767d91SRobert Wu     }
94*05767d91SRobert Wu     if (mChannelCount == kUnspecified) {
95*05767d91SRobert Wu         mChannelCount = DefaultStreamValues::ChannelCount;
96*05767d91SRobert Wu     }
97*05767d91SRobert Wu     if (mContentType == kUnspecified) {
98*05767d91SRobert Wu         mContentType = ContentType::Music;
99*05767d91SRobert Wu     }
100*05767d91SRobert Wu     if (static_cast<const int32_t>(mUsage) == kUnspecified) {
101*05767d91SRobert Wu         mUsage = Usage::Media;
102*05767d91SRobert Wu     }
103*05767d91SRobert Wu 
104*05767d91SRobert Wu     mSharingMode = SharingMode::Shared;
105*05767d91SRobert Wu 
106*05767d91SRobert Wu     return Result::OK;
107*05767d91SRobert Wu }
108*05767d91SRobert Wu 
109*05767d91SRobert Wu 
finishCommonOpen(SLAndroidConfigurationItf configItf)110*05767d91SRobert Wu SLresult AudioStreamOpenSLES::finishCommonOpen(SLAndroidConfigurationItf configItf) {
111*05767d91SRobert Wu     // Setting privacy sensitive mode and allowed capture policy are not supported for OpenSL ES.
112*05767d91SRobert Wu     mPrivacySensitiveMode = PrivacySensitiveMode::Unspecified;
113*05767d91SRobert Wu     mAllowedCapturePolicy = AllowedCapturePolicy::Unspecified;
114*05767d91SRobert Wu 
115*05767d91SRobert Wu     // Spatialization Behavior is not supported for OpenSL ES.
116*05767d91SRobert Wu     mSpatializationBehavior = SpatializationBehavior::Never;
117*05767d91SRobert Wu 
118*05767d91SRobert Wu     SLresult result = registerBufferQueueCallback();
119*05767d91SRobert Wu     if (SL_RESULT_SUCCESS != result) {
120*05767d91SRobert Wu         return result;
121*05767d91SRobert Wu     }
122*05767d91SRobert Wu 
123*05767d91SRobert Wu     result = updateStreamParameters(configItf);
124*05767d91SRobert Wu     if (SL_RESULT_SUCCESS != result) {
125*05767d91SRobert Wu         return result;
126*05767d91SRobert Wu     }
127*05767d91SRobert Wu 
128*05767d91SRobert Wu     Result oboeResult = configureBufferSizes(mSampleRate);
129*05767d91SRobert Wu     if (Result::OK != oboeResult) {
130*05767d91SRobert Wu         return (SLresult) oboeResult;
131*05767d91SRobert Wu     }
132*05767d91SRobert Wu 
133*05767d91SRobert Wu     allocateFifo();
134*05767d91SRobert Wu 
135*05767d91SRobert Wu     calculateDefaultDelayBeforeCloseMillis();
136*05767d91SRobert Wu 
137*05767d91SRobert Wu     return SL_RESULT_SUCCESS;
138*05767d91SRobert Wu }
139*05767d91SRobert Wu 
roundUpDivideByN(int32_t x,int32_t n)140*05767d91SRobert Wu static int32_t roundUpDivideByN(int32_t x, int32_t n) {
141*05767d91SRobert Wu     return (x + n - 1) / n;
142*05767d91SRobert Wu }
143*05767d91SRobert Wu 
calculateOptimalBufferQueueLength()144*05767d91SRobert Wu int32_t AudioStreamOpenSLES::calculateOptimalBufferQueueLength() {
145*05767d91SRobert Wu     int32_t queueLength = kBufferQueueLengthDefault;
146*05767d91SRobert Wu     int32_t likelyFramesPerBurst = estimateNativeFramesPerBurst();
147*05767d91SRobert Wu     int32_t minCapacity = mBufferCapacityInFrames; // specified by app or zero
148*05767d91SRobert Wu     // The buffer capacity needs to be at least twice the size of the requested callbackSize
149*05767d91SRobert Wu     // so that we can have double buffering.
150*05767d91SRobert Wu     minCapacity = std::max(minCapacity, kDoubleBufferCount * mFramesPerCallback);
151*05767d91SRobert Wu     if (minCapacity > 0) {
152*05767d91SRobert Wu         int32_t queueLengthFromCapacity = roundUpDivideByN(minCapacity, likelyFramesPerBurst);
153*05767d91SRobert Wu         queueLength = std::max(queueLength, queueLengthFromCapacity);
154*05767d91SRobert Wu     }
155*05767d91SRobert Wu     queueLength = std::min(queueLength, kBufferQueueLengthMax); // clip to max
156*05767d91SRobert Wu     // TODO Investigate the effect of queueLength on latency for normal streams. (not low latency)
157*05767d91SRobert Wu     return queueLength;
158*05767d91SRobert Wu }
159*05767d91SRobert Wu 
160*05767d91SRobert Wu /**
161*05767d91SRobert Wu  * The best information we have is if DefaultStreamValues::FramesPerBurst
162*05767d91SRobert Wu  * was set by the app based on AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER.
163*05767d91SRobert Wu  * Without that we just have to guess.
164*05767d91SRobert Wu  * @return
165*05767d91SRobert Wu  */
estimateNativeFramesPerBurst()166*05767d91SRobert Wu int32_t AudioStreamOpenSLES::estimateNativeFramesPerBurst() {
167*05767d91SRobert Wu     int32_t framesPerBurst = DefaultStreamValues::FramesPerBurst;
168*05767d91SRobert Wu     LOGD("AudioStreamOpenSLES:%s() DefaultStreamValues::FramesPerBurst = %d",
169*05767d91SRobert Wu             __func__, DefaultStreamValues::FramesPerBurst);
170*05767d91SRobert Wu     framesPerBurst = std::max(framesPerBurst, 16);
171*05767d91SRobert Wu     // Calculate the size of a fixed duration high latency buffer based on sample rate.
172*05767d91SRobert Wu     // Estimate sample based on default options in order of priority.
173*05767d91SRobert Wu     int32_t sampleRate = 48000;
174*05767d91SRobert Wu     sampleRate = (DefaultStreamValues::SampleRate > 0)
175*05767d91SRobert Wu             ? DefaultStreamValues::SampleRate : sampleRate;
176*05767d91SRobert Wu     sampleRate = (mSampleRate > 0) ? mSampleRate : sampleRate;
177*05767d91SRobert Wu     int32_t framesPerHighLatencyBuffer =
178*05767d91SRobert Wu             (kHighLatencyBufferSizeMillis * sampleRate) / kMillisPerSecond;
179*05767d91SRobert Wu     // For high latency streams, use a larger buffer size.
180*05767d91SRobert Wu     // Performance Mode support was added in N_MR1 (7.1)
181*05767d91SRobert Wu     if (getSdkVersion() >= __ANDROID_API_N_MR1__
182*05767d91SRobert Wu             && mPerformanceMode != PerformanceMode::LowLatency
183*05767d91SRobert Wu             && framesPerBurst < framesPerHighLatencyBuffer) {
184*05767d91SRobert Wu         // Find a multiple of framesPerBurst >= framesPerHighLatencyBuffer.
185*05767d91SRobert Wu         int32_t numBursts = roundUpDivideByN(framesPerHighLatencyBuffer, framesPerBurst);
186*05767d91SRobert Wu         framesPerBurst *= numBursts;
187*05767d91SRobert Wu         LOGD("AudioStreamOpenSLES:%s() NOT low latency, numBursts = %d, mSampleRate = %d, set framesPerBurst = %d",
188*05767d91SRobert Wu              __func__, numBursts, mSampleRate, framesPerBurst);
189*05767d91SRobert Wu     }
190*05767d91SRobert Wu     return framesPerBurst;
191*05767d91SRobert Wu }
192*05767d91SRobert Wu 
configureBufferSizes(int32_t sampleRate)193*05767d91SRobert Wu Result AudioStreamOpenSLES::configureBufferSizes(int32_t sampleRate) {
194*05767d91SRobert Wu     LOGD("AudioStreamOpenSLES:%s(%d) initial mFramesPerBurst = %d, mFramesPerCallback = %d",
195*05767d91SRobert Wu             __func__, mSampleRate, mFramesPerBurst, mFramesPerCallback);
196*05767d91SRobert Wu     mFramesPerBurst = estimateNativeFramesPerBurst();
197*05767d91SRobert Wu     mFramesPerCallback = (mFramesPerCallback > 0) ? mFramesPerCallback : mFramesPerBurst;
198*05767d91SRobert Wu     LOGD("AudioStreamOpenSLES:%s(%d) final mFramesPerBurst = %d, mFramesPerCallback = %d",
199*05767d91SRobert Wu          __func__, mSampleRate, mFramesPerBurst, mFramesPerCallback);
200*05767d91SRobert Wu 
201*05767d91SRobert Wu     mBytesPerCallback = mFramesPerCallback * getBytesPerFrame();
202*05767d91SRobert Wu     if (mBytesPerCallback <= 0) {
203*05767d91SRobert Wu         LOGE("AudioStreamOpenSLES::open() bytesPerCallback < 0 = %d, bad format?",
204*05767d91SRobert Wu              mBytesPerCallback);
205*05767d91SRobert Wu         return Result::ErrorInvalidFormat; // causing bytesPerFrame == 0
206*05767d91SRobert Wu     }
207*05767d91SRobert Wu 
208*05767d91SRobert Wu     for (int i = 0; i < mBufferQueueLength; ++i) {
209*05767d91SRobert Wu         mCallbackBuffer[i] = std::make_unique<uint8_t[]>(mBytesPerCallback);
210*05767d91SRobert Wu     }
211*05767d91SRobert Wu 
212*05767d91SRobert Wu     if (!usingFIFO()) {
213*05767d91SRobert Wu         mBufferCapacityInFrames = mFramesPerBurst * mBufferQueueLength;
214*05767d91SRobert Wu         // Check for overflow.
215*05767d91SRobert Wu         if (mBufferCapacityInFrames <= 0) {
216*05767d91SRobert Wu             mBufferCapacityInFrames = 0;
217*05767d91SRobert Wu             LOGE("AudioStreamOpenSLES::open() numeric overflow because mFramesPerBurst = %d",
218*05767d91SRobert Wu                  mFramesPerBurst);
219*05767d91SRobert Wu             return Result::ErrorOutOfRange;
220*05767d91SRobert Wu         }
221*05767d91SRobert Wu         mBufferSizeInFrames = mBufferCapacityInFrames;
222*05767d91SRobert Wu     }
223*05767d91SRobert Wu 
224*05767d91SRobert Wu     return Result::OK;
225*05767d91SRobert Wu }
226*05767d91SRobert Wu 
convertPerformanceMode(PerformanceMode oboeMode) const227*05767d91SRobert Wu SLuint32 AudioStreamOpenSLES::convertPerformanceMode(PerformanceMode oboeMode) const {
228*05767d91SRobert Wu     SLuint32 openslMode = SL_ANDROID_PERFORMANCE_NONE;
229*05767d91SRobert Wu     switch(oboeMode) {
230*05767d91SRobert Wu         case PerformanceMode::None:
231*05767d91SRobert Wu             openslMode =  SL_ANDROID_PERFORMANCE_NONE;
232*05767d91SRobert Wu             break;
233*05767d91SRobert Wu         case PerformanceMode::LowLatency:
234*05767d91SRobert Wu             openslMode =  (getSessionId() == SessionId::None) ?  SL_ANDROID_PERFORMANCE_LATENCY : SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS;
235*05767d91SRobert Wu             break;
236*05767d91SRobert Wu         case PerformanceMode::PowerSaving:
237*05767d91SRobert Wu             openslMode =  SL_ANDROID_PERFORMANCE_POWER_SAVING;
238*05767d91SRobert Wu             break;
239*05767d91SRobert Wu         default:
240*05767d91SRobert Wu             break;
241*05767d91SRobert Wu     }
242*05767d91SRobert Wu     return openslMode;
243*05767d91SRobert Wu }
244*05767d91SRobert Wu 
convertPerformanceMode(SLuint32 openslMode) const245*05767d91SRobert Wu PerformanceMode AudioStreamOpenSLES::convertPerformanceMode(SLuint32 openslMode) const {
246*05767d91SRobert Wu     PerformanceMode oboeMode = PerformanceMode::None;
247*05767d91SRobert Wu     switch(openslMode) {
248*05767d91SRobert Wu         case SL_ANDROID_PERFORMANCE_NONE:
249*05767d91SRobert Wu             oboeMode =  PerformanceMode::None;
250*05767d91SRobert Wu             break;
251*05767d91SRobert Wu         case SL_ANDROID_PERFORMANCE_LATENCY:
252*05767d91SRobert Wu         case SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS:
253*05767d91SRobert Wu             oboeMode =  PerformanceMode::LowLatency;
254*05767d91SRobert Wu             break;
255*05767d91SRobert Wu         case SL_ANDROID_PERFORMANCE_POWER_SAVING:
256*05767d91SRobert Wu             oboeMode =  PerformanceMode::PowerSaving;
257*05767d91SRobert Wu             break;
258*05767d91SRobert Wu         default:
259*05767d91SRobert Wu             break;
260*05767d91SRobert Wu     }
261*05767d91SRobert Wu     return oboeMode;
262*05767d91SRobert Wu }
263*05767d91SRobert Wu 
logUnsupportedAttributes()264*05767d91SRobert Wu void AudioStreamOpenSLES::logUnsupportedAttributes() {
265*05767d91SRobert Wu     // Log unsupported attributes
266*05767d91SRobert Wu     // only report if changed from the default
267*05767d91SRobert Wu 
268*05767d91SRobert Wu     // Device ID
269*05767d91SRobert Wu     if (mDeviceId != kUnspecified) {
270*05767d91SRobert Wu         LOGW("Device ID [AudioStreamBuilder::setDeviceId()] "
271*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
272*05767d91SRobert Wu     }
273*05767d91SRobert Wu     // Sharing Mode
274*05767d91SRobert Wu     if (mSharingMode != SharingMode::Shared) {
275*05767d91SRobert Wu         LOGW("SharingMode [AudioStreamBuilder::setSharingMode()] "
276*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
277*05767d91SRobert Wu     }
278*05767d91SRobert Wu     // Performance Mode
279*05767d91SRobert Wu     int sdkVersion = getSdkVersion();
280*05767d91SRobert Wu     if (mPerformanceMode != PerformanceMode::None && sdkVersion < __ANDROID_API_N_MR1__) {
281*05767d91SRobert Wu         LOGW("PerformanceMode [AudioStreamBuilder::setPerformanceMode()] "
282*05767d91SRobert Wu              "is not supported on OpenSLES streams running on pre-Android N-MR1 versions.");
283*05767d91SRobert Wu     }
284*05767d91SRobert Wu     // Content Type
285*05767d91SRobert Wu     if (mContentType != ContentType::Music) {
286*05767d91SRobert Wu         LOGW("ContentType [AudioStreamBuilder::setContentType()] "
287*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
288*05767d91SRobert Wu     }
289*05767d91SRobert Wu 
290*05767d91SRobert Wu     // Session Id
291*05767d91SRobert Wu     if (mSessionId != SessionId::None) {
292*05767d91SRobert Wu         LOGW("SessionId [AudioStreamBuilder::setSessionId()] "
293*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
294*05767d91SRobert Wu     }
295*05767d91SRobert Wu 
296*05767d91SRobert Wu     // Privacy Sensitive Mode
297*05767d91SRobert Wu     if (mPrivacySensitiveMode != PrivacySensitiveMode::Unspecified) {
298*05767d91SRobert Wu         LOGW("PrivacySensitiveMode [AudioStreamBuilder::setPrivacySensitiveMode()] "
299*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
300*05767d91SRobert Wu     }
301*05767d91SRobert Wu 
302*05767d91SRobert Wu     // Spatialization Behavior
303*05767d91SRobert Wu     if (mSpatializationBehavior != SpatializationBehavior::Unspecified) {
304*05767d91SRobert Wu         LOGW("SpatializationBehavior [AudioStreamBuilder::setSpatializationBehavior()] "
305*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
306*05767d91SRobert Wu     }
307*05767d91SRobert Wu 
308*05767d91SRobert Wu     // Allowed Capture Policy
309*05767d91SRobert Wu     if (mAllowedCapturePolicy != AllowedCapturePolicy::Unspecified) {
310*05767d91SRobert Wu         LOGW("AllowedCapturePolicy [AudioStreamBuilder::setAllowedCapturePolicy()] "
311*05767d91SRobert Wu              "is not supported on OpenSLES streams.");
312*05767d91SRobert Wu     }
313*05767d91SRobert Wu }
314*05767d91SRobert Wu 
configurePerformanceMode(SLAndroidConfigurationItf configItf)315*05767d91SRobert Wu SLresult AudioStreamOpenSLES::configurePerformanceMode(SLAndroidConfigurationItf configItf) {
316*05767d91SRobert Wu 
317*05767d91SRobert Wu     if (configItf == nullptr) {
318*05767d91SRobert Wu         LOGW("%s() called with NULL configuration", __func__);
319*05767d91SRobert Wu         mPerformanceMode = PerformanceMode::None;
320*05767d91SRobert Wu         return SL_RESULT_INTERNAL_ERROR;
321*05767d91SRobert Wu     }
322*05767d91SRobert Wu     if (getSdkVersion() < __ANDROID_API_N_MR1__) {
323*05767d91SRobert Wu         LOGW("%s() not supported until N_MR1", __func__);
324*05767d91SRobert Wu         mPerformanceMode = PerformanceMode::None;
325*05767d91SRobert Wu         return SL_RESULT_SUCCESS;
326*05767d91SRobert Wu     }
327*05767d91SRobert Wu 
328*05767d91SRobert Wu     SLresult result = SL_RESULT_SUCCESS;
329*05767d91SRobert Wu     SLuint32 performanceMode = convertPerformanceMode(getPerformanceMode());
330*05767d91SRobert Wu     result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
331*05767d91SRobert Wu                                                      &performanceMode, sizeof(performanceMode));
332*05767d91SRobert Wu     if (SL_RESULT_SUCCESS != result) {
333*05767d91SRobert Wu         LOGW("SetConfiguration(PERFORMANCE_MODE, SL %u) returned %s",
334*05767d91SRobert Wu              performanceMode, getSLErrStr(result));
335*05767d91SRobert Wu         mPerformanceMode = PerformanceMode::None;
336*05767d91SRobert Wu     }
337*05767d91SRobert Wu 
338*05767d91SRobert Wu     return result;
339*05767d91SRobert Wu }
340*05767d91SRobert Wu 
updateStreamParameters(SLAndroidConfigurationItf configItf)341*05767d91SRobert Wu SLresult AudioStreamOpenSLES::updateStreamParameters(SLAndroidConfigurationItf configItf) {
342*05767d91SRobert Wu     SLresult result = SL_RESULT_SUCCESS;
343*05767d91SRobert Wu     if(getSdkVersion() >= __ANDROID_API_N_MR1__ && configItf != nullptr) {
344*05767d91SRobert Wu         SLuint32 performanceMode = 0;
345*05767d91SRobert Wu         SLuint32 performanceModeSize = sizeof(performanceMode);
346*05767d91SRobert Wu         result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
347*05767d91SRobert Wu                                                 &performanceModeSize, &performanceMode);
348*05767d91SRobert Wu         // A bug in GetConfiguration() before P caused a wrong result code to be returned.
349*05767d91SRobert Wu         if (getSdkVersion() <= __ANDROID_API_O_MR1__) {
350*05767d91SRobert Wu             result = SL_RESULT_SUCCESS; // Ignore actual result before P.
351*05767d91SRobert Wu         }
352*05767d91SRobert Wu 
353*05767d91SRobert Wu         if (SL_RESULT_SUCCESS != result) {
354*05767d91SRobert Wu             LOGW("GetConfiguration(SL_ANDROID_KEY_PERFORMANCE_MODE) returned %d", result);
355*05767d91SRobert Wu             mPerformanceMode = PerformanceMode::None; // If we can't query it then assume None.
356*05767d91SRobert Wu         } else {
357*05767d91SRobert Wu             mPerformanceMode = convertPerformanceMode(performanceMode); // convert SL to Oboe mode
358*05767d91SRobert Wu         }
359*05767d91SRobert Wu     } else {
360*05767d91SRobert Wu         mPerformanceMode = PerformanceMode::None; // If we can't query it then assume None.
361*05767d91SRobert Wu     }
362*05767d91SRobert Wu     return result;
363*05767d91SRobert Wu }
364*05767d91SRobert Wu 
365*05767d91SRobert Wu // This is called under mLock.
close_l()366*05767d91SRobert Wu Result AudioStreamOpenSLES::close_l() {
367*05767d91SRobert Wu     if (mState == StreamState::Closed) {
368*05767d91SRobert Wu         return Result::ErrorClosed;
369*05767d91SRobert Wu     }
370*05767d91SRobert Wu 
371*05767d91SRobert Wu     AudioStreamBuffered::close();
372*05767d91SRobert Wu 
373*05767d91SRobert Wu     onBeforeDestroy();
374*05767d91SRobert Wu 
375*05767d91SRobert Wu     if (mObjectInterface != nullptr) {
376*05767d91SRobert Wu         (*mObjectInterface)->Destroy(mObjectInterface);
377*05767d91SRobert Wu         mObjectInterface = nullptr;
378*05767d91SRobert Wu     }
379*05767d91SRobert Wu 
380*05767d91SRobert Wu     onAfterDestroy();
381*05767d91SRobert Wu 
382*05767d91SRobert Wu     mSimpleBufferQueueInterface = nullptr;
383*05767d91SRobert Wu     EngineOpenSLES::getInstance().close();
384*05767d91SRobert Wu 
385*05767d91SRobert Wu     setState(StreamState::Closed);
386*05767d91SRobert Wu 
387*05767d91SRobert Wu     return Result::OK;
388*05767d91SRobert Wu }
389*05767d91SRobert Wu 
enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq)390*05767d91SRobert Wu SLresult AudioStreamOpenSLES::enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq) {
391*05767d91SRobert Wu     SLresult result = (*bq)->Enqueue(
392*05767d91SRobert Wu             bq, mCallbackBuffer[mCallbackBufferIndex].get(), mBytesPerCallback);
393*05767d91SRobert Wu     mCallbackBufferIndex = (mCallbackBufferIndex + 1) % mBufferQueueLength;
394*05767d91SRobert Wu     return result;
395*05767d91SRobert Wu }
396*05767d91SRobert Wu 
getBufferDepth(SLAndroidSimpleBufferQueueItf bq)397*05767d91SRobert Wu int32_t AudioStreamOpenSLES::getBufferDepth(SLAndroidSimpleBufferQueueItf bq) {
398*05767d91SRobert Wu     SLAndroidSimpleBufferQueueState queueState;
399*05767d91SRobert Wu     SLresult result = (*bq)->GetState(bq, &queueState);
400*05767d91SRobert Wu     return (result == SL_RESULT_SUCCESS) ? queueState.count : -1;
401*05767d91SRobert Wu }
402*05767d91SRobert Wu 
processBufferCallback(SLAndroidSimpleBufferQueueItf bq)403*05767d91SRobert Wu bool AudioStreamOpenSLES::processBufferCallback(SLAndroidSimpleBufferQueueItf bq) {
404*05767d91SRobert Wu     bool shouldStopStream = false;
405*05767d91SRobert Wu     // Ask the app callback to process the buffer.
406*05767d91SRobert Wu     DataCallbackResult result =
407*05767d91SRobert Wu             fireDataCallback(mCallbackBuffer[mCallbackBufferIndex].get(), mFramesPerCallback);
408*05767d91SRobert Wu     if (result == DataCallbackResult::Continue) {
409*05767d91SRobert Wu         // Pass the buffer to OpenSLES.
410*05767d91SRobert Wu         SLresult enqueueResult = enqueueCallbackBuffer(bq);
411*05767d91SRobert Wu         if (enqueueResult != SL_RESULT_SUCCESS) {
412*05767d91SRobert Wu             LOGE("%s() returned %d", __func__, enqueueResult);
413*05767d91SRobert Wu             shouldStopStream = true;
414*05767d91SRobert Wu         }
415*05767d91SRobert Wu         // Update Oboe client position with frames handled by the callback.
416*05767d91SRobert Wu         if (getDirection() == Direction::Input) {
417*05767d91SRobert Wu             mFramesRead += mFramesPerCallback;
418*05767d91SRobert Wu         } else {
419*05767d91SRobert Wu             mFramesWritten += mFramesPerCallback;
420*05767d91SRobert Wu         }
421*05767d91SRobert Wu     } else if (result == DataCallbackResult::Stop) {
422*05767d91SRobert Wu         LOGD("Oboe callback returned Stop");
423*05767d91SRobert Wu         shouldStopStream = true;
424*05767d91SRobert Wu     } else {
425*05767d91SRobert Wu         LOGW("Oboe callback returned unexpected value = %d", static_cast<int>(result));
426*05767d91SRobert Wu         shouldStopStream = true;
427*05767d91SRobert Wu     }
428*05767d91SRobert Wu     if (shouldStopStream) {
429*05767d91SRobert Wu         mCallbackBufferIndex = 0;
430*05767d91SRobert Wu     }
431*05767d91SRobert Wu     return shouldStopStream;
432*05767d91SRobert Wu }
433*05767d91SRobert Wu 
434*05767d91SRobert Wu // This callback handler is called every time a buffer has been processed by OpenSL ES.
bqCallbackGlue(SLAndroidSimpleBufferQueueItf bq,void * context)435*05767d91SRobert Wu static void bqCallbackGlue(SLAndroidSimpleBufferQueueItf bq, void *context) {
436*05767d91SRobert Wu     bool shouldStopStream = (reinterpret_cast<AudioStreamOpenSLES *>(context))
437*05767d91SRobert Wu             ->processBufferCallback(bq);
438*05767d91SRobert Wu     if (shouldStopStream) {
439*05767d91SRobert Wu         (reinterpret_cast<AudioStreamOpenSLES *>(context))->requestStop();
440*05767d91SRobert Wu     }
441*05767d91SRobert Wu }
442*05767d91SRobert Wu 
registerBufferQueueCallback()443*05767d91SRobert Wu SLresult AudioStreamOpenSLES::registerBufferQueueCallback() {
444*05767d91SRobert Wu     // The BufferQueue
445*05767d91SRobert Wu     SLresult result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
446*05767d91SRobert Wu                                                 &mSimpleBufferQueueInterface);
447*05767d91SRobert Wu     if (SL_RESULT_SUCCESS != result) {
448*05767d91SRobert Wu         LOGE("get buffer queue interface:%p result:%s",
449*05767d91SRobert Wu              mSimpleBufferQueueInterface,
450*05767d91SRobert Wu              getSLErrStr(result));
451*05767d91SRobert Wu     } else {
452*05767d91SRobert Wu         // Register the BufferQueue callback
453*05767d91SRobert Wu         result = (*mSimpleBufferQueueInterface)->RegisterCallback(mSimpleBufferQueueInterface,
454*05767d91SRobert Wu                                                                   bqCallbackGlue, this);
455*05767d91SRobert Wu         if (SL_RESULT_SUCCESS != result) {
456*05767d91SRobert Wu             LOGE("RegisterCallback result:%s", getSLErrStr(result));
457*05767d91SRobert Wu         }
458*05767d91SRobert Wu     }
459*05767d91SRobert Wu     return result;
460*05767d91SRobert Wu }
461*05767d91SRobert Wu 
getFramesProcessedByServer()462*05767d91SRobert Wu int64_t AudioStreamOpenSLES::getFramesProcessedByServer() {
463*05767d91SRobert Wu     updateServiceFrameCounter();
464*05767d91SRobert Wu     int64_t millis64 = mPositionMillis.get();
465*05767d91SRobert Wu     int64_t framesProcessed = millis64 * getSampleRate() / kMillisPerSecond;
466*05767d91SRobert Wu     return framesProcessed;
467*05767d91SRobert Wu }
468*05767d91SRobert Wu 
waitForStateChange(StreamState currentState,StreamState * nextState,int64_t timeoutNanoseconds)469*05767d91SRobert Wu Result AudioStreamOpenSLES::waitForStateChange(StreamState currentState,
470*05767d91SRobert Wu                                                      StreamState *nextState,
471*05767d91SRobert Wu                                                      int64_t timeoutNanoseconds) {
472*05767d91SRobert Wu     Result oboeResult = Result::ErrorTimeout;
473*05767d91SRobert Wu     int64_t sleepTimeNanos = 20 * kNanosPerMillisecond; // arbitrary
474*05767d91SRobert Wu     int64_t timeLeftNanos = timeoutNanoseconds;
475*05767d91SRobert Wu 
476*05767d91SRobert Wu     while (true) {
477*05767d91SRobert Wu         const StreamState state = getState(); // this does not require a lock
478*05767d91SRobert Wu         if (nextState != nullptr) {
479*05767d91SRobert Wu             *nextState = state;
480*05767d91SRobert Wu         }
481*05767d91SRobert Wu         if (currentState != state) { // state changed?
482*05767d91SRobert Wu             oboeResult = Result::OK;
483*05767d91SRobert Wu             break;
484*05767d91SRobert Wu         }
485*05767d91SRobert Wu 
486*05767d91SRobert Wu         // Did we timeout or did user ask for non-blocking?
487*05767d91SRobert Wu         if (timeLeftNanos <= 0) {
488*05767d91SRobert Wu             break;
489*05767d91SRobert Wu         }
490*05767d91SRobert Wu 
491*05767d91SRobert Wu         if (sleepTimeNanos > timeLeftNanos){
492*05767d91SRobert Wu             sleepTimeNanos = timeLeftNanos;
493*05767d91SRobert Wu         }
494*05767d91SRobert Wu         AudioClock::sleepForNanos(sleepTimeNanos);
495*05767d91SRobert Wu         timeLeftNanos -= sleepTimeNanos;
496*05767d91SRobert Wu     }
497*05767d91SRobert Wu 
498*05767d91SRobert Wu     return oboeResult;
499*05767d91SRobert Wu }
500