am ca20104a: Merge "Fix issue 2678048: binder death detection in AudioFlinger is broken." into kraken
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user