VT: Traffic recorder renewal

1. Switch head & tail definition to prevent confusing

HeadIdx_(n+1) = (HeadIdx_(n) + 1) mod Sizeof(RingBuffer)

X = filled index
O = vacant index
                                           head
          O O O X head                 O O X X
        O         X                  O         X
       O           X     write      O           X
       O           X     ----->     O           X
        O         X                  O         X
          O X X X                      O X X X
        tail                          tail

2. Preserve data when print information.
   The recorder keeps data as possible as it can.
   (Current recorder keeps data for 2000ms)

3. Limit traffic recorder size between 4 and 1024 entries.

Bug: 171688417

Change-Id: I7502f09f31d841b04a5d29efb7bb1b904059b3c7
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index dc0ddb9..63b8251 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -62,6 +62,9 @@
 static const size_t kMaxPacketSize = 1280;
 static char kCNAME[255] = "someone@somewhere";
 
+static const size_t kTrafficRecorderMaxEntries = 128;
+static const size_t kTrafficRecorderMaxTimeSpanMs = 2000;
+
 static int UniformRand(int limit) {
     return ((double)rand() * limit) / RAND_MAX;
 }
@@ -71,7 +74,8 @@
       mFd(dup(fd)),
       mLooper(new ALooper),
       mReflector(new AHandlerReflector<ARTPWriter>(this)),
-      mTrafficRec(new TrafficRecorder<uint32_t, size_t>(128)) {
+      mTrafficRec(new TrafficRecorder<uint32_t, size_t>(
+              kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
     CHECK_GE(fd, 0);
     mIsIPv6 = false;
 
@@ -122,7 +126,8 @@
       mFd(dup(fd)),
       mLooper(new ALooper),
       mReflector(new AHandlerReflector<ARTPWriter>(this)),
-      mTrafficRec(new TrafficRecorder<uint32_t, size_t>(128)) {
+      mTrafficRec(new TrafficRecorder<uint32_t, size_t>(
+              kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
     CHECK_GE(fd, 0);
     mIsIPv6 = false;
 
diff --git a/media/libstagefright/rtsp/TrafficRecorder.h b/media/libstagefright/rtsp/TrafficRecorder.h
index f8e7c03..a7b2a3c 100644
--- a/media/libstagefright/rtsp/TrafficRecorder.h
+++ b/media/libstagefright/rtsp/TrafficRecorder.h
@@ -27,19 +27,23 @@
 template <class Time, class Bytes>
 class TrafficRecorder : public RefBase {
 private:
+    constexpr static size_t kMinNumEntries = 4;
+    constexpr static size_t kMaxNumEntries = 1024;
+
     size_t mSize;
     size_t mSizeMask;
     Time *mTimeArray = NULL;
     Bytes *mBytesArray = NULL;
-    size_t mHeadIdx = 0;
-    size_t mTailIdx = 0;
+    size_t mHeadIdx;
+    size_t mTailIdx;
 
-    Time mClock = 0;
-    Time mLastTimeOfPrint = 0;
-    Bytes mAccuBytesOfPrint = 0;
+    int mLastReadIdx;
+
+    const Time mRecordLimit;
+    Time mClock;
+    Time mLastTimeOfPrint;
 public:
-    TrafficRecorder();
-    TrafficRecorder(size_t size);
+    TrafficRecorder(size_t size, Time accuTimeLimit);
     virtual ~TrafficRecorder();
 
     void init();
@@ -53,18 +57,19 @@
 };
 
 template <class Time, class Bytes>
-TrafficRecorder<Time, Bytes>::TrafficRecorder() {
-    TrafficRecorder(128);
-}
-
-template <class Time, class Bytes>
-TrafficRecorder<Time, Bytes>::TrafficRecorder(size_t size) {
-    size_t exp;
-    for (exp = 0; exp < 32; exp++) {
-        if (size <= (1ul << exp)) {
-            break;
-        }
+TrafficRecorder<Time, Bytes>::TrafficRecorder(size_t size, Time recordLimit)
+    : mRecordLimit(recordLimit) {
+    if (size > kMaxNumEntries) {
+        LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+        size = kMaxNumEntries;
+    } else if (size < kMinNumEntries) {
+        LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+        size = kMinNumEntries;
     }
+
+    size_t exp = ((sizeof(size_t) == 8) ?
+                  64 - __builtin_clzl(size - 1) :
+                  32 - __builtin_clz(size - 1));
     mSize = (1ul << exp);         // size = 2^exp
     mSizeMask = mSize - 1;
 
@@ -84,9 +89,14 @@
 template <class Time, class Bytes>
 void TrafficRecorder<Time, Bytes>::init() {
     mHeadIdx = 0;
-    mTailIdx = 0;
-    mTimeArray[0] = 0;
-    mBytesArray[0] = 0;
+    mTailIdx = mSizeMask;
+    for (int i = 0 ; i < mSize ; i++) {
+        mTimeArray[i] = 0;
+        mBytesArray[i] = 0;
+    }
+    mLastReadIdx = 0;
+    mLastTimeOfPrint = 0;
+    mClock = 0;
 }
 
 template <class Time, class Bytes>
@@ -96,53 +106,64 @@
 
 template <class Time, class Bytes>
 Bytes TrafficRecorder<Time, Bytes>::readBytesForLastPeriod(Time period) {
-    Bytes bytes = 0;
+    // Not enough data
+    if (period > mClock)
+        return 0;
 
-    size_t i = mTailIdx;
-    while (i != mHeadIdx) {
-        LOG(VERBOSE) << "READ " << i << " time " << mTimeArray[i] << " \t EndOfPeriod " << mClock - period;
+    Bytes bytes = 0;
+    int i = mHeadIdx;
+    while (i != mTailIdx) {
+        LOG(VERBOSE) << "READ " << i << " time " << mTimeArray[i]
+                << " \t EndOfPeriod " << mClock - period
+                << "\t\t Bytes:" << mBytesArray[i] << "\t\t Accu: " << bytes;
         if (mTimeArray[i] < mClock - period) {
             break;
         }
         bytes += mBytesArray[i];
-        i = (i + mSize - 1) & mSizeMask;
+        i = (i - 1) & mSizeMask;
     }
-    mHeadIdx = i;
+    mLastReadIdx = (i + 1) & mSizeMask;
+
     return bytes;
 }
 
 template <class Time, class Bytes>
 void TrafficRecorder<Time, Bytes>::writeBytes(Bytes bytes) {
-    size_t writeIdx;
-    if (mClock == mTimeArray[mTailIdx]) {
-        writeIdx = mTailIdx;
+    int writeIdx;
+    if (mClock == mTimeArray[mHeadIdx]) {
+        writeIdx = mHeadIdx;
         mBytesArray[writeIdx] += bytes;
     } else {
-        writeIdx = (mTailIdx + 1) % mSize;
+        writeIdx = (mHeadIdx + 1) & mSizeMask;
         mTimeArray[writeIdx] = mClock;
         mBytesArray[writeIdx] = bytes;
     }
 
     LOG(VERBOSE) << "WRITE " << writeIdx << " time " << mClock;
-    if (writeIdx == mHeadIdx) {
-        LOG(WARNING) << "Traffic recorder size exceeded at " << mHeadIdx;
-        mHeadIdx = (mHeadIdx + 1) & mSizeMask;
+    if (writeIdx == mTailIdx) {
+        mTailIdx = (mTailIdx + 1) & mSizeMask;
     }
 
-    mTailIdx = writeIdx;
-    mAccuBytesOfPrint += bytes;
+    mHeadIdx = writeIdx;
 }
 
 template <class Time, class Bytes>
 void TrafficRecorder<Time, Bytes>::printAccuBitsForLastPeriod(Time period, Time unit) {
-    Time duration = mClock - mLastTimeOfPrint;
-    float numOfUnit = (float)duration / unit;
-    if (duration > period) {
-        ALOGD("Actual Tx period %.0f ms \t %.0f Bits/Unit",
-              numOfUnit * 1000.f, mAccuBytesOfPrint * 8.f / numOfUnit);
-        mLastTimeOfPrint = mClock;
-        mAccuBytesOfPrint = 0;
-        init();
+    Time timeSinceLastPrint = mClock - mLastTimeOfPrint;
+    if (timeSinceLastPrint < period)
+        return;
+
+    Bytes sum = readBytesForLastPeriod(period);
+    Time readPeriod = mClock - mTimeArray[mLastReadIdx];
+
+    float numOfUnit = (float)(readPeriod) / (unit + FLT_MIN);
+    ALOGD("Actual Tx period %.3f unit \t %.0f bytes (%.0f Kbits)/Unit",
+          numOfUnit, sum / numOfUnit, sum * 8.f / numOfUnit / 1000.f);
+    mLastTimeOfPrint = mClock;
+
+    if (mClock - mTimeArray[mTailIdx] < mRecordLimit) {
+        // Size is not enough to record bytes for mRecordLimit period
+        ALOGW("Traffic recorder size is not enough. mRecordLimit %d", mRecordLimit);
     }
 }