diff options
author | Eric Laurent <elaurent@google.com> | 2013-09-18 18:47:13 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2013-09-18 19:00:22 -0700 |
commit | d1b28d41dbda203ffb420ba2e36cbe736b163ff8 (patch) | |
tree | 8515326721a76081b458cce1329e13b7252d2fbe | |
parent | 5baf2af52cd186633b7173196c1e4a4cd3435f22 (diff) | |
download | frameworks_av-d1b28d41dbda203ffb420ba2e36cbe736b163ff8.zip frameworks_av-d1b28d41dbda203ffb420ba2e36cbe736b163ff8.tar.gz frameworks_av-d1b28d41dbda203ffb420ba2e36cbe736b163ff8.tar.bz2 |
audioflniger: fix leaked audiosession references
acquireAudioSessionId() should not create session references
if the caller is not listed in the known notification clients.
It happens when the MediaPlayer or AudioTrack is created by the
mediaserver on behalf of a client (e.g CameraService). In this case
releaseAudioSessionId() can be called from a different pid and
the session reference will not be removed.
Also we will not be able to remove the reference if the client
process dies.
Bug: 10606426.
Change-Id: Ibb5e27518daeb484a2e66302e4c6221cbaca5b70
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 8fbac42..f6e4c6a 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -264,6 +264,12 @@ void AudioFlinger::dumpClients(int fd, const Vector<String16>& args) } } + result.append("Notification Clients:\n"); + for (size_t i = 0; i < mNotificationClients.size(); ++i) { + snprintf(buffer, SIZE, " pid: %d\n", mNotificationClients.keyAt(i)); + result.append(buffer); + } + result.append("Global session refs:\n"); result.append(" session pid count\n"); for (size_t i = 0; i < mAudioSessionRefs.size(); i++) { @@ -1850,6 +1856,16 @@ void AudioFlinger::acquireAudioSessionId(int audioSession) Mutex::Autolock _l(mLock); pid_t caller = IPCThreadState::self()->getCallingPid(); ALOGV("acquiring %d from %d", audioSession, caller); + + // Ignore requests received from processes not known as notification client. The request + // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be + // called from a different pid leaving a stale session reference. Also we don't know how + // to clear this reference if the client process dies. + if (mNotificationClients.indexOfKey(caller) < 0) { + ALOGV("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession); + return; + } + size_t num = mAudioSessionRefs.size(); for (size_t i = 0; i< num; i++) { AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i); @@ -1882,7 +1898,9 @@ void AudioFlinger::releaseAudioSessionId(int audioSession) return; } } - ALOGW("session id %d not found for pid %d", audioSession, caller); + // If the caller is mediaserver it is likely that the session being released was acquired + // on behalf of a process not in notification clients and we ignore the warning. + ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller); } void AudioFlinger::purgeStaleEffects_l() { |