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

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

Fix issue 3217707.

The problem is that when the A2DP headset is disconnected, there is a transition
period during which the A2DP sink pumps data at a very high pace.
This makes that:
1 the audio flinger mixer thread spins and starves binder threads thus delaying
the completion of the A2DP output stream shutdown
2 we read the audio http audio stream faster than normal and we reach the end of stream
for audio while video is still playing if the streamed file is small enough.

The fix consists in detecting abnormal short write intervals and sleep to restore
a normal write pace.

Change-Id: Iab127882494ab0e26266371dc0ce5c2ff6fa476e
parent 1c602b3e
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -260,6 +260,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
    if (pRate) *pRate = lRate;

    mDevice = device;
    mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
    return NO_ERROR;
}

@@ -288,6 +289,7 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t
        if (mStandby) {
            acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
            mStandby = false;
            mLastWriteTime = systemTime();
        }

        status = init();
@@ -308,6 +310,15 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t
            buffer = (char *)buffer + status;
        }

        // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
        // does no spin and starve other threads.
        // NOTE: It is likely that the A2DP headset is being disconnected
        nsecs_t now = systemTime();
        if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
            LOGV("A2DP sink runs too fast");
            usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
        }
        mLastWriteTime = now;
        return bytes;

    }
@@ -316,7 +327,7 @@ Error:
    standby();

    // Simulate audio output timing in case of error
    usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
    usleep(mBufferDurationUs);

    return status;
}
+2 −0
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ private:
                uint32_t    mDevice;
                bool        mClosing;
                bool        mSuspended;
                nsecs_t     mLastWriteTime;
                uint32_t    mBufferDurationUs;
    };

    friend class A2dpAudioStreamOut;