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

Commit 0cbec133 authored by Ziyang Cheng's avatar Ziyang Cheng Committed by Android (Google) Code Review
Browse files

Merge "Prevent offload underrun during active playback."

parents cd07037a 8f194f19
Loading
Loading
Loading
Loading
+35 −29
Original line number Diff line number Diff line
@@ -5889,6 +5889,20 @@ uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid) const
    return trackCount;
}

bool AudioFlinger::PlaybackThread::checkRunningTimestamp()
{
    uint64_t position = 0;
    struct timespec unused;
    const status_t ret = mOutput->getPresentationPosition(&position, &unused);
    if (ret == NO_ERROR) {
        if (position != mLastCheckedTimestampPosition) {
            mLastCheckedTimestampPosition = position;
            return true;
        }
    }
    return false;
}

// isTrackAllowed_l() must be called with ThreadBase::mLock held
bool AudioFlinger::MixerThread::isTrackAllowed_l(
        audio_channel_mask_t channelMask, audio_format_t format,
@@ -6317,10 +6331,14 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                // fill a buffer, then remove it from active list.
                // Only consider last track started for mixer state control
                if (--(track->mRetryCount) <= 0) {
                    const bool running = checkRunningTimestamp();
                    if (running) { // still running, give us more time.
                        track->mRetryCount = kMaxTrackRetriesOffload;
                    } else {
                        ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
                        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
                        // indicate to client process that the track was disabled because of
                        // underrun; it will then automatically call start() when data is available
                        track->disable();
                        // only do hw pause when track is going to be removed due to BUFFER TIMEOUT.
                        // unlike mixerthread, HAL can be paused for direct output
@@ -6331,6 +6349,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
                            doHwPause = true;
                            mHwPaused = true;
                        }
                    }
                } else if (last) {
                    mixerStatus = MIXER_TRACKS_ENABLED;
                }
@@ -6540,6 +6559,7 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l()

void AudioFlinger::DirectOutputThread::flushHw_l()
{
    PlaybackThread::flushHw_l();
    mOutput->flush();
    mHwPaused = false;
    mFlushPending = false;
@@ -6675,8 +6695,7 @@ void AudioFlinger::AsyncCallbackThread::setAsyncError()
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
        AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
    :   DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
        mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
        mOffloadUnderrunPosition(~0LL)
        mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
{
    //FIXME: mStandby should be set to true by ThreadBase constructo
    mStandby = true;
@@ -6893,19 +6912,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                if (--(track->mRetryCount) <= 0) {
                    bool running = false;
                    uint64_t position = 0;
                    struct timespec unused;
                    // The running check restarts the retry counter at least once.
                    status_t ret = mOutput->stream->getPresentationPosition(&position, &unused);
                    if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
                        running = true;
                        mOffloadUnderrunPosition = position;
                    }
                    if (ret == NO_ERROR) {
                        ALOGVV("underrun counter, running(%d): %lld vs %lld", running,
                                (long long)position, (long long)mOffloadUnderrunPosition);
                    }
                    const bool running = checkRunningTimestamp();
                    if (running) { // still running, give us more time.
                        track->mRetryCount = kMaxTrackRetriesOffload;
                    } else {
@@ -6976,7 +6983,6 @@ void AudioFlinger::OffloadThread::flushHw_l()
    mPausedBytesRemaining = 0;
    // reset bytes written count to reflect that DSP buffers are empty after flush.
    mBytesWritten = 0;
    mOffloadUnderrunPosition = ~0LL;

    if (mUseAsyncWrite) {
        // discard any pending drain or write ack by incrementing sequence
+10 −6
Original line number Diff line number Diff line
@@ -1376,6 +1376,14 @@ protected:
                struct audio_patch mDownStreamPatch;

                std::atomic_bool mCheckOutputStageEffects{};

                // A differential check on the timestamps to see if there is a change in the
                // timestamp frame position between the last call to checkRunningTimestamp.
                uint64_t mLastCheckedTimestampPosition = ~0LL;

                bool checkRunningTimestamp();

    virtual     void flushHw_l() { mLastCheckedTimestampPosition = ~0LL; }
};

class MixerThread : public PlaybackThread {
@@ -1493,7 +1501,7 @@ public:
    virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
                                                   status_t& status);

    virtual     void        flushHw_l();
                void        flushHw_l() override;

                void        setMasterBalance(float balance) override;

@@ -1558,7 +1566,7 @@ public:
    OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                  audio_io_handle_t id, bool systemReady);
    virtual                 ~OffloadThread() {};
    virtual     void        flushHw_l();
                void        flushHw_l() override;

protected:
    // threadLoop snippets
@@ -1575,10 +1583,6 @@ private:
    size_t      mPausedWriteLength;     // length in bytes of write interrupted by pause
    size_t      mPausedBytesRemaining;  // bytes still waiting in mixbuffer after resume
    bool        mKeepWakeLock;          // keep wake lock while waiting for write callback
    uint64_t    mOffloadUnderrunPosition; // Current frame position for offloaded playback
                                          // used and valid only during underrun.  ~0 if
                                          // no underrun has occurred during playback and
                                          // is not reset on standby.
};

class AsyncCallbackThread : public Thread {