diff options
author | Eric Laurent <elaurent@google.com> | 2011-07-22 09:04:31 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-07-25 18:41:12 -0700 |
commit | feb0db689c17dced50afaee54c659f1676e2d505 (patch) | |
tree | a949f6cb66c3c5886cd0682fcb3781b0fd5db0a8 /services/audioflinger | |
parent | 288b66b60c9b3af3d84408885d0a4030c45eea9a (diff) | |
download | frameworks_av-feb0db689c17dced50afaee54c659f1676e2d505.zip frameworks_av-feb0db689c17dced50afaee54c659f1676e2d505.tar.gz frameworks_av-feb0db689c17dced50afaee54c659f1676e2d505.tar.bz2 |
Fix issue 4604090: notification sound interrupted.
The problem is that the audio HAL fails to acquire the wake lock when playing the notification.
This is because of a change that removed the mediaserver process form the system group for honeycomb.
The fix consists in requesting the wake lock from PowerManagerService when AudioFlinger mixer
wakes up.
A consequence of this change is that audio HALs or pcm drivers do not have to hold wake locks
anymore as in the past.
Change-Id: I4fb3cc84816c9c408ab7fec75886baf801e1ecb5
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/Android.mk | 3 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 114 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 29 |
3 files changed, 132 insertions, 14 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index a0407b9..fa49592 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -21,7 +21,8 @@ LOCAL_SHARED_LIBRARIES := \ libhardware \ libhardware_legacy \ libeffects \ - libdl + libdl \ + libpowermanager LOCAL_STATIC_LIBRARIES := \ libcpustats \ diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index cb1f921..95b9918 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) { @@ -4021,6 +4107,8 @@ bool AudioFlinger::RecordThread::threadLoop() mStartStopCond.broadcast(); + releaseWakeLock(); + LOGV("RecordThread %p exiting", this); return false; } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index e2cf946..edd3e2a 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -43,6 +43,8 @@ #include "AudioBufferProvider.h" +#include <powermanager/IPowerManager.h> + namespace android { class audio_track_cblk_t; @@ -287,6 +289,8 @@ private: status_t dumpBase(int fd, const Vector<String16>& args); status_t dumpEffectChains(int fd, const Vector<String16>& args); + void clearPowerManager(); + // base for record and playback class TrackBase : public AudioBufferProvider, public RefBase { @@ -386,6 +390,21 @@ private: int mParam; }; + class PMDeathRecipient : public IBinder::DeathRecipient { + public: + PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {} + virtual ~PMDeathRecipient() {} + + // IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who); + + private: + PMDeathRecipient(const PMDeathRecipient&); + PMDeathRecipient& operator = (const PMDeathRecipient&); + + wp<ThreadBase> mThread; + }; + virtual status_t initCheck() const = 0; int type() const { return mType; } uint32_t sampleRate() const; @@ -462,6 +481,11 @@ private: protected: + void acquireWakeLock(); + void acquireWakeLock_l(); + void releaseWakeLock(); + void releaseWakeLock_l(); + friend class Track; friend class TrackBase; friend class PlaybackThread; @@ -490,6 +514,11 @@ private: Vector< sp<EffectChain> > mEffectChains; uint32_t mDevice; // output device for PlaybackThread // input + output devices for RecordThread + static const int kNameLength = 32; + char mName[kNameLength]; + sp<IPowerManager> mPowerManager; + sp<IBinder> mWakeLockToken; + sp<PMDeathRecipient> mDeathRecipient; }; // --- PlaybackThread --- |