xref: /aosp_15_r20/frameworks/av/media/libaaudio/src/core/AudioStream.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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         // We only call this for logging in "dumpsys audio". So ignore return code.
210         (void) mPlayerBase->startWithStatus(getDeviceIds());
211     }
212     return result;
213 }
214 
systemPause()215 aaudio_result_t AudioStream::systemPause() {
216 
217     if (!isPauseSupported()) {
218         return AAUDIO_ERROR_UNIMPLEMENTED;
219     }
220 
221     if (collidesWithCallback()) {
222         ALOGE("%s cannot be called from a callback!", __func__);
223         return AAUDIO_ERROR_INVALID_STATE;
224     }
225 
226     std::lock_guard<std::mutex> lock(mStreamLock);
227     switch (getState()) {
228         // Proceed with pausing.
229         case AAUDIO_STREAM_STATE_STARTING:
230         case AAUDIO_STREAM_STATE_STARTED:
231             break;
232 
233         case AAUDIO_STREAM_STATE_DISCONNECTED:
234             // This must not happen after deprecating AAUDIO_STREAM_STATE_DISCONNECTED
235             ALOGE("%s, unexpected state = AAUDIO_STREAM_STATE_DISCONNECTED", __func__);
236             break;
237 
238             // Transition from one inactive state to another.
239         case AAUDIO_STREAM_STATE_OPEN:
240         case AAUDIO_STREAM_STATE_STOPPED:
241         case AAUDIO_STREAM_STATE_FLUSHED:
242             setState(AAUDIO_STREAM_STATE_PAUSED);
243             return AAUDIO_OK;
244 
245             // Redundant?
246         case AAUDIO_STREAM_STATE_PAUSING:
247         case AAUDIO_STREAM_STATE_PAUSED:
248             return AAUDIO_OK;
249 
250             // Don't interfere with transitional states or when closed.
251         case AAUDIO_STREAM_STATE_STOPPING:
252         case AAUDIO_STREAM_STATE_FLUSHING:
253         case AAUDIO_STREAM_STATE_CLOSING:
254         case AAUDIO_STREAM_STATE_CLOSED:
255         default:
256             ALOGW("%s() stream not running, state = %s",
257                   __func__, AudioGlobal_convertStreamStateToText(getState()));
258             return AAUDIO_ERROR_INVALID_STATE;
259     }
260 
261     aaudio_result_t result = requestPause_l();
262     if (result == AAUDIO_OK) {
263         // We only call this for logging in "dumpsys audio". So ignore return code.
264         (void) mPlayerBase->pauseWithStatus();
265     }
266     return result;
267 }
268 
safeFlush()269 aaudio_result_t AudioStream::safeFlush() {
270     if (!isFlushSupported()) {
271         ALOGE("flush not supported for this stream");
272         return AAUDIO_ERROR_UNIMPLEMENTED;
273     }
274 
275     if (collidesWithCallback()) {
276         ALOGE("stream cannot be flushed from a callback!");
277         return AAUDIO_ERROR_INVALID_STATE;
278     }
279 
280     std::lock_guard<std::mutex> lock(mStreamLock);
281     aaudio_result_t result = AAudio_isFlushAllowed(getState());
282     if (result != AAUDIO_OK) {
283         return result;
284     }
285 
286     return requestFlush_l();
287 }
288 
systemStopInternal()289 aaudio_result_t AudioStream::systemStopInternal() {
290     std::lock_guard<std::mutex> lock(mStreamLock);
291     return systemStopInternal_l();
292 }
293 
systemStopInternal_l()294 aaudio_result_t AudioStream::systemStopInternal_l() {
295     aaudio_result_t result = safeStop_l();
296     if (result == AAUDIO_OK) {
297         // We only call this for logging in "dumpsys audio". So ignore return code.
298         (void) mPlayerBase->stopWithStatus();
299     }
300     return result;
301 }
302 
systemStopFromApp()303 aaudio_result_t AudioStream::systemStopFromApp() {
304     // This check can and should be done outside the lock.
305     if (collidesWithCallback()) {
306         ALOGE("stream cannot be stopped by calling from a callback!");
307         return AAUDIO_ERROR_INVALID_STATE;
308     }
309     return systemStopInternal();
310 }
311 
safeStop_l()312 aaudio_result_t AudioStream::safeStop_l() {
313 
314     switch (getState()) {
315         // Proceed with stopping.
316         case AAUDIO_STREAM_STATE_STARTING:
317         case AAUDIO_STREAM_STATE_STARTED:
318             break;
319         case AAUDIO_STREAM_STATE_DISCONNECTED:
320             // This must not happen after deprecating AAUDIO_STREAM_STATE_DISCONNECTED
321             ALOGE("%s, unexpected state = AAUDIO_STREAM_STATE_DISCONNECTED", __func__);
322             break;
323 
324         // Transition from one inactive state to another.
325         case AAUDIO_STREAM_STATE_OPEN:
326         case AAUDIO_STREAM_STATE_PAUSED:
327         case AAUDIO_STREAM_STATE_FLUSHED:
328             setState(AAUDIO_STREAM_STATE_STOPPED);
329             return AAUDIO_OK;
330 
331         // Redundant?
332         case AAUDIO_STREAM_STATE_STOPPING:
333         case AAUDIO_STREAM_STATE_STOPPED:
334             return AAUDIO_OK;
335 
336         // Don't interfere with transitional states or when closed.
337         case AAUDIO_STREAM_STATE_PAUSING:
338         case AAUDIO_STREAM_STATE_FLUSHING:
339         case AAUDIO_STREAM_STATE_CLOSING:
340         case AAUDIO_STREAM_STATE_CLOSED:
341         default:
342             ALOGW("%s() stream not running, state = %s", __func__,
343                   AudioGlobal_convertStreamStateToText(getState()));
344             return AAUDIO_ERROR_INVALID_STATE;
345     }
346 
347     return requestStop_l();
348 }
349 
safeRelease()350 aaudio_result_t AudioStream::safeRelease() {
351     if (collidesWithCallback()) {
352         ALOGE("%s cannot be called from a callback!", __func__);
353         return AAUDIO_ERROR_INVALID_STATE;
354     }
355     // This may get temporarily unlocked in the MMAP release() when joining callback threads.
356     std::lock_guard<std::mutex> lock(mStreamLock);
357     if (getState() == AAUDIO_STREAM_STATE_CLOSING) { // already released?
358         return AAUDIO_OK;
359     }
360     return release_l();
361 }
362 
safeReleaseClose()363 aaudio_result_t AudioStream::safeReleaseClose() {
364     if (collidesWithCallback()) {
365         ALOGE("%s cannot be called from a callback!", __func__);
366         return AAUDIO_ERROR_INVALID_STATE;
367     }
368     return safeReleaseCloseInternal();
369 }
370 
safeReleaseCloseInternal()371 aaudio_result_t AudioStream::safeReleaseCloseInternal() {
372     // This get temporarily unlocked in the MMAP release() when joining callback threads.
373     std::lock_guard<std::mutex> lock(mStreamLock);
374     releaseCloseFinal_l();
375     return AAUDIO_OK;
376 }
377 
close_l()378 void AudioStream::close_l() {
379     // Releasing the stream will set the state to CLOSING.
380     assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
381     // setState() prevents a transition from CLOSING to any state other than CLOSED.
382     // State is checked by destructor.
383     setState(AAUDIO_STREAM_STATE_CLOSED);
384 
385     if (!mMetricsId.empty()) {
386         android::mediametrics::LogItem(mMetricsId)
387                 .set(AMEDIAMETRICS_PROP_FRAMESTRANSFERRED,
388                         getDirection() == AAUDIO_DIRECTION_INPUT ? getFramesWritten()
389                                                                  : getFramesRead())
390                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
391                 .record();
392     }
393 }
394 
setState(aaudio_stream_state_t state)395 void AudioStream::setState(aaudio_stream_state_t state) {
396     aaudio_stream_state_t oldState = mState.load();
397     ALOGD("%s(s#%d) from %d to %d", __func__, getId(), oldState, state);
398     if (state == oldState) {
399         return; // no change
400     }
401     LOG_ALWAYS_FATAL_IF(state == AAUDIO_STREAM_STATE_DISCONNECTED,
402                         "Disconnected state must be separated from mState");
403     // CLOSED is a final state
404     if (oldState == AAUDIO_STREAM_STATE_CLOSED) {
405         ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
406 
407     // Once CLOSING, we can only move to CLOSED state.
408     } else if (oldState == AAUDIO_STREAM_STATE_CLOSING
409                && state != AAUDIO_STREAM_STATE_CLOSED) {
410         ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
411 
412     } else {
413         mState.store(state);
414         // Wake up a wakeForStateChange thread if it exists.
415         syscall(SYS_futex, &mState, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
416     }
417 }
418 
setDisconnected()419 void AudioStream::setDisconnected() {
420     const bool old = isDisconnected();
421     ALOGD("%s setting disconnected, current disconnected: %d, current state: %d",
422           __func__, old, getState());
423     if (old) {
424         return; // no change, the stream is already disconnected
425     }
426     mDisconnected.store(true);
427     // Wake up a wakeForStateChange thread if it exists.
428     syscall(SYS_futex, &mState, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
429     // Track transition to DISCONNECTED state.
430     android::mediametrics::LogItem(mMetricsId)
431             .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
432             .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
433             .record();
434 }
435 
waitForStateChange(aaudio_stream_state_t currentState,aaudio_stream_state_t * nextState,int64_t timeoutNanoseconds)436 aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
437                                                 aaudio_stream_state_t *nextState,
438                                                 int64_t timeoutNanoseconds)
439 {
440     aaudio_result_t result = updateStateMachine();
441     if (result != AAUDIO_OK) {
442         return result;
443     }
444 
445     int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
446     aaudio_stream_state_t state = getStateExternal();
447     while (state == currentState && timeoutNanoseconds > 0) {
448         if (durationNanos > timeoutNanoseconds) {
449             durationNanos = timeoutNanoseconds;
450         }
451         struct timespec time;
452         time.tv_sec = durationNanos / AAUDIO_NANOS_PER_SECOND;
453         // Add the fractional nanoseconds.
454         time.tv_nsec = durationNanos - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
455 
456         // Sleep for durationNanos. If mState changes from the callback
457         // thread, this thread will wake up earlier.
458         syscall(SYS_futex, &mState, FUTEX_WAIT_PRIVATE, currentState, &time, NULL, 0);
459         timeoutNanoseconds -= durationNanos;
460         aaudio_result_t result = updateStateMachine();
461         if (result != AAUDIO_OK) {
462             return result;
463         }
464 
465         state = getStateExternal();
466     }
467     if (nextState != nullptr) {
468         *nextState = state;
469     }
470     return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
471 }
472 
473 // This registers the callback thread with the server before
474 // passing control to the app. This gives the server an opportunity to boost
475 // the thread's performance characteristics.
wrapUserThread()476 void* AudioStream::wrapUserThread() {
477     void* procResult = nullptr;
478     mThreadRegistrationResult = registerThread();
479     if (mThreadRegistrationResult == AAUDIO_OK) {
480         // Run callback loop. This may take a very long time.
481         procResult = mThreadProc(mThreadArg);
482         mThreadRegistrationResult = unregisterThread();
483     }
484     return procResult;
485 }
486 
487 
488 // This is the entry point for the new thread created by createThread_l().
489 // It converts the 'C' function call to a C++ method call.
AudioStream_internalThreadProc(void * threadArg)490 static void* AudioStream_internalThreadProc(void* threadArg) {
491     AudioStream *audioStream = (AudioStream *) threadArg;
492     // Prevent the stream from being deleted while being used.
493     // This is just for extra safety. It is probably not needed because
494     // this callback should be joined before the stream is closed.
495     android::sp<AudioStream> protectedStream(audioStream);
496     // Balance the incStrong() in createThread_l().
497     protectedStream->decStrong(nullptr);
498     return protectedStream->wrapUserThread();
499 }
500 
501 // This is not exposed in the API.
502 // 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)503 aaudio_result_t AudioStream::createThread_l(int64_t periodNanoseconds,
504                                             aaudio_audio_thread_proc_t threadProc,
505                                             void* threadArg)
506 {
507     if (mHasThread) {
508         ALOGD("%s() - previous thread was not joined, join now to be safe", __func__);
509         joinThread_l(nullptr);
510     }
511     if (threadProc == nullptr) {
512         return AAUDIO_ERROR_NULL;
513     }
514     // Pass input parameters to the background thread.
515     mThreadProc = threadProc;
516     mThreadArg = threadArg;
517     setPeriodNanoseconds(periodNanoseconds);
518     mHasThread = true;
519     // Prevent this object from getting deleted before the thread has a chance to create
520     // its strong pointer. Assume the thread will call decStrong().
521     this->incStrong(nullptr);
522     int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
523     if (err != 0) {
524         android::status_t status = -errno;
525         ALOGE("%s() - pthread_create() failed, %d", __func__, status);
526         this->decStrong(nullptr); // Because the thread won't do it.
527         mHasThread = false;
528         return AAudioConvert_androidToAAudioResult(status);
529     } else {
530         // TODO Use AAudioThread or maybe AndroidThread
531         // Name the thread with an increasing index, "AAudio_#", for debugging.
532         static std::atomic<uint32_t> nextThreadIndex{1};
533         char name[16]; // max length for a pthread_name
534         uint32_t index = nextThreadIndex++;
535         // Wrap the index so that we do not hit the 16 char limit
536         // and to avoid hard-to-read large numbers.
537         index = index % 100000;  // arbitrary
538         snprintf(name, sizeof(name), "AAudio_%u", index);
539         err = pthread_setname_np(mThread, name);
540         ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
541 
542         return AAUDIO_OK;
543     }
544 }
545 
joinThread(void ** returnArg)546 aaudio_result_t AudioStream::joinThread(void** returnArg) {
547     // This may get temporarily unlocked in the MMAP release() when joining callback threads.
548     std::lock_guard<std::mutex> lock(mStreamLock);
549     return joinThread_l(returnArg);
550 }
551 
552 // This must be called under mStreamLock.
joinThread_l(void ** returnArg)553 aaudio_result_t AudioStream::joinThread_l(void** returnArg) {
554     if (!mHasThread) {
555         ALOGD("joinThread() - but has no thread or already join()ed");
556         return AAUDIO_ERROR_INVALID_STATE;
557     }
558     aaudio_result_t result = AAUDIO_OK;
559     // If the callback is stopping the stream because the app passed back STOP
560     // then we don't need to join(). The thread is already about to exit.
561     if (!pthread_equal(pthread_self(), mThread)) {
562         // Called from an app thread. Not the callback.
563         // Unlock because the callback may be trying to stop the stream but is blocked.
564         mStreamLock.unlock();
565         int err = pthread_join(mThread, returnArg);
566         mStreamLock.lock();
567         if (err) {
568             ALOGE("%s() pthread_join() returns err = %d", __func__, err);
569             result = AAudioConvert_androidToAAudioResult(-err);
570         } else {
571             ALOGD("%s() pthread_join succeeded", __func__);
572             // Prevent joining a second time, which has undefined behavior.
573             mHasThread = false;
574         }
575     } else {
576         ALOGD("%s() pthread_join() called on itself!", __func__);
577     }
578     return (result != AAUDIO_OK) ? result : mThreadRegistrationResult;
579 }
580 
maybeCallDataCallback(void * audioData,int32_t numFrames)581 aaudio_data_callback_result_t AudioStream::maybeCallDataCallback(void *audioData,
582                                                                  int32_t numFrames) {
583     aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
584     AAudioStream_dataCallback dataCallback = getDataCallbackProc();
585     if (dataCallback != nullptr) {
586         // Store thread ID of caller to detect stop() and close() calls from callback.
587         pid_t expected = CALLBACK_THREAD_NONE;
588         if (mDataCallbackThread.compare_exchange_strong(expected, gettid())) {
589             result = (*dataCallback)(
590                     (AAudioStream *) this,
591                     getDataCallbackUserData(),
592                     audioData,
593                     numFrames);
594             mDataCallbackThread.store(CALLBACK_THREAD_NONE);
595         } else {
596             ALOGW("%s() data callback already running!", __func__);
597         }
598     }
599     return result;
600 }
601 
maybeCallErrorCallback(aaudio_result_t result)602 void AudioStream::maybeCallErrorCallback(aaudio_result_t result) {
603     AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
604     if (errorCallback != nullptr) {
605         // Store thread ID of caller to detect stop() and close() calls from callback.
606         pid_t expected = CALLBACK_THREAD_NONE;
607         if (mErrorCallbackThread.compare_exchange_strong(expected, gettid())) {
608             (*errorCallback)(
609                     (AAudioStream *) this,
610                     getErrorCallbackUserData(),
611                     result);
612             mErrorCallbackThread.store(CALLBACK_THREAD_NONE);
613         } else {
614             ALOGW("%s() error callback already running!", __func__);
615         }
616     }
617 }
618 
619 // Is this running on the same thread as a callback?
620 // Note: This cannot be implemented using a thread_local because that would
621 // require using a thread_local variable that is shared between streams.
622 // So a thread_local variable would prevent stopping or closing stream A from
623 // a callback on stream B, which is currently legal and not so terrible.
collidesWithCallback() const624 bool AudioStream::collidesWithCallback() const {
625     pid_t thisThread = gettid();
626     // Compare the current thread ID with the thread ID of the callback
627     // threads to see it they match. If so then this code is being
628     // called from one of the stream callback functions.
629     return ((mErrorCallbackThread.load() == thisThread)
630             || (mDataCallbackThread.load() == thisThread));
631 }
632 
633 #if AAUDIO_USE_VOLUME_SHAPER
applyVolumeShaper(const::android::media::VolumeShaper::Configuration & configuration,const::android::media::VolumeShaper::Operation & operation)634 ::android::binder::Status AudioStream::MyPlayerBase::applyVolumeShaper(
635         const ::android::media::VolumeShaper::Configuration& configuration,
636         const ::android::media::VolumeShaper::Operation& operation) {
637     android::sp<AudioStream> audioStream;
638     {
639         std::lock_guard<std::mutex> lock(mParentLock);
640         audioStream = mParent.promote();
641     }
642     if (audioStream) {
643         return audioStream->applyVolumeShaper(configuration, operation);
644     }
645     return android::NO_ERROR;
646 }
647 #endif
648 
setDuckAndMuteVolume(float duckAndMuteVolume)649 void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
650     ALOGD("%s() to %f", __func__, duckAndMuteVolume);
651     std::lock_guard<std::mutex> lock(mStreamLock);
652     mDuckAndMuteVolume = duckAndMuteVolume;
653     doSetVolume(); // apply this change
654 }
655 
getStateExternal() const656 aaudio_stream_state_t AudioStream::getStateExternal() const {
657     if (isDisconnected()) {
658         return AAUDIO_STREAM_STATE_DISCONNECTED;
659     }
660     return getState();
661 }
662 
getTagsAsString() const663 std::string AudioStream::getTagsAsString() const {
664     return android::base::Join(mTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
665 }
666 
registerWithAudioManager(const android::sp<AudioStream> & parent)667 void AudioStream::MyPlayerBase::registerWithAudioManager(const android::sp<AudioStream>& parent) {
668     std::lock_guard<std::mutex> lock(mParentLock);
669     mParent = parent;
670     if (!mRegistered) {
671         init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(parent->getUsage()),
672             (audio_session_t)parent->getSessionId());
673         mRegistered = true;
674     }
675 }
676 
unregisterWithAudioManager()677 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
678     std::lock_guard<std::mutex> lock(mParentLock);
679     if (mRegistered) {
680         baseDestroy();
681         mRegistered = false;
682     }
683 }
684 
playerSetVolume()685 android::status_t AudioStream::MyPlayerBase::playerSetVolume() {
686     android::sp<AudioStream> audioStream;
687     {
688         std::lock_guard<std::mutex> lock(mParentLock);
689         audioStream = mParent.promote();
690     }
691     if (audioStream) {
692         // No pan and only left volume is taken into account from IPLayer interface
693         audioStream->setDuckAndMuteVolume(mVolumeMultiplierL  /* mPanMultiplierL */);
694     }
695     return android::NO_ERROR;
696 }
697 
destroy()698 void AudioStream::MyPlayerBase::destroy() {
699     unregisterWithAudioManager();
700 }
701 
702 }  // namespace aaudio
703