AudioFlinger::Thread ensure proper add / sub
Bug: 126772841
Bug: 130371615
Test: 24 hours recording with 64 bit audioserver
Change-Id: I71305448ee194d1cc325ab238f1681aee93ab18d
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index c997cfa..ee6c335 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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.
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0b203c4..6b9bf19 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -44,6 +44,7 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
#include <audio_utils/minifloat.h>
+#include <audio_utils/safe_math.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio.h>
@@ -7875,7 +7876,7 @@
RecordThread *recordThread = (RecordThread *) threadBase.get();
const int32_t rear = recordThread->mRsmpInRear;
const int32_t front = mRsmpInFront;
- const ssize_t filled = rear - front;
+ const ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
size_t framesIn;
bool overrun = false;
@@ -7889,7 +7890,8 @@
} else {
// client is not keeping up with server, but give it latest data
framesIn = recordThread->mRsmpInFrames;
- mRsmpInFront = /* front = */ rear - framesIn;
+ mRsmpInFront = /* front = */ audio_utils::safe_sub_overflow(
+ rear, static_cast<int32_t>(framesIn));
overrun = true;
}
if (framesAvailable != NULL) {
@@ -7913,7 +7915,7 @@
RecordThread *recordThread = (RecordThread *) threadBase.get();
int32_t rear = recordThread->mRsmpInRear;
int32_t front = mRsmpInFront;
- ssize_t filled = rear - front;
+ ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
// FIXME should not be P2 (don't want to increase latency)
// FIXME if client not keeping up, discard
LOG_ALWAYS_FATAL_IF(!(0 <= filled && (size_t) filled <= recordThread->mRsmpInFrames));
@@ -7946,13 +7948,13 @@
void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
AudioBufferProvider::Buffer* buffer)
{
- size_t stepCount = buffer->frameCount;
+ int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
if (stepCount == 0) {
return;
}
ALOG_ASSERT(stepCount <= mRsmpInUnrel);
mRsmpInUnrel -= stepCount;
- mRsmpInFront += stepCount;
+ mRsmpInFront = audio_utils::safe_add_overflow(mRsmpInFront, stepCount);
buffer->raw = NULL;
buffer->frameCount = 0;
}