Attempt to solve the double-GC problem
Fix the issue where Bitmap requires two GC passes
to release its byte[] by using some questionable
ref-counting hacks to manage whether or not
native has a strong or weak ref to the byte[]
Change-Id: Ia90a883579f61c0b1904b5549a66bd0ef34b32c5
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a8355c2..1965cd3 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -23,6 +23,7 @@
#include "android_os_Parcel.h"
#include "android_util_Binder.h"
+#include "android/graphics/Bitmap.h"
#include "android/graphics/GraphicsJNI.h"
#include "android/graphics/Region.h"
@@ -168,22 +169,19 @@
}
}
- const ssize_t rowBytes =
+ const size_t rowBytes =
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
- SkBitmap* bitmap = new SkBitmap();
- bitmap->setInfo(screenshotInfo, (size_t)rowBytes);
- if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
- // takes ownership of ScreenshotClient
- SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
- (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
- (void*) (screenshot.get()));
- screenshot.detach();
- pixels->setImmutable();
- bitmap->setPixelRef(pixels)->unref();
- bitmap->lockPixels();
+ if (!screenshotInfo.fWidth || !screenshotInfo.fHeight) {
+ return NULL;
}
+ Bitmap* bitmap = new Bitmap(
+ (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
+ screenshotInfo, rowBytes, nullptr);
+ screenshot.detach();
+ bitmap->pixelRef()->setImmutable();
+
return GraphicsJNI::createBitmap(env, bitmap,
GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
}