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