1*05767d91SRobert Wu /*
2*05767d91SRobert Wu * Copyright 2017 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
19*05767d91SRobert Wu #include <SLES/OpenSLES.h>
20*05767d91SRobert Wu #include <SLES/OpenSLES_Android.h>
21*05767d91SRobert Wu #include <common/AudioClock.h>
22*05767d91SRobert Wu
23*05767d91SRobert Wu #include "common/OboeDebug.h"
24*05767d91SRobert Wu #include "oboe/AudioStreamBuilder.h"
25*05767d91SRobert Wu #include "AudioOutputStreamOpenSLES.h"
26*05767d91SRobert Wu #include "AudioStreamOpenSLES.h"
27*05767d91SRobert Wu #include "OpenSLESUtilities.h"
28*05767d91SRobert Wu #include "OutputMixerOpenSLES.h"
29*05767d91SRobert Wu
30*05767d91SRobert Wu using namespace oboe;
31*05767d91SRobert Wu
OpenSLES_convertOutputUsage(Usage oboeUsage)32*05767d91SRobert Wu static SLuint32 OpenSLES_convertOutputUsage(Usage oboeUsage) {
33*05767d91SRobert Wu SLuint32 openslStream;
34*05767d91SRobert Wu switch(oboeUsage) {
35*05767d91SRobert Wu case Usage::Media:
36*05767d91SRobert Wu case Usage::Game:
37*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_MEDIA;
38*05767d91SRobert Wu break;
39*05767d91SRobert Wu case Usage::VoiceCommunication:
40*05767d91SRobert Wu case Usage::VoiceCommunicationSignalling:
41*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_VOICE;
42*05767d91SRobert Wu break;
43*05767d91SRobert Wu case Usage::Alarm:
44*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_ALARM;
45*05767d91SRobert Wu break;
46*05767d91SRobert Wu case Usage::Notification:
47*05767d91SRobert Wu case Usage::NotificationEvent:
48*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_NOTIFICATION;
49*05767d91SRobert Wu break;
50*05767d91SRobert Wu case Usage::NotificationRingtone:
51*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_RING;
52*05767d91SRobert Wu break;
53*05767d91SRobert Wu case Usage::AssistanceAccessibility:
54*05767d91SRobert Wu case Usage::AssistanceNavigationGuidance:
55*05767d91SRobert Wu case Usage::AssistanceSonification:
56*05767d91SRobert Wu case Usage::Assistant:
57*05767d91SRobert Wu default:
58*05767d91SRobert Wu openslStream = SL_ANDROID_STREAM_SYSTEM;
59*05767d91SRobert Wu break;
60*05767d91SRobert Wu }
61*05767d91SRobert Wu return openslStream;
62*05767d91SRobert Wu }
63*05767d91SRobert Wu
AudioOutputStreamOpenSLES(const AudioStreamBuilder & builder)64*05767d91SRobert Wu AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder)
65*05767d91SRobert Wu : AudioStreamOpenSLES(builder) {
66*05767d91SRobert Wu }
67*05767d91SRobert Wu
68*05767d91SRobert Wu // These will wind up in <SLES/OpenSLES_Android.h>
69*05767d91SRobert Wu constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
70*05767d91SRobert Wu
71*05767d91SRobert Wu constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO
72*05767d91SRobert Wu | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT);
73*05767d91SRobert Wu
74*05767d91SRobert Wu constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD
75*05767d91SRobert Wu | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY);
76*05767d91SRobert Wu
77*05767d91SRobert Wu constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT
78*05767d91SRobert Wu | SL_SPEAKER_SIDE_RIGHT);
79*05767d91SRobert Wu
channelCountToChannelMask(int channelCount) const80*05767d91SRobert Wu SLuint32 AudioOutputStreamOpenSLES::channelCountToChannelMask(int channelCount) const {
81*05767d91SRobert Wu SLuint32 channelMask = 0;
82*05767d91SRobert Wu
83*05767d91SRobert Wu switch (channelCount) {
84*05767d91SRobert Wu case 1:
85*05767d91SRobert Wu channelMask = SL_SPEAKER_FRONT_CENTER;
86*05767d91SRobert Wu break;
87*05767d91SRobert Wu
88*05767d91SRobert Wu case 2:
89*05767d91SRobert Wu channelMask = SL_ANDROID_SPEAKER_STEREO;
90*05767d91SRobert Wu break;
91*05767d91SRobert Wu
92*05767d91SRobert Wu case 4: // Quad
93*05767d91SRobert Wu channelMask = SL_ANDROID_SPEAKER_QUAD;
94*05767d91SRobert Wu break;
95*05767d91SRobert Wu
96*05767d91SRobert Wu case 6: // 5.1
97*05767d91SRobert Wu channelMask = SL_ANDROID_SPEAKER_5DOT1;
98*05767d91SRobert Wu break;
99*05767d91SRobert Wu
100*05767d91SRobert Wu case 8: // 7.1
101*05767d91SRobert Wu channelMask = SL_ANDROID_SPEAKER_7DOT1;
102*05767d91SRobert Wu break;
103*05767d91SRobert Wu
104*05767d91SRobert Wu default:
105*05767d91SRobert Wu channelMask = channelCountToChannelMaskDefault(channelCount);
106*05767d91SRobert Wu break;
107*05767d91SRobert Wu }
108*05767d91SRobert Wu return channelMask;
109*05767d91SRobert Wu }
110*05767d91SRobert Wu
open()111*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::open() {
112*05767d91SRobert Wu logUnsupportedAttributes();
113*05767d91SRobert Wu
114*05767d91SRobert Wu SLAndroidConfigurationItf configItf = nullptr;
115*05767d91SRobert Wu
116*05767d91SRobert Wu
117*05767d91SRobert Wu if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){
118*05767d91SRobert Wu // TODO: Allow floating point format on API <21 using float->int16 converter
119*05767d91SRobert Wu return Result::ErrorInvalidFormat;
120*05767d91SRobert Wu }
121*05767d91SRobert Wu
122*05767d91SRobert Wu // If audio format is unspecified then choose a suitable default.
123*05767d91SRobert Wu // API 21+: FLOAT
124*05767d91SRobert Wu // API <21: INT16
125*05767d91SRobert Wu if (mFormat == AudioFormat::Unspecified){
126*05767d91SRobert Wu mFormat = (getSdkVersion() < __ANDROID_API_L__) ?
127*05767d91SRobert Wu AudioFormat::I16 : AudioFormat::Float;
128*05767d91SRobert Wu }
129*05767d91SRobert Wu
130*05767d91SRobert Wu Result oboeResult = AudioStreamOpenSLES::open();
131*05767d91SRobert Wu if (Result::OK != oboeResult) return oboeResult;
132*05767d91SRobert Wu
133*05767d91SRobert Wu SLresult result = OutputMixerOpenSL::getInstance().open();
134*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
135*05767d91SRobert Wu AudioStreamOpenSLES::close();
136*05767d91SRobert Wu return Result::ErrorInternal;
137*05767d91SRobert Wu }
138*05767d91SRobert Wu
139*05767d91SRobert Wu SLuint32 bitsPerSample = static_cast<SLuint32>(getBytesPerSample() * kBitsPerByte);
140*05767d91SRobert Wu
141*05767d91SRobert Wu // configure audio source
142*05767d91SRobert Wu mBufferQueueLength = calculateOptimalBufferQueueLength();
143*05767d91SRobert Wu SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
144*05767d91SRobert Wu SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType
145*05767d91SRobert Wu static_cast<SLuint32>(mBufferQueueLength)}; // numBuffers
146*05767d91SRobert Wu
147*05767d91SRobert Wu // Define the audio data format.
148*05767d91SRobert Wu SLDataFormat_PCM format_pcm = {
149*05767d91SRobert Wu SL_DATAFORMAT_PCM, // formatType
150*05767d91SRobert Wu static_cast<SLuint32>(mChannelCount), // numChannels
151*05767d91SRobert Wu static_cast<SLuint32>(mSampleRate * kMillisPerSecond), // milliSamplesPerSec
152*05767d91SRobert Wu bitsPerSample, // bitsPerSample
153*05767d91SRobert Wu bitsPerSample, // containerSize;
154*05767d91SRobert Wu channelCountToChannelMask(mChannelCount), // channelMask
155*05767d91SRobert Wu getDefaultByteOrder(),
156*05767d91SRobert Wu };
157*05767d91SRobert Wu
158*05767d91SRobert Wu SLDataSource audioSrc = {&loc_bufq, &format_pcm};
159*05767d91SRobert Wu
160*05767d91SRobert Wu /**
161*05767d91SRobert Wu * API 21 (Lollipop) introduced support for floating-point data representation and an extended
162*05767d91SRobert Wu * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format
163*05767d91SRobert Wu * type, creating it from our original format.
164*05767d91SRobert Wu */
165*05767d91SRobert Wu SLAndroidDataFormat_PCM_EX format_pcm_ex;
166*05767d91SRobert Wu if (getSdkVersion() >= __ANDROID_API_L__) {
167*05767d91SRobert Wu SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
168*05767d91SRobert Wu // Fill in the format structure.
169*05767d91SRobert Wu format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
170*05767d91SRobert Wu // Use in place of the previous format.
171*05767d91SRobert Wu audioSrc.pFormat = &format_pcm_ex;
172*05767d91SRobert Wu }
173*05767d91SRobert Wu
174*05767d91SRobert Wu result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface,
175*05767d91SRobert Wu &audioSrc);
176*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
177*05767d91SRobert Wu LOGE("createAudioPlayer() result:%s", getSLErrStr(result));
178*05767d91SRobert Wu goto error;
179*05767d91SRobert Wu }
180*05767d91SRobert Wu
181*05767d91SRobert Wu // Configure the stream.
182*05767d91SRobert Wu result = (*mObjectInterface)->GetInterface(mObjectInterface,
183*05767d91SRobert Wu SL_IID_ANDROIDCONFIGURATION,
184*05767d91SRobert Wu (void *)&configItf);
185*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
186*05767d91SRobert Wu LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s",
187*05767d91SRobert Wu __func__, getSLErrStr(result));
188*05767d91SRobert Wu } else {
189*05767d91SRobert Wu result = configurePerformanceMode(configItf);
190*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
191*05767d91SRobert Wu goto error;
192*05767d91SRobert Wu }
193*05767d91SRobert Wu
194*05767d91SRobert Wu SLuint32 presetValue = OpenSLES_convertOutputUsage(getUsage());
195*05767d91SRobert Wu result = (*configItf)->SetConfiguration(configItf,
196*05767d91SRobert Wu SL_ANDROID_KEY_STREAM_TYPE,
197*05767d91SRobert Wu &presetValue,
198*05767d91SRobert Wu sizeof(presetValue));
199*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
200*05767d91SRobert Wu goto error;
201*05767d91SRobert Wu }
202*05767d91SRobert Wu }
203*05767d91SRobert Wu
204*05767d91SRobert Wu result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
205*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
206*05767d91SRobert Wu LOGE("Realize player object result:%s", getSLErrStr(result));
207*05767d91SRobert Wu goto error;
208*05767d91SRobert Wu }
209*05767d91SRobert Wu
210*05767d91SRobert Wu result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_PLAY, &mPlayInterface);
211*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
212*05767d91SRobert Wu LOGE("GetInterface PLAY result:%s", getSLErrStr(result));
213*05767d91SRobert Wu goto error;
214*05767d91SRobert Wu }
215*05767d91SRobert Wu
216*05767d91SRobert Wu result = finishCommonOpen(configItf);
217*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
218*05767d91SRobert Wu goto error;
219*05767d91SRobert Wu }
220*05767d91SRobert Wu
221*05767d91SRobert Wu setState(StreamState::Open);
222*05767d91SRobert Wu return Result::OK;
223*05767d91SRobert Wu
224*05767d91SRobert Wu error:
225*05767d91SRobert Wu close(); // Clean up various OpenSL objects and prevent resource leaks.
226*05767d91SRobert Wu return Result::ErrorInternal; // TODO convert error from SLES to OBOE
227*05767d91SRobert Wu }
228*05767d91SRobert Wu
onAfterDestroy()229*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::onAfterDestroy() {
230*05767d91SRobert Wu OutputMixerOpenSL::getInstance().close();
231*05767d91SRobert Wu return Result::OK;
232*05767d91SRobert Wu }
233*05767d91SRobert Wu
close()234*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::close() {
235*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES::%s()", __func__);
236*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
237*05767d91SRobert Wu Result result = Result::OK;
238*05767d91SRobert Wu if (getState() == StreamState::Closed){
239*05767d91SRobert Wu result = Result::ErrorClosed;
240*05767d91SRobert Wu } else {
241*05767d91SRobert Wu (void) requestPause_l();
242*05767d91SRobert Wu if (OboeGlobals::areWorkaroundsEnabled()) {
243*05767d91SRobert Wu sleepBeforeClose();
244*05767d91SRobert Wu }
245*05767d91SRobert Wu // invalidate any interfaces
246*05767d91SRobert Wu mPlayInterface = nullptr;
247*05767d91SRobert Wu result = AudioStreamOpenSLES::close_l();
248*05767d91SRobert Wu }
249*05767d91SRobert Wu return result;
250*05767d91SRobert Wu }
251*05767d91SRobert Wu
setPlayState_l(SLuint32 newState)252*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::setPlayState_l(SLuint32 newState) {
253*05767d91SRobert Wu
254*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__);
255*05767d91SRobert Wu Result result = Result::OK;
256*05767d91SRobert Wu
257*05767d91SRobert Wu if (mPlayInterface == nullptr){
258*05767d91SRobert Wu LOGE("AudioOutputStreamOpenSLES::%s() mPlayInterface is null", __func__);
259*05767d91SRobert Wu return Result::ErrorInvalidState;
260*05767d91SRobert Wu }
261*05767d91SRobert Wu
262*05767d91SRobert Wu SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState);
263*05767d91SRobert Wu if (SL_RESULT_SUCCESS != slResult) {
264*05767d91SRobert Wu LOGW("AudioOutputStreamOpenSLES(): %s() returned %s", __func__, getSLErrStr(slResult));
265*05767d91SRobert Wu result = Result::ErrorInternal; // TODO convert slResult to Result::Error
266*05767d91SRobert Wu }
267*05767d91SRobert Wu return result;
268*05767d91SRobert Wu }
269*05767d91SRobert Wu
requestStart()270*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestStart() {
271*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__);
272*05767d91SRobert Wu
273*05767d91SRobert Wu mLock.lock();
274*05767d91SRobert Wu StreamState initialState = getState();
275*05767d91SRobert Wu switch (initialState) {
276*05767d91SRobert Wu case StreamState::Starting:
277*05767d91SRobert Wu case StreamState::Started:
278*05767d91SRobert Wu mLock.unlock();
279*05767d91SRobert Wu return Result::OK;
280*05767d91SRobert Wu case StreamState::Closed:
281*05767d91SRobert Wu mLock.unlock();
282*05767d91SRobert Wu return Result::ErrorClosed;
283*05767d91SRobert Wu default:
284*05767d91SRobert Wu break;
285*05767d91SRobert Wu }
286*05767d91SRobert Wu
287*05767d91SRobert Wu // We use a callback if the user requests one
288*05767d91SRobert Wu // OR if we have an internal callback to read the blocking IO buffer.
289*05767d91SRobert Wu setDataCallbackEnabled(true);
290*05767d91SRobert Wu
291*05767d91SRobert Wu setState(StreamState::Starting);
292*05767d91SRobert Wu closePerformanceHint();
293*05767d91SRobert Wu
294*05767d91SRobert Wu if (getBufferDepth(mSimpleBufferQueueInterface) == 0) {
295*05767d91SRobert Wu // Enqueue the first buffer if needed to start the streaming.
296*05767d91SRobert Wu // We may need to stop the current stream.
297*05767d91SRobert Wu bool shouldStopStream = processBufferCallback(mSimpleBufferQueueInterface);
298*05767d91SRobert Wu if (shouldStopStream) {
299*05767d91SRobert Wu LOGD("Stopping the current stream.");
300*05767d91SRobert Wu if (requestStop_l() != Result::OK) {
301*05767d91SRobert Wu LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
302*05767d91SRobert Wu }
303*05767d91SRobert Wu setState(initialState);
304*05767d91SRobert Wu mLock.unlock();
305*05767d91SRobert Wu return Result::ErrorClosed;
306*05767d91SRobert Wu }
307*05767d91SRobert Wu }
308*05767d91SRobert Wu
309*05767d91SRobert Wu Result result = setPlayState_l(SL_PLAYSTATE_PLAYING);
310*05767d91SRobert Wu if (result == Result::OK) {
311*05767d91SRobert Wu setState(StreamState::Started);
312*05767d91SRobert Wu mLock.unlock();
313*05767d91SRobert Wu } else {
314*05767d91SRobert Wu setState(initialState);
315*05767d91SRobert Wu mLock.unlock();
316*05767d91SRobert Wu }
317*05767d91SRobert Wu return result;
318*05767d91SRobert Wu }
319*05767d91SRobert Wu
requestPause()320*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestPause() {
321*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__);
322*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
323*05767d91SRobert Wu return requestPause_l();
324*05767d91SRobert Wu }
325*05767d91SRobert Wu
326*05767d91SRobert Wu // Call under mLock
requestPause_l()327*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestPause_l() {
328*05767d91SRobert Wu StreamState initialState = getState();
329*05767d91SRobert Wu switch (initialState) {
330*05767d91SRobert Wu case StreamState::Pausing:
331*05767d91SRobert Wu case StreamState::Paused:
332*05767d91SRobert Wu return Result::OK;
333*05767d91SRobert Wu case StreamState::Uninitialized:
334*05767d91SRobert Wu case StreamState::Closed:
335*05767d91SRobert Wu return Result::ErrorClosed;
336*05767d91SRobert Wu default:
337*05767d91SRobert Wu break;
338*05767d91SRobert Wu }
339*05767d91SRobert Wu
340*05767d91SRobert Wu setState(StreamState::Pausing);
341*05767d91SRobert Wu Result result = setPlayState_l(SL_PLAYSTATE_PAUSED);
342*05767d91SRobert Wu if (result == Result::OK) {
343*05767d91SRobert Wu // Note that OpenSL ES does NOT reset its millisecond position when OUTPUT is paused.
344*05767d91SRobert Wu int64_t framesWritten = getFramesWritten();
345*05767d91SRobert Wu if (framesWritten >= 0) {
346*05767d91SRobert Wu setFramesRead(framesWritten);
347*05767d91SRobert Wu }
348*05767d91SRobert Wu setState(StreamState::Paused);
349*05767d91SRobert Wu } else {
350*05767d91SRobert Wu setState(initialState);
351*05767d91SRobert Wu }
352*05767d91SRobert Wu return result;
353*05767d91SRobert Wu }
354*05767d91SRobert Wu
355*05767d91SRobert Wu /**
356*05767d91SRobert Wu * Flush/clear the queue buffers
357*05767d91SRobert Wu */
requestFlush()358*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestFlush() {
359*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
360*05767d91SRobert Wu return requestFlush_l();
361*05767d91SRobert Wu }
362*05767d91SRobert Wu
requestFlush_l()363*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestFlush_l() {
364*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__);
365*05767d91SRobert Wu if (getState() == StreamState::Closed) {
366*05767d91SRobert Wu return Result::ErrorClosed;
367*05767d91SRobert Wu }
368*05767d91SRobert Wu
369*05767d91SRobert Wu Result result = Result::OK;
370*05767d91SRobert Wu if (mPlayInterface == nullptr || mSimpleBufferQueueInterface == nullptr) {
371*05767d91SRobert Wu result = Result::ErrorInvalidState;
372*05767d91SRobert Wu } else {
373*05767d91SRobert Wu SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface);
374*05767d91SRobert Wu if (slResult != SL_RESULT_SUCCESS){
375*05767d91SRobert Wu LOGW("Failed to clear buffer queue. OpenSLES error: %s", getSLErrStr(slResult));
376*05767d91SRobert Wu result = Result::ErrorInternal;
377*05767d91SRobert Wu }
378*05767d91SRobert Wu }
379*05767d91SRobert Wu return result;
380*05767d91SRobert Wu }
381*05767d91SRobert Wu
requestStop()382*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestStop() {
383*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
384*05767d91SRobert Wu return requestStop_l();
385*05767d91SRobert Wu }
386*05767d91SRobert Wu
requestStop_l()387*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::requestStop_l() {
388*05767d91SRobert Wu LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__);
389*05767d91SRobert Wu
390*05767d91SRobert Wu StreamState initialState = getState();
391*05767d91SRobert Wu switch (initialState) {
392*05767d91SRobert Wu case StreamState::Stopping:
393*05767d91SRobert Wu case StreamState::Stopped:
394*05767d91SRobert Wu return Result::OK;
395*05767d91SRobert Wu case StreamState::Uninitialized:
396*05767d91SRobert Wu case StreamState::Closed:
397*05767d91SRobert Wu return Result::ErrorClosed;
398*05767d91SRobert Wu default:
399*05767d91SRobert Wu break;
400*05767d91SRobert Wu }
401*05767d91SRobert Wu
402*05767d91SRobert Wu setState(StreamState::Stopping);
403*05767d91SRobert Wu
404*05767d91SRobert Wu Result result = setPlayState_l(SL_PLAYSTATE_STOPPED);
405*05767d91SRobert Wu if (result == Result::OK) {
406*05767d91SRobert Wu
407*05767d91SRobert Wu // Also clear the buffer queue so the old data won't be played if the stream is restarted.
408*05767d91SRobert Wu // Call the _l function that expects to already be under a lock.
409*05767d91SRobert Wu if (requestFlush_l() != Result::OK) {
410*05767d91SRobert Wu LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
411*05767d91SRobert Wu }
412*05767d91SRobert Wu
413*05767d91SRobert Wu mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped.
414*05767d91SRobert Wu int64_t framesWritten = getFramesWritten();
415*05767d91SRobert Wu if (framesWritten >= 0) {
416*05767d91SRobert Wu setFramesRead(framesWritten);
417*05767d91SRobert Wu }
418*05767d91SRobert Wu setState(StreamState::Stopped);
419*05767d91SRobert Wu } else {
420*05767d91SRobert Wu setState(initialState);
421*05767d91SRobert Wu }
422*05767d91SRobert Wu return result;
423*05767d91SRobert Wu }
424*05767d91SRobert Wu
setFramesRead(int64_t framesRead)425*05767d91SRobert Wu void AudioOutputStreamOpenSLES::setFramesRead(int64_t framesRead) {
426*05767d91SRobert Wu int64_t millisWritten = framesRead * kMillisPerSecond / getSampleRate();
427*05767d91SRobert Wu mPositionMillis.set(millisWritten);
428*05767d91SRobert Wu }
429*05767d91SRobert Wu
updateFramesRead()430*05767d91SRobert Wu void AudioOutputStreamOpenSLES::updateFramesRead() {
431*05767d91SRobert Wu if (usingFIFO()) {
432*05767d91SRobert Wu AudioStreamBuffered::updateFramesRead();
433*05767d91SRobert Wu } else {
434*05767d91SRobert Wu mFramesRead = getFramesProcessedByServer();
435*05767d91SRobert Wu }
436*05767d91SRobert Wu }
437*05767d91SRobert Wu
updateServiceFrameCounter()438*05767d91SRobert Wu Result AudioOutputStreamOpenSLES::updateServiceFrameCounter() {
439*05767d91SRobert Wu Result result = Result::OK;
440*05767d91SRobert Wu // Avoid deadlock if another thread is trying to stop or close this stream
441*05767d91SRobert Wu // and this is being called from a callback.
442*05767d91SRobert Wu if (mLock.try_lock()) {
443*05767d91SRobert Wu
444*05767d91SRobert Wu if (mPlayInterface == nullptr) {
445*05767d91SRobert Wu mLock.unlock();
446*05767d91SRobert Wu return Result::ErrorNull;
447*05767d91SRobert Wu }
448*05767d91SRobert Wu SLmillisecond msec = 0;
449*05767d91SRobert Wu SLresult slResult = (*mPlayInterface)->GetPosition(mPlayInterface, &msec);
450*05767d91SRobert Wu if (SL_RESULT_SUCCESS != slResult) {
451*05767d91SRobert Wu LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult));
452*05767d91SRobert Wu // set result based on SLresult
453*05767d91SRobert Wu result = Result::ErrorInternal;
454*05767d91SRobert Wu } else {
455*05767d91SRobert Wu mPositionMillis.update32(msec);
456*05767d91SRobert Wu }
457*05767d91SRobert Wu mLock.unlock();
458*05767d91SRobert Wu }
459*05767d91SRobert Wu return result;
460*05767d91SRobert Wu }
461