• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AAudioStream"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <atomic>
22 #include <stdint.h>
23 
24 #include <media/MediaMetricsItem.h>
25 
26 #include <aaudio/AAudio.h>
27 
28 #include "AudioStreamBuilder.h"
29 #include "AudioStream.h"
30 #include "AudioClock.h"
31 #include "AudioGlobal.h"
32 
33 namespace aaudio {
34 
35 // Sequential number assigned to streams solely for debugging purposes.
AAudio_getNextStreamId()36 static aaudio_stream_id_t AAudio_getNextStreamId() {
37     static std::atomic <aaudio_stream_id_t> nextStreamId{1};
38     return nextStreamId++;
39 }
40 
AudioStream()41 AudioStream::AudioStream()
42         : mPlayerBase(new MyPlayerBase())
43         , mStreamId(AAudio_getNextStreamId())
44         {
45     setPeriodNanoseconds(0);
46 }
47 
~AudioStream()48 AudioStream::~AudioStream() {
49     // Please preserve these logs because there have been several bugs related to
50     // AudioStream deletion and late callbacks.
51     ALOGD("%s(s#%u) mPlayerBase strongCount = %d",
52             __func__, getId(), mPlayerBase->getStrongCount());
53 
54     ALOGE_IF(pthread_equal(pthread_self(), mThread),
55             "%s() destructor running in callback", __func__);
56 
57     ALOGE_IF(mHasThread, "%s() callback thread never join()ed", __func__);
58 
59     // If the stream is deleted when OPEN or in use then audio resources will leak.
60     // This would indicate an internal error. So we want to find this ASAP.
61     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
62                           || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
63                           || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
64                         "~AudioStream() - still in use, state = %s",
65                         AudioGlobal_convertStreamStateToText(getState()));
66 }
67 
open(const AudioStreamBuilder & builder)68 aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
69 {
70     // Call here as well because the AAudioService will call this without calling build().
71     aaudio_result_t result = builder.validate();
72     if (result != AAUDIO_OK) {
73         return result;
74     }
75 
76     // Copy parameters from the Builder because the Builder may be deleted after this call.
77     // TODO AudioStream should be a subclass of AudioStreamParameters
78     mSamplesPerFrame = builder.getSamplesPerFrame();
79     mSampleRate = builder.getSampleRate();
80     mDeviceId = builder.getDeviceId();
81     mFormat = builder.getFormat();
82     mSharingMode = builder.getSharingMode();
83     mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
84     mPerformanceMode = builder.getPerformanceMode();
85 
86     mUsage = builder.getUsage();
87     if (mUsage == AAUDIO_UNSPECIFIED) {
88         mUsage = AAUDIO_USAGE_MEDIA;
89     }
90     mContentType = builder.getContentType();
91     if (mContentType == AAUDIO_UNSPECIFIED) {
92         mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
93     }
94     mInputPreset = builder.getInputPreset();
95     if (mInputPreset == AAUDIO_UNSPECIFIED) {
96         mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
97     }
98     mAllowedCapturePolicy = builder.getAllowedCapturePolicy();
99     if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
100         mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
101     }
102     mIsPrivacySensitive = builder.isPrivacySensitive();
103 
104     // callbacks
105     mFramesPerDataCallback = builder.getFramesPerDataCallback();
106     mDataCallbackProc = builder.getDataCallbackProc();
107     mErrorCallbackProc = builder.getErrorCallbackProc();
108     mDataCallbackUserData = builder.getDataCallbackUserData();
109     mErrorCallbackUserData = builder.getErrorCallbackUserData();
110 
111     return AAUDIO_OK;
112 }
113 
logOpenActual()114 void AudioStream::logOpenActual() {
115     if (mMetricsId.size() > 0) {
116         android::mediametrics::LogItem item(mMetricsId);
117         item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
118             .set(AMEDIAMETRICS_PROP_PERFORMANCEMODEACTUAL,
119                 AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
120             .set(AMEDIAMETRICS_PROP_SHARINGMODEACTUAL,
121                 AudioGlobal_convertSharingModeToText(getSharingMode()))
122             .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, getBufferCapacity())
123             .set(AMEDIAMETRICS_PROP_BURSTFRAMES, getFramesPerBurst())
124             .set(AMEDIAMETRICS_PROP_DIRECTION,
125                 AudioGlobal_convertDirectionToText(getDirection()));
126 
127         if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
128             item.set(AMEDIAMETRICS_PROP_PLAYERIID, mPlayerBase->getPlayerIId());
129         }
130         item.record();
131     }
132 }
133 
logReleaseBufferState()134 void AudioStream::logReleaseBufferState() {
135     if (mMetricsId.size() > 0) {
136         android::mediametrics::LogItem(mMetricsId)
137                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RELEASE)
138                 .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t) getBufferSize())
139                 .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
140                 .record();
141     }
142 }
143 
systemStart()144 aaudio_result_t AudioStream::systemStart() {
145     if (collidesWithCallback()) {
146         ALOGE("%s cannot be called from a callback!", __func__);
147         return AAUDIO_ERROR_INVALID_STATE;
148     }
149 
150     std::lock_guard<std::mutex> lock(mStreamLock);
151 
152     switch (getState()) {
153         // Is this a good time to start?
154         case AAUDIO_STREAM_STATE_OPEN:
155         case AAUDIO_STREAM_STATE_PAUSING:
156         case AAUDIO_STREAM_STATE_PAUSED:
157         case AAUDIO_STREAM_STATE_STOPPING:
158         case AAUDIO_STREAM_STATE_STOPPED:
159         case AAUDIO_STREAM_STATE_FLUSHING:
160         case AAUDIO_STREAM_STATE_FLUSHED:
161             break; // Proceed with starting.
162 
163         // Already started?
164         case AAUDIO_STREAM_STATE_STARTING:
165         case AAUDIO_STREAM_STATE_STARTED:
166             ALOGW("%s() stream was already started, state = %s", __func__,
167                   AudioGlobal_convertStreamStateToText(getState()));
168             return AAUDIO_ERROR_INVALID_STATE;
169 
170         // Don't start when the stream is dead!
171         case AAUDIO_STREAM_STATE_DISCONNECTED:
172         case AAUDIO_STREAM_STATE_CLOSING:
173         case AAUDIO_STREAM_STATE_CLOSED:
174         default:
175             ALOGW("%s() stream is dead, state = %s", __func__,
176                   AudioGlobal_convertStreamStateToText(getState()));
177             return AAUDIO_ERROR_INVALID_STATE;
178     }
179 
180     aaudio_result_t result = requestStart_l();
181     if (result == AAUDIO_OK) {
182         // We only call this for logging in "dumpsys audio". So ignore return code.
183         (void) mPlayerBase->startWithStatus(getDeviceId());
184     }
185     return result;
186 }
187 
systemPause()188 aaudio_result_t AudioStream::systemPause() {
189 
190     if (!isPauseSupported()) {
191         return AAUDIO_ERROR_UNIMPLEMENTED;
192     }
193 
194     if (collidesWithCallback()) {
195         ALOGE("%s cannot be called from a callback!", __func__);
196         return AAUDIO_ERROR_INVALID_STATE;
197     }
198 
199     std::lock_guard<std::mutex> lock(mStreamLock);
200     switch (getState()) {
201         // Proceed with pausing.
202         case AAUDIO_STREAM_STATE_STARTING:
203         case AAUDIO_STREAM_STATE_STARTED:
204         case AAUDIO_STREAM_STATE_DISCONNECTED:
205             break;
206 
207             // Transition from one inactive state to another.
208         case AAUDIO_STREAM_STATE_OPEN:
209         case AAUDIO_STREAM_STATE_STOPPED:
210         case AAUDIO_STREAM_STATE_FLUSHED:
211             setState(AAUDIO_STREAM_STATE_PAUSED);
212             return AAUDIO_OK;
213 
214             // Redundant?
215         case AAUDIO_STREAM_STATE_PAUSING:
216         case AAUDIO_STREAM_STATE_PAUSED:
217             return AAUDIO_OK;
218 
219             // Don't interfere with transitional states or when closed.
220         case AAUDIO_STREAM_STATE_STOPPING:
221         case AAUDIO_STREAM_STATE_FLUSHING:
222         case AAUDIO_STREAM_STATE_CLOSING:
223         case AAUDIO_STREAM_STATE_CLOSED:
224         default:
225             ALOGW("%s() stream not running, state = %s",
226                   __func__, AudioGlobal_convertStreamStateToText(getState()));
227             return AAUDIO_ERROR_INVALID_STATE;
228     }
229 
230     aaudio_result_t result = requestPause_l();
231     if (result == AAUDIO_OK) {
232         // We only call this for logging in "dumpsys audio". So ignore return code.
233         (void) mPlayerBase->pauseWithStatus();
234     }
235     return result;
236 }
237 
safeFlush()238 aaudio_result_t AudioStream::safeFlush() {
239     if (!isFlushSupported()) {
240         ALOGE("flush not supported for this stream");
241         return AAUDIO_ERROR_UNIMPLEMENTED;
242     }
243 
244     if (collidesWithCallback()) {
245         ALOGE("stream cannot be flushed from a callback!");
246         return AAUDIO_ERROR_INVALID_STATE;
247     }
248 
249     std::lock_guard<std::mutex> lock(mStreamLock);
250     aaudio_result_t result = AAudio_isFlushAllowed(getState());
251     if (result != AAUDIO_OK) {
252         return result;
253     }
254 
255     return requestFlush_l();
256 }
257 
systemStopInternal()258 aaudio_result_t AudioStream::systemStopInternal() {
259     std::lock_guard<std::mutex> lock(mStreamLock);
260     aaudio_result_t result = safeStop_l();
261     if (result == AAUDIO_OK) {
262         // We only call this for logging in "dumpsys audio". So ignore return code.
263         (void) mPlayerBase->stopWithStatus();
264     }
265     return result;
266 }
267 
systemStopFromApp()268 aaudio_result_t AudioStream::systemStopFromApp() {
269     // This check can and should be done outside the lock.
270     if (collidesWithCallback()) {
271         ALOGE("stream cannot be stopped by calling from a callback!");
272         return AAUDIO_ERROR_INVALID_STATE;
273     }
274     return systemStopInternal();
275 }
276 
safeStop_l()277 aaudio_result_t AudioStream::safeStop_l() {
278 
279     switch (getState()) {
280         // Proceed with stopping.
281         case AAUDIO_STREAM_STATE_STARTING:
282         case AAUDIO_STREAM_STATE_STARTED:
283         case AAUDIO_STREAM_STATE_DISCONNECTED:
284             break;
285 
286         // Transition from one inactive state to another.
287         case AAUDIO_STREAM_STATE_OPEN:
288         case AAUDIO_STREAM_STATE_PAUSED:
289         case AAUDIO_STREAM_STATE_FLUSHED:
290             setState(AAUDIO_STREAM_STATE_STOPPED);
291             return AAUDIO_OK;
292 
293         // Redundant?
294         case AAUDIO_STREAM_STATE_STOPPING:
295         case AAUDIO_STREAM_STATE_STOPPED:
296             return AAUDIO_OK;
297 
298         // Don't interfere with transitional states or when closed.
299         case AAUDIO_STREAM_STATE_PAUSING:
300         case AAUDIO_STREAM_STATE_FLUSHING:
301         case AAUDIO_STREAM_STATE_CLOSING:
302         case AAUDIO_STREAM_STATE_CLOSED:
303         default:
304             ALOGW("%s() stream not running, state = %s", __func__,
305                   AudioGlobal_convertStreamStateToText(getState()));
306             return AAUDIO_ERROR_INVALID_STATE;
307     }
308 
309     return requestStop_l();
310 }
311 
safeRelease()312 aaudio_result_t AudioStream::safeRelease() {
313     if (collidesWithCallback()) {
314         ALOGE("%s cannot be called from a callback!", __func__);
315         return AAUDIO_ERROR_INVALID_STATE;
316     }
317     // This may get temporarily unlocked in the MMAP release() when joining callback threads.
318     std::lock_guard<std::mutex> lock(mStreamLock);
319     if (getState() == AAUDIO_STREAM_STATE_CLOSING) { // already released?
320         return AAUDIO_OK;
321     }
322     return release_l();
323 }
324 
safeReleaseClose()325 aaudio_result_t AudioStream::safeReleaseClose() {
326     if (collidesWithCallback()) {
327         ALOGE("%s cannot be called from a callback!", __func__);
328         return AAUDIO_ERROR_INVALID_STATE;
329     }
330     return safeReleaseCloseInternal();
331 }
332 
safeReleaseCloseInternal()333 aaudio_result_t AudioStream::safeReleaseCloseInternal() {
334     // This get temporarily unlocked in the MMAP release() when joining callback threads.
335     std::lock_guard<std::mutex> lock(mStreamLock);
336     releaseCloseFinal_l();
337     return AAUDIO_OK;
338 }
339 
close_l()340 void AudioStream::close_l() {
341     // Releasing the stream will set the state to CLOSING.
342     assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
343     // setState() prevents a transition from CLOSING to any state other than CLOSED.
344     // State is checked by destructor.
345     setState(AAUDIO_STREAM_STATE_CLOSED);
346 
347     if (!mMetricsId.empty()) {
348         android::mediametrics::LogItem(mMetricsId)
349                 .set(AMEDIAMETRICS_PROP_FRAMESTRANSFERRED,
350                         getDirection() == AAUDIO_DIRECTION_INPUT ? getFramesWritten()
351                                                                  : getFramesRead())
352                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
353                 .record();
354     }
355 }
356 
setState(aaudio_stream_state_t state)357 void AudioStream::setState(aaudio_stream_state_t state) {
358     ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
359     if (state == mState) {
360         return; // no change
361     }
362     // Track transition to DISCONNECTED state.
363     if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
364         android::mediametrics::LogItem(mMetricsId)
365                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
366                 .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
367                 .record();
368     }
369     // CLOSED is a final state
370     if (mState == AAUDIO_STREAM_STATE_CLOSED) {
371         ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
372 
373     // Once CLOSING, we can only move to CLOSED state.
374     } else if (mState == AAUDIO_STREAM_STATE_CLOSING
375                && state != AAUDIO_STREAM_STATE_CLOSED) {
376         ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
377 
378     // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
379     } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
380                && !(state == AAUDIO_STREAM_STATE_CLOSING
381                    || state == AAUDIO_STREAM_STATE_CLOSED)) {
382         ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
383 
384     } else {
385         mState = state;
386     }
387 }
388 
waitForStateChange(aaudio_stream_state_t currentState,aaudio_stream_state_t * nextState,int64_t timeoutNanoseconds)389 aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
390                                                 aaudio_stream_state_t *nextState,
391                                                 int64_t timeoutNanoseconds)
392 {
393     aaudio_result_t result = updateStateMachine();
394     if (result != AAUDIO_OK) {
395         return result;
396     }
397 
398     int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
399     aaudio_stream_state_t state = getState();
400     while (state == currentState && timeoutNanoseconds > 0) {
401         if (durationNanos > timeoutNanoseconds) {
402             durationNanos = timeoutNanoseconds;
403         }
404         AudioClock::sleepForNanos(durationNanos);
405         timeoutNanoseconds -= durationNanos;
406 
407         aaudio_result_t result = updateStateMachine();
408         if (result != AAUDIO_OK) {
409             return result;
410         }
411 
412         state = getState();
413     }
414     if (nextState != nullptr) {
415         *nextState = state;
416     }
417     return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
418 }
419 
420 // This registers the callback thread with the server before
421 // passing control to the app. This gives the server an opportunity to boost
422 // the thread's performance characteristics.
wrapUserThread()423 void* AudioStream::wrapUserThread() {
424     void* procResult = nullptr;
425     mThreadRegistrationResult = registerThread();
426     if (mThreadRegistrationResult == AAUDIO_OK) {
427         // Run callback loop. This may take a very long time.
428         procResult = mThreadProc(mThreadArg);
429         mThreadRegistrationResult = unregisterThread();
430     }
431     return procResult;
432 }
433 
434 
435 // This is the entry point for the new thread created by createThread_l().
436 // It converts the 'C' function call to a C++ method call.
AudioStream_internalThreadProc(void * threadArg)437 static void* AudioStream_internalThreadProc(void* threadArg) {
438     AudioStream *audioStream = (AudioStream *) threadArg;
439     // Prevent the stream from being deleted while being used.
440     // This is just for extra safety. It is probably not needed because
441     // this callback should be joined before the stream is closed.
442     android::sp<AudioStream> protectedStream(audioStream);
443     // Balance the incStrong() in createThread_l().
444     protectedStream->decStrong(nullptr);
445     return protectedStream->wrapUserThread();
446 }
447 
448 // This is not exposed in the API.
449 // But it is still used internally to implement callbacks for MMAP mode.
createThread_l(int64_t periodNanoseconds,aaudio_audio_thread_proc_t threadProc,void * threadArg)450 aaudio_result_t AudioStream::createThread_l(int64_t periodNanoseconds,
451                                             aaudio_audio_thread_proc_t threadProc,
452                                             void* threadArg)
453 {
454     if (mHasThread) {
455         ALOGD("%s() - previous thread was not joined, join now to be safe", __func__);
456         joinThread_l(nullptr);
457     }
458     if (threadProc == nullptr) {
459         return AAUDIO_ERROR_NULL;
460     }
461     // Pass input parameters to the background thread.
462     mThreadProc = threadProc;
463     mThreadArg = threadArg;
464     setPeriodNanoseconds(periodNanoseconds);
465     mHasThread = true;
466     // Prevent this object from getting deleted before the thread has a chance to create
467     // its strong pointer. Assume the thread will call decStrong().
468     this->incStrong(nullptr);
469     int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
470     if (err != 0) {
471         android::status_t status = -errno;
472         ALOGE("%s() - pthread_create() failed, %d", __func__, status);
473         this->decStrong(nullptr); // Because the thread won't do it.
474         mHasThread = false;
475         return AAudioConvert_androidToAAudioResult(status);
476     } else {
477         // TODO Use AAudioThread or maybe AndroidThread
478         // Name the thread with an increasing index, "AAudio_#", for debugging.
479         static std::atomic<uint32_t> nextThreadIndex{1};
480         char name[16]; // max length for a pthread_name
481         uint32_t index = nextThreadIndex++;
482         // Wrap the index so that we do not hit the 16 char limit
483         // and to avoid hard-to-read large numbers.
484         index = index % 100000;  // arbitrary
485         snprintf(name, sizeof(name), "AAudio_%u", index);
486         err = pthread_setname_np(mThread, name);
487         ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
488 
489         return AAUDIO_OK;
490     }
491 }
492 
joinThread(void ** returnArg)493 aaudio_result_t AudioStream::joinThread(void** returnArg) {
494     // This may get temporarily unlocked in the MMAP release() when joining callback threads.
495     std::lock_guard<std::mutex> lock(mStreamLock);
496     return joinThread_l(returnArg);
497 }
498 
499 // This must be called under mStreamLock.
joinThread_l(void ** returnArg)500 aaudio_result_t AudioStream::joinThread_l(void** returnArg) {
501     if (!mHasThread) {
502         ALOGD("joinThread() - but has no thread or already join()ed");
503         return AAUDIO_ERROR_INVALID_STATE;
504     }
505     aaudio_result_t result = AAUDIO_OK;
506     // If the callback is stopping the stream because the app passed back STOP
507     // then we don't need to join(). The thread is already about to exit.
508     if (!pthread_equal(pthread_self(), mThread)) {
509         // Called from an app thread. Not the callback.
510         // Unlock because the callback may be trying to stop the stream but is blocked.
511         mStreamLock.unlock();
512         int err = pthread_join(mThread, returnArg);
513         mStreamLock.lock();
514         if (err) {
515             ALOGE("%s() pthread_join() returns err = %d", __func__, err);
516             result = AAudioConvert_androidToAAudioResult(-err);
517         } else {
518             ALOGD("%s() pthread_join succeeded", __func__);
519             // Prevent joining a second time, which has undefined behavior.
520             mHasThread = false;
521         }
522     } else {
523         ALOGD("%s() pthread_join() called on itself!", __func__);
524     }
525     return (result != AAUDIO_OK) ? result : mThreadRegistrationResult;
526 }
527 
maybeCallDataCallback(void * audioData,int32_t numFrames)528 aaudio_data_callback_result_t AudioStream::maybeCallDataCallback(void *audioData,
529                                                                  int32_t numFrames) {
530     aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
531     AAudioStream_dataCallback dataCallback = getDataCallbackProc();
532     if (dataCallback != nullptr) {
533         // Store thread ID of caller to detect stop() and close() calls from callback.
534         pid_t expected = CALLBACK_THREAD_NONE;
535         if (mDataCallbackThread.compare_exchange_strong(expected, gettid())) {
536             result = (*dataCallback)(
537                     (AAudioStream *) this,
538                     getDataCallbackUserData(),
539                     audioData,
540                     numFrames);
541             mDataCallbackThread.store(CALLBACK_THREAD_NONE);
542         } else {
543             ALOGW("%s() data callback already running!", __func__);
544         }
545     }
546     return result;
547 }
548 
maybeCallErrorCallback(aaudio_result_t result)549 void AudioStream::maybeCallErrorCallback(aaudio_result_t result) {
550     AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
551     if (errorCallback != nullptr) {
552         // Store thread ID of caller to detect stop() and close() calls from callback.
553         pid_t expected = CALLBACK_THREAD_NONE;
554         if (mErrorCallbackThread.compare_exchange_strong(expected, gettid())) {
555             (*errorCallback)(
556                     (AAudioStream *) this,
557                     getErrorCallbackUserData(),
558                     result);
559             mErrorCallbackThread.store(CALLBACK_THREAD_NONE);
560         } else {
561             ALOGW("%s() error callback already running!", __func__);
562         }
563     }
564 }
565 
566 // Is this running on the same thread as a callback?
567 // Note: This cannot be implemented using a thread_local because that would
568 // require using a thread_local variable that is shared between streams.
569 // So a thread_local variable would prevent stopping or closing stream A from
570 // a callback on stream B, which is currently legal and not so terrible.
collidesWithCallback() const571 bool AudioStream::collidesWithCallback() const {
572     pid_t thisThread = gettid();
573     // Compare the current thread ID with the thread ID of the callback
574     // threads to see it they match. If so then this code is being
575     // called from one of the stream callback functions.
576     return ((mErrorCallbackThread.load() == thisThread)
577             || (mDataCallbackThread.load() == thisThread));
578 }
579 
580 #if AAUDIO_USE_VOLUME_SHAPER
applyVolumeShaper(const::android::media::VolumeShaper::Configuration & configuration,const::android::media::VolumeShaper::Operation & operation)581 ::android::binder::Status AudioStream::MyPlayerBase::applyVolumeShaper(
582         const ::android::media::VolumeShaper::Configuration& configuration,
583         const ::android::media::VolumeShaper::Operation& operation) {
584     android::sp<AudioStream> audioStream;
585     {
586         std::lock_guard<std::mutex> lock(mParentLock);
587         audioStream = mParent.promote();
588     }
589     if (audioStream) {
590         return audioStream->applyVolumeShaper(configuration, operation);
591     }
592     return android::NO_ERROR;
593 }
594 #endif
595 
setDuckAndMuteVolume(float duckAndMuteVolume)596 void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
597     ALOGD("%s() to %f", __func__, duckAndMuteVolume);
598     mDuckAndMuteVolume = duckAndMuteVolume;
599     doSetVolume(); // apply this change
600 }
601 
registerWithAudioManager(const android::sp<AudioStream> & parent)602 void AudioStream::MyPlayerBase::registerWithAudioManager(const android::sp<AudioStream>& parent) {
603     std::lock_guard<std::mutex> lock(mParentLock);
604     mParent = parent;
605     if (!mRegistered) {
606         init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(parent->getUsage()),
607             (audio_session_t)parent->getSessionId());
608         mRegistered = true;
609     }
610 }
611 
unregisterWithAudioManager()612 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
613     std::lock_guard<std::mutex> lock(mParentLock);
614     if (mRegistered) {
615         baseDestroy();
616         mRegistered = false;
617     }
618 }
619 
playerSetVolume()620 android::status_t AudioStream::MyPlayerBase::playerSetVolume() {
621     android::sp<AudioStream> audioStream;
622     {
623         std::lock_guard<std::mutex> lock(mParentLock);
624         audioStream = mParent.promote();
625     }
626     if (audioStream) {
627         // No pan and only left volume is taken into account from IPLayer interface
628         audioStream->setDuckAndMuteVolume(mVolumeMultiplierL  /* mPanMultiplierL */);
629     }
630     return android::NO_ERROR;
631 }
632 
destroy()633 void AudioStream::MyPlayerBase::destroy() {
634     unregisterWithAudioManager();
635 }
636 
637 }  // namespace aaudio
638