Merge "SoundPool: Improve single stream SoundPool handling" am: 0f8c08544a am: 4140a29ad5

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1640980

Change-Id: Ia9a5ec255a1d35dbefe882980db682a077079888
This commit is contained in:
Andy Hung
2021-03-16 23:35:24 +00:00
committed by Automerger Merge Worker
2 changed files with 22 additions and 6 deletions

View File

@@ -43,6 +43,14 @@ static constexpr bool kPlayOnCallingThread = true;
// Amount of time for a StreamManager thread to wait before closing. // Amount of time for a StreamManager thread to wait before closing.
static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND; static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
// Debug flag:
// kForceLockStreamManagerStop is set to true to force lock the StreamManager
// worker thread during stop. This limits concurrency of Stream processing.
// Normally we lock the StreamManager worker thread during stop ONLY
// for SoundPools configured with a single Stream.
//
static constexpr bool kForceLockStreamManagerStop = false;
//////////// ////////////
StreamMap::StreamMap(int32_t streams) { StreamMap::StreamMap(int32_t streams) {
@@ -103,6 +111,7 @@ StreamManager::StreamManager(
: StreamMap(streams) : StreamMap(streams)
, mAttributes(*attributes) , mAttributes(*attributes)
, mOpPackageName(std::move(opPackageName)) , mOpPackageName(std::move(opPackageName))
, mLockStreamManagerStop(streams == 1 || kForceLockStreamManagerStop)
{ {
ALOGV("%s(%d, %zu, ...)", __func__, streams, threads); ALOGV("%s(%d, %zu, ...)", __func__, streams, threads);
forEach([this](Stream *stream) { forEach([this](Stream *stream) {
@@ -113,7 +122,8 @@ StreamManager::StreamManager(
}); });
mThreadPool = std::make_unique<ThreadPool>( mThreadPool = std::make_unique<ThreadPool>(
std::min(threads, (size_t)std::thread::hardware_concurrency()), std::min((size_t)streams, // do not make more threads than streams to play
std::min(threads, (size_t)std::thread::hardware_concurrency())),
"SoundPool_"); "SoundPool_");
} }
@@ -375,12 +385,12 @@ void StreamManager::run(int32_t id)
} }
mRestartStreams.erase(it); mRestartStreams.erase(it);
mProcessingStreams.emplace(stream); mProcessingStreams.emplace(stream);
lock.unlock(); if (!mLockStreamManagerStop) lock.unlock();
stream->stop(); stream->stop();
ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID()); ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID());
if (Stream* nextStream = stream->playPairStream()) { if (Stream* nextStream = stream->playPairStream()) {
ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID()); ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID());
lock.lock(); if (!mLockStreamManagerStop) lock.lock();
if (nextStream->getStopTimeNs() > 0) { if (nextStream->getStopTimeNs() > 0) {
// the next stream was stopped before we can move it to the active queue. // the next stream was stopped before we can move it to the active queue.
ALOGV("%s(%d) stopping started streamID:%d", ALOGV("%s(%d) stopping started streamID:%d",
@@ -390,7 +400,7 @@ void StreamManager::run(int32_t id)
addToActiveQueue_l(nextStream); addToActiveQueue_l(nextStream);
} }
} else { } else {
lock.lock(); if (!mLockStreamManagerStop) lock.lock();
mAvailableStreams.insert(stream); mAvailableStreams.insert(stream);
} }
mProcessingStreams.erase(stream); mProcessingStreams.erase(stream);

View File

@@ -437,6 +437,14 @@ private:
void sanityCheckQueue_l() const REQUIRES(mStreamManagerLock); void sanityCheckQueue_l() const REQUIRES(mStreamManagerLock);
const audio_attributes_t mAttributes; const audio_attributes_t mAttributes;
const std::string mOpPackageName;
// For legacy compatibility, we lock the stream manager on stop when
// there is only one stream. This allows a play to be called immediately
// after stopping, otherwise it is possible that the play might be discarded
// (returns 0) because that stream may be in the worker thread call to stop.
const bool mLockStreamManagerStop;
std::unique_ptr<ThreadPool> mThreadPool; // locked internally std::unique_ptr<ThreadPool> mThreadPool; // locked internally
// mStreamManagerLock is used to lock access for transitions between the // mStreamManagerLock is used to lock access for transitions between the
@@ -477,8 +485,6 @@ private:
// The paired stream may be active or restarting. // The paired stream may be active or restarting.
// No particular order. // No particular order.
std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock); std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock);
const std::string mOpPackageName;
}; };
} // namespace android::soundpool } // namespace android::soundpool