summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/Threads.cpp
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2013-01-14 14:12:05 -0800
committerMarco Nelissen <marcone@google.com>2013-10-25 14:06:03 -0700
commit9cae217050aa1347d4ac5053c305754879e3f97f (patch)
treedff82f277cba8f34af39eaeeb00adec01bbda26c /services/audioflinger/Threads.cpp
parentbe567be3f92026f5964c1c9ecce00e30bb7df412 (diff)
downloadframeworks_av-9cae217050aa1347d4ac5053c305754879e3f97f.zip
frameworks_av-9cae217050aa1347d4ac5053c305754879e3f97f.tar.gz
frameworks_av-9cae217050aa1347d4ac5053c305754879e3f97f.tar.bz2
Assign blame for playback wakelocks.
Set a work source for the playback wakelock, so that playback is counted against the requesting app instead of the media server. Cherrypicked from master. b/9464621 Change-Id: I7329f88a288a95a582a78005a1c3d16a5a611e31
Diffstat (limited to 'services/audioflinger/Threads.cpp')
-rw-r--r--services/audioflinger/Threads.cpp95
1 files changed, 76 insertions, 19 deletions
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9c8fd1f..ae059fb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -503,17 +503,7 @@ String16 AudioFlinger::ThreadBase::getWakeLockTag()
void AudioFlinger::ThreadBase::acquireWakeLock_l(int uid)
{
- 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) {
- ALOGW("Thread %s cannot connect to the power manager service", mName);
- } else {
- mPowerManager = interface_cast<IPowerManager>(binder);
- binder->linkToDeath(mDeathRecipient);
- }
- }
+ getPowerManager_l();
if (mPowerManager != 0) {
sp<IBinder> binder = new BBinder();
status_t status;
@@ -553,6 +543,41 @@ void AudioFlinger::ThreadBase::releaseWakeLock_l()
}
}
+void AudioFlinger::ThreadBase::updateWakeLockUids(const SortedVector<int> &uids) {
+ Mutex::Autolock _l(mLock);
+ updateWakeLockUids_l(uids);
+}
+
+void AudioFlinger::ThreadBase::getPowerManager_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) {
+ ALOGW("Thread %s cannot connect to the power manager service", mName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+}
+
+void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) {
+
+ getPowerManager_l();
+ if (mWakeLockToken == NULL) {
+ ALOGE("no wake lock to update!");
+ return;
+ }
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status;
+ status = mPowerManager->updateWakeLockUids(mWakeLockToken, uids.size(), uids.array());
+ ALOGV("acquireWakeLock_l() %s status %d", mName, status);
+ }
+}
+
void AudioFlinger::ThreadBase::clearPowerManager()
{
Mutex::Autolock _l(mLock);
@@ -977,6 +1002,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
: ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type),
mNormalFrameCount(0), mMixBuffer(NULL),
mAllocMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
+ mActiveTracksGeneration(0),
// mStreamTypes[] initialized in constructor body
mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
@@ -1160,6 +1186,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
int sessionId,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
+ int uid,
status_t *status)
{
sp<Track> track;
@@ -1293,10 +1320,10 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
if (!isTimed) {
track = new Track(this, client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, sessionId, *flags);
+ channelMask, frameCount, sharedBuffer, sessionId, uid, *flags);
} else {
track = TimedTrack::create(this, client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, sessionId);
+ channelMask, frameCount, sharedBuffer, sessionId, uid);
}
if (track == 0 || track->getCblk() == NULL || track->name() < 0) {
lStatus = NO_MEMORY;
@@ -1432,6 +1459,8 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
track->mResetDone = false;
track->mPresentationCompleteFrames = 0;
mActiveTracks.add(track);
+ mWakeLockUids.add(track->uid());
+ mActiveTracksGeneration++;
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -2127,6 +2156,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// FIXME could this be made local to while loop?
writeFrames = 0;
+ int lastGeneration = 0;
+
cacheParameters_l();
sleepTime = idleSleepTime;
@@ -2183,6 +2214,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
break;
}
releaseWakeLock_l();
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
ALOGV("wait async completion");
mWaitWorkCV.wait(mLock);
ALOGV("async completion/wake");
@@ -2213,6 +2246,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
}
releaseWakeLock_l();
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
// wait until we have something to do...
ALOGV("%s going to sleep", myName.string());
mWaitWorkCV.wait(mLock);
@@ -2237,11 +2272,18 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// mMixerStatusIgnoringFastTracks is also updated internally
mMixerStatus = prepareTracks_l(&tracksToRemove);
+ // compare with previously applied list
+ if (lastGeneration != mActiveTracksGeneration) {
+ // update wakelock
+ updateWakeLockUids_l(mWakeLockUids);
+ lastGeneration = mActiveTracksGeneration;
+ }
+
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
lockEffectChains_l(effectChains);
- }
+ } // mLock scope ends
if (mBytesRemaining == 0) {
mCurrentWriteLength = 0;
@@ -2351,6 +2393,8 @@ if (mType == MIXER) {
}
releaseWakeLock();
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
ALOGV("Thread %p type %d exiting", this, mType);
return false;
@@ -2364,6 +2408,8 @@ void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tra
for (size_t i=0 ; i<count ; i++) {
const sp<Track>& track = tracksToRemove.itemAt(i);
mActiveTracks.remove(track);
+ mWakeLockUids.remove(track->uid());
+ mActiveTracksGeneration++;
ALOGV("removeTracks_l removing track on session %d", track->sessionId());
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
@@ -4213,7 +4259,8 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
mSampleRate,
mFormat,
mChannelMask,
- frameCount);
+ frameCount,
+ IPCThreadState::self()->getCallingUid());
if (outputTrack->cblk() != NULL) {
thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
mOutputTracks.add(outputTrack);
@@ -4315,7 +4362,6 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
snprintf(mName, kNameLength, "AudioIn_%X", id);
readInputParameters();
- mClientUid = IPCThreadState::self()->getCallingUid();
}
@@ -4347,7 +4393,11 @@ bool AudioFlinger::RecordThread::threadLoop()
nsecs_t lastWarning = 0;
inputStandBy();
- acquireWakeLock(mClientUid);
+ {
+ Mutex::Autolock _l(mLock);
+ activeTrack = mActiveTrack;
+ acquireWakeLock_l(activeTrack != 0 ? activeTrack->uid() : -1);
+ }
// used to verify we've read at least once before evaluating how many bytes were read
bool readOnce = false;
@@ -4360,6 +4410,12 @@ bool AudioFlinger::RecordThread::threadLoop()
{ // scope for mLock
Mutex::Autolock _l(mLock);
checkForNewParameters_l();
+ if (mActiveTrack != 0 && activeTrack != mActiveTrack) {
+ SortedVector<int> tmp;
+ tmp.add(mActiveTrack->uid());
+ updateWakeLockUids_l(tmp);
+ }
+ activeTrack = mActiveTrack;
if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
standby();
@@ -4372,7 +4428,7 @@ bool AudioFlinger::RecordThread::threadLoop()
// go to sleep
mWaitWorkCV.wait(mLock);
ALOGV("RecordThread: loop starting");
- acquireWakeLock_l(mClientUid);
+ acquireWakeLock_l(mActiveTrack != 0 ? mActiveTrack->uid() : -1);
continue;
}
if (mActiveTrack != 0) {
@@ -4582,6 +4638,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR
audio_channel_mask_t channelMask,
size_t frameCount,
int sessionId,
+ int uid,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
status_t *status)
@@ -4651,7 +4708,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR
Mutex::Autolock _l(mLock);
track = new RecordTrack(this, client, sampleRate,
- format, channelMask, frameCount, sessionId);
+ format, channelMask, frameCount, sessionId, uid);
if (track->getCblk() == 0) {
ALOGE("createRecordTrack_l() no control block");