diff options
author | Chet Haase <chet@google.com> | 2012-10-22 15:07:26 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2012-10-22 15:25:19 -0700 |
commit | 547e66531d521eb1eadac87edb0f79f8c2f1bbe0 (patch) | |
tree | b7687d438e358ace879a20228d0c2c6a820d0c58 /libs | |
parent | d6e3ad54907ec085aa41e5c77296e9f385c22e67 (diff) | |
download | frameworks_base-547e66531d521eb1eadac87edb0f79f8c2f1bbe0.zip frameworks_base-547e66531d521eb1eadac87edb0f79f8c2f1bbe0.tar.gz frameworks_base-547e66531d521eb1eadac87edb0f79f8c2f1bbe0.tar.bz2 |
Don't null the reference to Bitmap pixels until we're really ready
A change in the VM triggers a native memory error more aggressively than before,
showing that there's a bug in the logic of recycling bitmaps. Since the pixel
memory is allocated on the Java heap, nulling out the reference to that memory
in the Java level Bitmap object can cause that memory to get collected at any time.
Meanwhile, we may have a reference to that memory at the native level for rendering
purposes, causing an error if/when we access that memory after it has been collected
by the VM.
The fix is to avoid setting the reference to the pixels to null unless we are
not referring to it in native code. This is determined at the time we call
recycle() - we return a boolean to indicate whether the native code is still
using the memory. if not, the Java code can null out the reference and allow the
VM to collect it. Otherwise, it will get collected later when the encompassing
Bitmap object is collected.
Issue #7339156 HTML5 tests crash the app (Vellamo)
Change-Id: I3a0d6b9a6c5dd3b86cc2b0ff7719007e774b5e3c
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/ResourceCache.cpp | 21 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 4 |
2 files changed, 18 insertions, 7 deletions
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 81f7b94..347bd78 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -265,27 +265,38 @@ void ResourceCache::destructorLocked(SkiaColorFilter* resource) { } } -void ResourceCache::recycle(SkBitmap* resource) { +/** + * Return value indicates whether resource was actually recycled, which happens when RefCnt + * reaches 0. + */ +bool ResourceCache::recycle(SkBitmap* resource) { Mutex::Autolock _l(mLock); - recycleLocked(resource); + return recycleLocked(resource); } -void ResourceCache::recycleLocked(SkBitmap* resource) { +/** + * Return value indicates whether resource was actually recycled, which happens when RefCnt + * reaches 0. + */ +bool ResourceCache::recycleLocked(SkBitmap* resource) { ssize_t index = mCache->indexOfKey(resource); if (index < 0) { // not tracking this resource; just recycle the pixel data resource->setPixels(NULL, NULL); - return; + return true; } ResourceReference* ref = mCache->valueAt(index); if (ref == NULL) { // Should not get here - shouldn't get a call to recycle if we're not yet tracking it - return; + return true; } ref->recycled = true; if (ref->refCount == 0) { deleteResourceReferenceLocked(resource, ref); + return true; } + // Still referring to resource, don't recycle yet + return false; } /** diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index a80670c..ab493e5 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -99,8 +99,8 @@ public: void destructorLocked(SkiaShader* resource); void destructorLocked(SkiaColorFilter* resource); - void recycle(SkBitmap* resource); - void recycleLocked(SkBitmap* resource); + bool recycle(SkBitmap* resource); + bool recycleLocked(SkBitmap* resource); private: void deleteResourceReferenceLocked(void* resource, ResourceReference* ref); |