Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 135ebfe0 authored by Andy Hung's avatar Andy Hung Committed by Automerger Merge Worker
Browse files

Merge "SoundPool: Implement generic garbage collection" am: 361e9e1d

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

Change-Id: I367d1f2dc65e2a2837f50782e17b2b19b5289265
parents 35d612b5 361e9e1d
Loading
Loading
Loading
Loading
+11 −9
Original line number Original line Diff line number Diff line
@@ -228,10 +228,9 @@ Stream* Stream::getPairStream() const
   return mStreamManager->getPairStream(this);
   return mStreamManager->getPairStream(this);
}
}


Stream* Stream::playPairStream() {
Stream* Stream::playPairStream(std::vector<std::any>& garbage) {
    Stream* pairStream = getPairStream();
    Stream* pairStream = getPairStream();
    LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!");
    LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!");
    sp<AudioTrack> releaseTracks[2];
    {
    {
        ALOGV("%s: track streamID: %d", __func__, (int)getStreamID());
        ALOGV("%s: track streamID: %d", __func__, (int)getStreamID());
        // TODO: Do we really want to force a simultaneous synchronization between
        // TODO: Do we really want to force a simultaneous synchronization between
@@ -260,7 +259,7 @@ Stream* Stream::playPairStream() {
        const int pairState = pairStream->mState;
        const int pairState = pairStream->mState;
        pairStream->play_l(pairStream->mSound, pairStream->mStreamID,
        pairStream->play_l(pairStream->mSound, pairStream->mStreamID,
                pairStream->mLeftVolume, pairStream->mRightVolume, pairStream->mPriority,
                pairStream->mLeftVolume, pairStream->mRightVolume, pairStream->mPriority,
                pairStream->mLoop, pairStream->mRate, releaseTracks);
                pairStream->mLoop, pairStream->mRate, garbage);
        if (pairStream->mState == IDLE) {
        if (pairStream->mState == IDLE) {
            return nullptr; // AudioTrack error
            return nullptr; // AudioTrack error
        }
        }
@@ -269,17 +268,16 @@ Stream* Stream::playPairStream() {
            pairStream->mAudioTrack->pause();
            pairStream->mAudioTrack->pause();
        }
        }
    }
    }
    // release tracks outside of Stream lock
    return pairStream;
    return pairStream;
}
}


void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
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,
        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.
    // oldTrack and newTrack are placeholders to be released by garbage without the lock.
    sp<AudioTrack> &oldTrack = releaseTracks[0];
    sp<AudioTrack> oldTrack;
    sp<AudioTrack> &newTrack = releaseTracks[1];
    sp<AudioTrack> newTrack;
    status_t status = NO_ERROR;
    status_t status = NO_ERROR;


    {
    {
@@ -383,8 +381,12 @@ exit:
        mState = IDLE;
        mState = IDLE;
        mSoundID = 0;
        mSoundID = 0;
        mSound.reset();
        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 */
/* static */
+6 −3
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@


#include "Sound.h"
#include "Sound.h"


#include <any>
#include <android-base/thread_annotations.h>
#include <android-base/thread_annotations.h>
#include <audio_utils/clock.h>
#include <audio_utils/clock.h>
#include <media/AudioTrack.h>
#include <media/AudioTrack.h>
@@ -90,8 +91,9 @@ public:
    void mute(bool muting);
    void mute(bool muting);
    void dump() const NO_THREAD_SAFETY_ANALYSIS; // disable for ALOGV (see func for details).
    void dump() const NO_THREAD_SAFETY_ANALYSIS; // disable for ALOGV (see func for details).


    // returns the pair stream if successful, nullptr otherwise
    // returns the pair stream if successful, nullptr otherwise.
    Stream* playPairStream();
    // 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
    // These parameters are explicitly checked in the SoundPool class
    // so never deviate from the Java API specified values.
    // so never deviate from the Java API specified values.
@@ -123,9 +125,10 @@ public:
    Stream* getPairStream() const;
    Stream* getPairStream() const;


private:
private:
    // garbage is used to release tracks and data outside of any lock.
    void play_l(const std::shared_ptr<Sound>& sound, int streamID,
    void play_l(const std::shared_ptr<Sound>& sound, int streamID,
            float leftVolume, float rightVolume, int priority, int loop, float rate,
            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 stop_l() REQUIRES(mLock);
    void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
    void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);


+11 −2
Original line number Original line Diff line number Diff line
@@ -157,6 +157,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
            __func__, sound.get(), soundID, leftVolume, rightVolume, priority, loop, rate);
            __func__, sound.get(), soundID, leftVolume, rightVolume, priority, loop, rate);
    bool launchThread = false;
    bool launchThread = false;
    int32_t streamID = 0;
    int32_t streamID = 0;
    std::vector<std::any> garbage;


    { // for lock
    { // for lock
        std::unique_lock lock(mStreamManagerLock);
        std::unique_lock lock(mStreamManagerLock);
@@ -243,7 +244,7 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
            removeFromQueues_l(newStream);
            removeFromQueues_l(newStream);
            mProcessingStreams.emplace(newStream);
            mProcessingStreams.emplace(newStream);
            lock.unlock();
            lock.unlock();
            if (Stream* nextStream = newStream->playPairStream()) {
            if (Stream* nextStream = newStream->playPairStream(garbage)) {
                lock.lock();
                lock.lock();
                ALOGV("%s: starting streamID:%d", __func__, nextStream->getStreamID());
                ALOGV("%s: starting streamID:%d", __func__, nextStream->getStreamID());
                addToActiveQueue_l(nextStream);
                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_IF(id != 0, "%s: launched thread %d", __func__, id);
    }
    }
    ALOGV("%s: returning %d", __func__, streamID);
    ALOGV("%s: returning %d", __func__, streamID);
    // garbage is cleared here outside mStreamManagerLock.
    return streamID;
    return streamID;
}
}


@@ -359,6 +361,7 @@ void StreamManager::run(int32_t id)
{
{
    ALOGV("%s(%d) entering", __func__, id);
    ALOGV("%s(%d) entering", __func__, id);
    int64_t waitTimeNs = 0;  // on thread start, mRestartStreams can be non-empty.
    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);
    std::unique_lock lock(mStreamManagerLock);
    while (!mQuit) {
    while (!mQuit) {
        if (waitTimeNs > 0) {
        if (waitTimeNs > 0) {
@@ -388,7 +391,7 @@ void StreamManager::run(int32_t id)
            if (!mLockStreamManagerStop) 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(garbage)) {
                ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID());
                ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID());
                if (!mLockStreamManagerStop) lock.lock();
                if (!mLockStreamManagerStop) lock.lock();
                if (nextStream->getStopTimeNs() > 0) {
                if (nextStream->getStopTimeNs() > 0) {
@@ -405,6 +408,12 @@ void StreamManager::run(int32_t id)
            }
            }
            mProcessingStreams.erase(stream);
            mProcessingStreams.erase(stream);
            sanityCheckQueue_l();
            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);
    ALOGV("%s(%d) exiting", __func__, id);