6464 lines · 216.3 KB · C++
RawDownload
/* //device/include/server/AudioFlinger/AudioFlinger.cpp**** Copyright 2007, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License");** you may not use this file except in compliance with the License.** You may obtain a copy of the License at****     http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/  #define LOG_TAG "AudioFlinger"//#define LOG_NDEBUG 0 #include <math.h>#include <signal.h>#include <sys/time.h>#include <sys/resource.h> #include <binder/IServiceManager.h>#include <utils/Log.h>#include <binder/Parcel.h>#include <binder/IPCThreadState.h>#include <utils/String16.h>#include <utils/threads.h> #include <cutils/properties.h> #include <media/AudioTrack.h>#include <media/AudioRecord.h> #include <private/media/AudioTrackShared.h>#include <private/media/AudioEffectShared.h>#include <hardware_legacy/AudioHardwareInterface.h> #include "AudioMixer.h"#include "AudioFlinger.h" #ifdef WITH_A2DP#include "A2dpAudioInterface.h"#endif #ifdef LVMX#include "lifevibes.h"#endif #include <media/EffectsFactoryApi.h>#include <media/EffectVisualizerApi.h> // ----------------------------------------------------------------------------// the sim build doesn't have gettid #ifndef HAVE_GETTID# define gettid getpid#endif // ---------------------------------------------------------------------------- extern const char * const gEffectLibPath; namespace android { static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";static const char* kHardwareLockedString = "Hardware lock is taken\n"; //static const nsecs_t kStandbyTimeInNsecs = seconds(3);static const float MAX_GAIN = 4096.0f;static const float MAX_GAIN_INT = 0x1000; // retry counts for buffer fill timeout// 50 * ~20msecs = 1 secondstatic const int8_t kMaxTrackRetries = 50;static const int8_t kMaxTrackStartupRetries = 50;// allow less retry attempts on direct output thread.// direct outputs can be a scarce resource in audio hardware and should// be released as quickly as possible.static const int8_t kMaxTrackRetriesDirect = 2; static const int kDumpLockRetries = 50;static const int kDumpLockSleep = 20000; static const nsecs_t kWarningThrottle = seconds(5);  #define AUDIOFLINGER_SECURITY_ENABLED 0 // ---------------------------------------------------------------------------- static bool recordingAllowed() {#ifndef HAVE_ANDROID_OS    return true;#endif#if AUDIOFLINGER_SECURITY_ENABLED    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;    bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));    if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");    return ok;#else    return true;#endif} static bool settingsAllowed() {#ifndef HAVE_ANDROID_OS    return true;#endif#if AUDIOFLINGER_SECURITY_ENABLED    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");    return ok;#else    return true;#endif} // ---------------------------------------------------------------------------- AudioFlinger::AudioFlinger()    : BnAudioFlinger(),        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1){    mHardwareStatus = AUDIO_HW_IDLE;     mAudioHardware = AudioHardwareInterface::create();     mHardwareStatus = AUDIO_HW_INIT;    if (mAudioHardware->initCheck() == NO_ERROR) {        // open 16-bit output stream for s/w mixer        mMode = AudioSystem::MODE_NORMAL;        setMode(mMode);         setMasterVolume(1.0f);        setMasterMute(false);    } else {        LOGE("Couldn't even initialize the stubbed audio hardware!");    }#ifdef LVMX    LifeVibes::init();    mLifeVibesClientPid = -1;#endif} AudioFlinger::~AudioFlinger(){    while (!mRecordThreads.isEmpty()) {        // closeInput() will remove first entry from mRecordThreads        closeInput(mRecordThreads.keyAt(0));    }    while (!mPlaybackThreads.isEmpty()) {        // closeOutput() will remove first entry from mPlaybackThreads        closeOutput(mPlaybackThreads.keyAt(0));    }    if (mAudioHardware) {        delete mAudioHardware;    }}   status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args){    const size_t SIZE = 256;    char buffer[SIZE];    String8 result;     result.append("Clients:\n");    for (size_t i = 0; i < mClients.size(); ++i) {        wp<Client> wClient = mClients.valueAt(i);        if (wClient != 0) {            sp<Client> client = wClient.promote();            if (client != 0) {                snprintf(buffer, SIZE, "  pid: %d\n", client->pid());                result.append(buffer);            }        }    }    write(fd, result.string(), result.size());    return NO_ERROR;}  status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args){    const size_t SIZE = 256;    char buffer[SIZE];    String8 result;    int hardwareStatus = mHardwareStatus;     snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);    result.append(buffer);    write(fd, result.string(), result.size());    return NO_ERROR;} status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args){    const size_t SIZE = 256;    char buffer[SIZE];    String8 result;    snprintf(buffer, SIZE, "Permission Denial: "            "can't dump AudioFlinger from pid=%d, uid=%d\n",            IPCThreadState::self()->getCallingPid(),            IPCThreadState::self()->getCallingUid());    result.append(buffer);    write(fd, result.string(), result.size());    return NO_ERROR;} static bool tryLock(Mutex& mutex){    bool locked = false;    for (int i = 0; i < kDumpLockRetries; ++i) {        if (mutex.tryLock() == NO_ERROR) {            locked = true;            break;        }        usleep(kDumpLockSleep);    }    return locked;} status_t AudioFlinger::dump(int fd, const Vector<String16>& args){    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {        dumpPermissionDenial(fd, args);    } else {        // get state of hardware lock        bool hardwareLocked = tryLock(mHardwareLock);        if (!hardwareLocked) {            String8 result(kHardwareLockedString);            write(fd, result.string(), result.size());        } else {            mHardwareLock.unlock();        }         bool locked = tryLock(mLock);         // failed to lock - AudioFlinger is probably deadlocked        if (!locked) {            String8 result(kDeadlockedString);            write(fd, result.string(), result.size());        }         dumpClients(fd, args);        dumpInternals(fd, args);         // dump playback threads        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {            mPlaybackThreads.valueAt(i)->dump(fd, args);        }         // dump record threads        for (size_t i = 0; i < mRecordThreads.size(); i++) {            mRecordThreads.valueAt(i)->dump(fd, args);        }         if (mAudioHardware) {            mAudioHardware->dumpState(fd, args);        }        if (locked) mLock.unlock();    }    return NO_ERROR;}  // IAudioFlinger interface  sp<IAudioTrack> AudioFlinger::createTrack(        pid_t pid,        int streamType,        uint32_t sampleRate,        int format,        int channelCount,        int frameCount,        uint32_t flags,        const sp<IMemory>& sharedBuffer,        int output,        int *sessionId,        status_t *status){    sp<PlaybackThread::Track> track;    sp<TrackHandle> trackHandle;    sp<Client> client;    wp<Client> wclient;    status_t lStatus;    int lSessionId;     if (streamType >= AudioSystem::NUM_STREAM_TYPES) {        LOGE("invalid stream type");        lStatus = BAD_VALUE;        goto Exit;    }     {        Mutex::Autolock _l(mLock);        PlaybackThread *thread = checkPlaybackThread_l(output);        PlaybackThread *effectThread = NULL;        if (thread == NULL) {            LOGE("unknown output thread");            lStatus = BAD_VALUE;            goto Exit;        }         wclient = mClients.valueFor(pid);         if (wclient != NULL) {            client = wclient.promote();        } else {            client = new Client(this, pid);            mClients.add(pid, client);        }         LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);        if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);                if (mPlaybackThreads.keyAt(i) != output) {                    // prevent same audio session on different output threads                    uint32_t sessions = t->hasAudioSession(*sessionId);                    if (sessions & PlaybackThread::TRACK_SESSION) {                        lStatus = BAD_VALUE;                        goto Exit;                    }                    // check if an effect with same session ID is waiting for a track to be created                    if (sessions & PlaybackThread::EFFECT_SESSION) {                        effectThread = t.get();                    }                }            }            lSessionId = *sessionId;        } else {            // if no audio session id is provided, create one here            lSessionId = nextUniqueId();            if (sessionId != NULL) {                *sessionId = lSessionId;            }        }        LOGV("createTrack() lSessionId: %d", lSessionId);         track = thread->createTrack_l(client, streamType, sampleRate, format,                channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);         // move effect chain to this output thread if an effect on same session was waiting        // for a track to be created        if (lStatus == NO_ERROR && effectThread != NULL) {            Mutex::Autolock _dl(thread->mLock);            Mutex::Autolock _sl(effectThread->mLock);            moveEffectChain_l(lSessionId, effectThread, thread, true);        }    }    if (lStatus == NO_ERROR) {        trackHandle = new TrackHandle(track);    } else {        // remove local strong reference to Client before deleting the Track so that the Client        // destructor is called by the TrackBase destructor with mLock held        client.clear();        track.clear();    } Exit:    if(status) {        *status = lStatus;    }    return trackHandle;} uint32_t AudioFlinger::sampleRate(int output) const{    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        LOGW("sampleRate() unknown thread %d", output);        return 0;    }    return thread->sampleRate();} int AudioFlinger::channelCount(int output) const{    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        LOGW("channelCount() unknown thread %d", output);        return 0;    }    return thread->channelCount();} int AudioFlinger::format(int output) const{    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        LOGW("format() unknown thread %d", output);        return 0;    }    return thread->format();} size_t AudioFlinger::frameCount(int output) const{    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        LOGW("frameCount() unknown thread %d", output);        return 0;    }    return thread->frameCount();} uint32_t AudioFlinger::latency(int output) const{    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        LOGW("latency() unknown thread %d", output);        return 0;    }    return thread->latency();} status_t AudioFlinger::setMasterVolume(float value){    // check calling permissions    if (!settingsAllowed()) {        return PERMISSION_DENIED;    }     // when hw supports master volume, don't scale in sw mixer    AutoMutex lock(mHardwareLock);    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;    if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {        value = 1.0f;    }    mHardwareStatus = AUDIO_HW_IDLE;     mMasterVolume = value;    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)       mPlaybackThreads.valueAt(i)->setMasterVolume(value);     return NO_ERROR;} status_t AudioFlinger::setMode(int mode){    status_t ret;     // check calling permissions    if (!settingsAllowed()) {        return PERMISSION_DENIED;    }    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {        LOGW("Illegal value: setMode(%d)", mode);        return BAD_VALUE;    }     { // scope for the lock        AutoMutex lock(mHardwareLock);        mHardwareStatus = AUDIO_HW_SET_MODE;        ret = mAudioHardware->setMode(mode);        mHardwareStatus = AUDIO_HW_IDLE;    }     if (NO_ERROR == ret) {        Mutex::Autolock _l(mLock);        mMode = mode;        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)           mPlaybackThreads.valueAt(i)->setMode(mode);#ifdef LVMX        LifeVibes::setMode(mode);#endif    }     return ret;} status_t AudioFlinger::setMicMute(bool state){    // check calling permissions    if (!settingsAllowed()) {        return PERMISSION_DENIED;    }     AutoMutex lock(mHardwareLock);    mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;    status_t ret = mAudioHardware->setMicMute(state);    mHardwareStatus = AUDIO_HW_IDLE;    return ret;} bool AudioFlinger::getMicMute() const

Lines 1–500 of 6464.