Merge "Add ability to reuse bitmaps when decoding PNG content"
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index ee07d4b..164b357 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -225,6 +225,9 @@
     if (javaBitmap == NULL) {
         bitmap = new SkBitmap;
     } else {
+        if (sampleSize != 1) {
+            return nullObjectReturn("SkImageDecoder: Cannot reuse bitmap with sampleSize != 1");
+        }
         bitmap = (SkBitmap *) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
         // config of supplied bitmap overrules config set in options
         prefConfig = bitmap->getConfig();
@@ -232,7 +235,7 @@
     Res_png_9patch      dummy9Patch;
 
     SkAutoTDelete<SkImageDecoder>   add(decoder);
-    SkAutoTDelete<SkBitmap>         adb(bitmap);
+    SkAutoTDelete<SkBitmap>         adb(bitmap, (javaBitmap == NULL));
 
     decoder->setPeeker(&peeker);
     if (!isPurgeable) {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index f6a9c63..fe723f2 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -44,10 +44,11 @@
 
         /**
          * If set, decode methods that take the Options object will attempt to
-         * reuse this bitmap when loading content. This is a hint to the decoder
-         * only, and the decoder may choose to create a new Bitmap instead. The
+         * reuse this bitmap when loading content. If the decode operation cannot
+         * use this bitmap, the decode method will return <code>null</code> and
+         * will throw an IllegalArgumentException. The
          * current implementation necessitates that the reused bitmap be of the
-         * same size as the source content and in jpeg format (whether as a
+         * same size as the source content and in jpeg or png format (whether as a
          * resource or as a stream). The {@link android.graphics.Bitmap.Config
          * configuration} of the reused bitmap will override the setting of
          * {@link #inPreferredConfig}, if set.
@@ -389,6 +390,10 @@
             }
         }
 
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
+
         return bm;
     }
 
@@ -421,7 +426,11 @@
         if ((offset | length) < 0 || data.length < offset + length) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        return nativeDecodeByteArray(data, offset, length, opts);
+        Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
+        return bm;
     }
 
     /**
@@ -488,6 +497,9 @@
             if (tempStorage == null) tempStorage = new byte[16 * 1024];
             bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
         }
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
 
         return finishDecode(bm, outPadding, opts);
     }
@@ -558,6 +570,9 @@
      */
     public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
         Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
         return finishDecode(bm, outPadding, opts);
     }