Merge "SoundPool: Implement generic garbage collection"
This commit is contained in:
commit
361e9e1da9
@ -228,10 +228,9 @@ Stream* Stream::getPairStream() const
|
||||
return mStreamManager->getPairStream(this);
|
||||
}
|
||||
|
||||
Stream* Stream::playPairStream() {
|
||||
Stream* Stream::playPairStream(std::vector<std::any>& garbage) {
|
||||
Stream* pairStream = getPairStream();
|
||||
LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!");
|
||||
sp<AudioTrack> releaseTracks[2];
|
||||
{
|
||||
ALOGV("%s: track streamID: %d", __func__, (int)getStreamID());
|
||||
// TODO: Do we really want to force a simultaneous synchronization between
|
||||
@ -260,7 +259,7 @@ Stream* Stream::playPairStream() {
|
||||
const int pairState = pairStream->mState;
|
||||
pairStream->play_l(pairStream->mSound, pairStream->mStreamID,
|
||||
pairStream->mLeftVolume, pairStream->mRightVolume, pairStream->mPriority,
|
||||
pairStream->mLoop, pairStream->mRate, releaseTracks);
|
||||
pairStream->mLoop, pairStream->mRate, garbage);
|
||||
if (pairStream->mState == IDLE) {
|
||||
return nullptr; // AudioTrack error
|
||||
}
|
||||
@ -269,17 +268,16 @@ Stream* Stream::playPairStream() {
|
||||
pairStream->mAudioTrack->pause();
|
||||
}
|
||||
}
|
||||
// release tracks outside of Stream lock
|
||||
return pairStream;
|
||||
}
|
||||
|
||||
void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
|
||||
float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate,
|
||||
sp<AudioTrack> releaseTracks[2])
|
||||
std::vector<std::any>& garbage)
|
||||
{
|
||||
// These tracks are released without the lock.
|
||||
sp<AudioTrack> &oldTrack = releaseTracks[0];
|
||||
sp<AudioTrack> &newTrack = releaseTracks[1];
|
||||
// oldTrack and newTrack are placeholders to be released by garbage without the lock.
|
||||
sp<AudioTrack> oldTrack;
|
||||
sp<AudioTrack> newTrack;
|
||||
status_t status = NO_ERROR;
|
||||
|
||||
{
|
||||
@ -383,8 +381,12 @@ exit:
|
||||
mState = IDLE;
|
||||
mSoundID = 0;
|
||||
mSound.reset();
|
||||
mAudioTrack.clear(); // actual release from releaseTracks[]
|
||||
mAudioTrack.clear(); // actual release from garbage
|
||||
}
|
||||
|
||||
// move tracks to garbage to be released later outside of lock.
|
||||
if (newTrack) garbage.emplace_back(std::move(newTrack));
|
||||
if (oldTrack) garbage.emplace_back(std::move(oldTrack));
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
#include <any>
|
||||
#include <android-base/thread_annotations.h>
|
||||
#include <audio_utils/clock.h>
|
||||
#include <media/AudioTrack.h>
|
||||
@ -90,8 +91,9 @@ public:
|
||||
void mute(bool muting);
|
||||
void dump() const NO_THREAD_SAFETY_ANALYSIS; // disable for ALOGV (see func for details).
|
||||
|
||||
// returns the pair stream if successful, nullptr otherwise
|
||||
Stream* playPairStream();
|
||||
// returns the pair stream if successful, nullptr otherwise.
|
||||
// garbage is used to release tracks and data outside of any lock.
|
||||
Stream* playPairStream(std::vector<std::any>& garbage);
|
||||
|
||||
// These parameters are explicitly checked in the SoundPool class
|
||||
// so never deviate from the Java API specified values.
|
||||
@ -123,9 +125,10 @@ public:
|
||||
Stream* getPairStream() const;
|
||||
|
||||
private:
|
||||
// garbage is used to release tracks and data outside of any lock.
|
||||
void play_l(const std::shared_ptr<Sound>& sound, int streamID,
|
||||
float leftVolume, float rightVolume, int priority, int loop, float rate,
|
||||
sp<AudioTrack> releaseTracks[2]) REQUIRES(mLock);
|
||||
std::vector<std::any>& garbage) REQUIRES(mLock);
|
||||
void stop_l() REQUIRES(mLock);
|
||||
void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
|
||||
|
||||
|
@ -157,6 +157,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
|
||||
__func__, sound.get(), soundID, leftVolume, rightVolume, priority, loop, rate);
|
||||
bool launchThread = false;
|
||||
int32_t streamID = 0;
|
||||
std::vector<std::any> garbage;
|
||||
|
||||
{ // for lock
|
||||
std::unique_lock lock(mStreamManagerLock);
|
||||
@ -243,7 +244,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
|
||||
removeFromQueues_l(newStream);
|
||||
mProcessingStreams.emplace(newStream);
|
||||
lock.unlock();
|
||||
if (Stream* nextStream = newStream->playPairStream()) {
|
||||
if (Stream* nextStream = newStream->playPairStream(garbage)) {
|
||||
lock.lock();
|
||||
ALOGV("%s: starting streamID:%d", __func__, nextStream->getStreamID());
|
||||
addToActiveQueue_l(nextStream);
|
||||
@ -266,6 +267,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
|
||||
ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id);
|
||||
}
|
||||
ALOGV("%s: returning %d", __func__, streamID);
|
||||
// garbage is cleared here outside mStreamManagerLock.
|
||||
return streamID;
|
||||
}
|
||||
|
||||
@ -359,6 +361,7 @@ void StreamManager::run(int32_t id)
|
||||
{
|
||||
ALOGV("%s(%d) entering", __func__, id);
|
||||
int64_t waitTimeNs = 0; // on thread start, mRestartStreams can be non-empty.
|
||||
std::vector<std::any> garbage; // used for garbage collection
|
||||
std::unique_lock lock(mStreamManagerLock);
|
||||
while (!mQuit) {
|
||||
if (waitTimeNs > 0) {
|
||||
@ -388,7 +391,7 @@ void StreamManager::run(int32_t id)
|
||||
if (!mLockStreamManagerStop) lock.unlock();
|
||||
stream->stop();
|
||||
ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID());
|
||||
if (Stream* nextStream = stream->playPairStream()) {
|
||||
if (Stream* nextStream = stream->playPairStream(garbage)) {
|
||||
ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID());
|
||||
if (!mLockStreamManagerStop) lock.lock();
|
||||
if (nextStream->getStopTimeNs() > 0) {
|
||||
@ -405,6 +408,12 @@ void StreamManager::run(int32_t id)
|
||||
}
|
||||
mProcessingStreams.erase(stream);
|
||||
sanityCheckQueue_l();
|
||||
if (!garbage.empty()) {
|
||||
lock.unlock();
|
||||
// garbage audio tracks (etc) are cleared here outside mStreamManagerLock.
|
||||
garbage.clear();
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
ALOGV("%s(%d) exiting", __func__, id);
|
||||
|
Loading…
x
Reference in New Issue
Block a user