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

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

Merge "Fix slow AudioTrack and AudioRecord destruction" into klp-dev

parents 291a09c3 5a6cd224
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -398,18 +398,20 @@ private:

                void        pause();    // suspend thread from execution at next loop boundary
                void        resume();   // allow thread to execute, if not requested to exit
                void        pauseConditional();
                                        // like pause(), but only if prior resume() wasn't latched

    private:
                void        pauseInternal(nsecs_t ns = 0LL);
                                        // like pause(), but only used internally within thread

        friend class AudioRecord;
        virtual bool        threadLoop();
        AudioRecord&        mReceiver;
        virtual ~AudioRecordThread();
        Mutex               mMyLock;    // Thread::mLock is private
        Condition           mMyCond;    // Thread::mThreadExitedCondition is private
        bool                mPaused;    // whether thread is currently paused
        bool                mResumeLatch;   // whether next pauseConditional() will be a nop
        bool                mPaused;    // whether thread is requested to pause at next loop entry
        bool                mPausedInt; // whether thread internally requests pause
        nsecs_t             mPausedNs;  // if mPausedInt then associated timeout, otherwise ignored
    };

            // body of AudioRecordThread::threadLoop()
+6 −4
Original line number Diff line number Diff line
@@ -598,18 +598,20 @@ protected:

                void        pause();    // suspend thread from execution at next loop boundary
                void        resume();   // allow thread to execute, if not requested to exit
                void        pauseConditional();
                                        // like pause(), but only if prior resume() wasn't latched

    private:
                void        pauseInternal(nsecs_t ns = 0LL);
                                        // like pause(), but only used internally within thread

        friend class AudioTrack;
        virtual bool        threadLoop();
        AudioTrack&         mReceiver;
        virtual ~AudioTrackThread();
        Mutex               mMyLock;    // Thread::mLock is private
        Condition           mMyCond;    // Thread::mThreadExitedCondition is private
        bool                mPaused;    // whether thread is currently paused
        bool                mResumeLatch;   // whether next pauseConditional() will be a nop
        bool                mPaused;    // whether thread is requested to pause at next loop entry
        bool                mPausedInt; // whether thread internally requests pause
        nsecs_t             mPausedNs;  // if mPausedInt then associated timeout, otherwise ignored
    };

            // body of AudioTrackThread::threadLoop()
+30 −24
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ AudioRecord::~AudioRecord()
        // Otherwise the callback thread will never exit.
        stop();
        if (mAudioRecordThread != 0) {
            mProxy->interrupt();
            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
            mAudioRecordThread->requestExitAndWait();
            mAudioRecordThread.clear();
@@ -960,7 +961,7 @@ void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who)
// =========================================================================

AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mResumeLatch(false)
    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL)
{
}

@@ -977,25 +978,32 @@ bool AudioRecord::AudioRecordThread::threadLoop()
            // caller will check for exitPending()
            return true;
        }
        if (mPausedInt) {
            mPausedInt = false;
            if (mPausedNs > 0) {
                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
            } else {
                mMyCond.wait(mMyLock);
            }
            return true;
        }
    }
    nsecs_t ns =  mReceiver.processAudioBuffer(this);
    switch (ns) {
    case 0:
        return true;
    case NS_WHENEVER:
        sleep(1);
        return true;
    case NS_INACTIVE:
        pauseConditional();
        pauseInternal();
        return true;
    case NS_NEVER:
        return false;
    case NS_WHENEVER:
        // FIXME increase poll interval, or make event-driven
        ns = 1000000000LL;
        // fall through
    default:
        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
        struct timespec req;
        req.tv_sec = ns / 1000000000LL;
        req.tv_nsec = ns % 1000000000LL;
        nanosleep(&req, NULL /*rem*/);
        pauseInternal(ns);
        return true;
    }
}
@@ -1004,38 +1012,36 @@ void AudioRecord::AudioRecordThread::requestExit()
{
    // must be in this order to avoid a race condition
    Thread::requestExit();
    resume();
}

void AudioRecord::AudioRecordThread::pause()
{
    AutoMutex _l(mMyLock);
    mPaused = true;
    mResumeLatch = false;
    if (mPaused || mPausedInt) {
        mPaused = false;
        mPausedInt = false;
        mMyCond.signal();
    }
}

void AudioRecord::AudioRecordThread::pauseConditional()
void AudioRecord::AudioRecordThread::pause()
{
    AutoMutex _l(mMyLock);
    if (mResumeLatch) {
        mResumeLatch = false;
    } else {
    mPaused = true;
}
}

void AudioRecord::AudioRecordThread::resume()
{
    AutoMutex _l(mMyLock);
    if (mPaused) {
        mPaused = false;
        mResumeLatch = false;
        mMyCond.signal();
    } else {
        mResumeLatch = true;
    }
}

void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
{
    AutoMutex _l(mMyLock);
    mPausedInt = true;
    mPausedNs = ns;
}

// -------------------------------------------------------------------------

}; // namespace android
+29 −24
Original line number Diff line number Diff line
@@ -1782,7 +1782,7 @@ void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who)
// =========================================================================

AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mResumeLatch(false)
    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL)
{
}

@@ -1799,25 +1799,32 @@ bool AudioTrack::AudioTrackThread::threadLoop()
            // caller will check for exitPending()
            return true;
        }
        if (mPausedInt) {
            mPausedInt = false;
            if (mPausedNs > 0) {
                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
            } else {
                mMyCond.wait(mMyLock);
            }
            return true;
        }
    }
    nsecs_t ns = mReceiver.processAudioBuffer(this);
    switch (ns) {
    case 0:
        return true;
    case NS_WHENEVER:
        sleep(1);
        return true;
    case NS_INACTIVE:
        pauseConditional();
        pauseInternal();
        return true;
    case NS_NEVER:
        return false;
    case NS_WHENEVER:
        // FIXME increase poll interval, or make event-driven
        ns = 1000000000LL;
        // fall through
    default:
        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
        struct timespec req;
        req.tv_sec = ns / 1000000000LL;
        req.tv_nsec = ns % 1000000000LL;
        nanosleep(&req, NULL /*rem*/);
        pauseInternal(ns);
        return true;
    }
}
@@ -1826,36 +1833,34 @@ void AudioTrack::AudioTrackThread::requestExit()
{
    // must be in this order to avoid a race condition
    Thread::requestExit();
    resume();
}

void AudioTrack::AudioTrackThread::pause()
{
    AutoMutex _l(mMyLock);
    mPaused = true;
    mResumeLatch = false;
    if (mPaused || mPausedInt) {
        mPaused = false;
        mPausedInt = false;
        mMyCond.signal();
    }
}

void AudioTrack::AudioTrackThread::pauseConditional()
void AudioTrack::AudioTrackThread::pause()
{
    AutoMutex _l(mMyLock);
    if (mResumeLatch) {
        mResumeLatch = false;
    } else {
    mPaused = true;
}
}

void AudioTrack::AudioTrackThread::resume()
{
    AutoMutex _l(mMyLock);
    if (mPaused) {
        mPaused = false;
        mResumeLatch = false;
        mMyCond.signal();
    } else {
        mResumeLatch = true;
    }
}

void AudioTrack::AudioTrackThread::pauseInternal(nsecs_t ns)
{
    AutoMutex _l(mMyLock);
    mPausedInt = true;
    mPausedNs = ns;
}

}; // namespace android