am ca20104a: Merge "Fix issue 2678048: binder death detection in AudioFlinger is broken." into kraken

This commit is contained in:
Eric Laurent
2010-05-13 09:17:30 -07:00
committed by Android Git Automerger
2 changed files with 92 additions and 38 deletions

View File

@@ -142,6 +142,7 @@ AudioFlinger::AudioFlinger()
} }
#ifdef LVMX #ifdef LVMX
LifeVibes::init(); LifeVibes::init();
mLifeVibesClientPid = -1;
#endif #endif
} }
@@ -596,8 +597,10 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
int musicEnabled = -1; int musicEnabled = -1;
if (NO_ERROR == param.get(key, value)) { if (NO_ERROR == param.get(key, value)) {
if (value == LifevibesEnable) { if (value == LifevibesEnable) {
mLifeVibesClientPid = IPCThreadState::self()->getCallingPid();
musicEnabled = 1; musicEnabled = 1;
} else if (value == LifevibesDisable) { } else if (value == LifevibesDisable) {
mLifeVibesClientPid = -1;
musicEnabled = 0; musicEnabled = 0;
} }
} }
@@ -609,7 +612,7 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
mHardwareStatus = AUDIO_SET_PARAMETER; mHardwareStatus = AUDIO_SET_PARAMETER;
result = mAudioHardware->setParameters(keyValuePairs); result = mAudioHardware->setParameters(keyValuePairs);
#ifdef LVMX #ifdef LVMX
if ((NO_ERROR == result) && (musicEnabled != -1)) { if (musicEnabled != -1) {
LifeVibes::enableMusic((bool) musicEnabled); LifeVibes::enableMusic((bool) musicEnabled);
} }
#endif #endif
@@ -713,51 +716,57 @@ status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrame
void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
{ {
LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
sp<IBinder> binder = client->asBinder(); int pid = IPCThreadState::self()->getCallingPid();
if (mNotificationClients.indexOf(binder) < 0) { if (mNotificationClients.indexOfKey(pid) < 0) {
LOGV("Adding notification client %p", binder.get()); sp<NotificationClient> notificationClient = new NotificationClient(this,
binder->linkToDeath(this); client,
mNotificationClients.add(binder); pid);
} LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
// the config change is always sent from playback or record threads to avoid deadlock mNotificationClients.add(pid, notificationClient);
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
}
for (size_t i = 0; i < mRecordThreads.size(); i++) { sp<IBinder> binder = client->asBinder();
mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED); binder->linkToDeath(notificationClient);
}
}
void AudioFlinger::binderDied(const wp<IBinder>& who) { // 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++) {
mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
}
LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); for (size_t i = 0; i < mRecordThreads.size(); i++) {
Mutex::Autolock _l(mLock); mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
IBinder *binder = who.unsafe_get();
if (binder != NULL) {
int index = mNotificationClients.indexOf(binder);
if (index >= 0) {
LOGV("Removing notification client %p", binder);
mNotificationClients.removeAt(index);
} }
} }
} }
void AudioFlinger::removeNotificationClient(pid_t pid)
{
Mutex::Autolock _l(mLock);
int index = mNotificationClients.indexOfKey(pid);
if (index >= 0) {
sp <NotificationClient> client = mNotificationClients.valueFor(pid);
LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
#ifdef LVMX
if (pid == mLifeVibesClientPid) {
LOGV("Disabling lifevibes");
LifeVibes::enableMusic(false);
mLifeVibesClientPid = -1;
}
#endif
mNotificationClients.removeItem(pid);
}
}
// audioConfigChanged_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held
void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) { void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
{
size_t size = mNotificationClients.size(); size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
sp<IBinder> binder = mNotificationClients.itemAt(i); mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
client->ioConfigChanged(event, ioHandle, param2);
} }
} }
@@ -768,6 +777,7 @@ void AudioFlinger::removeClient_l(pid_t pid)
mClients.removeItem(pid); mClients.removeItem(pid);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id) AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
@@ -3086,6 +3096,28 @@ const sp<MemoryDealer>& AudioFlinger::Client::heap() const
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
const sp<IAudioFlingerClient>& client,
pid_t pid)
: mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
{
}
AudioFlinger::NotificationClient::~NotificationClient()
{
mClient.clear();
}
void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
{
sp<NotificationClient> keep(this);
{
mAudioFlinger->removeNotificationClient(mPid);
}
}
// ----------------------------------------------------------------------------
AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track) AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
: BnAudioTrack(), : BnAudioTrack(),
mTrack(track) mTrack(track)

View File

@@ -57,7 +57,7 @@ class AudioResampler;
static const nsecs_t kStandbyTimeInNsecs = seconds(3); static const nsecs_t kStandbyTimeInNsecs = seconds(3);
class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient class AudioFlinger : public BnAudioFlinger
{ {
public: public:
static void instantiate(); static void instantiate();
@@ -139,9 +139,6 @@ public:
virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output); virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output);
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
enum hardware_call_state { enum hardware_call_state {
AUDIO_HW_IDLE = 0, AUDIO_HW_IDLE = 0,
AUDIO_HW_INIT, AUDIO_HW_INIT,
@@ -205,6 +202,27 @@ private:
pid_t mPid; pid_t mPid;
}; };
// --- Notification Client ---
class NotificationClient : public IBinder::DeathRecipient {
public:
NotificationClient(const sp<AudioFlinger>& audioFlinger,
const sp<IAudioFlingerClient>& client,
pid_t pid);
virtual ~NotificationClient();
sp<IAudioFlingerClient> client() { return mClient; }
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
private:
NotificationClient(const NotificationClient&);
NotificationClient& operator = (const NotificationClient&);
sp<AudioFlinger> mAudioFlinger;
pid_t mPid;
sp<IAudioFlingerClient> mClient;
};
class TrackHandle; class TrackHandle;
class RecordHandle; class RecordHandle;
@@ -685,6 +703,7 @@ private:
void removeClient_l(pid_t pid); void removeClient_l(pid_t pid);
void removeNotificationClient(pid_t pid);
// record thread // record thread
@@ -796,8 +815,11 @@ private:
DefaultKeyedVector< int, sp<RecordThread> > mRecordThreads; DefaultKeyedVector< int, sp<RecordThread> > mRecordThreads;
SortedVector< sp<IBinder> > mNotificationClients; DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
int mNextThreadId; int mNextThreadId;
#ifdef LVMX
int mLifeVibesClientPid;
#endif
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------