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

Commit aef692f5 authored by Eric Laurent's avatar Eric Laurent
Browse files

Fix issue 2116700: Ringer screwy while connected over Bluetooth.

There was a regression introduced in AudioFlinger by change 24114 for suspended output:
The suspended output was not reading and mixing audio tracks.
When the phone is ringing, the A2DP output is suspended if the SCO headset and A2DP headset are the same. As the ringtone is played over the duplicated output, the fact that the A2DP output was not reading data was causing the hardware output to be stalled from time to time.
parent 31c07199
Loading
Loading
Loading
Loading
+106 −97
Original line number Diff line number Diff line
@@ -1227,11 +1227,6 @@ bool AudioFlinger::MixerThread::threadLoop()
            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
       }


        // output audio to hardware
        if (mSuspended) {
            usleep(kMaxBufferRecoveryInUsecs);
        } else {
        if (LIKELY(enabledTracks)) {
            // mix buffers...
            mAudioMixer->process(curBuf);
@@ -1239,21 +1234,27 @@ bool AudioFlinger::MixerThread::threadLoop()
            standbyTime = systemTime() + kStandbyTimeInNsecs;
        } else {
            sleepTime += kBufferRecoveryInUsecs;
            if (sleepTime > kMaxBufferRecoveryInUsecs) {
                sleepTime = kMaxBufferRecoveryInUsecs;
            }
            // There was nothing to mix this round, which means all
            // active tracks were late. Sleep a little bit to give
            // them another chance. If we're too late, write 0s to audio
            // hardware to avoid underrun.
                if (mBytesWritten == 0 || sleepTime < kMaxBufferRecoveryInUsecs) {
                    usleep(kBufferRecoveryInUsecs);
                } else {
            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) {
                memset (curBuf, 0, mixBufferSize);
                sleepTime = 0;
            }
        }
            // sleepTime == 0 means PCM data were written to mMixBuffer[]

        if (mSuspended) {
            sleepTime = kMaxBufferRecoveryInUsecs;
        }
        // sleepTime == 0 means we must write to audio hardware
        if (sleepTime == 0) {
            mLastWriteTime = systemTime();
            mInWrite = true;
            LOGV("mOutput->write() thread %p frames %d", this, mFrameCount);
            int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
            if (bytesWritten > 0) mBytesWritten += bytesWritten;
            mNumWrites++;
@@ -1261,10 +1262,11 @@ bool AudioFlinger::MixerThread::threadLoop()
            mStandby = false;
            nsecs_t delta = systemTime() - mLastWriteTime;
            if (delta > maxPeriod) {
                    LOGW("write blocked for %llu msecs", ns2ms(delta));
                LOGW("write blocked for %llu msecs, thread %p", ns2ms(delta), this);
                mNumDelayedWrites++;
            }
            }
        } else {
            usleep(sleepTime);
        }

        // finally let go of all our tracks, without the lock held
@@ -1718,10 +1720,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
            }
       }

        // output audio to hardware
        if (mSuspended) {
            usleep(kMaxBufferRecoveryInUsecs);
        } else {
        if (activeTrack != 0) {
            AudioBufferProvider::Buffer buffer;
            size_t frameCount = mFrameCount;
@@ -1743,16 +1741,24 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
            standbyTime = systemTime() + kStandbyTimeInNsecs;
        } else {
            sleepTime += kBufferRecoveryInUsecs;
                if (mBytesWritten == 0 || !AudioSystem::isLinearPCM(mFormat) ||
                    sleepTime < kMaxBufferRecoveryInUsecs) {
                    usleep(kBufferRecoveryInUsecs);
                } else {
            if (sleepTime > kMaxBufferRecoveryInUsecs) {
                sleepTime = kMaxBufferRecoveryInUsecs;
            }
            // There was nothing to mix this round, which means all
            // active tracks were late. Sleep a little bit to give
            // them another chance. If we're too late, write 0s to audio
            // hardware to avoid underrun.
            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs &&
                AudioSystem::isLinearPCM(mFormat)) {
                memset (mMixBuffer, 0, mFrameCount * mFrameSize);
                sleepTime = 0;
            }
        }

            // sleepTime == 0 means PCM data were written to mMixBuffer[]
        if (mSuspended) {
            sleepTime = kMaxBufferRecoveryInUsecs;
        }
        // sleepTime == 0 means we must write to audio hardware
        if (sleepTime == 0) {
            mLastWriteTime = systemTime();
            mInWrite = true;
@@ -1761,7 +1767,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
            mNumWrites++;
            mInWrite = false;
            mStandby = false;
            }
        } else {
            usleep(sleepTime);
        }

        // finally let go of removed track, without the lock held
@@ -1915,36 +1922,38 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
        }

        bool mustSleep = true;
        if (LIKELY(enabledTracks)) {
            // mix buffers...
            mAudioMixer->process(curBuf);
            if (!mSuspended) {
            sleepTime = 0;
            standbyTime = systemTime() + kStandbyTimeInNsecs;
        } else {
            sleepTime += kBufferRecoveryInUsecs;
            if (sleepTime > kMaxBufferRecoveryInUsecs) {
                sleepTime = kMaxBufferRecoveryInUsecs;
            }
            // There was nothing to mix this round, which means all
            // active tracks were late. Sleep a little bit to give
            // them another chance. If we're too late, write 0s to audio
            // hardware to avoid underrun.
            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) {
                memset (curBuf, 0, mixBufferSize);
                sleepTime = 0;
            }
        }

        if (mSuspended) {
            sleepTime = kMaxBufferRecoveryInUsecs;
        }
        // sleepTime == 0 means we must write to audio hardware
        if (sleepTime == 0) {
            for (size_t i = 0; i < outputTracks.size(); i++) {
                outputTracks[i]->write(curBuf, mFrameCount);
                    mustSleep = false;
            }
            mStandby = false;
            mBytesWritten += mixBufferSize;
            }
        } else {
            // flush remaining overflow buffers in output tracks
            for (size_t i = 0; i < outputTracks.size(); i++) {
                if (outputTracks[i]->isActive()) {
                    outputTracks[i]->write(curBuf, 0);
                    standbyTime = systemTime() + kStandbyTimeInNsecs;
                    mustSleep = false;
                }
            }
        }
        if (mustSleep) {
//            LOGV("threadLoop() sleeping %d", sleepTime);
            usleep(sleepTime);
            if (sleepTime < kMaxBufferRecoveryInUsecs) {
                sleepTime += kBufferRecoveryInUsecs;
            }
        } else {
            sleepTime = kBufferRecoveryInUsecs;
        }

        // finally let go of all our tracks, without the lock held