summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/audioflinger/AudioFlinger.cpp102
-rw-r--r--services/audioflinger/AudioFlinger.h17
-rw-r--r--services/audioflinger/Effects.cpp4
-rw-r--r--services/audioflinger/Threads.cpp33
-rw-r--r--services/audioflinger/Threads.h19
-rw-r--r--services/audioflinger/Tracks.cpp4
6 files changed, 87 insertions, 92 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e256f32..11170c2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -82,6 +82,7 @@ namespace android {
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
static const char kHardwareLockedString[] = "Hardware lock is taken\n";
+static const char kClientLockedString[] = "Client lock is taken\n";
nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
@@ -382,7 +383,16 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
write(fd, result.string(), result.size());
}
+ bool clientLocked = dumpTryLock(mClientLock);
+ if (!clientLocked) {
+ String8 result(kClientLockedString);
+ write(fd, result.string(), result.size());
+ }
dumpClients(fd, args);
+ if (clientLocked) {
+ mClientLock.unlock();
+ }
+
dumpInternals(fd, args);
// dump playback threads
@@ -426,8 +436,9 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
return NO_ERROR;
}
-sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
+sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
{
+ Mutex::Autolock _cl(mClientLock);
// If pid is already in the mClients wp<> map, then use that entry
// (for which promote() is always != 0), otherwise create a new entry and Client.
sp<Client> client = mClients.valueFor(pid).promote();
@@ -564,7 +575,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
}
pid_t pid = IPCThreadState::self()->getCallingPid();
- client = registerPid_l(pid);
+ client = registerPid(pid);
PlaybackThread *effectThread = NULL;
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
@@ -623,7 +634,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the Track so that the
- // Client destructor is called by the TrackBase destructor with mLock held
+ // Client destructor is called by the TrackBase destructor with mClientLock held
+ Mutex::Autolock _cl(mClientLock);
client.clear();
track.clear();
goto Exit;
@@ -1140,21 +1152,29 @@ status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrame
void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
{
-
Mutex::Autolock _l(mLock);
+ bool clientAdded = false;
+ {
+ Mutex::Autolock _cl(mClientLock);
- pid_t pid = IPCThreadState::self()->getCallingPid();
- if (mNotificationClients.indexOfKey(pid) < 0) {
- sp<NotificationClient> notificationClient = new NotificationClient(this,
- client,
- pid);
- ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ if (mNotificationClients.indexOfKey(pid) < 0) {
+ sp<NotificationClient> notificationClient = new NotificationClient(this,
+ client,
+ pid);
+ ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
- mNotificationClients.add(pid, notificationClient);
+ mNotificationClients.add(pid, notificationClient);
- sp<IBinder> binder = client->asBinder();
- binder->linkToDeath(notificationClient);
+ sp<IBinder> binder = client->asBinder();
+ binder->linkToDeath(notificationClient);
+ clientAdded = true;
+ }
+ }
+ // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
+ // ThreadBase mutex and teh locknig order is ThreadBase::mLock then AudioFlinger::mClientLock.
+ if (clientAdded) {
// the config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -1170,8 +1190,10 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
void AudioFlinger::removeNotificationClient(pid_t pid)
{
Mutex::Autolock _l(mLock);
-
- mNotificationClients.removeItem(pid);
+ {
+ Mutex::Autolock _cl(mClientLock);
+ mNotificationClients.removeItem(pid);
+ }
ALOGV("%d died, releasing its sessions", pid);
size_t num = mAudioSessionRefs.size();
@@ -1194,22 +1216,18 @@ void AudioFlinger::removeNotificationClient(pid_t pid)
}
}
-// audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- audio_io_handle_t ioHandle,
- const void *param2)
+void AudioFlinger::audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2)
{
- size_t size = notificationClients.size();
+ Mutex::Autolock _l(mClientLock);
+ size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
- notificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event,
+ mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event,
ioHandle,
param2);
}
}
-// removeClient_l() must be called with AudioFlinger::mLock held
+// removeClient_l() must be called with AudioFlinger::mClientLock held
void AudioFlinger::removeClient_l(pid_t pid)
{
ALOGV("removeClient_l() pid %d, calling pid %d", pid,
@@ -1247,7 +1265,7 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
}
-// Client destructor must be called with AudioFlinger::mLock held
+// Client destructor must be called with AudioFlinger::mClientLock held
AudioFlinger::Client::~Client()
{
mAudioFlinger->removeClient_l(mPid);
@@ -1377,7 +1395,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
}
pid_t pid = IPCThreadState::self()->getCallingPid();
- client = registerPid_l(pid);
+ client = registerPid(pid);
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
lSessionId = *sessionId;
@@ -1400,7 +1418,8 @@ sp<IAudioRecord> AudioFlinger::openRecord(
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
- // Client destructor is called by the TrackBase destructor with mLock held
+ // Client destructor is called by the TrackBase destructor with mClientLock held
+ Mutex::Autolock _cl(mClientLock);
client.clear();
recordTrack.clear();
goto Exit;
@@ -1638,7 +1657,7 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
}
// notify client processes of the new output creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
// the first primary output opened designates the primary hw device
if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
@@ -1674,7 +1693,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
return id;
}
@@ -1724,7 +1743,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
}
}
}
- audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_CLOSED, output, NULL);
+ audioConfigChanged(AudioSystem::OUTPUT_CLOSED, output, NULL);
}
thread->exit();
// The thread entity (active unit of execution) is no longer running here,
@@ -1904,7 +1923,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
}
// notify client processes of the new input creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::INPUT_OPENED);
return id;
}
@@ -1929,7 +1948,7 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
}
ALOGV("closeInput() %d", input);
- audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_CLOSED, input, NULL);
+ audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL);
mRecordThreads.removeItem(input);
}
thread->exit();
@@ -1973,13 +1992,16 @@ void AudioFlinger::acquireAudioSessionId(int audioSession, pid_t pid)
caller = pid;
}
- // 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) {
- ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
- return;
+ {
+ Mutex::Autolock _cl(mClientLock);
+ // 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) {
+ ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
+ return;
+ }
}
size_t num = mAudioSessionRefs.size();
@@ -2348,7 +2370,7 @@ sp<IEffect> AudioFlinger::createEffect(
}
}
- sp<Client> client = registerPid_l(pid);
+ sp<Client> client = registerPid(pid);
// create effect on selected output thread
handle = thread->createEffect_l(client, effectClient, priority, sessionId,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 894bd35..c1d4c08 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -453,11 +453,7 @@ private:
// no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
float streamVolume_l(audio_stream_type_t stream) const
{ return mStreamTypes[stream].volume; }
- void audioConfigChanged_l(const DefaultKeyedVector< pid_t,sp<NotificationClient> >&
- notificationClients,
- int event,
- audio_io_handle_t ioHandle,
- const void *param2);
+ void audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
// Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.
// They all share the same ID space, but the namespaces are actually independent
@@ -482,8 +478,6 @@ private:
void removeClient_l(pid_t pid);
void removeNotificationClient(pid_t pid);
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients() {
- Mutex::Autolock _l(mLock); return mNotificationClients; }
bool isNonOffloadableGlobalEffectEnabled_l();
void onNonOffloadableGlobalEffectEnable();
@@ -553,7 +547,11 @@ private:
};
mutable Mutex mLock;
-
+ // protects mClients and mNotificationClients.
+ // must be locked after mLock and ThreadBase::mLock if both must be locked
+ // avoids acquiring AudioFlinger::mLock from inside thread loop.
+ mutable Mutex mClientLock;
+ // protected by mClientLock
DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
mutable Mutex mHardwareLock;
@@ -602,6 +600,7 @@ private:
DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
+ // protected by mClientLock
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
volatile int32_t mNextUniqueId; // updated by android_atomic_inc
@@ -622,7 +621,7 @@ private:
// to be created
private:
- sp<Client> registerPid_l(pid_t pid); // always returns non-0
+ sp<Client> registerPid(pid_t pid); // always returns non-0
// for use from destructor
status_t closeOutput_nonvirtual(audio_io_handle_t output);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 29b56db..77aca00 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1162,8 +1162,8 @@ void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
- // Client destructor must run with AudioFlinger mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ // Client destructor must run with AudioFlinger client mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
mClient.clear();
}
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 470b018..8243a8b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -401,8 +401,7 @@ status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8&
}
// post condition: mConfigEvents.isEmpty()
-void AudioFlinger::ThreadBase::processConfigEvents_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients)
+void AudioFlinger::ThreadBase::processConfigEvents_l()
{
bool configChanged = false;
@@ -423,7 +422,7 @@ void AudioFlinger::ThreadBase::processConfigEvents_l(
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- audioConfigChanged_l(notificationClients, data->mEvent, data->mParam);
+ audioConfigChanged(data->mEvent, data->mParam);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -1638,15 +1637,11 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
return out_s8;
}
-// audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param) {
+void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
AudioSystem::OutputDescriptor desc;
void *param2 = NULL;
- ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event,
+ ALOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event,
param);
switch (event) {
@@ -1667,7 +1662,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(
default:
break;
}
- mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2);
+ mAudioFlinger->audioConfigChanged(event, mId, param2);
}
void AudioFlinger::PlaybackThread::writeCallback()
@@ -2317,15 +2312,11 @@ bool AudioFlinger::PlaybackThread::threadLoop()
Vector< sp<EffectChain> > effectChains;
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients =
- mAudioFlinger->notificationClients();
-
{ // scope for mLock
Mutex::Autolock _l(mLock);
- processConfigEvents_l(notificationClients);
- notificationClients.clear();
+ processConfigEvents_l();
if (logString != NULL) {
mNBLogWriter->logTimestamp();
@@ -4695,14 +4686,11 @@ reacquire_wakelock:
// activeTracks accumulates a copy of a subset of mActiveTracks
Vector< sp<RecordTrack> > activeTracks;
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients =
- mAudioFlinger->notificationClients();
{ // scope for mLock
Mutex::Autolock _l(mLock);
- processConfigEvents_l(notificationClients);
- notificationClients.clear();
+ processConfigEvents_l();
// check exitPending here because checkForNewParameters_l() and
// checkForNewParameters_l() can temporarily release mLock
@@ -5605,10 +5593,7 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
return out_s8;
}
-void AudioFlinger::RecordThread::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param __unused) {
+void AudioFlinger::RecordThread::audioConfigChanged(int event, int param __unused) {
AudioSystem::OutputDescriptor desc;
const void *param2 = NULL;
@@ -5627,7 +5612,7 @@ void AudioFlinger::RecordThread::audioConfigChanged_l(
default:
break;
}
- mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2);
+ mAudioFlinger->audioConfigChanged(event, mId, param2);
}
void AudioFlinger::RecordThread::readInputParameters_l()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 9578993..cc2b246 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -200,10 +200,7 @@ public:
status_t& status) = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0) = 0;
+ virtual void audioConfigChanged(int event, int param = 0) = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
@@ -212,8 +209,7 @@ public:
void sendIoConfigEvent_l(int event, int param = 0);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
- void processConfigEvents_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients);
+ void processConfigEvents_l();
virtual void cacheParameters_l() = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
@@ -502,10 +498,7 @@ public:
{ return android_atomic_acquire_load(&mSuspended) > 0; }
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0);
+ virtual void audioConfigChanged(int event, int param = 0);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
// Consider also removing and passing an explicit mMainBuffer initialization
@@ -652,7 +645,6 @@ private:
friend class AudioFlinger; // for numerous
- PlaybackThread(const Client&);
PlaybackThread& operator = (const PlaybackThread&);
status_t addTrack_l(const sp<Track>& track);
@@ -1037,10 +1029,7 @@ public:
status_t& status);
virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0);
+ virtual void audioConfigChanged(int event, int param = 0);
void readInputParameters_l();
virtual uint32_t getInputFramesLost();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index d8f3423..88ead74 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -198,8 +198,8 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase()
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
if (mClient != 0) {
- // Client destructor must run with AudioFlinger mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ // Client destructor must run with AudioFlinger client mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
// If the client's reference count drops to zero, the associated destructor
// must run with AudioFlinger lock held. Thus the explicit clear() rather than
// relying on the automatic clear() at end of scope.