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