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<? extends java.lang.Object>"
+ return="java.lang.Class<?>"
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.