|
|
|
@ -20,30 +20,13 @@
|
|
|
|
|
#include <android-base/macros.h>
|
|
|
|
|
#include <private/media/AudioTrackShared.h>
|
|
|
|
|
#include <utils/Log.h>
|
|
|
|
|
#include <audio_utils/safe_math.h>
|
|
|
|
|
|
|
|
|
|
#include <linux/futex.h>
|
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
|
|
|
|
|
|
// TODO: consider pulling this into a shared header.
|
|
|
|
|
// safe_sub_overflow is used ensure that subtraction occurs in the same native type
|
|
|
|
|
// with proper 2's complement overflow. Without calling this function, it is possible,
|
|
|
|
|
// for example, that optimizing compilers may elect to treat 32 bit subtraction
|
|
|
|
|
// as 64 bit subtraction when storing into a 64 bit destination as integer overflow is
|
|
|
|
|
// technically undefined.
|
|
|
|
|
template<typename T,
|
|
|
|
|
typename U,
|
|
|
|
|
typename = std::enable_if_t<std::is_same<std::decay_t<T>,
|
|
|
|
|
std::decay_t<U>>{}>>
|
|
|
|
|
// ensure arguments are same type (ignoring volatile, which is used in cblk variables).
|
|
|
|
|
auto safe_sub_overflow(const T& a, const U& b) {
|
|
|
|
|
std::decay_t<T> result;
|
|
|
|
|
(void)__builtin_sub_overflow(a, b, &result);
|
|
|
|
|
// note if __builtin_sub_overflow returns true, an overflow occurred.
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// used to clamp a value to size_t. TODO: move to another file.
|
|
|
|
|
template <typename T>
|
|
|
|
|
size_t clampToSize(T x) {
|
|
|
|
@ -204,7 +187,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques
|
|
|
|
|
front = cblk->u.mStreaming.mFront;
|
|
|
|
|
}
|
|
|
|
|
// write to rear, read from front
|
|
|
|
|
ssize_t filled = safe_sub_overflow(rear, front);
|
|
|
|
|
ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
|
|
|
|
|
// pipe should not be overfull
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
if (mIsOut) {
|
|
|
|
@ -702,7 +685,7 @@ void ServerProxy::flushBufferIfNeeded()
|
|
|
|
|
const size_t overflowBit = mFrameCountP2 << 1;
|
|
|
|
|
const size_t mask = overflowBit - 1;
|
|
|
|
|
int32_t newFront = (front & ~mask) | (flush & mask);
|
|
|
|
|
ssize_t filled = safe_sub_overflow(rear, newFront);
|
|
|
|
|
ssize_t filled = audio_utils::safe_sub_overflow(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.
|
|
|
|
@ -744,7 +727,7 @@ int32_t AudioTrackServerProxy::getRear() const
|
|
|
|
|
const size_t overflowBit = mFrameCountP2 << 1;
|
|
|
|
|
const size_t mask = overflowBit - 1;
|
|
|
|
|
int32_t newRear = (rear & ~mask) | (stop & mask);
|
|
|
|
|
ssize_t filled = safe_sub_overflow(newRear, front);
|
|
|
|
|
ssize_t filled = audio_utils::safe_sub_overflow(newRear, front);
|
|
|
|
|
// overflowBit is unsigned, so cast to signed for comparison.
|
|
|
|
|
if (filled >= (ssize_t)overflowBit) {
|
|
|
|
|
// front and rear offsets span the overflow bit of the p2 mask
|
|
|
|
@ -796,7 +779,7 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
|
|
|
|
|
front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
|
|
|
|
|
rear = cblk->u.mStreaming.mRear;
|
|
|
|
|
}
|
|
|
|
|
ssize_t filled = safe_sub_overflow(rear, front);
|
|
|
|
|
ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
|
|
|
|
|
// pipe should not already be overfull
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down",
|
|
|
|
@ -923,7 +906,7 @@ size_t AudioTrackServerProxy::framesReady()
|
|
|
|
|
return mFrameCount;
|
|
|
|
|
}
|
|
|
|
|
const int32_t rear = getRear();
|
|
|
|
|
ssize_t filled = safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
|
|
|
|
|
ssize_t filled = audio_utils::safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
|
|
|
|
|
// pipe should not already be overfull
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down",
|
|
|
|
@ -949,7 +932,7 @@ size_t AudioTrackServerProxy::framesReadySafe() const
|
|
|
|
|
return mFrameCount;
|
|
|
|
|
}
|
|
|
|
|
const int32_t rear = getRear();
|
|
|
|
|
const ssize_t filled = safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
|
|
|
|
|
const ssize_t filled = audio_utils::safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
return 0; // error condition, silently return 0.
|
|
|
|
|
}
|
|
|
|
@ -1259,7 +1242,7 @@ size_t AudioRecordServerProxy::framesReadySafe() const
|
|
|
|
|
}
|
|
|
|
|
const int32_t front = android_atomic_acquire_load(&mCblk->u.mStreaming.mFront);
|
|
|
|
|
const int32_t rear = mCblk->u.mStreaming.mRear;
|
|
|
|
|
const ssize_t filled = safe_sub_overflow(rear, front);
|
|
|
|
|
const ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
return 0; // error condition, silently return 0.
|
|
|
|
|
}
|
|
|
|
|