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