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

Commit 4de95592 authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: fix crash when starting offload thread

Passing a sp to parent thread to AsyncCallbackThread() constructor
causes a strong reference to be acquired on the OffloadThread inside
its constructor which causes an early launch of the thread loop
with unpredictable consequences.

Pass a wp to parent thread instead.

Also move the creation of the AsyncCallbackThread to
readOutputParameters() where mUseAsyncWrite is initialized which
makes more sense.

Also change the type of AsyncCallbackThread parent thread to PlaybackThread
instead of OffloadThread to allow a broder use of non blocking write which
in theory is not limited to audio offload use case.

Bug: 8174034.
Change-Id: I4b093b022030cd4f5eb8b8e477333e91098a6549
parent 1802399c
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -1594,6 +1594,7 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
        if (mOutput->stream->set_callback(mOutput->stream,
                                      AudioFlinger::PlaybackThread::asyncCallback, this) == 0) {
            mUseAsyncWrite = true;
            mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
        }
    }

@@ -3746,9 +3747,9 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l()
// ----------------------------------------------------------------------------

AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
        const sp<AudioFlinger::OffloadThread>& offloadThread)
        const wp<AudioFlinger::PlaybackThread>& playbackThread)
    :   Thread(false /*canCallJava*/),
        mOffloadThread(offloadThread),
        mPlaybackThread(playbackThread),
        mWriteAckSequence(0),
        mDrainSequence(0)
{
@@ -3783,13 +3784,13 @@ bool AudioFlinger::AsyncCallbackThread::threadLoop()
            mDrainSequence &= ~1;
        }
        {
            sp<AudioFlinger::OffloadThread> offloadThread = mOffloadThread.promote();
            if (offloadThread != 0) {
            sp<AudioFlinger::PlaybackThread> playbackThread = mPlaybackThread.promote();
            if (playbackThread != 0) {
                if (writeAckSequence & 1) {
                    offloadThread->resetWriteBlocked(writeAckSequence >> 1);
                    playbackThread->resetWriteBlocked(writeAckSequence >> 1);
                }
                if (drainSequence & 1) {
                    offloadThread->resetDraining(drainSequence >> 1);
                    playbackThread->resetDraining(drainSequence >> 1);
                }
            }
        }
@@ -3847,7 +3848,6 @@ AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
        mHwPaused(false),
        mPausedBytesRemaining(0)
{
    mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
}

AudioFlinger::OffloadThread::~OffloadThread()
+6 −6
Original line number Diff line number Diff line
@@ -759,7 +759,7 @@ private:
class AsyncCallbackThread : public Thread {
public:

    AsyncCallbackThread(const sp<OffloadThread>& offloadThread);
    AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);

    virtual             ~AsyncCallbackThread();

@@ -776,7 +776,7 @@ public:
            void        resetDraining();

private:
    wp<OffloadThread>   mOffloadThread;
    const wp<PlaybackThread>   mPlaybackThread;
    // mWriteAckSequence corresponds to the last write sequence passed by the offload thread via
    // setWriteBlocked(). The sequence is shifted one bit to the left and the lsb is used
    // to indicate that the callback has been received via resetWriteBlocked()