From 0a887bcd5c5a8056735d221ad71afcff1f6eb1a6 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 30 Nov 2015 16:09:55 -0800 Subject: DO NOT MERGE SoundPool: add lock for findSample access from SoundPoolThread Sample decoding still occurs in SoundPoolThread without holding the SoundPool lock. Bug: 25781119 Change-Id: I11fde005aa9cf5438e0390a0d2dfe0ec1dd282e8 (cherry picked from commit 0275a982abecee683f16c827d405eafe51fb67ae) --- media/jni/soundpool/SoundPool.cpp | 41 ++++++++++++++++++++++++++------------- media/jni/soundpool/SoundPool.h | 4 ++-- 2 files changed, 29 insertions(+), 16 deletions(-) (limited to 'media') diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index a705bcc..d4b54c3 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -187,6 +187,17 @@ bool SoundPool::startThreads() return mDecodeThread != NULL; } +sp SoundPool::findSample(int sampleID) +{ + Mutex::Autolock lock(&mLock); + return findSample_l(sampleID); +} + +sp SoundPool::findSample_l(int sampleID) +{ + return mSamples.valueFor(sampleID); +} + SoundChannel* SoundPool::findChannel(int channelID) { for (int i = 0; i < mMaxChannels; ++i) { @@ -211,18 +222,21 @@ int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unuse { ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", fd, offset, length, priority); - Mutex::Autolock lock(&mLock); - sp sample = new Sample(++mNextSampleID, fd, offset, length); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -void SoundPool::doLoad(sp& sample) -{ - ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); - sample->startLoad(); - mDecodeThread->loadSample(sample->sampleID()); + int sampleID; + { + Mutex::Autolock lock(&mLock); + sampleID = ++mNextSampleID; + sp sample = new Sample(sampleID, fd, offset, length); + mSamples.add(sampleID, sample); + sample->startLoad(); + } + // mDecodeThread->loadSample() must be called outside of mLock. + // mDecodeThread->loadSample() may block on mDecodeThread message queue space; + // the message queue emptying may block on SoundPool::findSample(). + // + // It theoretically possible that sample loads might decode out-of-order. + mDecodeThread->loadSample(sampleID); + return sampleID; } bool SoundPool::unload(int sampleID) @@ -237,7 +251,6 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, { ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", sampleID, leftVolume, rightVolume, priority, loop, rate); - sp sample; SoundChannel* channel; int channelID; @@ -247,7 +260,7 @@ int SoundPool::play(int sampleID, float leftVolume, float rightVolume, return 0; } // is sample ready? - sample = findSample(sampleID); + sp sample(findSample_l(sampleID)); if ((sample == 0) || (sample->state() != Sample::READY)) { ALOGW(" sample %d not READY", sampleID); return 0; diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h index 4aacf53..98d2fa2 100644 --- a/media/jni/soundpool/SoundPool.h +++ b/media/jni/soundpool/SoundPool.h @@ -180,6 +180,7 @@ public: // called from SoundPoolThread void sampleLoaded(int sampleID); + sp findSample(int sampleID); // called from AudioTrack thread void done_l(SoundChannel* channel); @@ -191,8 +192,7 @@ public: private: SoundPool() {} // no default constructor bool startThreads(); - void doLoad(sp& sample); - sp findSample(int sampleID) { return mSamples.valueFor(sampleID); } + sp findSample_l(int sampleID); SoundChannel* findChannel (int channelID); SoundChannel* findNextChannel (int channelID); SoundChannel* allocateChannel_l(int priority, int sampleID); -- cgit v1.1