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

Commit 23704d3a authored by Glenn Kasten's avatar Glenn Kasten Committed by Android (Google) Code Review
Browse files

Merge "Mark similar and different sections in threadLoop"

parents f17981b3 bea6b952
Loading
Loading
Loading
Loading
+78 −9
Original line number Diff line number Diff line
@@ -1993,9 +1993,12 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l()

bool AudioFlinger::MixerThread::threadLoop()
{
    // DirectOutputThread has single trackToRemove instead of Vector
    Vector< sp<Track> > tracksToRemove;
    // DirectOutputThread has activeTrack here
    nsecs_t standbyTime = systemTime();
    size_t mixBufferSize = mFrameCount * mFrameSize;

    // FIXME: Relaxed timing because of a certain device that can't meet latency
    // Should be reduced to 2x after the vendor fixes the driver issue
    // increase threshold again due to low power audio mode. The way this warning threshold is
@@ -2003,18 +2006,25 @@ bool AudioFlinger::MixerThread::threadLoop()
    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
    nsecs_t lastWarning = 0;
    bool longStandbyExit = false;

    uint32_t activeSleepTime = activeSleepTimeUs();
    uint32_t idleSleepTime = idleSleepTimeUs();
    uint32_t sleepTime = idleSleepTime;

    uint32_t sleepTimeShift = 0;
    Vector< sp<EffectChain> > effectChains;
    CpuStats cpuStats;

    // DirectOutputThread has shorter standbyDelay

    acquireWakeLock();

    while (!exitPending())
    {
        cpuStats.sample();

        // DirectOutputThread has rampVolume, leftVol, rightVol

        processConfigEvents();

        mixer_state mixerStatus = MIXER_IDLE;
@@ -2024,13 +2034,16 @@ bool AudioFlinger::MixerThread::threadLoop()

            if (checkForNewParameters_l()) {
                mixBufferSize = mFrameCount * mFrameSize;

                // FIXME: Relaxed timing because of a certain device that can't meet latency
                // Should be reduced to 2x after the vendor fixes the driver issue
                // increase threshold again due to low power audio mode. The way this warning
                // threshold is calculated and its usefulness should be reconsidered anyway.
                maxPeriod = seconds(mFrameCount) / mSampleRate * 15;

                activeSleepTime = activeSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
                // DirectOutputThread updates standbyDelay also
            }

            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -2136,6 +2149,9 @@ bool AudioFlinger::MixerThread::threadLoop()

        // only process effects if we're going to write
        if (sleepTime == 0) {

            // DirectOutputThread adds applyVolume here

            for (size_t i = 0; i < effectChains.size(); i ++) {
                effectChains[i]->process_l();
            }
@@ -2146,14 +2162,16 @@ bool AudioFlinger::MixerThread::threadLoop()

        // sleepTime == 0 means we must write to audio hardware
        if (sleepTime == 0) {
            // FIXME Only in MixerThread, and rewrite to reduce number of system calls
            mLastWriteTime = systemTime();
            mInWrite = true;
            mBytesWritten += mixBufferSize;

            int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
            mNumWrites++;
            mInWrite = false;

            // Only in MixerThread: start of write blocked detection
            nsecs_t now = systemTime();
            nsecs_t delta = now - mLastWriteTime;
            if (!mStandby && delta > maxPeriod) {
@@ -2167,12 +2185,14 @@ bool AudioFlinger::MixerThread::threadLoop()
                    longStandbyExit = true;
                }
            }
            // end of write blocked detection

            mStandby = false;
        } else {
            usleep(sleepTime);
        }

        // finally let go of all our tracks, without the lock held
        // finally let go of removed track(s), without the lock held
        // since we can't guarantee the destructors won't acquire that
        // same lock.
        tracksToRemove.clear();
@@ -2182,6 +2202,7 @@ bool AudioFlinger::MixerThread::threadLoop()
        effectChains.clear();
    }

    // put output stream into standby mode
    if (!mStandby) {
        mOutput->stream->common.standby(&mOutput->stream->common);
    }
@@ -2706,13 +2727,21 @@ void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t ri

bool AudioFlinger::DirectOutputThread::threadLoop()
{
    // MixerThread has Vector instead of single trackToRemove
    sp<Track> trackToRemove;
    // MixerThread does not have activeTrack here
    sp<Track> activeTrack;
    nsecs_t standbyTime = systemTime();
    size_t mixBufferSize = mFrameCount * mFrameSize;

    // MixerThread has relaxed timing: maxPeriod, lastWarning, longStandbyExit

    uint32_t activeSleepTime = activeSleepTimeUs();
    uint32_t idleSleepTime = idleSleepTimeUs();
    uint32_t sleepTime = idleSleepTime;

    // MixerThread has sleepTimeShift and cpuStats

    // use shorter standby delay as on normal output to release
    // hardware resources as soon as possible
    nsecs_t standbyDelay = microseconds(activeSleepTime*2);
@@ -2721,9 +2750,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop()

    while (!exitPending())
    {
        // MixerThread has cpuStats.sample()

        bool rampVolume;
        uint16_t leftVol;
        uint16_t rightVol;

        Vector< sp<EffectChain> > effectChains;

        processConfigEvents();
@@ -2735,6 +2767,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop()

            if (checkForNewParameters_l()) {
                mixBufferSize = mFrameCount * mFrameSize;

                // different calculations here
                standbyDelay = microseconds(activeSleepTime*2);

                activeSleepTime = activeSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
                standbyDelay = microseconds(activeSleepTime*2);
@@ -2743,7 +2779,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
            // put audio hardware into standby after short delay
            if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
                        mSuspended)) {
                // wait until we have something to do...
                if (!mStandby) {
                    ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended);
                    mOutput->stream->common.standby(&mOutput->stream->common);
@@ -2758,19 +2793,27 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
                    if (exitPending()) break;

                    releaseWakeLock_l();
                    // wait until we have something to do...
                    ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid());
                    mWaitWorkCV.wait(mLock);
                    ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
                    acquireWakeLock_l();

                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
                    checkSilentMode_l();

                    // MixerThread has different standbyDelay
                    standbyTime = systemTime() + standbyDelay;
                    sleepTime = idleSleepTime;
                    // MixerThread has "sleepTimeShift = 0"
                    continue;
                }
            }

            // MixerThread has "mixerStatus = prepareTracks_l(...)"

            // equivalent to MixerThread's lockEffectChains_l, but without the lock
            // FIXME - is it OK to omit the lock here?
            effectChains = mEffectChains;

            // find out which tracks need to be processed
@@ -2939,9 +2982,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop()

        // only process effects if we're going to write
        if (sleepTime == 0) {

            // MixerThread does not have applyVolume
            if (mixerStatus == MIXER_TRACKS_READY) {
                applyVolume(leftVol, rightVol, rampVolume);
            }

            for (size_t i = 0; i < effectChains.size(); i ++) {
                effectChains[i]->process_l();
            }
@@ -2959,12 +3005,15 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
            mNumWrites++;
            mInWrite = false;

            // MixerThread has write blocked detection here

            mStandby = false;
        } else {
            usleep(sleepTime);
        }

        // finally let go of removed track, without the lock held
        // finally let go of removed track(s), without the lock held
        // since we can't guarantee the destructors won't acquire that
        // same lock.
        trackToRemove.clear();
@@ -2975,6 +3024,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
        effectChains.clear();
    }

    // put output stream into standby mode
    if (!mStandby) {
        mOutput->stream->common.standby(&mOutput->stream->common);
    }
@@ -3100,8 +3150,11 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
    Vector< sp<Track> > tracksToRemove;
    nsecs_t standbyTime = systemTime();
    size_t mixBufferSize = mFrameCount * mFrameSize;

    // Only in DuplicatingThread
    SortedVector< sp<OutputTrack> > outputTracks;
    uint32_t writeFrames = 0;

    uint32_t activeSleepTime = activeSleepTimeUs();
    uint32_t idleSleepTime = idleSleepTimeUs();
    uint32_t sleepTime = idleSleepTime;
@@ -3111,6 +3164,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop()

    while (!exitPending())
    {
        // MixerThread has cpuStats.sample

        processConfigEvents();

        mixer_state mixerStatus = MIXER_IDLE;
@@ -3120,13 +3175,17 @@ bool AudioFlinger::DuplicatingThread::threadLoop()

            if (checkForNewParameters_l()) {
                mixBufferSize = mFrameCount * mFrameSize;

                // Only in DuplicatingThread
                updateWaitTime();

                activeSleepTime = activeSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
            }

            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;

            // Only in DuplicatingThread
            for (size_t i = 0; i < mOutputTracks.size(); i++) {
                outputTracks.add(mOutputTracks[i]);
            }
@@ -3135,6 +3194,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
            if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
                         mSuspended)) {
                if (!mStandby) {
                    // DuplicatingThread implements standby by stopping all tracks
                    for (size_t i = 0; i < outputTracks.size(); i++) {
                        outputTracks[i]->stop();
                    }
@@ -3156,10 +3216,12 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
                    ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
                    acquireWakeLock_l();

                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
                    checkSilentMode_l();

                    standbyTime = systemTime() + mStandbyTimeInNsecs;
                    sleepTime = idleSleepTime;
                    // MixerThread has sleepTimeShift
                    continue;
                }
            }
@@ -3172,6 +3234,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
            lockEffectChains_l(effectChains);
        }

        // Duplicating Thread is completely different here
        if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
            // mix buffers...
            if (outputsReady(outputTracks)) {
@@ -3223,11 +3286,14 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
            }
            mStandby = false;
            mBytesWritten += mixBufferSize;

            // MixerThread has write blocked detection here

        } else {
            usleep(sleepTime);
        }

        // finally let go of all our tracks, without the lock held
        // finally let go of removed track(s), without the lock held
        // since we can't guarantee the destructors won't acquire that
        // same lock.
        tracksToRemove.clear();
@@ -3238,6 +3304,9 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
        effectChains.clear();
    }

    // MixerThread and DirectOutpuThread have standby here,
    // but for DuplicatingThread this is handled by the outputTracks

    releaseWakeLock();

    ALOGV("Thread %p type %d exiting", this, mType);