Add tracking of parcel memory allocations.

Change-Id: I76ffed0e69ccfe70e87d98646f11d4de7c3fd980
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 2ee99f8..6a69761 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -205,7 +205,11 @@
 
     // Explicitly close all file descriptors in the parcel.
     void                closeFileDescriptors();
-    
+
+    // Debugging: get metrics on current allocations.
+    static size_t       getGlobalAllocSize();
+    static size_t       getGlobalAllocCount();
+
 private:
     typedef void        (*release_func)(Parcel* parcel,
                                         const uint8_t* data, size_t dataSize,
diff --git a/include/private/binder/Static.h b/include/private/binder/Static.h
index 6a03594..eeb37d7 100644
--- a/include/private/binder/Static.h
+++ b/include/private/binder/Static.h
@@ -34,7 +34,12 @@
 extern Mutex gProcessMutex;
 extern sp<ProcessState> gProcess;
 
-// For ServiceManager.cpp
+// For Parcel.cpp
+extern Mutex gParcelGlobalAllocSizeLock;
+extern size_t gParcelGlobalAllocSize;
+extern size_t gParcelGlobalAllocCount;
+
+// For IServiceManager.cpp
 extern Mutex gDefaultServiceManagerLock;
 extern sp<IServiceManager> gDefaultServiceManager;
 extern sp<IPermissionController> gPermissionController;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 09238c2..98a3dd7 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -35,6 +35,7 @@
 #include <cutils/ashmem.h>
 
 #include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
 
 #include <inttypes.h>
 #include <stdio.h>
@@ -48,6 +49,8 @@
 
 #define LOG_REFS(...)
 //#define LOG_REFS(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
+#define LOG_ALLOC(...)
+//#define LOG_ALLOC(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
 
 // ---------------------------------------------------------------------------
 
@@ -291,12 +294,24 @@
 
 Parcel::Parcel()
 {
+    LOG_ALLOC("Parcel %p: constructing", this);
     initState();
 }
 
 Parcel::~Parcel()
 {
     freeDataNoInit();
+    LOG_ALLOC("Parcel %p: destroyed", this);
+}
+
+size_t Parcel::getGlobalAllocSize() {
+    AutoMutex _l(gParcelGlobalAllocSizeLock);
+    return gParcelGlobalAllocSize;
+}
+
+size_t Parcel::getGlobalAllocCount() {
+    AutoMutex _l(gParcelGlobalAllocSizeLock);
+    return gParcelGlobalAllocCount;
 }
 
 const uint8_t* Parcel::data() const
@@ -1488,11 +1503,20 @@
 void Parcel::freeDataNoInit()
 {
     if (mOwner) {
+        LOG_ALLOC("Parcel %p: freeing other owner data", this);
         //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
         mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
     } else {
+        LOG_ALLOC("Parcel %p: freeing allocated data", this);
         releaseObjects();
-        if (mData) free(mData);
+        if (mData) {
+            LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
+            gParcelGlobalAllocSizeLock.lock();
+            gParcelGlobalAllocSize -= mDataCapacity;
+            gParcelGlobalAllocCount--;
+            gParcelGlobalAllocSizeLock.unlock();
+            free(mData);
+        }
         if (mObjects) free(mObjects);
     }
 }
@@ -1521,6 +1545,11 @@
     releaseObjects();
 
     if (data) {
+        LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
+        gParcelGlobalAllocSizeLock.lock();
+        gParcelGlobalAllocSize += desired;
+        gParcelGlobalAllocSize -= mDataCapacity;
+        gParcelGlobalAllocSizeLock.unlock();
         mData = data;
         mDataCapacity = desired;
     }
@@ -1600,6 +1629,12 @@
         mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
         mOwner = NULL;
 
+        LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
+        gParcelGlobalAllocSizeLock.lock();
+        gParcelGlobalAllocSize += desired;
+        gParcelGlobalAllocCount++;
+        gParcelGlobalAllocSizeLock.unlock();
+
         mData = data;
         mObjects = objects;
         mDataSize = (mDataSize < desired) ? mDataSize : desired;
@@ -1634,6 +1669,12 @@
         if (desired > mDataCapacity) {
             uint8_t* data = (uint8_t*)realloc(mData, desired);
             if (data) {
+                LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity,
+                        desired);
+                gParcelGlobalAllocSizeLock.lock();
+                gParcelGlobalAllocSize += desired;
+                gParcelGlobalAllocSize -= mDataCapacity;
+                gParcelGlobalAllocSizeLock.unlock();
                 mData = data;
                 mDataCapacity = desired;
             } else if (desired > mDataCapacity) {
@@ -1664,6 +1705,12 @@
             ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
         }
 
+        LOG_ALLOC("Parcel %p: allocating with %zu capacity", this, desired);
+        gParcelGlobalAllocSizeLock.lock();
+        gParcelGlobalAllocSize += desired;
+        gParcelGlobalAllocCount++;
+        gParcelGlobalAllocSizeLock.unlock();
+
         mData = data;
         mDataSize = mDataPos = 0;
         ALOGV("continueWrite Setting data size of %p to %zu", this, mDataSize);
@@ -1676,6 +1723,7 @@
 
 void Parcel::initState()
 {
+    LOG_ALLOC("Parcel %p: initState", this);
     mError = NO_ERROR;
     mData = 0;
     mDataSize = 0;
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 2062692..b870c34 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -90,7 +90,13 @@
 
 static LibBinderIPCtStatics gIPCStatics;
 
-// ------------ ServiceManager.cpp
+// ------------ Parcel.cpp
+
+Mutex gParcelGlobalAllocSizeLock;
+size_t gParcelGlobalAllocSize = 0;
+size_t gParcelGlobalAllocCount = 0;
+
+// ------------ IServiceManager.cpp
 
 Mutex gDefaultServiceManagerLock;
 sp<IServiceManager> gDefaultServiceManager;