summaryrefslogtreecommitdiffstats
path: root/libs/audioflinger
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2009-08-10 23:22:32 -0700
committerEric Laurent <elaurent@google.com>2009-08-11 09:43:09 -0700
commit6c30a71122a6ef2189304c136f13a87727804b0a (patch)
tree751724a4b228a74384fae3e7cbb4ff11bd7aca82 /libs/audioflinger
parent33bb0c9f2acaa4300e962f9039e08bffc735ab8e (diff)
downloadframeworks_base-6c30a71122a6ef2189304c136f13a87727804b0a.zip
frameworks_base-6c30a71122a6ef2189304c136f13a87727804b0a.tar.gz
frameworks_base-6c30a71122a6ef2189304c136f13a87727804b0a.tar.bz2
Fix issue 2046140: master: media_server crash when powering down A2DP headset while a ringtone is playing.
This is because the AudioFlinger duplicating thread is closed while the output tracks are still active. This cause the output tracks objects to be destroyed at a time where they can be in use by the destination output mixer. The fix consists in adding the OutputTrack to the track list (mTracks) of its destination thread so that a strong reference is help during the mixer processed and the track is detroyed only when safe by destination thread. Also added detection of problems when creating the output track (e.g. no more tracks in mixer). In this case the output track is not added to output track list of duplicating thread.
Diffstat (limited to 'libs/audioflinger')
-rw-r--r--libs/audioflinger/AudioFlinger.cpp49
-rw-r--r--libs/audioflinger/AudioFlinger.h6
2 files changed, 30 insertions, 25 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index fab75ef..77a126c 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1860,9 +1860,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
mSuspended) {
if (!mStandby) {
for (size_t i = 0; i < outputTracks.size(); i++) {
- mLock.unlock();
outputTracks[i]->stop();
- mLock.lock();
}
mStandby = true;
mBytesWritten = 0;
@@ -1903,9 +1901,9 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
if (!mSuspended) {
for (size_t i = 0; i < outputTracks.size(); i++) {
outputTracks[i]->write(curBuf, mFrameCount);
+ mustSleep = false;
}
mStandby = false;
- mustSleep = false;
mBytesWritten += mixBufferSize;
}
} else {
@@ -1935,11 +1933,14 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
outputTracks.clear();
}
- if (!mStandby) {
- for (size_t i = 0; i < outputTracks.size(); i++) {
- mLock.unlock();
- outputTracks[i]->stop();
- mLock.lock();
+ { // scope for the mLock
+
+ Mutex::Autolock _l(mLock);
+ if (!mStandby) {
+ LOGV("DuplicatingThread() exiting out of standby");
+ for (size_t i = 0; i < mOutputTracks.size(); i++) {
+ mOutputTracks[i]->destroy();
+ }
}
}
@@ -1957,9 +1958,11 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
mFormat,
mChannelCount,
frameCount);
- thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
- mOutputTracks.add(outputTrack);
- LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+ if (outputTrack->cblk() != NULL) {
+ thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
+ mOutputTracks.add(outputTrack);
+ LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+ }
}
void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
@@ -1967,6 +1970,7 @@ void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mOutputTracks.size(); i++) {
if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
+ mOutputTracks[i]->destroy();
mOutputTracks.removeAt(i);
return;
}
@@ -2456,20 +2460,23 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
{
PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
- mCblk->out = 1;
- mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->volume[0] = mCblk->volume[1] = 0x1000;
- mOutBuffer.frameCount = 0;
- mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
-
- LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
- mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
-
+ if (mCblk != NULL) {
+ mCblk->out = 1;
+ mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+ mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+ mOutBuffer.frameCount = 0;
+ mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
+ playbackThread->mTracks.add(this);
+ LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
+ mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
+ } else {
+ LOGW("Error creating output track on thread %p", playbackThread);
+ }
}
AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
{
- stop();
+ clearBufferQueue();
}
status_t AudioFlinger::PlaybackThread::OutputTrack::start()
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 4ba5977..65c148e 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -245,6 +245,7 @@ private:
virtual status_t start() = 0;
virtual void stop() = 0;
sp<IMemory> getCblk() const;
+ audio_track_cblk_t* cblk() const { return mCblk; }
protected:
friend class ThreadBase;
@@ -260,10 +261,6 @@ private:
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
- audio_track_cblk_t* cblk() const {
- return mCblk;
- }
-
int format() const {
return mFormat;
}
@@ -528,6 +525,7 @@ private:
private:
friend class AudioFlinger;
+ friend class OutputTrack;
friend class Track;
friend class TrackBase;
friend class MixerThread;