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

Commit 46b6b5df authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioFlinger: do not enter standby on offload stream when underrunning

When an offloaded track has been underrunning long enough for the
stream to enter standby, do not enter standby: entering standby will
release DSP resources and cause problems if we resume after recovering
from the underrun.

Bug: 322874013
Fixes: 333970720
Test: offload playback test with forced underrrun
Change-Id: I942fd3f401c226977f4f0684ed0e5a7a03db735d
Merged-In: I942fd3f401c226977f4f0684ed0e5a7a03db735d
parent 5c0ed421
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -375,6 +375,8 @@ public:
    virtual void triggerEvents(AudioSystem::sync_event_t type) = 0;

    virtual void disable() = 0;
    virtual bool isDisabled() const = 0;

    virtual int& fastIndex() = 0;
    virtual bool isPlaybackRestricted() const = 0;

+2 −0
Original line number Diff line number Diff line
@@ -275,6 +275,8 @@ protected:
    void triggerEvents(AudioSystem::sync_event_t type) final;
    void invalidate() final;
    void disable() final;
    bool isDisabled() const final;

    int& fastIndex() final { return mFastIndex; }
    bool isPlaybackRestricted() const final {
        // The monitor is only created for tracks that can be silenced.
+15 −10
Original line number Diff line number Diff line
@@ -6156,8 +6156,8 @@ PlaybackThread::mixer_state MixerThread::prepareTracks_l(
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                if (--(track->retryCount()) <= 0) {
                    ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p",
                            trackId, this);
                    ALOGI("%s BUFFER TIMEOUT: remove track(%d) from active list due to underrun"
                          " on thread %d", __func__, trackId, mId);
                    tracksToRemove->add(track);
                    // indicate to client process that the track was disabled because of underrun;
                    // it will then automatically call start() when data is available
@@ -6914,7 +6914,8 @@ PlaybackThread::mixer_state DirectOutputThread::prepareTracks_l(
                    if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
                        track->retryCount() = kMaxTrackRetriesOffload;
                    } else {
                        ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
                        ALOGI("%s BUFFER TIMEOUT: remove track(%d) from active list due to"
                              " underrun on thread %d", __func__, trackId, mId);
                        tracksToRemove->add(track);
                        // indicate to client process that the track was disabled because of
                        // underrun; it will then automatically call start() when data is available
@@ -7034,16 +7035,20 @@ bool DirectOutputThread::shouldStandby_l()
{
    bool trackPaused = false;
    bool trackStopped = false;
    bool trackDisabled = false;

    // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
    // do not put the HAL in standby when paused. NuPlayer clear the offloaded AudioTrack
    // after a timeout and we will enter standby then.
    // On offload threads, do not enter standby if the main track is still underrunning.
    if (mTracks.size() > 0) {
        trackPaused = mTracks[mTracks.size() - 1]->isPaused();
        trackStopped = mTracks[mTracks.size() - 1]->isStopped() ||
                           mTracks[mTracks.size() - 1]->state() == IAfTrackBase::IDLE;
        const auto& mainTrack = mTracks[mTracks.size() - 1];

        trackPaused = mainTrack->isPaused();
        trackStopped = mainTrack->isStopped() || mainTrack->state() == IAfTrackBase::IDLE;
        trackDisabled = (mType == OFFLOAD) && mainTrack->isDisabled();
    }

    return !mStandby && !(trackPaused || (mHwPaused && !trackStopped));
    return !mStandby && !(trackPaused || (mHwPaused && !trackStopped) || trackDisabled);
}

// checkForNewParameter_l() must be called with ThreadBase::mutex() held
@@ -7508,8 +7513,8 @@ PlaybackThread::mixer_state OffloadThread::prepareTracks_l(
                    if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
                        track->retryCount() = kMaxTrackRetriesOffload;
                    } else {
                        ALOGV("OffloadThread: BUFFER TIMEOUT: remove track(%d) from active list",
                                track->id());
                        ALOGI("%s BUFFER TIMEOUT: remove track(%d) from active list due to"
                              " underrun on thread %d", __func__, track->id(), mId);
                        tracksToRemove->add(track);
                        // tell client process that the track was disabled because of underrun;
                        // it will then automatically call start() when data is available
+6 −0
Original line number Diff line number Diff line
@@ -1881,6 +1881,12 @@ void Track::disable()
    signalClientFlag(CBLK_DISABLED);
}

bool Track::isDisabled() const {
    audio_track_cblk_t* cblk = mCblk;
    return (cblk != nullptr)
            && ((android_atomic_release_load(&cblk->mFlags) & CBLK_DISABLED) != 0);
}

void Track::signalClientFlag(int32_t flag)
{
    // FIXME should use proxy, and needs work