Merge changes I61ae54f3,I57cb668e,I7a3f1e1a,Id28a2f9b into jb-mr2-dev

* changes:
  Add BufferQueueInterposer and use it for virtual displays
  Add DisplaySurface abstraction
  Fix argument types in IGraphicBufferProducer methods
  Minor cleanups/fixes before virtual display refactoring
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 26c2d1c..29838e4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -117,6 +117,7 @@
 static bool g_compress = false;
 static bool g_nohup = false;
 static int g_initialSleepSecs = 0;
+static const char* g_kernelTraceFuncs = NULL;
 
 /* Global state */
 static bool g_traceAborted = false;
@@ -132,6 +133,30 @@
 static const char* k_tracingOverwriteEnablePath =
     "/sys/kernel/debug/tracing/options/overwrite";
 
+static const char* k_currentTracerPath =
+    "/sys/kernel/debug/tracing/current_tracer";
+
+static const char* k_printTgidPath =
+    "/sys/kernel/debug/tracing/options/print-tgid";
+
+static const char* k_funcgraphAbsTimePath =
+    "/sys/kernel/debug/tracing/options/funcgraph-abstime";
+
+static const char* k_funcgraphCpuPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-cpu";
+
+static const char* k_funcgraphProcPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-proc";
+
+static const char* k_funcgraphFlatPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-flat";
+
+static const char* k_funcgraphDurationPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-duration";
+
+static const char* k_ftraceFilterPath =
+    "/sys/kernel/debug/tracing/set_ftrace_filter";
+
 static const char* k_tracingOnPath =
     "/sys/kernel/debug/tracing/tracing_on";
 
@@ -148,10 +173,22 @@
     return access(filename, W_OK) != -1;
 }
 
-// Write a string to a file, returning true if the write was successful.
-static bool writeStr(const char* filename, const char* str)
+// Truncate a file.
+static bool truncateFile(const char* path)
 {
-    int fd = open(filename, O_WRONLY);
+    int err = truncate(path, 0);
+    if (err != 0) {
+        fprintf(stderr, "error truncating %s: %s (%d)\n", path,
+                strerror(errno), errno);
+        return false;
+    }
+
+    return true;
+}
+
+static bool _writeStr(const char* filename, const char* str, int flags)
+{
+    int fd = open(filename, flags);
     if (fd == -1) {
         fprintf(stderr, "error opening %s: %s (%d)\n", filename,
                 strerror(errno), errno);
@@ -171,6 +208,18 @@
     return ok;
 }
 
+// Write a string to a file, returning true if the write was successful.
+static bool writeStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_WRONLY);
+}
+
+// Append a string to a file, returning true if the write was successful.
+static bool appendStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_APPEND|O_WRONLY);
+}
+
 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
 // file.
 static bool setKernelOptionEnable(const char* filename, bool enable)
@@ -244,16 +293,7 @@
 // Clear the contents of the kernel trace.
 static bool clearTrace()
 {
-    int traceFD = creat(k_tracePath, 0);
-    if (traceFD == -1) {
-        fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
-                strerror(errno), errno);
-        return false;
-    }
-
-    close(traceFD);
-
-    return true;
+    return truncateFile(k_tracePath);
 }
 
 // Set the size of the kernel's trace buffer in kilobytes.
@@ -275,6 +315,14 @@
     return writeStr(k_traceClockPath, enable ? "global" : "local");
 }
 
+static bool setPrintTgidEnableIfPresent(bool enable)
+{
+    if (fileExists(k_printTgidPath)) {
+        return setKernelOptionEnable(k_printTgidPath, enable);
+    }
+    return true;
+}
+
 // Poke all the binder-enabled processes in the system to get them to re-read
 // their system properties.
 static bool pokeBinderServices()
@@ -330,8 +378,90 @@
     return ok;
 }
 
-// Enable tracing in the kernel.
-static bool startTrace()
+// Verify that the comma separated list of functions are being traced by the
+// kernel.
+static bool verifyKernelTraceFuncs(const char* funcs)
+{
+    int fd = open(k_ftraceFilterPath, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
+            strerror(errno), errno);
+        return false;
+    }
+
+    char buf[4097];
+    ssize_t n = read(fd, buf, 4096);
+    close(fd);
+    if (n == -1) {
+        fprintf(stderr, "error reading %s: %s (%d)\n", k_ftraceFilterPath,
+            strerror(errno), errno);
+        return false;
+    }
+
+    buf[n] = '\0';
+    String8 funcList = String8::format("\n%s", buf);
+
+    // Make sure that every function listed in funcs is in the list we just
+    // read from the kernel.
+    bool ok = true;
+    char* myFuncs = strdup(funcs);
+    char* func = strtok(myFuncs, ",");
+    while (func) {
+        String8 fancyFunc = String8::format("\n%s\n", func);
+        bool found = funcList.find(fancyFunc.string(), 0) >= 0;
+        if (!found || func[0] == '\0') {
+            fprintf(stderr, "error: \"%s\" is not a valid kernel function "
+                "to trace.\n", func);
+            ok = false;
+        }
+        func = strtok(NULL, ",");
+    }
+    free(myFuncs);
+
+    return ok;
+}
+
+// Set the comma separated list of functions that the kernel is to trace.
+static bool setKernelTraceFuncs(const char* funcs)
+{
+    bool ok = true;
+
+    if (funcs == NULL || funcs[0] == '\0') {
+        // Disable kernel function tracing.
+        ok &= writeStr(k_currentTracerPath, "nop");
+        if (fileExists(k_ftraceFilterPath)) {
+            ok &= truncateFile(k_ftraceFilterPath);
+        }
+    } else {
+        // Enable kernel function tracing.
+        ok &= writeStr(k_currentTracerPath, "function_graph");
+        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
+        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
+
+        // Set the requested filter functions.
+        ok &= truncateFile(k_ftraceFilterPath);
+        char* myFuncs = strdup(funcs);
+        char* func = strtok(myFuncs, ",");
+        while (func) {
+            ok &= appendStr(k_ftraceFilterPath, func);
+            func = strtok(NULL, ",");
+        }
+        free(myFuncs);
+
+        // Verify that the set functions are being traced.
+        if (ok) {
+            ok &= verifyKernelTraceFuncs(funcs);
+        }
+    }
+
+    return ok;
+}
+
+// Set all the kernel tracing settings to the desired state for this trace
+// capture.
+static bool setUpTrace()
 {
     bool ok = true;
 
@@ -339,6 +469,8 @@
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
     ok &= setGlobalClockEnable(true);
+    ok &= setPrintTgidEnableIfPresent(true);
+    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
     // Set up the tags property.
     uint64_t tags = 0;
@@ -373,18 +505,12 @@
         }
     }
 
-    // Enable tracing.
-    ok &= setTracingEnabled(true);
-
     return ok;
 }
 
-// Disable tracing in the kernel.
-static void stopTrace()
+// Reset all the kernel tracing settings to their default state.
+static void cleanUpTrace()
 {
-    // Disable tracing.
-    setTracingEnabled(false);
-
     // Disable all tracing that we're able to.
     disableKernelTraceEvents();
 
@@ -393,10 +519,23 @@
 
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
+    setTraceBufferSizeKB(1);
     setGlobalClockEnable(false);
+    setPrintTgidEnableIfPresent(false);
+    setKernelTraceFuncs(NULL);
+}
 
-    // Note that we can't reset the trace buffer size here because that would
-    // clear the trace before we've read it.
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+    return setTracingEnabled(true);
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+    setTracingEnabled(false);
 }
 
 // Read the current kernel trace and write it to stdout.
@@ -556,6 +695,7 @@
     fprintf(stderr, "options include:\n"
                     "  -b N            use a trace buffer size of N KB\n"
                     "  -c              trace into a circular buffer\n"
+                    "  -k fname,...    trace the listed kernel functions\n"
                     "  -n              ignore signals\n"
                     "  -s N            sleep for N seconds before tracing [default 0]\n"
                     "  -t N            trace for N seconds [defualt 5]\n"
@@ -592,7 +732,7 @@
             {           0,                0, 0,  0 }
         };
 
-        ret = getopt_long(argc, argv, "b:cns:t:z",
+        ret = getopt_long(argc, argv, "b:ck:ns:t:z",
                           long_options, &option_index);
 
         if (ret < 0) {
@@ -614,6 +754,10 @@
                 g_traceOverwrite = true;
             break;
 
+            case 'k':
+                g_kernelTraceFuncs = optarg;
+                break;
+
             case 'n':
                 g_nohup = true;
                 break;
@@ -663,7 +807,9 @@
         sleep(g_initialSleepSecs);
     }
 
-    bool ok = startTrace();
+    bool ok = true;
+    ok &= setUpTrace();
+    ok &= startTrace();
 
     if (ok && traceStart) {
         printf("capturing trace...");
@@ -709,7 +855,7 @@
 
     // Reset the trace buffer size to 1.
     if (traceStop)
-        setTraceBufferSizeKB(1);
+        cleanUpTrace();
 
     return g_traceAborted ? 1 : 0;
 }
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 08eddcb..47f9552 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -103,16 +103,23 @@
             uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
 
-    /* triggers screen off and waits for it to complete */
+    /* triggers screen off and waits for it to complete
+     * requires ACCESS_SURFACE_FLINGER permission.
+     */
     virtual void blank(const sp<IBinder>& display) = 0;
 
-    /* triggers screen on and waits for it to complete */
+    /* triggers screen on and waits for it to complete
+     * requires ACCESS_SURFACE_FLINGER permission.
+     */
     virtual void unblank(const sp<IBinder>& display) = 0;
 
     /* returns information about a display
      * intended to be used to get information about built-in displays */
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
 
+    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
+     * This function will fail if there is a secure window on screen.
+     */
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
             uint32_t reqWidth, uint32_t reqHeight,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5996c90..1677c76 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -108,7 +108,7 @@
 void Layer::onFirstRef()
 {
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
-    sp<BufferQueue> bq = new SurfaceTextureLayer();
+    sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
     mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
             GL_TEXTURE_EXTERNAL_OES, false, bq);
 
@@ -153,8 +153,9 @@
     mFlinger->signalLayerUpdate();
 }
 
-// called with SurfaceFlinger::mStateLock as soon as the layer is entered
-// in the purgatory list
+// called with SurfaceFlinger::mStateLock from the drawing thread after
+// the layer has been remove from the current state list (and just before
+// it's removed from the drawing state list)
 void Layer::onRemoved() {
     mSurfaceFlingerConsumer->abandon();
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 88c7fa0..7fcbd2e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -573,39 +573,7 @@
         const sp<IGraphicBufferProducer>& bufferProducer) const {
     Mutex::Autolock _l(mStateLock);
     sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());
-
-    // We want to determine whether the IGraphicBufferProducer was created by
-    // SurfaceFlinger.  Check to see if we can find it in the layer list.
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
-    size_t count = currentLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const sp<Layer>& layer(currentLayers[i]);
-        // Get the consumer interface of SurfaceFlingerConsumer's
-        // BufferQueue.  If it's the same Binder object as the graphic
-        // buffer producer interface, return success.
-        sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
-        if (lbcBinder == surfaceTextureBinder) {
-            return true;
-        }
-    }
-
-    // Check the layers in the purgatory.  This check is here so that if a
-    // GLConsumer gets destroyed before all the clients are done using it,
-    // the error will not be reported as "surface XYZ is not authenticated", but
-    // will instead fail later on when the client tries to use the surface,
-    // which should be reported as "surface XYZ returned an -ENODEV".  The
-    // purgatorized layers are no less authentic than the visible ones, so this
-    // should not cause any harm.
-    size_t purgatorySize =  mLayerPurgatory.size();
-    for (size_t i=0 ; i<purgatorySize ; i++) {
-        const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
-        sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
-        if (lbcBinder == surfaceTextureBinder) {
-            return true;
-        }
-    }
-
-    return false;
+    return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
 status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
@@ -1674,6 +1642,7 @@
 
 void SurfaceFlinger::addClientLayer(const sp<Client>& client,
         const sp<IBinder>& handle,
+        const sp<IGraphicBufferProducer>& gbc,
         const sp<Layer>& lbc)
 {
     // attach this layer to the client
@@ -1682,45 +1651,22 @@
     // add this layer to the current state list
     Mutex::Autolock _l(mStateLock);
     mCurrentState.layersSortedByZ.add(lbc);
+    mGraphicBufferProducerList.add(gbc->asBinder());
 }
 
 status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer)
 {
     Mutex::Autolock _l(mStateLock);
-    status_t err = purgatorizeLayer_l(layer);
-    if (err == NO_ERROR)
-        setTransactionFlags(eTransactionNeeded);
-    return err;
-}
-
-status_t SurfaceFlinger::removeLayer_l(const sp<Layer>& layer)
-{
     ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
     if (index >= 0) {
+        mLayersPendingRemoval.push(layer);
         mLayersRemoved = true;
+        setTransactionFlags(eTransactionNeeded);
         return NO_ERROR;
     }
     return status_t(index);
 }
 
-status_t SurfaceFlinger::purgatorizeLayer_l(const sp<Layer>& layer)
-{
-    // 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).
-    ssize_t err = removeLayer_l(layer);
-    if (err >= 0) {
-        mLayerPurgatory.add(layer);
-    }
-
-    mLayersPendingRemoval.push(layer);
-
-    // 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 Client::destroySurface(),
-    // ~Client() and ~LayerCleaner().
-    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
-}
-
 uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
 {
     return android_atomic_release_load(&mTransactionFlags);
@@ -1955,7 +1901,7 @@
     }
 
     if (result == NO_ERROR) {
-        addClientLayer(client, *handle, layer);
+        addClientLayer(client, *handle, *gbp, layer);
         setTransactionFlags(eTransactionNeeded);
     }
     return result;
@@ -2008,44 +1954,25 @@
 
 status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
 {
-    /*
-     * called by the window manager, when a surface should be marked for
-     * destruction.
-     *
-     * The surface is removed from the current and drawing lists, but placed
-     * in the purgatory queue, so it's not destroyed right-away (we need
-     * to wait for all client's references to go away first).
-     */
-
-    status_t err = NAME_NOT_FOUND;
-    Mutex::Autolock _l(mStateLock);
-    sp<Layer> layer = client->getLayerUser(handle);
-
-    if (layer != 0) {
-        err = purgatorizeLayer_l(layer);
-        if (err == NO_ERROR) {
-            setTransactionFlags(eTransactionNeeded);
-        }
+    // called by the window manager when it wants to remove a Layer
+    status_t err = NO_ERROR;
+    sp<Layer> l(client->getLayerUser(handle));
+    if (l != NULL) {
+        err = removeLayer(l);
+        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
     }
     return err;
 }
 
 status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
 {
-    // called by ~LayerCleaner() when all references are gone
+    // called by ~LayerCleaner() when all references to the IBinder (handle)
+    // are gone
     status_t err = NO_ERROR;
     sp<Layer> l(layer.promote());
     if (l != NULL) {
-        Mutex::Autolock _l(mStateLock);
-        err = 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.
-            ssize_t idx = mLayerPurgatory.remove(l);
-            ALOGE_IF(idx < 0,
-                    "layer=%p is not in the purgatory list", l.get());
-        }
+        err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
     }
@@ -2357,18 +2284,6 @@
     }
 
     /*
-     * Dump the layers in the purgatory
-     */
-
-    const size_t purgatorySize = mLayerPurgatory.size();
-    snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
-    result.append(buffer);
-    for (size_t i=0 ; i<purgatorySize ; i++) {
-        const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
-        layer->shortDump(result, buffer, SIZE);
-    }
-
-    /*
      * Dump Display state
      */
 
@@ -2482,6 +2397,7 @@
 {
     switch (code) {
         case CREATE_CONNECTION:
+        case CREATE_DISPLAY:
         case SET_TRANSACTION_STATE:
         case BOOT_FINISHED:
         case BLANK:
@@ -2500,6 +2416,7 @@
             break;
         }
         case CAPTURE_SCREEN:
+        case CAPTURE_SCREEN_DEPRECATED:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -2717,9 +2634,11 @@
         const Layer::State& state(layer->drawingState());
         if (state.layerStack == hw->getLayerStack()) {
             if (state.z >= minLayerZ && state.z <= maxLayerZ) {
-                if (filtering) layer->setFiltering(true);
-                layer->draw(hw);
-                if (filtering) layer->setFiltering(false);
+                if (layer->isVisible()) {
+                    if (filtering) layer->setFiltering(true);
+                    layer->draw(hw);
+                    if (filtering) layer->setFiltering(false);
+                }
             }
         }
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f124347..e6734d2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -128,6 +128,7 @@
     friend class Client;
     friend class DisplayEventConnection;
     friend class Layer;
+    friend class SurfaceTextureLayer;
 
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -272,8 +273,6 @@
 
     // called in response to the window-manager calling
     // ISurfaceComposerClient::destroySurface()
-    // The specified layer is first placed in a purgatory list
-    // until all references from the client are released.
     status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
 
     // called when all clients have released all their references to
@@ -285,11 +284,10 @@
     status_t removeLayer(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
-    void addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
-        const sp<Layer>& lbc);
-
-    status_t removeLayer_l(const sp<Layer>& layer);
-    status_t purgatorizeLayer_l(const sp<Layer>& layer);
+    void addClientLayer(const sp<Client>& client,
+            const sp<IBinder>& handle,
+            const sp<IGraphicBufferProducer>& gbc,
+            const sp<Layer>& lbc);
 
     /* ------------------------------------------------------------------------
      * Boot animation, on/off animations and screen capture
@@ -403,10 +401,10 @@
     State mCurrentState;
     volatile int32_t mTransactionFlags;
     Condition mTransactionCV;
-    SortedVector< sp<Layer> > mLayerPurgatory;
     bool mTransactionPending;
     bool mAnimTransactionPending;
     Vector< sp<Layer> > mLayersPendingRemoval;
+    SortedVector< wp<IBinder> > mGraphicBufferProducerList;
 
     // protected by mStateLock (but we could use another lock)
     bool mLayersRemoved;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 395c8c8..d0f0dae 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -20,17 +20,35 @@
 
 #include <utils/Errors.h>
 
+#include "SurfaceFlinger.h"
 #include "SurfaceTextureLayer.h"
 
 namespace android {
 // ---------------------------------------------------------------------------
 
 
-SurfaceTextureLayer::SurfaceTextureLayer()
-    : BufferQueue(true) {
+SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
+    : BufferQueue(true), flinger(flinger) {
 }
 
 SurfaceTextureLayer::~SurfaceTextureLayer() {
+    // remove ourselves from SurfaceFlinger's list. We do this asynchronously
+    // because we don't know where this dtor is called from, it could be
+    // called with the mStateLock held, leading to a dead-lock (it actually
+    // happens).
+    class MessageCleanUpList : public MessageBase {
+        sp<SurfaceFlinger> flinger;
+        wp<IBinder> gbp;
+    public:
+        MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
+            : flinger(flinger), gbp(gbp) { }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            flinger->mGraphicBufferProducerList.remove(gbp);
+            return true;
+        }
+    };
+    flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
 }
 
 status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index a75ccf4..13cff2f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -28,15 +28,16 @@
 // ---------------------------------------------------------------------------
 
 class Layer;
+class SurfaceFlinger;
 
 /*
  * This is a thin wrapper around BufferQueue, used by the Layer class.
  */
-class SurfaceTextureLayer : public BufferQueue
-{
+class SurfaceTextureLayer : public BufferQueue {
+    sp<SurfaceFlinger> flinger;
 public:
-    SurfaceTextureLayer();
-    ~SurfaceTextureLayer();
+    SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
+    virtual ~SurfaceTextureLayer();
 
     // After calling the superclass connect(), set or clear synchronous
     // mode appropriately for the specified API.