Home | History | Annotate | Download | only in core
      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 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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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.
    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 
    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 
    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 
    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.
    413 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
    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 
    431 void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
    432     ALOGD("%s() to %f", __func__, duckAndMuteVolume);
    433     mDuckAndMuteVolume = duckAndMuteVolume;
    434     doSetVolume(); // apply this change
    435 }
    436 
    437 AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
    438 }
    439 
    440 AudioStream::MyPlayerBase::~MyPlayerBase() {
    441     ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
    442 }
    443 
    444 void AudioStream::MyPlayerBase::registerWithAudioManager() {
    445     if (!mRegistered) {
    446         init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
    447         mRegistered = true;
    448     }
    449 }
    450 
    451 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
    452     if (mRegistered) {
    453         baseDestroy();
    454         mRegistered = false;
    455     }
    456 }
    457 
    458 void AudioStream::MyPlayerBase::destroy() {
    459     unregisterWithAudioManager();
    460 }
    461