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