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 #include <aaudio/AAudio.h>
24
25 #include "AudioStreamBuilder.h"
26 #include "AudioStream.h"
27 #include "AudioClock.h"
28
29 using namespace aaudio;
30
31
32 // Sequential number assigned to streams solely for debugging purposes.
AAudio_getNextStreamId()33 static aaudio_stream_id_t AAudio_getNextStreamId() {
34 static std::atomic <aaudio_stream_id_t> nextStreamId{1};
35 return nextStreamId++;
36 }
37
AudioStream()38 AudioStream::AudioStream()
39 : mPlayerBase(new MyPlayerBase(this))
40 , mStreamId(AAudio_getNextStreamId())
41 {
42 // mThread is a pthread_t of unknown size so we need memset.
43 memset(&mThread, 0, sizeof(mThread));
44 setPeriodNanoseconds(0);
45 }
46
~AudioStream()47 AudioStream::~AudioStream() {
48 // If the stream is deleted when OPEN or in use then audio resources will leak.
49 // This would indicate an internal error. So we want to find this ASAP.
50 LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
51 || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
52 || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
53 "~AudioStream() - still in use, state = %s",
54 AAudio_convertStreamStateToText(getState()));
55
56 mPlayerBase->clearParentReference(); // remove reference to this AudioStream
57 }
58
open(const AudioStreamBuilder & builder)59 aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
60 {
61 // Call here as well because the AAudioService will call this without calling build().
62 aaudio_result_t result = builder.validate();
63 if (result != AAUDIO_OK) {
64 return result;
65 }
66
67 // Copy parameters from the Builder because the Builder may be deleted after this call.
68 // TODO AudioStream should be a subclass of AudioStreamParameters
69 mSamplesPerFrame = builder.getSamplesPerFrame();
70 mSampleRate = builder.getSampleRate();
71 mDeviceId = builder.getDeviceId();
72 mFormat = builder.getFormat();
73 mSharingMode = builder.getSharingMode();
74 mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
75 mPerformanceMode = builder.getPerformanceMode();
76
77 mUsage = builder.getUsage();
78 if (mUsage == AAUDIO_UNSPECIFIED) {
79 mUsage = AAUDIO_USAGE_MEDIA;
80 }
81 mContentType = builder.getContentType();
82 if (mContentType == AAUDIO_UNSPECIFIED) {
83 mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
84 }
85 mInputPreset = builder.getInputPreset();
86 if (mInputPreset == AAUDIO_UNSPECIFIED) {
87 mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
88 }
89 mAllowedCapturePolicy = builder.getAllowedCapturePolicy();
90 if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
91 mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
92 }
93
94 // callbacks
95 mFramesPerDataCallback = builder.getFramesPerDataCallback();
96 mDataCallbackProc = builder.getDataCallbackProc();
97 mErrorCallbackProc = builder.getErrorCallbackProc();
98 mDataCallbackUserData = builder.getDataCallbackUserData();
99 mErrorCallbackUserData = builder.getErrorCallbackUserData();
100
101 return AAUDIO_OK;
102 }
103
systemStart()104 aaudio_result_t AudioStream::systemStart() {
105 std::lock_guard<std::mutex> lock(mStreamLock);
106
107 if (collidesWithCallback()) {
108 ALOGE("%s cannot be called from a callback!", __func__);
109 return AAUDIO_ERROR_INVALID_STATE;
110 }
111
112 aaudio_result_t result = requestStart();
113 if (result == AAUDIO_OK) {
114 // We only call this for logging in "dumpsys audio". So ignore return code.
115 (void) mPlayerBase->start();
116 }
117 return result;
118 }
119
systemPause()120 aaudio_result_t AudioStream::systemPause() {
121 std::lock_guard<std::mutex> lock(mStreamLock);
122
123 if (!isPauseSupported()) {
124 return AAUDIO_ERROR_UNIMPLEMENTED;
125 }
126
127 if (collidesWithCallback()) {
128 ALOGE("%s cannot be called from a callback!", __func__);
129 return AAUDIO_ERROR_INVALID_STATE;
130 }
131
132 switch (getState()) {
133 // Proceed with pausing.
134 case AAUDIO_STREAM_STATE_STARTING:
135 case AAUDIO_STREAM_STATE_STARTED:
136 case AAUDIO_STREAM_STATE_DISCONNECTED:
137 break;
138
139 // Transition from one inactive state to another.
140 case AAUDIO_STREAM_STATE_OPEN:
141 case AAUDIO_STREAM_STATE_STOPPED:
142 case AAUDIO_STREAM_STATE_FLUSHED:
143 setState(AAUDIO_STREAM_STATE_PAUSED);
144 return AAUDIO_OK;
145
146 // Redundant?
147 case AAUDIO_STREAM_STATE_PAUSING:
148 case AAUDIO_STREAM_STATE_PAUSED:
149 return AAUDIO_OK;
150
151 // Don't interfere with transitional states or when closed.
152 case AAUDIO_STREAM_STATE_STOPPING:
153 case AAUDIO_STREAM_STATE_FLUSHING:
154 case AAUDIO_STREAM_STATE_CLOSING:
155 case AAUDIO_STREAM_STATE_CLOSED:
156 default:
157 ALOGW("safePause() stream not running, state = %s",
158 AAudio_convertStreamStateToText(getState()));
159 return AAUDIO_ERROR_INVALID_STATE;
160 }
161
162 aaudio_result_t result = requestPause();
163 if (result == AAUDIO_OK) {
164 // We only call this for logging in "dumpsys audio". So ignore return code.
165 (void) mPlayerBase->pause();
166 }
167 return result;
168 }
169
safeFlush()170 aaudio_result_t AudioStream::safeFlush() {
171 if (!isFlushSupported()) {
172 ALOGE("flush not supported for this stream");
173 return AAUDIO_ERROR_UNIMPLEMENTED;
174 }
175
176 std::lock_guard<std::mutex> lock(mStreamLock);
177 if (collidesWithCallback()) {
178 ALOGE("stream cannot be flushed from a callback!");
179 return AAUDIO_ERROR_INVALID_STATE;
180 }
181
182 aaudio_result_t result = AAudio_isFlushAllowed(getState());
183 if (result != AAUDIO_OK) {
184 return result;
185 }
186
187 return requestFlush();
188 }
189
systemStopFromCallback()190 aaudio_result_t AudioStream::systemStopFromCallback() {
191 std::lock_guard<std::mutex> lock(mStreamLock);
192 aaudio_result_t result = safeStop();
193 if (result == AAUDIO_OK) {
194 // We only call this for logging in "dumpsys audio". So ignore return code.
195 (void) mPlayerBase->stop();
196 }
197 return result;
198 }
199
systemStopFromApp()200 aaudio_result_t AudioStream::systemStopFromApp() {
201 std::lock_guard<std::mutex> lock(mStreamLock);
202 if (collidesWithCallback()) {
203 ALOGE("stream cannot be stopped by calling from a callback!");
204 return AAUDIO_ERROR_INVALID_STATE;
205 }
206 aaudio_result_t result = safeStop();
207 if (result == AAUDIO_OK) {
208 // We only call this for logging in "dumpsys audio". So ignore return code.
209 (void) mPlayerBase->stop();
210 }
211 return result;
212 }
213
214 // This must be called under mStreamLock.
safeStop()215 aaudio_result_t AudioStream::safeStop() {
216
217 switch (getState()) {
218 // Proceed with stopping.
219 case AAUDIO_STREAM_STATE_STARTING:
220 case AAUDIO_STREAM_STATE_STARTED:
221 case AAUDIO_STREAM_STATE_DISCONNECTED:
222 break;
223
224 // Transition from one inactive state to another.
225 case AAUDIO_STREAM_STATE_OPEN:
226 case AAUDIO_STREAM_STATE_PAUSED:
227 case AAUDIO_STREAM_STATE_FLUSHED:
228 setState(AAUDIO_STREAM_STATE_STOPPED);
229 return AAUDIO_OK;
230
231 // Redundant?
232 case AAUDIO_STREAM_STATE_STOPPING:
233 case AAUDIO_STREAM_STATE_STOPPED:
234 return AAUDIO_OK;
235
236 // Don't interfere with transitional states or when closed.
237 case AAUDIO_STREAM_STATE_PAUSING:
238 case AAUDIO_STREAM_STATE_FLUSHING:
239 case AAUDIO_STREAM_STATE_CLOSING:
240 case AAUDIO_STREAM_STATE_CLOSED:
241 default:
242 ALOGW("%s() stream not running, state = %s", __func__,
243 AAudio_convertStreamStateToText(getState()));
244 return AAUDIO_ERROR_INVALID_STATE;
245 }
246
247 return requestStop();
248 }
249
safeClose()250 aaudio_result_t AudioStream::safeClose() {
251 // This get temporarily unlocked in the close when joining callback threads.
252 std::lock_guard<std::mutex> lock(mStreamLock);
253 if (collidesWithCallback()) {
254 ALOGE("%s cannot be called from a callback!", __func__);
255 return AAUDIO_ERROR_INVALID_STATE;
256 }
257 return close();
258 }
259
setState(aaudio_stream_state_t state)260 void AudioStream::setState(aaudio_stream_state_t state) {
261 ALOGV("%s(%d) from %d to %d", __func__, getId(), mState, state);
262 // CLOSED is a final state
263 if (mState == AAUDIO_STREAM_STATE_CLOSED) {
264 ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
265
266 // Once DISCONNECTED, we can only move to CLOSED state.
267 } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
268 && state != AAUDIO_STREAM_STATE_CLOSED) {
269 ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
270
271 } else {
272 mState = state;
273 }
274 }
275
waitForStateChange(aaudio_stream_state_t currentState,aaudio_stream_state_t * nextState,int64_t timeoutNanoseconds)276 aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentState,
277 aaudio_stream_state_t *nextState,
278 int64_t timeoutNanoseconds)
279 {
280 aaudio_result_t result = updateStateMachine();
281 if (result != AAUDIO_OK) {
282 return result;
283 }
284
285 int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
286 aaudio_stream_state_t state = getState();
287 while (state == currentState && timeoutNanoseconds > 0) {
288 if (durationNanos > timeoutNanoseconds) {
289 durationNanos = timeoutNanoseconds;
290 }
291 AudioClock::sleepForNanos(durationNanos);
292 timeoutNanoseconds -= durationNanos;
293
294 aaudio_result_t result = updateStateMachine();
295 if (result != AAUDIO_OK) {
296 return result;
297 }
298
299 state = getState();
300 }
301 if (nextState != nullptr) {
302 *nextState = state;
303 }
304 return (state == currentState) ? AAUDIO_ERROR_TIMEOUT : AAUDIO_OK;
305 }
306
307 // This registers the callback thread with the server before
308 // passing control to the app. This gives the server an opportunity to boost
309 // the thread's performance characteristics.
wrapUserThread()310 void* AudioStream::wrapUserThread() {
311 void* procResult = nullptr;
312 mThreadRegistrationResult = registerThread();
313 if (mThreadRegistrationResult == AAUDIO_OK) {
314 // Run callback loop. This may take a very long time.
315 procResult = mThreadProc(mThreadArg);
316 mThreadRegistrationResult = unregisterThread();
317 }
318 return procResult;
319 }
320
321 // This is the entry point for the new thread created by createThread().
322 // It converts the 'C' function call to a C++ method call.
AudioStream_internalThreadProc(void * threadArg)323 static void* AudioStream_internalThreadProc(void* threadArg) {
324 AudioStream *audioStream = (AudioStream *) threadArg;
325 return audioStream->wrapUserThread();
326 }
327
328 // This is not exposed in the API.
329 // But it is still used internally to implement callbacks for MMAP mode.
createThread(int64_t periodNanoseconds,aaudio_audio_thread_proc_t threadProc,void * threadArg)330 aaudio_result_t AudioStream::createThread(int64_t periodNanoseconds,
331 aaudio_audio_thread_proc_t threadProc,
332 void* threadArg)
333 {
334 if (mHasThread) {
335 ALOGE("createThread() - mHasThread already true");
336 return AAUDIO_ERROR_INVALID_STATE;
337 }
338 if (threadProc == nullptr) {
339 return AAUDIO_ERROR_NULL;
340 }
341 // Pass input parameters to the background thread.
342 mThreadProc = threadProc;
343 mThreadArg = threadArg;
344 setPeriodNanoseconds(periodNanoseconds);
345 int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
346 if (err != 0) {
347 android::status_t status = -errno;
348 ALOGE("createThread() - pthread_create() failed, %d", status);
349 return AAudioConvert_androidToAAudioResult(status);
350 } else {
351 // TODO Use AAudioThread or maybe AndroidThread
352 // Name the thread with an increasing index, "AAudio_#", for debugging.
353 static std::atomic<uint32_t> nextThreadIndex{1};
354 char name[16]; // max length for a pthread_name
355 uint32_t index = nextThreadIndex++;
356 // Wrap the index so that we do not hit the 16 char limit
357 // and to avoid hard-to-read large numbers.
358 index = index % 100000; // arbitrary
359 snprintf(name, sizeof(name), "AAudio_%u", index);
360 err = pthread_setname_np(mThread, name);
361 ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
362
363 mHasThread = true;
364 return AAUDIO_OK;
365 }
366 }
367
368 // This must be called under mStreamLock.
joinThread(void ** returnArg,int64_t timeoutNanoseconds __unused)369 aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused)
370 {
371 if (!mHasThread) {
372 ALOGE("joinThread() - but has no thread");
373 return AAUDIO_ERROR_INVALID_STATE;
374 }
375 aaudio_result_t result = AAUDIO_OK;
376 // If the callback is stopping the stream because the app passed back STOP
377 // then we don't need to join(). The thread is already about to exit.
378 if (pthread_self() != mThread) {
379 // Called from an app thread. Not the callback.
380 // Unlock because the callback may be trying to stop the stream but is blocked.
381 mStreamLock.unlock();
382 #if 0
383 // TODO implement equivalent of pthread_timedjoin_np()
384 struct timespec abstime;
385 int err = pthread_timedjoin_np(mThread, returnArg, &abstime);
386 #else
387 int err = pthread_join(mThread, returnArg);
388 #endif
389 mStreamLock.lock();
390 if (err) {
391 ALOGE("%s() pthread_join() returns err = %d", __func__, err);
392 result = AAudioConvert_androidToAAudioResult(-err);
393 }
394 }
395 // This must be set false so that the callback thread can be created
396 // when the stream is restarted.
397 mHasThread = false;
398 return (result != AAUDIO_OK) ? result : mThreadRegistrationResult;
399 }
400
maybeCallDataCallback(void * audioData,int32_t numFrames)401 aaudio_data_callback_result_t AudioStream::maybeCallDataCallback(void *audioData,
402 int32_t numFrames) {
403 aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
404 AAudioStream_dataCallback dataCallback = getDataCallbackProc();
405 if (dataCallback != nullptr) {
406 // Store thread ID of caller to detect stop() and close() calls from callback.
407 pid_t expected = CALLBACK_THREAD_NONE;
408 if (mDataCallbackThread.compare_exchange_strong(expected, gettid())) {
409 result = (*dataCallback)(
410 (AAudioStream *) this,
411 getDataCallbackUserData(),
412 audioData,
413 numFrames);
414 mDataCallbackThread.store(CALLBACK_THREAD_NONE);
415 } else {
416 ALOGW("%s() data callback already running!", __func__);
417 }
418 }
419 return result;
420 }
421
maybeCallErrorCallback(aaudio_result_t result)422 void AudioStream::maybeCallErrorCallback(aaudio_result_t result) {
423 AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
424 if (errorCallback != nullptr) {
425 // Store thread ID of caller to detect stop() and close() calls from callback.
426 pid_t expected = CALLBACK_THREAD_NONE;
427 if (mErrorCallbackThread.compare_exchange_strong(expected, gettid())) {
428 (*errorCallback)(
429 (AAudioStream *) this,
430 getErrorCallbackUserData(),
431 result);
432 mErrorCallbackThread.store(CALLBACK_THREAD_NONE);
433 } else {
434 ALOGW("%s() error callback already running!", __func__);
435 }
436 }
437 }
438
439 // Is this running on the same thread as a callback?
440 // Note: This cannot be implemented using a thread_local because that would
441 // require using a thread_local variable that is shared between streams.
442 // So a thread_local variable would prevent stopping or closing stream A from
443 // a callback on stream B, which is currently legal and not so terrible.
collidesWithCallback() const444 bool AudioStream::collidesWithCallback() const {
445 pid_t thisThread = gettid();
446 // Compare the current thread ID with the thread ID of the callback
447 // threads to see it they match. If so then this code is being
448 // called from one of the stream callback functions.
449 return ((mErrorCallbackThread.load() == thisThread)
450 || (mDataCallbackThread.load() == thisThread));
451 }
452
453 #if AAUDIO_USE_VOLUME_SHAPER
applyVolumeShaper(const android::media::VolumeShaper::Configuration & configuration __unused,const android::media::VolumeShaper::Operation & operation __unused)454 android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
455 const android::media::VolumeShaper::Configuration& configuration __unused,
456 const android::media::VolumeShaper::Operation& operation __unused) {
457 ALOGW("applyVolumeShaper() is not supported");
458 return android::media::VolumeShaper::Status::ok();
459 }
460 #endif
461
setDuckAndMuteVolume(float duckAndMuteVolume)462 void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
463 ALOGD("%s() to %f", __func__, duckAndMuteVolume);
464 mDuckAndMuteVolume = duckAndMuteVolume;
465 doSetVolume(); // apply this change
466 }
467
MyPlayerBase(AudioStream * parent)468 AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
469 }
470
~MyPlayerBase()471 AudioStream::MyPlayerBase::~MyPlayerBase() {
472 }
473
registerWithAudioManager()474 void AudioStream::MyPlayerBase::registerWithAudioManager() {
475 if (!mRegistered) {
476 init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
477 mRegistered = true;
478 }
479 }
480
unregisterWithAudioManager()481 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
482 if (mRegistered) {
483 baseDestroy();
484 mRegistered = false;
485 }
486 }
487
destroy()488 void AudioStream::MyPlayerBase::destroy() {
489 unregisterWithAudioManager();
490 }
491