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

Commit 4bb650bb authored by Phil Burk's avatar Phil Burk
Browse files

AudioFlinger: flush direct tracks that are paused



Normally the flush is processed on ObtainBuffer.
But that is not called when the track is paused.
So it was not possible to flush and re-prime a
track that was paused.

Now we flush synchronously for inactive tracks,
and flush from prepareTracks_l for active tracks.

Bug: 19193985
Bug: 27791443
Change-Id: I39a7e4921e45041c3a51cf91fd3995b5edee6dd4
Signed-off-by: default avatarPhil Burk <philburk@google.com>
parent 3fb45bb6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -522,6 +522,12 @@ public:
        mTimestampMutator.push(timestamp);
    }

    // Flushes the shared ring buffer if the client had requested it using mStreaming.mFlush.
    // If flush occurs then:
    //   cblk->u.mStreaming.mFront, ServerProxy::mFlush and ServerProxy::mFlushed will be modified
    //   client will be notified via Futex
    virtual void    flushBufferIfNeeded();

    // Total count of the number of flushed frames since creation (never reset).
    virtual int64_t     framesFlushed() const { return mFlushed; }

+51 −36
Original line number Diff line number Diff line
@@ -622,24 +622,20 @@ ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCo
}

__attribute__((no_sanitize("integer")))
status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
{
    LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0);
    if (mIsShutdown) {
        goto no_init;
    }
void ServerProxy::flushBufferIfNeeded()
{
    audio_track_cblk_t* cblk = mCblk;
    // compute number of frames available to write (AudioTrack) or read (AudioRecord),
    // or use previous cached value from framesReady(), with added barrier if it omits.
    int32_t front;
    int32_t rear;
    // See notes on barriers at ClientProxy::obtainBuffer()
    if (mIsOut) {
        int32_t flush = cblk->u.mStreaming.mFlush;
        rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
        front = cblk->u.mStreaming.mFront;
    // The acquire_load is not really required. But since the write is a release_store in the
    // client, using acquire_load here makes it easier for people to maintain the code,
    // and the logic for communicating ipc variables seems somewhat standard,
    // and there really isn't much penalty for 4 or 8 byte atomics.
    int32_t flush = android_atomic_acquire_load(&cblk->u.mStreaming.mFlush);
    if (flush != mFlush) {
        ALOGV("ServerProxy::flushBufferIfNeeded() mStreaming.mFlush = 0x%x, mFlush = 0x%0x",
                flush, mFlush);
        int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
        int32_t front = cblk->u.mStreaming.mFront;

        // effectively obtain then release whatever is in the buffer
        const size_t overflowBit = mFrameCountP2 << 1;
        const size_t mask = overflowBit - 1;
@@ -672,8 +668,27 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
            }
        }
        mFlushed += (newFront - front) & mask;
            front = newFront;
    }
}

__attribute__((no_sanitize("integer")))
status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
{
    LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0);
    if (mIsShutdown) {
        goto no_init;
    }
    {
    audio_track_cblk_t* cblk = mCblk;
    // compute number of frames available to write (AudioTrack) or read (AudioRecord),
    // or use previous cached value from framesReady(), with added barrier if it omits.
    int32_t front;
    int32_t rear;
    // See notes on barriers at ClientProxy::obtainBuffer()
    if (mIsOut) {
        flushBufferIfNeeded(); // might modify mFront
        rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
        front = cblk->u.mStreaming.mFront;
    } else {
        front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
        rear = cblk->u.mStreaming.mRear;
+11 −0
Original line number Diff line number Diff line
@@ -777,6 +777,13 @@ void AudioFlinger::PlaybackThread::Track::flush()
        Mutex::Autolock _l(thread->mLock);
        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();

        // Flush the ring buffer now if the track is not active in the PlaybackThread.
        // Otherwise the flush would not be done until the track is resumed.
        // Requires FastTrack removal be BLOCK_UNTIL_ACKED
        if (playbackThread->mActiveTracks.indexOf(this) < 0) {
            (void)mServerProxy->flushBufferIfNeeded();
        }

        if (isOffloaded()) {
            // If offloaded we allow flush during any state except terminated
            // and keep the track active to avoid problems if user is seeking
@@ -828,6 +835,10 @@ void AudioFlinger::PlaybackThread::Track::flushAck()
    if (!isOffloaded() && !isDirect())
        return;

    // Clear the client ring buffer so that the app can prime the buffer while paused.
    // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
    mServerProxy->flushBufferIfNeeded();

    mFlushHwPending = false;
}