diff options
author | Andy Hung <hunga@google.com> | 2015-07-15 17:04:20 -0700 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2015-07-16 10:27:06 -0700 |
commit | a2d75cdb1e389f2b4ce5992fb6652399b4d30966 (patch) | |
tree | 7356aa2f55de2f8c85c37f8a58fb4e135bb72754 /media/libmedia/AudioTrackShared.cpp | |
parent | 14ae2c0d1aa6e32e97cbb62dabb604820e1e5152 (diff) | |
download | frameworks_av-a2d75cdb1e389f2b4ce5992fb6652399b4d30966.zip frameworks_av-a2d75cdb1e389f2b4ce5992fb6652399b4d30966.tar.gz frameworks_av-a2d75cdb1e389f2b4ce5992fb6652399b4d30966.tar.bz2 |
Fix AudioTrack flush pointer wrap
Occurs when read offset / write offset span the power of 2
mask boundary.
Bug: 22513776
Change-Id: If863577dac6666e8b2083d78f78fe9b9490fcf76
Diffstat (limited to 'media/libmedia/AudioTrackShared.cpp')
-rw-r--r-- | media/libmedia/AudioTrackShared.cpp | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index 1d7aed2..c736ec6 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -374,6 +374,9 @@ void AudioTrackClientProxy::flush() size_t increment = mFrameCountP2 << 1; size_t mask = increment - 1; audio_track_cblk_t* cblk = mCblk; + // mFlush is 32 bits concatenated as [ flush_counter ] [ newfront_offset ] + // Should newFlush = cblk->u.mStreaming.mRear? Only problem is + // if you want to flush twice to the same rear location after a 32 bit wrap. int32_t newFlush = (cblk->u.mStreaming.mRear & mask) | ((cblk->u.mStreaming.mFlush & ~mask) + increment); android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush); @@ -613,9 +616,18 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) front = cblk->u.mStreaming.mFront; if (flush != mFlush) { // effectively obtain then release whatever is in the buffer - size_t mask = (mFrameCountP2 << 1) - 1; + const size_t overflowBit = mFrameCountP2 << 1; + const size_t mask = overflowBit - 1; int32_t newFront = (front & ~mask) | (flush & mask); ssize_t filled = rear - newFront; + if (filled >= (ssize_t)overflowBit) { + // front and rear offsets span the overflow bit of the p2 mask + // so rebasing newFront on the front offset is off by the overflow bit. + // adjust newFront to match rear offset. + ALOGV("flush wrap: filled %#x >= overflowBit %#x", filled, overflowBit); + newFront += overflowBit; + filled -= overflowBit; + } // Rather than shutting down on a corrupt flush, just treat it as a full flush if (!(0 <= filled && (size_t) filled <= mFrameCount)) { ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, " |