From 15a108550e3d74b406927d85c8e69018761adf49 Mon Sep 17 00:00:00 2001 From: sergeyv Date: Tue, 27 Dec 2016 14:32:03 -0800 Subject: [PATCH 1/3] Fix getConfig on recycled bitmap Test: android.graphics.cts.BitmapTest#testGetConfigOnRecycled bug:33789983 Change-Id: Ic91c16cbd83acdd6002021b44da57636ee27742d --- core/jni/android/graphics/Bitmap.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 8f74bf8a4b6fa..3c0b25cb30bf3 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -52,6 +52,7 @@ public: mAllocationSize = mBitmap->getAllocationByteCount(); mRowBytes = mBitmap->rowBytes(); mGenerationId = mBitmap->getGenerationID(); + mIsHardware = mBitmap->isHardware(); mBitmap.reset(); } @@ -118,6 +119,13 @@ public: return mGenerationId; } + bool isHardware() { + if (mBitmap) { + return mBitmap->isHardware(); + } + return mIsHardware; + } + ~BitmapWrapper() { } private: @@ -127,6 +135,7 @@ private: size_t mAllocationSize; size_t mRowBytes; uint32_t mGenerationId; + bool mIsHardware; }; // Convenience class that does not take a global ref on the pixels, relying @@ -775,7 +784,7 @@ static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) { static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) { LocalScopedBitmap bitmap(bitmapHandle); - if (bitmap->bitmap().isHardware()) { + if (bitmap->isHardware()) { return GraphicsJNI::hardwareLegacyBitmapConfig(); } return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType()); @@ -1208,7 +1217,7 @@ static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Ha // Paying the price for making Hardware Bitmap as Config: // later check for colorType will pass successfully, // because Hardware Config internally may be RGBA8888 or smth like that. - if (bitmap0->bitmap().isHardware() != bitmap1->bitmap().isHardware()) { + if (bitmap0->isHardware() != bitmap1->isHardware()) { return JNI_FALSE; } From 81f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0 Mon Sep 17 00:00:00 2001 From: sergeyv Date: Tue, 27 Dec 2016 18:08:01 -0800 Subject: [PATCH 2/3] HardwareBitmaps: support createBitmap methods that return immutable bitmap Test: testCreateScaledBitmap, testCreateTransformedBitmap, testCreateSubsetBitmap in HardwareBitmapTests bug:30999911 Change-Id: Ic128dfed78b18ad6f12dad50023ee7c2f5bfa4ad --- core/jni/android/graphics/Bitmap.cpp | 19 +++++++++++++++++++ graphics/java/android/graphics/Bitmap.java | 10 +++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 3c0b25cb30bf3..59cbc939890a0 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -1291,6 +1291,23 @@ static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) return static_cast(bitmapHandle->getAllocationByteCount()); } +static jobject Bitmap_nativeCopyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) { + LocalScopedBitmap bitmapHandle(bitmapPtr); + LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(), + "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig"); + Bitmap& hwuiBitmap = bitmapHandle->bitmap(); + SkBitmap src; + hwuiBitmap.getSkBitmap(&src); + + SkBitmap result; + HeapAllocator allocator; + if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) { + doThrowRE(env, "Could not copy a hardware bitmap."); + return NULL; + } + return createBitmap(env, allocator.getStorageObjAndReset(), kBitmapCreateFlag_None); +} + /////////////////////////////////////////////////////////////////////////////// static jclass make_globalref(JNIEnv* env, const char classname[]) { @@ -1349,6 +1366,8 @@ static const JNINativeMethod gBitmapMethods[] = { { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs }, { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw }, { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount }, + { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;", + (void*)Bitmap_nativeCopyPreserveInternalConfig }, }; int register_android_graphics_Bitmap(JNIEnv* env) diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index b6db327bff480..dd23f9989d986 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -753,6 +753,11 @@ public final class Bitmap implements Parcelable { return source; } + boolean isHardware = source.getConfig() == Config.HARDWARE; + if (isHardware) { + source = nativeCopyPreserveInternalConfig(source.mNativePtr); + } + int neww = width; int newh = height; Canvas canvas = new Canvas(); @@ -824,7 +829,9 @@ public final class Bitmap implements Parcelable { canvas.setBitmap(bitmap); canvas.drawBitmap(source, srcR, dstR, paint); canvas.setBitmap(null); - + if (isHardware) { + return bitmap.copy(Config.HARDWARE, false); + } return bitmap; } @@ -1773,4 +1780,5 @@ public final class Bitmap implements Parcelable { private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1); private static native void nativePrepareToDraw(long nativeBitmap); private static native int nativeGetAllocationByteCount(long nativeBitmap); + private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap); } From 980bead518fc5ddb52ae8d00258f91b087c1f91a Mon Sep 17 00:00:00 2001 From: sergeyv Date: Thu, 29 Dec 2016 12:05:51 -0800 Subject: [PATCH 3/3] Prohibit copyPixelsToBuffer & copyPixelsFromBuffer Test: BitmapTest#testHardwareCopyPixels(From|To)Buffer bug:30999911 Change-Id: I3bfa2846bff574bc0bfd54674eac794d1a6a0ff9 --- graphics/java/android/graphics/Bitmap.java | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index dd23f9989d986..a259937c0b731 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -371,6 +371,16 @@ public final class Bitmap implements Parcelable { } } + /** + * This is called by methods that want to throw an exception if the bitmap + * is {@link Config#HARDWARE}. + */ + private void checkHardware(String errorMessage) { + if (getConfig() == Config.HARDWARE) { + throw new IllegalStateException(errorMessage); + } + } + /** * Common code for checking that x and y are >= 0 * @@ -512,8 +522,11 @@ public final class Bitmap implements Parcelable { *

After this method returns, the current position of the buffer is * updated: the position is incremented by the number of elements written * in the buffer.

+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */ public void copyPixelsToBuffer(Buffer dst) { + checkHardware("unable to copyPixelsToBuffer, " + + "pixel access is not supported on Config#HARDWARE bitmaps"); int elements = dst.remaining(); int shift; if (dst instanceof ByteBuffer) { @@ -550,9 +563,11 @@ public final class Bitmap implements Parcelable { * updated: the position is incremented by the number of elements read from * the buffer. If you need to read the bitmap from the buffer again you must * first rewind the buffer.

+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */ public void copyPixelsFromBuffer(Buffer src) { checkRecycled("copyPixelsFromBuffer called on recycled bitmap"); + checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable"); int elements = src.remaining(); int shift; @@ -1435,9 +1450,8 @@ public final class Bitmap implements Parcelable { @ColorInt public int getPixel(int x, int y) { checkRecycled("Can't call getPixel() on a recycled bitmap"); - if (getConfig() == Config.HARDWARE) { - throw new IllegalStateException("Can't access pixels in hardware Bitmaps"); - } + checkHardware("unable to getPixel(), " + + "pixel access is not supported on Config#HARDWARE bitmaps"); checkPixelAccess(x, y); return nativeGetPixel(mNativePtr, x, y); } @@ -1469,9 +1483,8 @@ public final class Bitmap implements Parcelable { public void getPixels(@ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height) { checkRecycled("Can't call getPixels() on a recycled bitmap"); - if (getConfig() == Config.HARDWARE) { - throw new IllegalStateException("Can't access pixels in hardware Bitmaps"); - } + checkHardware("unable to getPixels(), " + + "pixel access is not supported on Config#HARDWARE bitmaps"); if (width == 0 || height == 0) { return; // nothing to do }