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