Avoid deadlock when deleting layers
Bug #7217459

Change-Id: I12bfa6c30c5030bd1b23ea6a3ce64240ab1dfba3
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 76b274b..fb525ee 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -50,6 +50,13 @@
     deleteTexture();
 }
 
+void Layer::freeResourcesLocked() {
+    if (colorFilter) {
+        Caches::getInstance().resourceCache.decrementRefcountLocked(colorFilter);
+        colorFilter = NULL;
+    }
+}
+
 void Layer::setPaint(SkPaint* paint) {
     OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
 }
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 420073a..d2cd440 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,10 +45,11 @@
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
 struct Layer {
-
     Layer(const uint32_t layerWidth, const uint32_t layerHeight);
     ~Layer();
 
+    void freeResourcesLocked();
+
     /**
      * Sets this layer's region to a rectangle. Computes the appropriate
      * texture coordinates.
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 1c83ea4..18d8324 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -155,7 +155,7 @@
     }
     ref->refCount--;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -201,7 +201,7 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -223,7 +223,7 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -242,7 +242,7 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -261,7 +261,7 @@
     }
     ref->destroyed = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -284,7 +284,7 @@
     }
     ref->recycled = true;
     if (ref->refCount == 0) {
-        deleteResourceReference(resource, ref);
+        deleteResourceReferenceLocked(resource, ref);
     }
 }
 
@@ -292,7 +292,7 @@
  * This method should only be called while the mLock mutex is held (that mutex is grabbed
  * by the various destructor() and recycle() methods which call this method).
  */
-void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
+void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
     }
@@ -326,6 +326,7 @@
             break;
             case kLayer: {
                 Layer* layer = (Layer*) resource;
+                layer->freeResourcesLocked();
                 delete layer;
             }
             break;
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 2053d96..a80670c 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -103,7 +103,7 @@
     void recycleLocked(SkBitmap* resource);
 
 private:
-    void deleteResourceReference(void* resource, ResourceReference* ref);
+    void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);
 
     void incrementRefcount(void* resource, ResourceType resourceType);
     void incrementRefcountLocked(void* resource, ResourceType resourceType);