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

Commit f2c643c8 authored by Glenn Kasten's avatar Glenn Kasten Committed by Android Git Automerger
Browse files

am 3b3cfcfa: Merge "Fix slow AudioTrack and AudioRecord destruction" into klp-dev

* commit '3b3cfcfa':
  Fix slow AudioTrack and AudioRecord destruction
parents af724697 3b3cfcfa
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