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

Commit b1af3771 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change Iccfa50fe into eclair

* changes:
  Fix issue 2323920: Notification & A2DP audio stutter.
parents fb4fa224 7e2aad1e
Loading
Loading
Loading
Loading
+71 −22
Original line number Original line Diff line number Diff line
@@ -932,6 +932,8 @@ status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String
    result.append(buffer);
    result.append(buffer);
    snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
    snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
    result.append(buffer);
    result.append(buffer);
    snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
    result.append(buffer);
    write(fd, result.string(), result.size());
    write(fd, result.string(), result.size());


    dumpBase(fd, args);
    dumpBase(fd, args);
@@ -1344,7 +1346,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
        if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
        if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
                !track->isPaused())
                !track->isPaused())
        {
        {
            //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
            //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);


            // compute volume for this track
            // compute volume for this track
            int16_t left, right;
            int16_t left, right;
@@ -1400,7 +1402,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            track->mRetryCount = kMaxTrackRetries;
            track->mRetryCount = kMaxTrackRetries;
            mixerStatus = MIXER_TRACKS_READY;
            mixerStatus = MIXER_TRACKS_READY;
        } else {
        } else {
            //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
            //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
            if (track->isStopped()) {
            if (track->isStopped()) {
                track->reset();
                track->reset();
            }
            }
@@ -1914,7 +1916,7 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
    :   MixerThread(audioFlinger, mainThread->getOutput(), id)
    :   MixerThread(audioFlinger, mainThread->getOutput(), id), mWaitTimeMs(UINT_MAX)
{
{
    mType = PlaybackThread::DUPLICATING;
    mType = PlaybackThread::DUPLICATING;
    addOutputTrack(mainThread);
    addOutputTrack(mainThread);
@@ -1952,6 +1954,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()


            if (checkForNewParameters_l()) {
            if (checkForNewParameters_l()) {
                mixBufferSize = mFrameCount*mFrameSize;
                mixBufferSize = mFrameCount*mFrameSize;
                updateWaitTime();
                activeSleepTime = activeSleepTimeUs();
                activeSleepTime = activeSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
            }
            }
@@ -2003,7 +2006,11 @@ bool AudioFlinger::DuplicatingThread::threadLoop()


        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
            // mix buffers...
            // mix buffers...
            if (outputsReady(outputTracks)) {
                mAudioMixer->process(curBuf);
                mAudioMixer->process(curBuf);
            } else {
                memset(curBuf, 0, mixBufferSize);
            }
            sleepTime = 0;
            sleepTime = 0;
            writeFrames = mFrameCount;
            writeFrames = mFrameCount;
        } else {
        } else {
@@ -2054,6 +2061,7 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
{
{
    int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
    int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
    OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
    OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
                                            this,
                                            mSampleRate,
                                            mSampleRate,
                                            mFormat,
                                            mFormat,
                                            mChannelCount,
                                            mChannelCount,
@@ -2062,6 +2070,7 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
        thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
        thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
        mOutputTracks.add(outputTrack);
        mOutputTracks.add(outputTrack);
        LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
        LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
        updateWaitTime();
    }
    }
}
}


@@ -2072,12 +2081,50 @@ void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
        if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
        if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
            mOutputTracks[i]->destroy();
            mOutputTracks[i]->destroy();
            mOutputTracks.removeAt(i);
            mOutputTracks.removeAt(i);
            updateWaitTime();
            return;
            return;
        }
        }
    }
    }
    LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
    LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
}
}


void AudioFlinger::DuplicatingThread::updateWaitTime()
{
    mWaitTimeMs = UINT_MAX;
    for (size_t i = 0; i < mOutputTracks.size(); i++) {
        sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
        if (strong != NULL) {
            uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
            if (waitTimeMs < mWaitTimeMs) {
                mWaitTimeMs = waitTimeMs;
            }
        }
    }
}


bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
{
    for (size_t i = 0; i < outputTracks.size(); i++) {
        sp <ThreadBase> thread = outputTracks[i]->thread().promote();
        if (thread == 0) {
            LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
            return false;
        }
        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
        if (playbackThread->standby() && !playbackThread->isSuspended()) {
            LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
            return false;
        }
    }
    return true;
}

uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
{
    return (mWaitTimeMs * 1000) / 2;
}

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


// TrackBase constructor must be called with AudioFlinger::mLock held
// TrackBase constructor must be called with AudioFlinger::mLock held
@@ -2616,12 +2663,13 @@ void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)


AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
            const wp<ThreadBase>& thread,
            const wp<ThreadBase>& thread,
            DuplicatingThread *sourceThread,
            uint32_t sampleRate,
            uint32_t sampleRate,
            int format,
            int format,
            int channelCount,
            int channelCount,
            int frameCount)
            int frameCount)
    :   Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
    :   Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
    mActive(false)
    mActive(false), mSourceThread(sourceThread)
{
{


    PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
    PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
@@ -2630,10 +2678,9 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
        mCblk->volume[0] = mCblk->volume[1] = 0x1000;
        mCblk->volume[0] = mCblk->volume[1] = 0x1000;
        mOutBuffer.frameCount = 0;
        mOutBuffer.frameCount = 0;
        mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
        playbackThread->mTracks.add(this);
        playbackThread->mTracks.add(this);
        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p",
                mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
                mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
    } else {
    } else {
        LOGW("Error creating output track on thread %p", playbackThread);
        LOGW("Error creating output track on thread %p", playbackThread);
    }
    }
@@ -2673,7 +2720,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
    inBuffer.frameCount = frames;
    inBuffer.frameCount = frames;
    inBuffer.i16 = data;
    inBuffer.i16 = data;


    uint32_t waitTimeLeftMs = mWaitTimeMs;
    uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();


    if (!mActive && frames != 0) {
    if (!mActive && frames != 0) {
        start();
        start();
@@ -2712,12 +2759,11 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
            mOutBuffer.frameCount = pInBuffer->frameCount;
            mOutBuffer.frameCount = pInBuffer->frameCount;
            nsecs_t startTime = systemTime();
            nsecs_t startTime = systemTime();
            if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
            if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
                LOGV ("OutputTrack::write() %p no more output buffers", this);
                LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
                outputBufferFull = true;
                outputBufferFull = true;
                break;
                break;
            }
            }
            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
            LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs);
            if (waitTimeLeftMs >= waitTimeMs) {
            if (waitTimeLeftMs >= waitTimeMs) {
                waitTimeLeftMs -= waitTimeMs;
                waitTimeLeftMs -= waitTimeMs;
            } else {
            } else {
@@ -2738,7 +2784,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
                mBufferQueue.removeAt(0);
                mBufferQueue.removeAt(0);
                delete [] pInBuffer->mBuffer;
                delete [] pInBuffer->mBuffer;
                delete pInBuffer;
                delete pInBuffer;
                LOGV("OutputTrack::write() %p released overflow buffer %d", this, mBufferQueue.size());
                LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
            } else {
            } else {
                break;
                break;
            }
            }
@@ -2747,6 +2793,8 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr


    // If we could not write all frames, allocate a buffer and queue it for next time.
    // If we could not write all frames, allocate a buffer and queue it for next time.
    if (inBuffer.frameCount) {
    if (inBuffer.frameCount) {
        sp<ThreadBase> thread = mThread.promote();
        if (thread != 0 && !thread->standby()) {
            if (mBufferQueue.size() < kMaxOverFlowBuffers) {
            if (mBufferQueue.size() < kMaxOverFlowBuffers) {
                pInBuffer = new Buffer;
                pInBuffer = new Buffer;
                pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
                pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
@@ -2754,9 +2802,10 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
                pInBuffer->i16 = pInBuffer->mBuffer;
                pInBuffer->i16 = pInBuffer->mBuffer;
                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
                mBufferQueue.add(pInBuffer);
                mBufferQueue.add(pInBuffer);
            LOGV("OutputTrack::write() %p adding overflow buffer %d", this, mBufferQueue.size());
                LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
            } else {
            } else {
            LOGW("OutputTrack::write() %p no more overflow buffers", this);
                LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
            }
        }
        }
    }
    }


+14 −3
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@


#include <stdint.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/types.h>
#include <limits.h>


#include <media/IAudioFlinger.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioFlingerClient.h>
#include <media/IAudioFlingerClient.h>
@@ -208,6 +209,7 @@ private:
    class PlaybackThread;
    class PlaybackThread;
    class MixerThread;
    class MixerThread;
    class DirectOutputThread;
    class DirectOutputThread;
    class DuplicatingThread;
    class Track;
    class Track;
    class RecordTrack;
    class RecordTrack;


@@ -324,6 +326,7 @@ private:
                    void        sendConfigEvent_l(int event, int param = 0);
                    void        sendConfigEvent_l(int event, int param = 0);
                    void        processConfigEvents();
                    void        processConfigEvents();
                    int         id() const { return mId;}
                    int         id() const { return mId;}
                    bool        standby() { return mStandby; }


        mutable     Mutex                   mLock;
        mutable     Mutex                   mLock;


@@ -452,6 +455,7 @@ private:
            };
            };


                                OutputTrack(  const wp<ThreadBase>& thread,
                                OutputTrack(  const wp<ThreadBase>& thread,
                                        DuplicatingThread *sourceThread,
                                        uint32_t sampleRate,
                                        uint32_t sampleRate,
                                        int format,
                                        int format,
                                        int channelCount,
                                        int channelCount,
@@ -471,13 +475,12 @@ private:
            void                clearBufferQueue();
            void                clearBufferQueue();


            // Maximum number of pending buffers allocated by OutputTrack::write()
            // Maximum number of pending buffers allocated by OutputTrack::write()
            static const uint8_t kMaxOverFlowBuffers = 3;
            static const uint8_t kMaxOverFlowBuffers = 10;


            Vector < Buffer* >          mBufferQueue;
            Vector < Buffer* >          mBufferQueue;
            AudioBufferProvider::Buffer mOutBuffer;
            AudioBufferProvider::Buffer mOutBuffer;
            uint32_t                    mWaitTimeMs;
            bool                        mActive;
            bool                        mActive;

            DuplicatingThread*          mSourceThread;
        };  // end of OutputTrack
        };  // end of OutputTrack


        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
@@ -520,6 +523,7 @@ private:
        virtual     int         type() const { return mType; }
        virtual     int         type() const { return mType; }
                    void        suspend() { mSuspended++; }
                    void        suspend() { mSuspended++; }
                    void        restore() { if (mSuspended) mSuspended--; }
                    void        restore() { if (mSuspended) mSuspended--; }
                    bool        isSuspended() { return (mSuspended != 0); }
        virtual     String8     getParameters(const String8& keys);
        virtual     String8     getParameters(const String8& keys);
        virtual     void        audioConfigChanged(int event, int param = 0);
        virtual     void        audioConfigChanged(int event, int param = 0);


@@ -635,9 +639,16 @@ private:
        virtual     bool        threadLoop();
        virtual     bool        threadLoop();
                    void        addOutputTrack(MixerThread* thread);
                    void        addOutputTrack(MixerThread* thread);
                    void        removeOutputTrack(MixerThread* thread);
                    void        removeOutputTrack(MixerThread* thread);
                    uint32_t    waitTimeMs() { return mWaitTimeMs; }
    protected:
        virtual     uint32_t    activeSleepTimeUs();


    private:
    private:
                    bool        outputsReady(SortedVector< sp<OutputTrack> > &outputTracks);
                    void        updateWaitTime();

        SortedVector < sp<OutputTrack> >  mOutputTracks;
        SortedVector < sp<OutputTrack> >  mOutputTracks;
                    uint32_t    mWaitTimeMs;
    };
    };


              PlaybackThread *checkPlaybackThread_l(int output) const;
              PlaybackThread *checkPlaybackThread_l(int output) const;