summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2011-07-27 09:02:47 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-07-27 09:02:47 -0700
commit99b25ba8da5fdb7a524b53c5db290f7a64f1259c (patch)
treeb9fdd68537ad28643a3081c93601b3dc289c0b74
parentdcd955bd86756be551cfd0a07e53caa55ab1a7fe (diff)
parentfeb0db689c17dced50afaee54c659f1676e2d505 (diff)
Merge "Fix issue 4604090: notification sound interrupted."
-rw-r--r--services/audioflinger/Android.mk3
-rw-r--r--services/audioflinger/AudioFlinger.cpp114
-rw-r--r--services/audioflinger/AudioFlinger.h29
3 files changed, 132 insertions, 14 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index a0407b98..fa495929 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 cb1f9213..95b9918b 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 e2cf946d..edd3e2ab 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 ---