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