Allow a system property "media.stagefright.cache-params" to override cache/prefetcher

default parameters. To override specify a property

adb shell setprop media.stagefright.cache-params "4096/20480/15" to
set the low water threshold to 4096 KB, the high water threshold to 20 MB
and the keepalive interval to 15 secs.

if high and/or lowwater mark are negative, the default values are used for
the respective value.

if keep-alive interval is 0, keep-alives are disabled.

Change-Id: I89a4a06836e4a2f473d7a92b567ab07818c2f87d
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 4edb613..2cacfa7 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -21,6 +21,7 @@
 #include "include/NuCachedSource2.h"
 #include "include/HTTPBase.h"
 
+#include <cutils/properties.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
@@ -186,7 +187,12 @@
       mLastAccessPos(0),
       mFetching(true),
       mLastFetchTimeUs(-1),
-      mNumRetriesLeft(kMaxNumRetries) {
+      mNumRetriesLeft(kMaxNumRetries),
+      mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
+      mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
+      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs) {
+    updateCacheParamsFromSystemProperty();
+
     mLooper->setName("NuCachedSource2");
     mLooper->registerHandler(mReflector);
     mLooper->start();
@@ -318,7 +324,8 @@
     bool keepAlive =
         !mFetching
             && mFinalStatus == OK
-            && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;
+            && mKeepAliveIntervalUs > 0
+            && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs;
 
     if (mFetching || keepAlive) {
         if (keepAlive) {
@@ -329,7 +336,7 @@
 
         mLastFetchTimeUs = ALooper::GetNowUs();
 
-        if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
+        if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
             LOGI("Cache full, done prefetching for now");
             mFetching = false;
         }
@@ -392,7 +399,7 @@
 
     if (!ignoreLowWaterThreshold && !force
             && mCacheOffset + mCache->totalSize() - mLastAccessPos
-                >= kLowWaterThreshold) {
+                >= mLowwaterThresholdBytes) {
         return;
     }
 
@@ -482,7 +489,7 @@
 }
 
 ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
-    CHECK_LE(size, (size_t)kHighWaterThreshold);
+    CHECK_LE(size, (size_t)mHighwaterThresholdBytes);
 
     LOGV("readInternal offset %lld size %d", offset, size);
 
@@ -580,4 +587,44 @@
     return mSource->getMIMEType();
 }
 
+void NuCachedSource2::updateCacheParamsFromSystemProperty() {
+    char value[PROPERTY_VALUE_MAX];
+    if (!property_get("media.stagefright.cache-params", value, NULL)) {
+        return;
+    }
+
+    updateCacheParamsFromString(value);
+}
+
+void NuCachedSource2::updateCacheParamsFromString(const char *s) {
+    ssize_t lowwaterMarkKb, highwaterMarkKb;
+    unsigned keepAliveSecs;
+
+    if (sscanf(s, "%ld/%ld/%u",
+               &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3
+        || lowwaterMarkKb >= highwaterMarkKb) {
+        LOGE("Failed to parse cache parameters from '%s'.", s);
+        return;
+    }
+
+    if (lowwaterMarkKb >= 0) {
+        mLowwaterThresholdBytes = lowwaterMarkKb * 1024;
+    } else {
+        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
+    }
+
+    if (highwaterMarkKb >= 0) {
+        mHighwaterThresholdBytes = highwaterMarkKb * 1024;
+    } else {
+        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
+    }
+
+    mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+
+    LOGV("lowwater = %d bytes, highwater = %d bytes, keepalive = %lld us",
+         mLowwaterThresholdBytes,
+         mHighwaterThresholdBytes,
+         mKeepAliveIntervalUs);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 22b2855..f04c566 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -63,13 +63,13 @@
     friend struct AHandlerReflector<NuCachedSource2>;
 
     enum {
-        kPageSize            = 65536,
-        kHighWaterThreshold  = 20 * 1024 * 1024,
-        kLowWaterThreshold   = 4 * 1024 * 1024,
+        kPageSize                       = 65536,
+        kDefaultHighWaterThreshold      = 20 * 1024 * 1024,
+        kDefaultLowWaterThreshold       = 4 * 1024 * 1024,
 
         // Read data after a 15 sec timeout whether we're actively
         // fetching or not.
-        kKeepAliveIntervalUs = 15000000,
+        kDefaultKeepAliveIntervalUs     = 15000000,
     };
 
     enum {
@@ -99,6 +99,12 @@
 
     int32_t mNumRetriesLeft;
 
+    size_t mHighwaterThresholdBytes;
+    size_t mLowwaterThresholdBytes;
+
+    // If the keep-alive interval is 0, keep-alives are disabled.
+    int64_t mKeepAliveIntervalUs;
+
     void onMessageReceived(const sp<AMessage> &msg);
     void onFetch();
     void onRead(const sp<AMessage> &msg);
@@ -112,6 +118,9 @@
     void restartPrefetcherIfNecessary_l(
             bool ignoreLowWaterThreshold = false, bool force = false);
 
+    void updateCacheParamsFromSystemProperty();
+    void updateCacheParamsFromString(const char *s);
+
     DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
 };