Refcount 9-patches and properly handle GC events

This change adds refcounting of Res_png_9patch instances, the native
data structure used to represent 9-patches. The Dalvik NinePatch class
now holds a native pointer instead of a Dalvik byte[]. This pointer
is used whenever we need to draw the 9-patch (software or hardware.)

Since we are now tracking garbage collection of NinePatch objects
libhwui's PatchCache must keep a list of free blocks in the VBO
used to store the meshes.

This change also removes unnecessary instances tracking from
GLES20DisplayList. Bitmaps and 9-patches are refcounted at the
native level and do not need to be tracked by the Dalvik layer.

Change-Id: Ib8682d573a538aaf1945f8ec5a9bd5da5d16f74b
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 3ab40da..70ab6e7 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -350,8 +350,7 @@
 // Paths
 ///////////////////////////////////////////////////////////////////////////////
 
-void PathCache::remove(const path_pair_t& pair) {
-    Vector<PathDescription> pathsToRemove;
+void PathCache::remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair) {
     LruCache<PathDescription, PathTexture*>::Iterator i(mCache);
 
     while (i.next()) {
@@ -362,10 +361,6 @@
             pathsToRemove.push(key);
         }
     }
-
-    for (size_t i = 0; i < pathsToRemove.size(); i++) {
-        mCache.remove(pathsToRemove.itemAt(i));
-    }
 }
 
 void PathCache::removeDeferred(SkPath* path) {
@@ -374,12 +369,20 @@
 }
 
 void PathCache::clearGarbage() {
-    Mutex::Autolock l(mLock);
-    size_t count = mGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        remove(mGarbage.itemAt(i));
+    Vector<PathDescription> pathsToRemove;
+
+    { // scope for the mutex
+        Mutex::Autolock l(mLock);
+        size_t count = mGarbage.size();
+        for (size_t i = 0; i < count; i++) {
+            remove(pathsToRemove, mGarbage.itemAt(i));
+        }
+        mGarbage.clear();
     }
-    mGarbage.clear();
+
+    for (size_t i = 0; i < pathsToRemove.size(); i++) {
+        mCache.remove(pathsToRemove.itemAt(i));
+    }
 }
 
 /**