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

Commit bd3b2b01 authored by Andy Hung's avatar Andy Hung
Browse files

AudioFlinger: remove false underruns if we retry for data

Test: see bug
Bug: 79999301
Change-Id: Ib35bd43ca59ea9f8857f08c5d6e7e3dbf68236a7
parent acb7d9dd
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -4273,6 +4273,37 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
    mMixerBufferValid = false;  // mMixerBuffer has no valid data until appropriate tracks found.
    mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found.

    // DeferredOperations handles statistics after setting mixerStatus.
    class DeferredOperations {
    public:
        DeferredOperations(mixer_state *mixerStatus)
            : mMixerStatus(mixerStatus) { }

        // when leaving scope, tally frames properly.
        ~DeferredOperations() {
            // Tally underrun frames only if we are actually mixing (MIXER_TRACKS_READY)
            // because that is when the underrun occurs.
            // We do not distinguish between FastTracks and NormalTracks here.
            if (*mMixerStatus == MIXER_TRACKS_READY) {
                for (const auto &underrun : mUnderrunFrames) {
                    underrun.first->mAudioTrackServerProxy->tallyUnderrunFrames(
                            underrun.second);
                }
            }
        }

        // tallyUnderrunFrames() is called to update the track counters
        // with the number of underrun frames for a particular mixer period.
        // We defer tallying until we know the final mixer status.
        void tallyUnderrunFrames(sp<Track> track, size_t underrunFrames) {
            mUnderrunFrames.emplace_back(track, underrunFrames);
        }

    private:
        const mixer_state * const mMixerStatus;
        std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
    } deferredOperations(&mixerStatus); // implicit nested scope for variable capture

    for (size_t i=0 ; i<count ; i++) {
        const sp<Track> t = mActiveTracks[i];

@@ -4307,13 +4338,14 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
            track->mObservedUnderruns = underruns;
            // don't count underruns that occur while stopping or pausing
            // or stopped which can occur when flush() is called while active
            size_t underrunFrames = 0;
            if (!(track->isStopping() || track->isPausing() || track->isStopped()) &&
                    recentUnderruns > 0) {
                // FIXME fast mixer will pull & mix partial buffers, but we count as a full underrun
                track->mAudioTrackServerProxy->tallyUnderrunFrames(recentUnderruns * mFrameCount);
            } else {
                track->mAudioTrackServerProxy->tallyUnderrunFrames(0);
                underrunFrames = recentUnderruns * mFrameCount;
            }
            // Immediately account for FastTrack underruns.
            track->mAudioTrackServerProxy->tallyUnderrunFrames(underrunFrames);

            // This is similar to the state machine for normal tracks,
            // with a few modifications for fast tracks.
@@ -4728,13 +4760,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
                mixerStatus = MIXER_TRACKS_READY;
            }
        } else {
            size_t underrunFrames = 0;
            if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
                ALOGV("track(%p) underrun,  framesReady(%zu) < framesDesired(%zd)",
                        track, framesReady, desiredFrames);
                track->mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
            } else {
                track->mAudioTrackServerProxy->tallyUnderrunFrames(0);
                underrunFrames = desiredFrames;
            }
            deferredOperations.tallyUnderrunFrames(track, underrunFrames);

            // clear effect chain input buffer if an active track underruns to avoid sending
            // previous audio buffer again to effects