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