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