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

Commit 23666474 authored by Kuowei Li's avatar Kuowei Li Committed by Andy Hung
Browse files

AudioFlinger: Fix direct output resource from being occupied for too long

When flush immediately follows pause, mState might be overwritten and not
processed. In this case, direct output will retry due to data underrun.
In the duration of retry, the ActiveCount in AudioPolicy will be
positive and user can't create new track.
Add isPausePending to make sure pause will be handled by the
direct output thread.

Test: Manual (see bug)
Test: Clarity MediaPlayer Offloaded with seek.
Bug: 175092336
Change-Id: Ief742d2ce44917da24885373a5770e47876bc3a5
parent f2efd2a6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -217,6 +217,10 @@ protected:
    void flushAck();
    bool isResumePending();
    void resumeAck();
    // For direct or offloaded tracks ensure that the pause state is acknowledged
    // by the playback thread in case of an immediate flush.
    bool isPausePending() const { return mPauseHwPending; }
    void pauseAck();
    void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten,
            uint32_t halSampleRate, const ExtendedTimestamp &timeStamp);

@@ -312,6 +316,7 @@ private:
    sp<AudioTrackServerProxy>  mAudioTrackServerProxy;
    bool                mResumeToStopping; // track was paused in stopping state.
    bool                mFlushHwPending; // track requests for thread flush
    bool                mPauseHwPending = false; // direct/offload track request for thread pause
    audio_output_flags_t mFlags;
    // If the last track change was notified to the client with readAndClearHasChanged
    std::atomic_flag     mChangeNotified = ATOMIC_FLAG_INIT;
+18 −4
Original line number Diff line number Diff line
@@ -5825,8 +5825,15 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
        sp<Track> l = mActiveTracks.getLatest();
        bool last = l.get() == track;

        if (track->isPausePending()) {
            track->pauseAck();
            // It is possible a track might have been flushed or stopped.
            // Other operations such as flush pending might occur on the next prepare.
            if (track->isPausing()) {
                track->setPaused();
            }
            // Always perform pause, as an immediate flush will change
            // the pause state to be no longer isPausing().
            if (mHwSupportsPause && last && !mHwPaused) {
                doHwPause = true;
                mHwPaused = true;
@@ -6368,8 +6375,15 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
            continue;
        }

        if (track->isPausePending()) {
            track->pauseAck();
            // It is possible a track might have been flushed or stopped.
            // Other operations such as flush pending might occur on the next prepare.
            if (track->isPausing()) {
                track->setPaused();
            }
            // Always perform pause if last, as an immediate flush will change
            // the pause state to be no longer isPausing().
            if (last) {
                if (mHwSupportsPause && !mHwPaused) {
                    doHwPause = true;
+8 −0
Original line number Diff line number Diff line
@@ -1177,6 +1177,9 @@ void AudioFlinger::PlaybackThread::Track::pause()
            mState = PAUSING;
            ALOGV("%s(%d): ACTIVE/RESUMING => PAUSING on thread %d",
                    __func__, mId, (int)mThreadIoHandle);
            if (isOffloadedOrDirect()) {
                mPauseHwPending = true;
            }
            playbackThread->broadcast_l();
            break;

@@ -1264,6 +1267,11 @@ void AudioFlinger::PlaybackThread::Track::flushAck()
    mFlushHwPending = false;
}

void AudioFlinger::PlaybackThread::Track::pauseAck()
{
    mPauseHwPending = false;
}

void AudioFlinger::PlaybackThread::Track::reset()
{
    // Do not reset twice to avoid discarding data written just after a flush and before