free gralloc buffers as soon as possible (when a surface is not visible any longer), client who have the buffers still mapped won't crash, btu may see garbage data
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index c40fec1..9916158 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -76,7 +76,9 @@
             eglDestroyImageKHR(dpy, mTextures[i].image);
             mTextures[i].image = EGL_NO_IMAGE_KHR;
         }
+        mBuffers[i].free();
     }
+    mSurface.clear();
 }
 
 void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
@@ -95,7 +97,6 @@
 status_t Layer::ditch()
 {
     // the layer is not on screen anymore. free as much resources as possible
-    mSurface.clear();
     destroy();
     return NO_ERROR;
 }
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index a368ca9..e0984fe 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -130,13 +130,10 @@
     return res;
 }
 
-
-
 // ===========================================================================
 // LayerBitmap
 // ===========================================================================
 
-
 LayerBitmap::LayerBitmap()
     : mInfo(0), mWidth(0), mHeight(0)
 {
@@ -184,7 +181,7 @@
     sp<Buffer> buffer(mBuffer);
     const uint32_t w = mWidth; 
     const uint32_t h = mHeight;
-    if (w != buffer->getWidth() || h != buffer->getHeight()) {
+    if (buffer!=0 && (w != buffer->getWidth() || h != buffer->getHeight())) {
         surface_info_t* info = mInfo;
         buffer = new Buffer(w, h, mFormat, mFlags);
         status_t err = buffer->initCheck();
@@ -200,6 +197,15 @@
     return buffer;
 }
 
+status_t LayerBitmap::free()
+{
+    mBuffer.clear();
+    mWidth = 0;
+    mHeight = 0;
+    return NO_ERROR;
+}
+
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 824e0f2..f3636c0 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -110,7 +110,8 @@
     status_t setSize(uint32_t w, uint32_t h);
 
     sp<Buffer> allocate();
-
+    status_t free();
+    
     sp<const Buffer>  getBuffer() const { return mBuffer; }
     sp<Buffer>        getBuffer()       { return mBuffer; }
     
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index e74e000..c386681 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1095,12 +1095,9 @@
 
 status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
 {
-    // First add the layer to the purgatory list, which makes sure it won't 
-    // go away, then remove it from the main list (through a transaction).
+    // remove the layer from the main list (through a transaction).
     ssize_t err = removeLayer_l(layerBase);
-    if (err >= 0) {
-        mLayerPurgatory.add(layerBase);
-    }
+
     // it's possible that we don't find a layer, because it might
     // have been destroyed already -- this is not technically an error
     // from the user because there is a race between BClient::destroySurface(),
@@ -1336,7 +1333,7 @@
 
 status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
 {
-    /* called by ~ISurface() when all references are gone */
+    // called by ~ISurface() when all references are gone
     
     class MessageDestroySurface : public MessageBase {
         SurfaceFlinger* flinger;
@@ -1349,33 +1346,21 @@
             sp<LayerBaseClient> l(layer);
             layer.clear(); // clear it outside of the lock;
             Mutex::Autolock _l(flinger->mStateLock);
-            // remove the layer from the current list -- chances are that it's 
-            // not in the list anyway, because it should have been removed 
-            // already upon request of the client (eg: window manager). 
-            // However, a buggy client could have not done that.
-            // Since we know we don't have any more clients, we don't need
-            // to use the purgatory.
+            /*
+             * remove the layer from the current list -- chances are that it's 
+             * not in the list anyway, because it should have been removed 
+             * already upon request of the client (eg: window manager). 
+             * However, a buggy client could have not done that.
+             * Since we know we don't have any more clients, we don't need
+             * to use the purgatory.
+             */
             status_t err = flinger->removeLayer_l(l);
-            if (err == NAME_NOT_FOUND) {
-                // The surface wasn't in the current list, which means it was
-                // removed already, which means it is in the purgatory, 
-                // and need to be removed from there.
-                // This needs to happen from the main thread since its dtor
-                // must run from there (b/c of OpenGL ES). Additionally, we
-                // can't really acquire our internal lock from 
-                // destroySurface() -- see postMessage() below.
-                ssize_t idx = flinger->mLayerPurgatory.remove(l);
-                LOGE_IF(idx < 0,
-                        "layer=%p is not in the purgatory list", l.get());
-            }
+            LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                    "error removing layer=%p (%s)", l.get(), strerror(-err));
             return true;
         }
     };
 
-    // It's better to not acquire our internal lock here, because it's hard
-    // to predict that it's not going to be already taken when ~Surface()
-    // is called.
-
     mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
     return NO_ERROR;
 }
@@ -1537,8 +1522,7 @@
                 mFreezeDisplay?"yes":"no", mFreezeCount,
                 mCurrentState.orientation, hw.canDraw());
         result.append(buffer);
-        snprintf(buffer, SIZE, "  purgatory size: %d, client count: %d\n",
-                mLayerPurgatory.size(), mClientsMap.size());
+        snprintf(buffer, SIZE, "  client count: %d\n", mClientsMap.size());
         result.append(buffer);
         const BufferAllocator& alloc(BufferAllocator::get());
         alloc.dump(result);
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 149eef0..b7b008d 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -307,8 +307,6 @@
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
-                SortedVector< sp<LayerBase> > mLayerPurgatory;
-
                 
                 // protected by mStateLock (but we could use another lock)
                 Tokenizer                               mTokens;