am 6534dd02: am 74261d84: Merge "Don\'t null the reference to Bitmap pixels until we\'re really ready" into jb-mr1-dev

* commit '6534dd0275c8d01de7e7400ba239d203c37c8164':
  Don't null the reference to Bitmap pixels until we're really ready
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index f485e03..63683b4 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -261,14 +261,14 @@
     delete bitmap;

 }

 

-static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {

+static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {

 #ifdef USE_OPENGL_RENDERER

     if (android::uirenderer::Caches::hasInstance()) {

-        android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);

-        return;

+        return android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);

     }

 #endif // USE_OPENGL_RENDERER

     bitmap->setPixels(NULL, NULL);

+    return true;

 }

 

 // These must match the int values in Bitmap.java

@@ -665,7 +665,7 @@
     {   "nativeCopy",               "(IIZ)Landroid/graphics/Bitmap;",

         (void*)Bitmap_copy },

     {   "nativeDestructor",         "(I)V", (void*)Bitmap_destructor },

-    {   "nativeRecycle",            "(I)V", (void*)Bitmap_recycle },

+    {   "nativeRecycle",            "(I)Z", (void*)Bitmap_recycle },

     {   "nativeCompress",           "(IIILjava/io/OutputStream;[B)Z",

         (void*)Bitmap_compress },

     {   "nativeErase",              "(II)V", (void*)Bitmap_erase },

diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 22ecc61..688fd7a 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -201,9 +201,14 @@
      */
     public void recycle() {
         if (!mRecycled) {
-            mBuffer = null;
-            nativeRecycle(mNativeBitmap);
-            mNinePatchChunk = null;
+            if (nativeRecycle(mNativeBitmap)) {
+                // return value indicates whether native pixel object was actually recycled.
+                // false indicates that it is still in use at the native level and these
+                // objects should not be collected now. They will be collected later when the
+                // Bitmap itself is collected.
+                mBuffer = null;
+                mNinePatchChunk = null;
+            }
             mRecycled = true;
         }
     }
@@ -1391,7 +1396,7 @@
     private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
                                             boolean isMutable);
     private static native void nativeDestructor(int nativeBitmap);
-    private static native void nativeRecycle(int nativeBitmap);
+    private static native boolean nativeRecycle(int nativeBitmap);
 
     private static native boolean nativeCompress(int nativeBitmap, int format,
                                             int quality, OutputStream stream,
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 81f7b94..347bd78 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -265,27 +265,38 @@
     }
 }
 
-void ResourceCache::recycle(SkBitmap* resource) {
+/**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycle(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    recycleLocked(resource);
+    return recycleLocked(resource);
 }
 
-void ResourceCache::recycleLocked(SkBitmap* resource) {
+/**
+ * Return value indicates whether resource was actually recycled, which happens when RefCnt
+ * reaches 0.
+ */
+bool ResourceCache::recycleLocked(SkBitmap* resource) {
     ssize_t index = mCache->indexOfKey(resource);
     if (index < 0) {
         // not tracking this resource; just recycle the pixel data
         resource->setPixels(NULL, NULL);
-        return;
+        return true;
     }
     ResourceReference* ref = mCache->valueAt(index);
     if (ref == NULL) {
         // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
-        return;
+        return true;
     }
     ref->recycled = true;
     if (ref->refCount == 0) {
         deleteResourceReferenceLocked(resource, ref);
+        return true;
     }
+    // Still referring to resource, don't recycle yet
+    return false;
 }
 
 /**
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index a80670c..ab493e5 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -99,8 +99,8 @@
     void destructorLocked(SkiaShader* resource);
     void destructorLocked(SkiaColorFilter* resource);
 
-    void recycle(SkBitmap* resource);
-    void recycleLocked(SkBitmap* resource);
+    bool recycle(SkBitmap* resource);
+    bool recycleLocked(SkBitmap* resource);
 
 private:
     void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);