From 603f6de35f21d74ae242d52d501f4f5c25ff4f4c Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Fri, 14 Sep 2012 15:31:25 -0700 Subject: Fix occasional crash bug with layers Launcher occasionally crashes with a stack trace indicating that the memory of a Layer object is corrupt. It is possible for us to delete a Layer structure and then, briefly, use it to draw a DisplayList again before that DisplayList gets recreated (without the layer that got deleted). When this happens, if the memory got corrupted, it's possible to crash. The fix is to add Layer to the other objects which we currently refcount (bitmaps, shaders, etc.). Then instead of deleting a Layer, we decrement the refcount. We increment when creating it, then increment it again when it's referenced from a DisplayList. Then we decrement the refcount instead of deleting it, and decrement when we clear a DisplayList that refers to it. Then when the refcount reaches 0, we delete it. Issue #6994632 Native crash in launcher when trying to launch all apps screen Change-Id: I0627be8d49bb2f9ba8d158a84b764bb4e7df934c --- libs/hwui/ResourceCache.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'libs/hwui/ResourceCache.cpp') diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index b0c57d155666..1c83ea463b4d 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -79,6 +79,10 @@ void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) { incrementRefcount((void*) filterResource, kColorFilter); } +void ResourceCache::incrementRefcount(Layer* layerResource) { + incrementRefcount((void*) layerResource, kLayer); +} + void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -109,6 +113,10 @@ void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) { incrementRefcountLocked((void*) filterResource, kColorFilter); } +void ResourceCache::incrementRefcountLocked(Layer* layerResource) { + incrementRefcountLocked((void*) layerResource, kLayer); +} + void ResourceCache::decrementRefcount(void* resource) { Mutex::Autolock _l(mLock); decrementRefcountLocked(resource); @@ -134,6 +142,10 @@ void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) { decrementRefcount((void*) filterResource); } +void ResourceCache::decrementRefcount(Layer* layerResource) { + decrementRefcount((void*) layerResource); +} + void ResourceCache::decrementRefcountLocked(void* resource) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -167,6 +179,10 @@ void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) { decrementRefcountLocked((void*) filterResource); } +void ResourceCache::decrementRefcountLocked(Layer* layerResource) { + decrementRefcountLocked((void*) layerResource); +} + void ResourceCache::destructor(SkPath* resource) { Mutex::Autolock _l(mLock); destructorLocked(resource); @@ -280,7 +296,7 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r if (ref->recycled && ref->resourceType == kBitmap) { ((SkBitmap*) resource)->setPixels(NULL, NULL); } - if (ref->destroyed) { + if (ref->destroyed || ref->resourceType == kLayer) { switch (ref->resourceType) { case kBitmap: { SkBitmap* bitmap = (SkBitmap*) resource; @@ -308,6 +324,11 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r delete filter; } break; + case kLayer: { + Layer* layer = (Layer*) resource; + delete layer; + } + break; } } mCache->removeItem(resource); -- cgit v1.2.3-59-g8ed1b