merge in jb-mr1.1-release history after reset to jb-mr1.1-dev
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index dffa788..479cd3e 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -84,6 +84,7 @@
     static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
     
     friend class Singleton<GraphicBufferAllocator>;
+    friend class BufferLiberatorThread;
     GraphicBufferAllocator();
     ~GraphicBufferAllocator();
     
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index cfc0293..624d7e0 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -109,35 +109,21 @@
 }
 
 void ConsumerBase::onBuffersReleased() {
-    sp<GraphicBuffer> bufRefs[BufferQueue::NUM_BUFFER_SLOTS];
+    Mutex::Autolock lock(mMutex);
 
-    { // Scope for the lock
-        Mutex::Autolock lock(mMutex);
+    CB_LOGV("onBuffersReleased");
 
-        CB_LOGV("onBuffersReleased");
-
-        if (mAbandoned) {
-            // Nothing to do if we're already abandoned.
-            return;
-        }
-
-        uint32_t mask = 0;
-        mBufferQueue->getReleasedBuffers(&mask);
-        for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
-            if (mask & (1 << i)) {
-                // Grab a local reference to the buffers so that they don't
-                // get freed while the lock is held.
-                bufRefs[i] = mSlots[i].mGraphicBuffer;
-
-                freeBufferLocked(i);
-            }
-        }
+    if (mAbandoned) {
+        // Nothing to do if we're already abandoned.
+        return;
     }
 
-    // Clear the local buffer references.  This would happen automatically
-    // when the array gets dtor'd, but I'm doing it explicitly for clarity.
+    uint32_t mask = 0;
+    mBufferQueue->getReleasedBuffers(&mask);
     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
-        bufRefs[i].clear();
+        if (mask & (1 << i)) {
+            freeBufferLocked(i);
+        }
     }
 }
 
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index ff550d9..72acd7d 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -129,21 +129,65 @@
     return err;
 }
 
-status_t GraphicBufferAllocator::free(buffer_handle_t handle)
-{
-    ATRACE_CALL();
-    status_t err;
+class BufferLiberatorThread : public Thread {
+public:
 
-    err = mAllocDev->free(mAllocDev, handle);
-
-    ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
-    if (err == NO_ERROR) {
-        Mutex::Autolock _l(sLock);
-        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        list.removeItem(handle);
+    static void queueCaptiveBuffer(buffer_handle_t handle) {
+        static sp<BufferLiberatorThread> thread(new BufferLiberatorThread);
+        static bool running = false;
+        if (!running) {
+            thread->run("BufferLiberator");
+            running = true;
+        }
+        {
+            Mutex::Autolock lock(thread->mMutex);
+            thread->mQueue.push_back(handle);
+            thread->mCondition.signal();
+        }
     }
 
-    return err;
+private:
+
+    BufferLiberatorThread() {}
+
+    virtual bool threadLoop() {
+        buffer_handle_t handle;
+        {
+            Mutex::Autolock lock(mMutex);
+            while (mQueue.isEmpty()) {
+                mCondition.wait(mMutex);
+            }
+            handle = mQueue[0];
+            mQueue.removeAt(0);
+        }
+
+        status_t err;
+        GraphicBufferAllocator& gba(GraphicBufferAllocator::get());
+        { // Scope for tracing
+            ATRACE_NAME("gralloc::free");
+            err = gba.mAllocDev->free(gba.mAllocDev, handle);
+        }
+        ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
+
+        if (err == NO_ERROR) {
+            Mutex::Autolock _l(GraphicBufferAllocator::sLock);
+            KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t>&
+                    list(GraphicBufferAllocator::sAllocList);
+            list.removeItem(handle);
+        }
+
+        return true;
+    }
+
+    Vector<buffer_handle_t> mQueue;
+    Condition mCondition;
+    Mutex mMutex;
+};
+
+status_t GraphicBufferAllocator::free(buffer_handle_t handle)
+{
+    BufferLiberatorThread::queueCaptiveBuffer(handle);
+    return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------