Merge "AudioFlinger: Preserve recent MMapThread history for dumpsys"
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index 6002ad9..c997cfa 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -26,6 +26,24 @@
 
 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) {
@@ -186,7 +204,7 @@
             front = cblk->u.mStreaming.mFront;
         }
         // write to rear, read from front
-        ssize_t filled = rear - front;
+        ssize_t filled = safe_sub_overflow(rear, front);
         // pipe should not be overfull
         if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
             if (mIsOut) {
@@ -684,7 +702,7 @@
         const size_t overflowBit = mFrameCountP2 << 1;
         const size_t mask = overflowBit - 1;
         int32_t newFront = (front & ~mask) | (flush & mask);
-        ssize_t filled = rear - newFront;
+        ssize_t filled = 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.
@@ -726,7 +744,7 @@
         const size_t overflowBit = mFrameCountP2 << 1;
         const size_t mask = overflowBit - 1;
         int32_t newRear = (rear & ~mask) | (stop & mask);
-        ssize_t filled = newRear - front;
+        ssize_t filled = 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
@@ -778,7 +796,7 @@
         front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
         rear = cblk->u.mStreaming.mRear;
     }
-    ssize_t filled = rear - front;
+    ssize_t filled = 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",
@@ -905,7 +923,7 @@
         return mFrameCount;
     }
     const int32_t rear = getRear();
-    ssize_t filled = rear - cblk->u.mStreaming.mFront;
+    ssize_t filled = 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",
@@ -931,7 +949,7 @@
         return mFrameCount;
     }
     const int32_t rear = getRear();
-    const ssize_t filled = rear - cblk->u.mStreaming.mFront;
+    const ssize_t filled = safe_sub_overflow(rear, cblk->u.mStreaming.mFront);
     if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
         return 0; // error condition, silently return 0.
     }
@@ -1241,7 +1259,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 = rear - front;
+    const ssize_t filled = safe_sub_overflow(rear, front);
     if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
         return 0; // error condition, silently return 0.
     }
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 09101d9..01b0432 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -66,8 +66,8 @@
     /* mMeasuredWarmupTs({0, 0}), */
     mWarmupCycles(0),
     mWarmupConsecutiveInRangeCycles(0),
-    // mDummyNBLogWriter
-    mNBLogWriter(&mDummyNBLogWriter),
+    mDummyNBLogWriter(new NBLog::Writer()),
+    mNBLogWriter(mDummyNBLogWriter.get()),
     mTimestampStatus(INVALID_OPERATION),
 
     mCommand(FastThreadState::INITIAL),
@@ -94,7 +94,7 @@
 {
     // LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
     // so this initialization permits a future change to remove the check for nullptr.
-    tlNBLogWriter = &mDummyNBLogWriter;
+    tlNBLogWriter = mDummyNBLogWriter.get();
     for (;;) {
 
         // either nanosleep, sched_yield, or busy wait
@@ -124,7 +124,8 @@
 
             // As soon as possible of learning of a new dump area, start using it
             mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
-            mNBLogWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &mDummyNBLogWriter;
+            mNBLogWriter = next->mNBLogWriter != NULL ?
+                    next->mNBLogWriter : mDummyNBLogWriter.get();
             setNBLogWriter(mNBLogWriter);   // FastMixer informs its AudioMixer, FastCapture ignores
             tlNBLogWriter = mNBLogWriter;
 
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 2a71414..bbb1d22 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -78,12 +78,13 @@
     unsigned        mColdGen;       // last observed mColdGen
     bool            mIsWarm;        // true means ready to mix,
                                     // false means wait for warmup before mixing
-    struct timespec mMeasuredWarmupTs;  // how long did it take for warmup to complete
-    uint32_t        mWarmupCycles;  // counter of number of loop cycles during warmup phase
-    uint32_t        mWarmupConsecutiveInRangeCycles;    // number of consecutive cycles in range
-    NBLog::Writer   mDummyNBLogWriter;
-    NBLog::Writer*  mNBLogWriter;   // always non-nullptr: real NBLog::Writer* or &mDummyNBLogWriter
-    status_t        mTimestampStatus;
+    struct timespec   mMeasuredWarmupTs;  // how long did it take for warmup to complete
+    uint32_t          mWarmupCycles;  // counter of number of loop cycles during warmup phase
+    uint32_t          mWarmupConsecutiveInRangeCycles;    // number of consecutive cycles in range
+    sp<NBLog::Writer> mDummyNBLogWriter;
+    NBLog::Writer*    mNBLogWriter;   // always non-nullptr: real NBLog::Writer* or
+                                      // mDummyNBLogWriter.get()
+    status_t          mTimestampStatus;
 
     FastThreadState::Command mCommand;
     bool            mAttemptedWrite;