Add ability to reuse bitmaps when loading new content

Change-Id: Ic5f5f40ee39787403977fb372b335dc21cf07243
diff --git a/api/current.xml b/api/current.xml
index acc7e3d..36d1699 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -75752,6 +75752,16 @@
  visibility="public"
 >
 </method>
+<field name="inBitmap"
+ type="android.graphics.Bitmap"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inDensity"
  type="int"
  transient="false"
@@ -250580,7 +250590,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
@@ -264830,9 +264840,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="beginIndex" type="int">
+<parameter name="start" type="int">
 </parameter>
-<parameter name="endIndex" type="int">
+<parameter name="end" type="int">
 </parameter>
 </method>
 <method name="ensureCapacity"
@@ -267530,7 +267540,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -273853,7 +273863,7 @@
 </exception>
 </method>
 <method name="getClass"
- return="java.lang.Class&lt;? extends java.lang.Object&gt;"
+ return="java.lang.Class&lt;?&gt;"
  abstract="false"
  native="true"
  synchronized="false"
@@ -276643,9 +276653,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -276659,9 +276669,9 @@
 </parameter>
 <parameter name="high" type="int">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -276673,9 +276683,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <parameter name="charsetName" type="java.lang.String">
 </parameter>
@@ -276705,9 +276715,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <parameter name="charset" type="java.nio.charset.Charset">
 </parameter>
@@ -276743,9 +276753,9 @@
 >
 <parameter name="data" type="char[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="charCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -276765,7 +276775,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="stringbuffer" type="java.lang.StringBuffer">
+<parameter name="stringBuffer" type="java.lang.StringBuffer">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -276789,7 +276799,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="sb" type="java.lang.StringBuilder">
+<parameter name="stringBuilder" type="java.lang.StringBuilder">
 </parameter>
 </constructor>
 <method name="charAt"
@@ -276841,9 +276851,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="beginIndex" type="int">
+<parameter name="start" type="int">
 </parameter>
-<parameter name="endIndex" type="int">
+<parameter name="end" type="int">
 </parameter>
 </method>
 <method name="compareTo"
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 1412f38..0254924 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -41,7 +41,7 @@
     /**
      * The setter function, if needed. ObjectAnimator hands off this functionality to
      * PropertyValuesHolder, since it holds all of the per-property information. This
-     * property can be manually set via setSetter(). Otherwise, it is automatically
+     * property is automatically
      * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator.
      */
     Method mSetter = null;
@@ -49,7 +49,7 @@
     /**
      * The getter function, if needed. ObjectAnimator hands off this functionality to
      * PropertyValuesHolder, since it holds all of the per-property information. This
-     * property can be manually set via setSetter(). Otherwise, it is automatically
+     * property is automatically
      * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator.
      * The getter is only derived and used if one of the values is null.
      */
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index b9c93b8..ee07d4b 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -32,6 +32,9 @@
 jfieldID gOptions_heightFieldID;
 jfieldID gOptions_mimeFieldID;
 jfieldID gOptions_mCancelID;
+jfieldID gOptions_bitmapFieldID;
+jclass gBitmap_class;
+jfieldID gBitmap_nativeBitmapFieldID;
 
 static jclass gFileDescriptor_class;
 static jfieldID gFileDescriptor_descriptor;
@@ -187,6 +190,7 @@
                         (allowPurgeable && optionsPurgeable(env, options));
     bool reportSizeToVM = optionsReportSizeToVM(env, options);
     bool preferQualityOverSpeed = false;
+    jobject javaBitmap = NULL;
     
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
@@ -203,6 +207,7 @@
         doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
         preferQualityOverSpeed = env->GetBooleanField(options,
                 gOptions_preferQualityOverSpeedFieldID);
+        javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
     }
 
     SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
@@ -216,7 +221,14 @@
 
     NinePatchPeeker     peeker(decoder);
     JavaPixelAllocator  javaAllocator(env, reportSizeToVM);
-    SkBitmap*           bitmap = new SkBitmap;
+    SkBitmap*           bitmap;
+    if (javaBitmap == NULL) {
+        bitmap = new SkBitmap;
+    } else {
+        bitmap = (SkBitmap *) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
+        // config of supplied bitmap overrules config set in options
+        prefConfig = bitmap->getConfig();
+    }
     Res_png_9patch      dummy9Patch;
 
     SkAutoTDelete<SkImageDecoder>   add(decoder);
@@ -233,14 +245,14 @@
     // happens earlier than AutoDecoderCancel object is added
     // to the gAutoDecoderCancelMutex linked list.
     if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
-        return nullObjectReturn("gOptions_mCancelID");;
+        return nullObjectReturn("gOptions_mCancelID");
     }
 
     SkImageDecoder::Mode decodeMode = mode;
     if (isPurgeable) {
         decodeMode = SkImageDecoder::kDecodeBounds_Mode;
     }
-    if (!decoder->decode(stream, bitmap, prefConfig, decodeMode)) {
+    if (!decoder->decode(stream, bitmap, prefConfig, decodeMode, javaBitmap != NULL)) {
         return nullObjectReturn("decoder->decode returned false");
     }
 
@@ -301,6 +313,11 @@
     }
     // promise we will never change our pixels (great for sharing and pictures)
     pr->setImmutable();
+
+    if (javaBitmap != NULL) {
+        // If a java bitmap was passed in for reuse, pass it back
+        return javaBitmap;
+    }
     // now create the java bitmap
     return GraphicsJNI::createBitmap(env, bitmap, false, ninePatchChunk);
 }
@@ -554,6 +571,8 @@
 int register_android_graphics_BitmapFactory(JNIEnv* env);
 int register_android_graphics_BitmapFactory(JNIEnv* env) {
     gOptions_class = make_globalref(env, "android/graphics/BitmapFactory$Options");
+    gOptions_bitmapFieldID = getFieldIDCheck(env, gOptions_class, "inBitmap",
+        "Landroid/graphics/Bitmap;");
     gOptions_justBoundsFieldID = getFieldIDCheck(env, gOptions_class, "inJustDecodeBounds", "Z");
     gOptions_sampleSizeFieldID = getFieldIDCheck(env, gOptions_class, "inSampleSize", "I");
     gOptions_configFieldID = getFieldIDCheck(env, gOptions_class, "inPreferredConfig",
@@ -569,6 +588,8 @@
     gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
     gOptions_mCancelID = getFieldIDCheck(env, gOptions_class, "mCancel", "Z");
 
+    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
+    gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
     gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
     gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
 
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 66f8f70..f6a9c63 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -43,6 +43,26 @@
         }
 
         /**
+         * 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
+         * current implementation necessitates that the reused bitmap be of the
+         * same size as the source content and in jpeg 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.
+         *
+         * <p>You should still always use the returned Bitmap of the decode
+         * method and not assume that reusing the bitmap worked, due to the
+         * constraints outlined above and failure situations that can occur.
+         * Checking whether the return value matches the value of the inBitmap
+         * set in the Options structure is a way to see if the bitmap was reused,
+         * but in all cases you should use the returned Bitmap to make sure
+         * that you are using the bitmap that was used as the decode destination.</p>
+         */
+        public Bitmap inBitmap;
+
+        /**
          * If set to true, the decoder will return null (no bitmap), but
          * the out... fields will still be set, allowing the caller to query
          * the bitmap without having to allocate the memory for its pixels.