Merge "Don't crash Launcher on config change." into honeycomb
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 747543f..e3593da 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -129,7 +129,7 @@
     mBitmapResources.clear();
 
     for (size_t i = 0; i < mShaders.size(); i++) {
-        delete mShaders.itemAt(i);
+        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
     }
     mShaders.clear();
 
@@ -181,7 +181,9 @@
 
     const Vector<SkiaShader*> &shaders = recorder.getShaders();
     for (size_t i = 0; i < shaders.size(); i++) {
-        mShaders.add(shaders.itemAt(i));
+        SkiaShader* shader = shaders.itemAt(i);
+        mShaders.add(shader);
+        caches.resourceCache.incrementRefcount(shader);
     }
 
     const Vector<SkPaint*> &paints = recorder.getPaints();
@@ -405,10 +407,14 @@
     }
     mBitmapResources.clear();
 
-    mPaints.clear();
-    mPaintMap.clear();
+    for (size_t i = 0; i < mShaders.size(); i++) {
+       caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+    }
     mShaders.clear();
     mShaderMap.clear();
+
+    mPaints.clear();
+    mPaintMap.clear();
     mMatrices.clear();
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index f183473..7152334 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -417,6 +417,7 @@
             shaderCopy = shader->copy();
             mShaderMap.add(shader, shaderCopy);
             mShaders.add(shaderCopy);
+            Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
         }
 
         addInt((int) shaderCopy);
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 00de39b..70d117a 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -67,12 +67,12 @@
 
 void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
     shaderResource->getSkShader()->safeRef();
-    incrementRefcount((void*)shaderResource, kShader);
+    incrementRefcount((void*) shaderResource, kShader);
 }
 
 void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
     filterResource->getSkColorFilter()->safeRef();
-    incrementRefcount((void*)filterResource, kColorFilter);
+    incrementRefcount((void*) filterResource, kColorFilter);
 }
 
 void ResourceCache::decrementRefcount(void* resource) {
@@ -91,17 +91,17 @@
 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
     bitmapResource->pixelRef()->safeUnref();
     bitmapResource->getColorTable()->safeUnref();
-    decrementRefcount((void*)bitmapResource);
+    decrementRefcount((void*) bitmapResource);
 }
 
 void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
     shaderResource->getSkShader()->safeUnref();
-    decrementRefcount((void*)shaderResource);
+    decrementRefcount((void*) shaderResource);
 }
 
 void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
     filterResource->getSkColorFilter()->safeUnref();
-    decrementRefcount((void*)filterResource);
+    decrementRefcount((void*) filterResource);
 }
 
 void ResourceCache::recycle(SkBitmap* resource) {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index a1783df..8878c709 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -205,9 +205,12 @@
 SkiaShader* SkiaLinearGradientShader::copy() {
     SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
     copy->copyFrom(*this);
-    copy->mBounds = mBounds;
-    copy->mColors = mColors;
-    copy->mPositions = mPositions;
+    copy->mBounds = new float[4];
+    memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
+    copy->mColors = new uint32_t[mCount];
+    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+    copy->mPositions = new float[mCount];
+    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
     return copy;
 }
@@ -270,8 +273,10 @@
 SkiaShader* SkiaCircularGradientShader::copy() {
     SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
     copy->copyFrom(*this);
-    copy->mColors = mColors;
-    copy->mPositions = mPositions;
+    copy->mColors = new uint32_t[mCount];
+    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+    copy->mPositions = new float[mCount];
+    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
     return copy;
 }
@@ -317,8 +322,10 @@
 SkiaShader* SkiaSweepGradientShader::copy() {
     SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
     copy->copyFrom(*this);
-    copy->mColors = mColors;
-    copy->mPositions = mPositions;
+    copy->mColors = new uint32_t[mCount];
+    memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
+    copy->mPositions = new float[mCount];
+    memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
     copy->mCount = mCount;
     return copy;
 }
@@ -362,15 +369,24 @@
 SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
         SkXfermode::Mode mode, SkShader* key):
         SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
-        NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) {
+        NULL, first->blend() || second->blend()),
+        mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
+}
+
+SkiaComposeShader::~SkiaComposeShader() {
+    if (mCleanup) {
+        delete mFirst;
+        delete mSecond;
+    }
 }
 
 SkiaShader* SkiaComposeShader::copy() {
     SkiaComposeShader* copy = new SkiaComposeShader();
     copy->copyFrom(*this);
-    copy->mFirst = mFirst;
-    copy->mSecond = mSecond;
+    copy->mFirst = mFirst->copy();
+    copy->mSecond = mSecond->copy();
     copy->mMode = mMode;
+    copy->cleanup();
     return copy;
 }
 
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 1ebde38..89dd131 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -234,6 +234,7 @@
  */
 struct SkiaComposeShader: public SkiaShader {
     SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, SkShader* key);
+    ~SkiaComposeShader();
     SkiaShader* copy();
 
     void set(TextureCache* textureCache, GradientCache* gradientCache);
@@ -243,12 +244,18 @@
             GLuint* textureUnit);
 
 private:
-    SkiaComposeShader() {
+    SkiaComposeShader(): mCleanup(false) {
+    }
+
+    void cleanup() {
+        mCleanup = true;
     }
 
     SkiaShader* mFirst;
     SkiaShader* mSecond;
     SkXfermode::Mode mMode;
+
+    bool mCleanup;
 }; // struct SkiaComposeShader
 
 }; // namespace uirenderer