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
29using namespace aaudio;
30
31AudioStream::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
39AudioStream::~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
52static 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
68aaudio_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
123aaudio_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
132aaudio_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
176aaudio_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
196aaudio_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
236aaudio_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
245void 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
261aaudio_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.
295void* 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.
308static 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.
315aaudio_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
353aaudio_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
370aaudio_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
391void 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.
413bool 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
423android::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
431void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
432    ALOGD("%s() to %f", __func__, duckAndMuteVolume);
433    mDuckAndMuteVolume = duckAndMuteVolume;
434    doSetVolume(); // apply this change
435}
436
437AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
438}
439
440AudioStream::MyPlayerBase::~MyPlayerBase() {
441    ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
442}
443
444void AudioStream::MyPlayerBase::registerWithAudioManager() {
445    if (!mRegistered) {
446        init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
447        mRegistered = true;
448    }
449}
450
451void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
452    if (mRegistered) {
453        baseDestroy();
454        mRegistered = false;
455    }
456}
457
458void AudioStream::MyPlayerBase::destroy() {
459    unregisterWithAudioManager();
460}
461