diff options
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 152 |
1 files changed, 125 insertions, 27 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index cb1f921..4e068b2 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -53,6 +53,7 @@ #include <audio_effects/effect_visualizer.h> #include <cpustats/ThreadCpuUsage.h> +#include <powermanager/PowerManager.h> // #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds // ---------------------------------------------------------------------------- @@ -887,14 +888,18 @@ void AudioFlinger::removeClient_l(pid_t pid) AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device) : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), - mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device) + mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), + mDevice(device) { + mDeathRecipient = new PMDeathRecipient(this); } AudioFlinger::ThreadBase::~ThreadBase() { mParamCond.broadcast(); mNewParameters.clear(); + // do not lock the mutex in destructor + releaseWakeLock_l(); } void AudioFlinger::ThreadBase::exit() @@ -1061,6 +1066,69 @@ status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String1 return NO_ERROR; } +void AudioFlinger::ThreadBase::acquireWakeLock() +{ + Mutex::Autolock _l(mLock); + acquireWakeLock_l(); +} + +void AudioFlinger::ThreadBase::acquireWakeLock_l() +{ + if (mPowerManager == 0) { + // use checkService() to avoid blocking if power service is not up yet + sp<IBinder> binder = + defaultServiceManager()->checkService(String16("power")); + if (binder == 0) { + LOGW("Thread %s cannot connect to the power manager service", mName); + } else { + mPowerManager = interface_cast<IPowerManager>(binder); + binder->linkToDeath(mDeathRecipient); + } + } + if (mPowerManager != 0) { + sp<IBinder> binder = new BBinder(); + status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, + binder, + String16(mName)); + if (status == NO_ERROR) { + mWakeLockToken = binder; + } + LOGV("acquireWakeLock_l() %s status %d", mName, status); + } +} + +void AudioFlinger::ThreadBase::releaseWakeLock() +{ + Mutex::Autolock _l(mLock); + releaseWakeLock(); +} + +void AudioFlinger::ThreadBase::releaseWakeLock_l() +{ + if (mWakeLockToken != 0) { + LOGV("releaseWakeLock_l() %s", mName); + if (mPowerManager != 0) { + mPowerManager->releaseWakeLock(mWakeLockToken, 0); + } + mWakeLockToken.clear(); + } +} + +void AudioFlinger::ThreadBase::clearPowerManager() +{ + Mutex::Autolock _l(mLock); + releaseWakeLock_l(); + mPowerManager.clear(); +} + +void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who) +{ + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + thread->clearPowerManager(); + } + LOGW("power manager service died !!!"); +} // ---------------------------------------------------------------------------- @@ -1072,6 +1140,8 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) { + snprintf(mName, kNameLength, "AudioOut_%d", id); + readOutputParameters(); mMasterVolume = mAudioFlinger->masterVolume(); @@ -1170,12 +1240,7 @@ status_t AudioFlinger::PlaybackThread::readyToRun() void AudioFlinger::PlaybackThread::onFirstRef() { - const size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, "Playback Thread %p", this); - - run(buffer, ANDROID_PRIORITY_URGENT_AUDIO); + run(mName, ANDROID_PRIORITY_URGENT_AUDIO); } // PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held @@ -1522,6 +1587,8 @@ bool AudioFlinger::MixerThread::threadLoop() const CentralTendencyStatistics& stats = cpu.statistics(); #endif + acquireWakeLock(); + while (!exitPending()) { #ifdef DEBUG_CPU_USAGE @@ -1585,10 +1652,12 @@ bool AudioFlinger::MixerThread::threadLoop() if (exitPending()) break; + releaseWakeLock_l(); // wait until we have something to do... LOGV("MixerThread %p TID %d going to sleep\n", this, gettid()); mWaitWorkCV.wait(mLock); LOGV("MixerThread %p TID %d waking up\n", this, gettid()); + acquireWakeLock_l(); if (mMasterMute == false) { char value[PROPERTY_VALUE_MAX]; @@ -1689,6 +1758,8 @@ bool AudioFlinger::MixerThread::threadLoop() mOutput->stream->common.standby(&mOutput->stream->common); } + releaseWakeLock(); + LOGV("MixerThread %p exiting", this); return false; } @@ -2176,6 +2247,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // hardware resources as soon as possible nsecs_t standbyDelay = microseconds(activeSleepTime*2); + acquireWakeLock(); + while (!exitPending()) { bool rampVolume; @@ -2215,9 +2288,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (exitPending()) break; + releaseWakeLock_l(); LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid()); mWaitWorkCV.wait(mLock); LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid()); + acquireWakeLock_l(); if (mMasterMute == false) { char value[PROPERTY_VALUE_MAX]; @@ -2436,6 +2511,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop() mOutput->stream->common.standby(&mOutput->stream->common); } + releaseWakeLock(); + LOGV("DirectOutputThread %p exiting", this); return false; } @@ -2561,6 +2638,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop() uint32_t sleepTime = idleSleepTime; Vector< sp<EffectChain> > effectChains; + acquireWakeLock(); + while (!exitPending()) { processConfigEvents(); @@ -2601,9 +2680,12 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (exitPending()) break; + releaseWakeLock_l(); LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid()); mWaitWorkCV.wait(mLock); LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid()); + acquireWakeLock_l(); + if (mMasterMute == false) { char value[PROPERTY_VALUE_MAX]; property_get("ro.audio.silent", value, "0"); @@ -2690,6 +2772,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop() effectChains.clear(); } + releaseWakeLock(); + return false; } @@ -3814,6 +3898,9 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { mType = ThreadBase::RECORD; + + snprintf(mName, kNameLength, "AudioIn_%d", id); + mReqChannelCount = popcount(channels); mReqSampleRate = sampleRate; readInputParameters(); @@ -3831,12 +3918,7 @@ AudioFlinger::RecordThread::~RecordThread() void AudioFlinger::RecordThread::onFirstRef() { - const size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, "Record Thread %p", this); - - run(buffer, PRIORITY_URGENT_AUDIO); + run(mName, PRIORITY_URGENT_AUDIO); } bool AudioFlinger::RecordThread::threadLoop() @@ -3847,6 +3929,8 @@ bool AudioFlinger::RecordThread::threadLoop() nsecs_t lastWarning = 0; + acquireWakeLock(); + // start recording while (!exitPending()) { @@ -3863,10 +3947,12 @@ bool AudioFlinger::RecordThread::threadLoop() if (exitPending()) break; + releaseWakeLock_l(); LOGV("RecordThread: loop stopping"); // go to sleep mWaitWorkCV.wait(mLock); LOGV("RecordThread: loop starting"); + acquireWakeLock_l(); continue; } if (mActiveTrack != 0) { @@ -3907,8 +3993,6 @@ bool AudioFlinger::RecordThread::threadLoop() for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } - // enable changes in effect chain - unlockEffectChains(effectChains); buffer.frameCount = mFrameCount; if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { @@ -4008,9 +4092,9 @@ bool AudioFlinger::RecordThread::threadLoop() // clear the overflow. usleep(kRecordThreadSleepUs); } - } else { - unlockEffectChains(effectChains); } + // enable changes in effect chain + unlockEffectChains(effectChains); effectChains.clear(); } @@ -4021,6 +4105,8 @@ bool AudioFlinger::RecordThread::threadLoop() mStartStopCond.broadcast(); + releaseWakeLock(); + LOGV("RecordThread %p exiting", this); return false; } @@ -5581,13 +5667,11 @@ size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle) } } - // Release effect engine here so that it is done immediately. Otherwise it will be released - // by the destructor when the last strong reference on the this object is released which can - // happen after next process is called on this effect. - if (size == 0 && mEffectInterface != NULL) { - // release effect engine - EffectRelease(mEffectInterface); - mEffectInterface = NULL; + // Prevent calls to process() and other functions on effect interface from now on. + // The effect engine will be released by the destructor when the last strong reference on + // this object is released which can happen after next process is called. + if (size == 0) { + mState = DESTROYED; } return size; @@ -5637,7 +5721,7 @@ void AudioFlinger::EffectModule::updateState() { mState = IDLE; } break; - default: //IDLE , ACTIVE + default: //IDLE , ACTIVE, DESTROYED break; } } @@ -5646,7 +5730,7 @@ void AudioFlinger::EffectModule::process() { Mutex::Autolock _l(mLock); - if (mEffectInterface == NULL || + if (mState == DESTROYED || mEffectInterface == NULL || mConfig.inputCfg.buffer.raw == NULL || mConfig.outputCfg.buffer.raw == NULL) { return; @@ -5822,6 +5906,12 @@ status_t AudioFlinger::EffectModule::start_l() return status; } +status_t AudioFlinger::EffectModule::stop() +{ + Mutex::Autolock _l(mLock); + return stop_l(); +} + status_t AudioFlinger::EffectModule::stop_l() { if (mEffectInterface == NULL) { @@ -5858,7 +5948,7 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode, Mutex::Autolock _l(mLock); // LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface); - if (mEffectInterface == NULL) { + if (mState == DESTROYED || mEffectInterface == NULL) { return NO_INIT; } status_t status = (*mEffectInterface)->command(mEffectInterface, @@ -5907,6 +5997,8 @@ status_t AudioFlinger::EffectModule::setEnabled(bool enabled) case ACTIVE: mState = STOPPING; break; + case DESTROYED: + return NO_ERROR; // simply ignore as we are being destroyed } for (size_t i = 1; i < mHandles.size(); i++) { sp<EffectHandle> h = mHandles[i].promote(); @@ -5928,6 +6020,7 @@ bool AudioFlinger::EffectModule::isEnabled() case IDLE: case STOPPING: case STOPPED: + case DESTROYED: default: return false; } @@ -5943,6 +6036,7 @@ bool AudioFlinger::EffectModule::isProcessEnabled() return true; case IDLE: case STARTING: + case DESTROYED: default: return false; } @@ -6544,6 +6638,10 @@ size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect) for (i = 0; i < size; i++) { if (effect == mEffects[i]) { + // calling stop here will remove pre-processing effect from the audio HAL. + // This is safe as we hold the EffectChain mutex which guarantees that we are not in + // the middle of a read from audio HAL + mEffects[i]->stop(); if (type == EFFECT_FLAG_TYPE_AUXILIARY) { delete[] effect->inBuffer(); } else { |