From 547e66531d521eb1eadac87edb0f79f8c2f1bbe0 Mon Sep 17 00:00:00 2001
From: Chet Haase <chet@google.com>
Date: Mon, 22 Oct 2012 15:07:26 -0700
Subject: Don't null the reference to Bitmap pixels until we're really ready

A change in the VM triggers a native memory error more aggressively than before,
showing that there's a bug in the logic of recycling bitmaps. Since the pixel
memory is allocated on the Java heap, nulling out the reference to that memory
in the Java level Bitmap object can cause that memory to get collected at any time.
Meanwhile, we may have a reference to that memory at the native level for rendering
purposes, causing an error if/when we access that memory after it has been collected
by the VM.

The fix is to avoid setting the reference to the pixels to null unless we are
not referring to it in native code. This is determined at the time we call
recycle() - we return a boolean to indicate whether the native code is still
using the memory. if not, the Java code can null out the reference and allow the
VM to collect it. Otherwise, it will get collected later when the encompassing
Bitmap object is collected.

Issue #7339156 HTML5 tests crash the app (Vellamo)

Change-Id: I3a0d6b9a6c5dd3b86cc2b0ff7719007e774b5e3c
---
 core/jni/android/graphics/Bitmap.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'core/jni')

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 @@ static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
     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 @@ static JNINativeMethod gBitmapMethods[] = {
     {   "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 },
-- 
cgit v1.1