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