From 462fd2fa9eef642b0574aa7409de0bde3fec8d43 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Mon, 14 Jan 2013 14:12:05 -0800 Subject: 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. Change-Id: I7329f88a288a95a582a78005a1c3d16a5a611e31 --- include/media/AudioTrack.h | 10 ++- include/media/IAudioFlinger.h | 1 + media/libmedia/AudioTrack.cpp | 20 +++-- media/libmedia/IAudioFlinger.cpp | 5 +- media/libmediaplayerservice/MediaPlayerService.cpp | 19 +++-- media/libmediaplayerservice/MediaPlayerService.h | 3 +- services/audioflinger/AudioFlinger.cpp | 9 +- services/audioflinger/AudioFlinger.h | 1 + services/audioflinger/PlaybackTracks.h | 10 ++- services/audioflinger/RecordTracks.h | 3 +- services/audioflinger/Threads.cpp | 96 +++++++++++++++++----- services/audioflinger/Threads.h | 8 +- services/audioflinger/TrackBase.h | 3 + services/audioflinger/Tracks.cpp | 36 ++++++-- 14 files changed, 171 insertions(+), 53 deletions(-) diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index e5cf896..bec77ce 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -187,7 +187,8 @@ public: int notificationFrames = 0, int sessionId = 0, transfer_type transferType = TRANSFER_DEFAULT, - const audio_offload_info_t *offloadInfo = NULL); + const audio_offload_info_t *offloadInfo = NULL, + int uid = -1); /* Creates an audio track and registers it with AudioFlinger. * With this constructor, the track is configured for static buffer mode. @@ -211,7 +212,8 @@ public: int notificationFrames = 0, int sessionId = 0, transfer_type transferType = TRANSFER_DEFAULT, - const audio_offload_info_t *offloadInfo = NULL); + const audio_offload_info_t *offloadInfo = NULL, + int uid = -1); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources associated with the AudioTrack. @@ -248,7 +250,8 @@ public: bool threadCanCallJava = false, int sessionId = 0, transfer_type transferType = TRANSFER_DEFAULT, - const audio_offload_info_t *offloadInfo = NULL); + const audio_offload_info_t *offloadInfo = NULL, + int uid = -1); /* Result of constructing the AudioTrack. This must be checked for successful initialization * before using any AudioTrack API (except for set()), because using @@ -751,6 +754,7 @@ private: sp mDeathNotifier; uint32_t mSequence; // incremented for each new IAudioTrack attempt audio_io_handle_t mOutput; // cached output io handle + int mClientUid; }; class TimedAudioTrack : public AudioTrack diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index eaf7780..899d79f 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -74,6 +74,7 @@ public: // output: server's description of IAudioTrack for display in logs. // Don't attempt to parse, as the format could change. String8& name, + int clientUid, status_t *status) = 0; virtual sp openRecord( diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a50ed1f..df58909 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -101,7 +101,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -109,7 +110,8 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, - 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, + offloadInfo, uid); } AudioTrack::AudioTrack( @@ -124,7 +126,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -132,7 +135,7 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, - sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); } AudioTrack::~AudioTrack() @@ -169,7 +172,8 @@ status_t AudioTrack::set( bool threadCanCallJava, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) { switch (transferType) { case TRANSFER_DEFAULT: @@ -313,6 +317,11 @@ status_t AudioTrack::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; + if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { + mClientUid = IPCThreadState::self()->getCallingUid(); + } else { + mClientUid = uid; + } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; @@ -961,6 +970,7 @@ status_t AudioTrack::createTrack_l( tid, &mSessionId, mName, + mClientUid, &status); if (track == 0) { diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index f9f6779..9df10f0 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -96,6 +96,7 @@ public: pid_t tid, int *sessionId, String8& name, + int clientUid, status_t *status) { Parcel data, reply; @@ -121,6 +122,7 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + data.writeInt32(clientUid); status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); if (lStatus != NO_ERROR) { ALOGE("createTrack error: %s", strerror(-lStatus)); @@ -780,6 +782,7 @@ status_t BnAudioFlinger::onTransact( audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); + int clientUid = data.readInt32(); String8 name; status_t status; sp track; @@ -791,7 +794,7 @@ status_t BnAudioFlinger::onTransact( track = createTrack( (audio_stream_type_t) streamType, sampleRate, format, channelMask, frameCount, &flags, buffer, output, tid, - &sessionId, name, &status); + &sessionId, name, clientUid, &status); } reply->writeInt32(flags); reply->writeInt32(sessionId); diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 9553458..cd052e6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -590,7 +590,7 @@ sp MediaPlayerService::Client::setDataSource_pre( } if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(mAudioSessionId); + mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid()); static_cast(p.get())->setAudioSink(mAudioOutput); } @@ -1296,12 +1296,13 @@ Exit: #undef LOG_TAG #define LOG_TAG "AudioSink" -MediaPlayerService::AudioOutput::AudioOutput(int sessionId) +MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid) : mCallback(NULL), mCallbackCookie(NULL), mCallbackData(NULL), mBytesWritten(0), mSessionId(sessionId), + mUid(uid), mFlags(AUDIO_OUTPUT_FLAG_NONE) { ALOGV("AudioOutput(%d)", sessionId); mStreamType = AUDIO_STREAM_MUSIC; @@ -1549,7 +1550,8 @@ status_t MediaPlayerService::AudioOutput::open( 0, // notification frames mSessionId, AudioTrack::TRANSFER_CALLBACK, - offloadInfo); + offloadInfo, + mUid); } else { t = new AudioTrack( mStreamType, @@ -1558,10 +1560,13 @@ status_t MediaPlayerService::AudioOutput::open( channelMask, frameCount, flags, - NULL, - NULL, - 0, - mSessionId); + NULL, // callback + NULL, // user data + 0, // notification frames + mSessionId, + AudioTrack::TRANSFER_DEFAULT, + NULL, // offload info + mUid); } if ((t == 0) || (t->initCheck() != NO_ERROR)) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 21f4117..05d44d4 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -72,7 +72,7 @@ class MediaPlayerService : public BnMediaPlayerService class CallbackData; public: - AudioOutput(int sessionId); + AudioOutput(int sessionId, int uid); virtual ~AudioOutput(); virtual bool ready() const { return mTrack != 0; } @@ -135,6 +135,7 @@ class MediaPlayerService : public BnMediaPlayerService uint32_t mSampleRateHz; // sample rate of the content, as set in open() float mMsecsPerFrame; int mSessionId; + int mUid; float mSendLevel; int mAuxEffectId; static bool mIsOnEmulator; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 8fedc7f..360db4f 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -451,6 +451,7 @@ sp AudioFlinger::createTrack( pid_t tid, int *sessionId, String8& name, + int clientUid, status_t *status) { sp track; @@ -486,6 +487,7 @@ sp AudioFlinger::createTrack( } pid_t pid = IPCThreadState::self()->getCallingPid(); + client = registerPid_l(pid); ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId); @@ -513,7 +515,7 @@ sp AudioFlinger::createTrack( ALOGV("createTrack() lSessionId: %d", lSessionId); track = thread->createTrack_l(client, streamType, sampleRate, format, - channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus); + channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus); // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless // move effect chain to this output thread if an effect on same session was waiting @@ -1289,8 +1291,11 @@ sp AudioFlinger::openRecord( } // create new record track. // The record track uses one track in mHardwareMixerThread by convention. + // TODO: the uid should be passed in as a parameter to openRecord recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask, - frameCount, lSessionId, flags, tid, &lStatus); + frameCount, lSessionId, + IPCThreadState::self()->getCallingUid(), + flags, tid, &lStatus); LOG_ALWAYS_FATAL_IF((recordTrack != 0) != (lStatus == NO_ERROR)); } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index d6b10f7..d244c14 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -109,6 +109,7 @@ public: pid_t tid, int *sessionId, String8& name, + int clientUid, status_t *status /*non-NULL*/); virtual sp openRecord( diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index ae0aba4..4b6c74d 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -31,6 +31,7 @@ public: size_t frameCount, const sp& sharedBuffer, int sessionId, + int uid, IAudioFlinger::track_flags_t flags); virtual ~Track(); virtual status_t initCheck() const; @@ -166,7 +167,8 @@ class TimedTrack : public Track { audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId); + int sessionId, + int uid); virtual ~TimedTrack(); class TimedBuffer { @@ -209,7 +211,8 @@ class TimedTrack : public Track { audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId); + int sessionId, + int uid); void timedYieldSamples_l(AudioBufferProvider::Buffer* buffer); void timedYieldSilence_l(uint32_t numFrames, @@ -256,7 +259,8 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - size_t frameCount); + size_t frameCount, + int uid); virtual ~OutputTrack(); virtual status_t start(AudioSystem::sync_event_t event = diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h index a4e1810..5ef6f58 100644 --- a/services/audioflinger/RecordTracks.h +++ b/services/audioflinger/RecordTracks.h @@ -28,7 +28,8 @@ public: audio_format_t format, audio_channel_mask_t channelMask, size_t frameCount, - int sessionId); + int sessionId, + int uid); virtual ~RecordTrack(); virtual status_t start(AudioSystem::sync_event_t event, int triggerSession); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 44384b8..ff7ccac 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -521,17 +521,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 binder = - defaultServiceManager()->checkService(String16("power")); - if (binder == 0) { - ALOGW("Thread %s cannot connect to the power manager service", mName); - } else { - mPowerManager = interface_cast(binder); - binder->linkToDeath(mDeathRecipient); - } - } + getPowerManager_l(); if (mPowerManager != 0) { sp binder = new BBinder(); status_t status; @@ -571,6 +561,41 @@ void AudioFlinger::ThreadBase::releaseWakeLock_l() } } +void AudioFlinger::ThreadBase::updateWakeLockUids(const SortedVector &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 binder = + defaultServiceManager()->checkService(String16("power")); + if (binder == 0) { + ALOGW("Thread %s cannot connect to the power manager service", mName); + } else { + mPowerManager = interface_cast(binder); + binder->linkToDeath(mDeathRecipient); + } + } +} + +void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector &uids) { + + getPowerManager_l(); + if (mWakeLockToken == NULL) { + ALOGE("no wake lock to update!"); + return; + } + if (mPowerManager != 0) { + sp 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); @@ -992,6 +1017,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp& audioFlinge : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type), mNormalFrameCount(0), mMixBuffer(NULL), mSuspended(0), mBytesWritten(0), + mActiveTracksGeneration(0), // mStreamTypes[] initialized in constructor body mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), @@ -1165,6 +1191,7 @@ sp AudioFlinger::PlaybackThread::createTrac int sessionId, IAudioFlinger::track_flags_t *flags, pid_t tid, + int uid, status_t *status) { sp track; @@ -1298,10 +1325,10 @@ sp 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); } // new Track always returns non-NULL, @@ -1439,6 +1466,8 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp& track) track->mResetDone = false; track->mPresentationCompleteFrames = 0; mActiveTracks.add(track); + mWakeLockUids.add(track->uid()); + mActiveTracksGeneration++; sp chain = getEffectChain_l(track->sessionId()); if (chain != 0) { ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), @@ -2135,6 +2164,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() // FIXME could this be made local to while loop? writeFrames = 0; + int lastGeneration = 0; + cacheParameters_l(); sleepTime = idleSleepTime; @@ -2191,6 +2222,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() break; } releaseWakeLock_l(); + mWakeLockUids.clear(); + mActiveTracksGeneration++; ALOGV("wait async completion"); mWaitWorkCV.wait(mLock); ALOGV("async completion/wake"); @@ -2221,6 +2254,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); @@ -2245,11 +2280,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; @@ -2359,6 +2401,8 @@ if (mType == MIXER) { } releaseWakeLock(); + mWakeLockUids.clear(); + mActiveTracksGeneration++; ALOGV("Thread %p type %d exiting", this, mType); return false; @@ -2372,6 +2416,8 @@ void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp >& tra for (size_t i=0 ; i& track = tracksToRemove.itemAt(i); mActiveTracks.remove(track); + mWakeLockUids.remove(track->uid()); + mActiveTracksGeneration++; ALOGV("removeTracks_l removing track on session %d", track->sessionId()); sp chain = getEffectChain_l(track->sessionId()); if (chain != 0) { @@ -4223,7 +4269,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); @@ -4325,7 +4372,6 @@ AudioFlinger::RecordThread::RecordThread(const sp& audioFlinger, snprintf(mName, kNameLength, "AudioIn_%X", id); readInputParameters(); - mClientUid = IPCThreadState::self()->getCallingUid(); } @@ -4348,7 +4394,12 @@ bool AudioFlinger::RecordThread::threadLoop() nsecs_t lastWarning = 0; inputStandBy(); - acquireWakeLock(mClientUid); + sp activeTrack; + { + 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; @@ -4358,7 +4409,6 @@ bool AudioFlinger::RecordThread::threadLoop() // start recording for (;;) { - sp activeTrack; TrackBase::track_state activeTrackState; Vector< sp > effectChains; @@ -4376,6 +4426,11 @@ bool AudioFlinger::RecordThread::threadLoop() processConfigEvents_l(); // return value 'reconfig' is currently unused bool reconfig = checkForNewParameters_l(); + if (mActiveTrack != 0 && activeTrack != mActiveTrack) { + SortedVector tmp; + tmp.add(mActiveTrack->uid()); + updateWakeLockUids_l(tmp); + } // make a stable copy of mActiveTrack activeTrack = mActiveTrack; if (activeTrack == 0) { @@ -4386,7 +4441,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; } @@ -4614,6 +4669,7 @@ sp AudioFlinger::RecordThread::createRe audio_channel_mask_t channelMask, size_t frameCount, int sessionId, + int uid, IAudioFlinger::track_flags_t *flags, pid_t tid, status_t *status) @@ -4683,7 +4739,7 @@ sp AudioFlinger::RecordThread::createRe Mutex::Autolock _l(mLock); track = new RecordTrack(this, client, sampleRate, - format, channelMask, frameCount, sessionId); + format, channelMask, frameCount, sessionId, uid); lStatus = track->initCheck(); if (lStatus != NO_ERROR) { diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 4ccbb10..2b4c9fd 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -244,6 +244,9 @@ protected: void acquireWakeLock_l(int uid = -1); void releaseWakeLock(); void releaseWakeLock_l(); + void updateWakeLockUids(const SortedVector &uids); + void updateWakeLockUids_l(const SortedVector &uids); + void getPowerManager_l(); void setEffectSuspended_l(const effect_uuid_t *type, bool suspend, int sessionId); @@ -424,6 +427,7 @@ public: int sessionId, IAudioFlinger::track_flags_t *flags, pid_t tid, + int uid, status_t *status /*non-NULL*/); AudioStreamOut* getOutput() const; @@ -497,6 +501,8 @@ private: void setMasterMute_l(bool muted) { mMasterMute = muted; } protected: SortedVector< wp > mActiveTracks; // FIXME check if this could be sp<> + SortedVector mWakeLockUids; + int mActiveTracksGeneration; // Allocate a track name for a given channel mask. // Returns name >= 0 if successful, -1 on failure. @@ -875,6 +881,7 @@ public: audio_channel_mask_t channelMask, size_t frameCount, int sessionId, + int uid, IAudioFlinger::track_flags_t *flags, pid_t tid, status_t *status /*non-NULL*/); @@ -954,5 +961,4 @@ private: // For dumpsys const sp mTeeSink; - int mClientUid; }; diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 00a91b7..05fde7c 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -45,6 +45,7 @@ public: size_t frameCount, const sp& sharedBuffer, int sessionId, + int uid, bool isOut); virtual ~TrackBase(); virtual status_t initCheck() const { return getCblk() != 0 ? NO_ERROR : NO_MEMORY; } @@ -55,6 +56,7 @@ public: sp getCblk() const { return mCblkMemory; } audio_track_cblk_t* cblk() const { return mCblk; } int sessionId() const { return mSessionId; } + int uid() const { return mUid; } virtual status_t setSyncEvent(const sp& event); protected: @@ -124,6 +126,7 @@ protected: // openRecord(), and then adjusted as needed const int mSessionId; + int mUid; Vector < sp >mSyncEvents; const bool mIsOut; ServerProxy* mServerProxy; diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 656dfbb..9152ea3 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -68,6 +68,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( size_t frameCount, const sp& sharedBuffer, int sessionId, + int clientUid, bool isOut) : RefBase(), mThread(thread), @@ -88,6 +89,18 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mId(android_atomic_inc(&nextTrackId)), mTerminated(false) { + // if the caller is us, trust the specified uid + if (IPCThreadState::self()->getCallingPid() != getpid_cached || clientUid == -1) { + int newclientUid = IPCThreadState::self()->getCallingUid(); + if (clientUid != -1 && clientUid != newclientUid) { + ALOGW("uid %d tried to pass itself off as %d", newclientUid, clientUid); + } + clientUid = newclientUid; + } + // clientUid contains the uid of the app that is responsible for this track, so we can blame + // battery usage on it. + mUid = clientUid; + // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); @@ -313,9 +326,10 @@ AudioFlinger::PlaybackThread::Track::Track( size_t frameCount, const sp& sharedBuffer, int sessionId, + int uid, IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, - sessionId, true /*isOut*/), + sessionId, uid, true /*isOut*/), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed mSharedBuffer(sharedBuffer), @@ -972,13 +986,14 @@ AudioFlinger::PlaybackThread::TimedTrack::create( audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId) { + int sessionId, + int uid) { if (!client->reserveTimedTrack()) return 0; return new TimedTrack( thread, client, streamType, sampleRate, format, channelMask, frameCount, - sharedBuffer, sessionId); + sharedBuffer, sessionId, uid); } AudioFlinger::PlaybackThread::TimedTrack::TimedTrack( @@ -990,9 +1005,10 @@ AudioFlinger::PlaybackThread::TimedTrack::TimedTrack( audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId) + int sessionId, + int uid) : Track(thread, client, streamType, sampleRate, format, channelMask, - frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED), + frameCount, sharedBuffer, sessionId, uid, IAudioFlinger::TRACK_TIMED), mQueueHeadInFlight(false), mTrimQueueHeadOnRelease(false), mFramesPendingInQueue(0), @@ -1487,9 +1503,10 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, - size_t frameCount) + size_t frameCount, + int uid) : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, - NULL, 0, IAudioFlinger::TRACK_DEFAULT), + NULL, 0, uid, IAudioFlinger::TRACK_DEFAULT), mActive(false), mSourceThread(sourceThread), mClientProxy(NULL) { @@ -1749,9 +1766,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( audio_format_t format, audio_channel_mask_t channelMask, size_t frameCount, - int sessionId) + int sessionId, + int uid) : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, false /*isOut*/), + channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/), mOverflow(false) { ALOGV("RecordTrack constructor"); -- cgit v1.1