Merge "IAudioFlinger: always initialize variables to ensure no info leak when writing them to Parcel." into mnc-dev
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 4e6c2a6..3cd0b0e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2290,11 +2290,11 @@
             // The widevine extractor does its own caching.
 
 #if 0
-            mCachedSource = new NuCachedSource2(
+            mCachedSource = NuCachedSource2::Create(
                     new ThrottledSource(
                         mConnectingDataSource, 50 * 1024 /* bytes/sec */));
 #else
-            mCachedSource = new NuCachedSource2(
+            mCachedSource = NuCachedSource2::Create(
                     mConnectingDataSource,
                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                     disconnectAtHighwatermark);
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 75ef288..5020c6c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -246,7 +246,7 @@
                 *contentType = httpSource->getMIMEType();
             }
 
-            source = new NuCachedSource2(
+            source = NuCachedSource2::Create(
                     httpSource,
                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                     disconnectAtHighwatermark);
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index f82636b..d6255d6 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -224,9 +224,6 @@
     // So whenever we call DataSource::readAt it may end up in a call to
     // IMediaHTTPConnection::readAt and therefore call back into JAVA.
     mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
-
-    Mutex::Autolock autoLock(mLock);
-    (new AMessage(kWhatFetchMore, mReflector))->post();
 }
 
 NuCachedSource2::~NuCachedSource2() {
@@ -237,6 +234,18 @@
     mCache = NULL;
 }
 
+// static
+sp<NuCachedSource2> NuCachedSource2::Create(
+        const sp<DataSource> &source,
+        const char *cacheConfig,
+        bool disconnectAtHighwatermark) {
+    sp<NuCachedSource2> instance = new NuCachedSource2(
+            source, cacheConfig, disconnectAtHighwatermark);
+    Mutex::Autolock autoLock(instance->mLock);
+    (new AMessage(kWhatFetchMore, instance->mReflector))->post();
+    return instance;
+}
+
 status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
     if (mSource->flags() & kIsHTTPBasedSource) {
         HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index d5c929e..578171f 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -23,6 +23,7 @@
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -1202,93 +1203,18 @@
 
 }
 
-// The returned buffer should be free()d.
-static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
-    *outSize = 0;
-
-    if ((size % 4) != 0) {
-        return NULL;
-    }
-
-    size_t n = size;
-    size_t padding = 0;
-    if (n >= 1 && s[n - 1] == '=') {
-        padding = 1;
-
-        if (n >= 2 && s[n - 2] == '=') {
-            padding = 2;
-        }
-    }
-
-    // We divide first to avoid overflow. It's OK to do this because we
-    // already made sure that size % 4 == 0.
-    size_t outLen = (size / 4) * 3 - padding;
-
-    void *buffer = malloc(outLen);
-    if (buffer == NULL) {
-        return NULL;
-    }
-
-    uint8_t *out = (uint8_t *)buffer;
-    size_t j = 0;
-    uint32_t accum = 0;
-    for (size_t i = 0; i < n; ++i) {
-        char c = s[i];
-        unsigned value;
-        if (c >= 'A' && c <= 'Z') {
-            value = c - 'A';
-        } else if (c >= 'a' && c <= 'z') {
-            value = 26 + c - 'a';
-        } else if (c >= '0' && c <= '9') {
-            value = 52 + c - '0';
-        } else if (c == '+') {
-            value = 62;
-        } else if (c == '/') {
-            value = 63;
-        } else if (c != '=') {
-            break;
-        } else {
-            if (i < n - padding) {
-                break;
-            }
-
-            value = 0;
-        }
-
-        accum = (accum << 6) | value;
-
-        if (((i + 1) % 4) == 0) {
-            out[j++] = (accum >> 16);
-
-            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
-            if (j < outLen) { out[j++] = accum & 0xff; }
-
-            accum = 0;
-        }
-    }
-
-    // Check if we exited the loop early.
-    if (j < outLen) {
-        free(buffer);
-        return NULL;
-    }
-
-    *outSize = outLen;
-    return (uint8_t *)buffer;
-}
-
 static void extractAlbumArt(
         const sp<MetaData> &fileMeta, const void *data, size_t size) {
     ALOGV("extractAlbumArt from '%s'", (const char *)data);
 
-    size_t flacSize;
-    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
-
-    if (flac == NULL) {
+    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
+    if (flacBuffer == NULL) {
         ALOGE("malformed base64 encoded data.");
         return;
     }
 
+    size_t flacSize = flacBuffer->size();
+    uint8_t *flac = flacBuffer->data();
     ALOGV("got flac of size %zu", flacSize);
 
     uint32_t picType;
@@ -1298,24 +1224,24 @@
     char type[128];
 
     if (flacSize < 8) {
-        goto exit;
+        return;
     }
 
     picType = U32_AT(flac);
 
     if (picType != 3) {
         // This is not a front cover.
-        goto exit;
+        return;
     }
 
     typeLen = U32_AT(&flac[4]);
     if (typeLen > sizeof(type) - 1) {
-        goto exit;
+        return;
     }
 
     // we've already checked above that flacSize >= 8
     if (flacSize - 8 < typeLen) {
-        goto exit;
+        return;
     }
 
     memcpy(type, &flac[8], typeLen);
@@ -1325,7 +1251,7 @@
 
     if (!strcmp(type, "-->")) {
         // This is not inline cover art, but an external url instead.
-        goto exit;
+        return;
     }
 
     descLen = U32_AT(&flac[8 + typeLen]);
@@ -1333,7 +1259,7 @@
     if (flacSize < 32 ||
         flacSize - 32 < typeLen ||
         flacSize - 32 - typeLen < descLen) {
-        goto exit;
+        return;
     }
 
     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
@@ -1341,7 +1267,7 @@
 
     // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
     if (flacSize - 32 - typeLen - descLen < dataLen) {
-        goto exit;
+        return;
     }
 
     ALOGV("got image data, %zu trailing bytes",
@@ -1351,10 +1277,6 @@
             kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
 
     fileMeta->setCString(kKeyAlbumArtMIME, type);
-
-exit:
-    free(flac);
-    flac = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
index dcf5bef..7da7db9 100644
--- a/media/libstagefright/foundation/base64.cpp
+++ b/media/libstagefright/foundation/base64.cpp
@@ -22,11 +22,11 @@
 namespace android {
 
 sp<ABuffer> decodeBase64(const AString &s) {
-    if ((s.size() % 4) != 0) {
+    size_t n = s.size();
+    if ((n % 4) != 0) {
         return NULL;
     }
 
-    size_t n = s.size();
     size_t padding = 0;
     if (n >= 1 && s.c_str()[n - 1] == '=') {
         padding = 1;
@@ -40,11 +40,16 @@
         }
     }
 
-    size_t outLen = 3 * s.size() / 4 - padding;
+    // We divide first to avoid overflow. It's OK to do this because we
+    // already made sure that n % 4 == 0.
+    size_t outLen = (n / 4) * 3 - padding;
 
     sp<ABuffer> buffer = new ABuffer(outLen);
 
     uint8_t *out = buffer->data();
+    if (out == NULL || buffer->size() < outLen) {
+        return NULL;
+    }
     size_t j = 0;
     uint32_t accum = 0;
     for (size_t i = 0; i < n; ++i) {
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 4252706..a29bdf9 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -28,7 +28,7 @@
 struct PageCache;
 
 struct NuCachedSource2 : public DataSource {
-    NuCachedSource2(
+    static sp<NuCachedSource2> Create(
             const sp<DataSource> &source,
             const char *cacheConfig = NULL,
             bool disconnectAtHighwatermark = false);
@@ -72,6 +72,11 @@
 private:
     friend struct AHandlerReflector<NuCachedSource2>;
 
+    NuCachedSource2(
+            const sp<DataSource> &source,
+            const char *cacheConfig,
+            bool disconnectAtHighwatermark);
+
     enum {
         kPageSize                       = 65536,
         kDefaultHighWaterThreshold      = 20 * 1024 * 1024,
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index e54cc5a..4790754 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -96,6 +96,15 @@
     const size_t SIZE = 256;
     char buffer[SIZE];
 
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        result.format("Permission Denial: "
+                "can't dump ResourceManagerService from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        write(fd, result.string(), result.size());
+        return PERMISSION_DENIED;
+    }
+
     snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
     result.append(buffer);
     result.append("  Policies:\n");