split surface management from surface's buffers management

Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index dcce25e..c11c855 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -122,7 +122,8 @@
     volatile int8_t index[NUM_BUFFER_MAX];
 
     int32_t     identity;       // surface's identity (const)
-    int32_t     reserved32[2];
+    int32_t     token;          // surface's token (for debugging)
+    int32_t     reserved32[1];
     Statistics  stats;
     int32_t     reserved;
     BufferData  buffers[NUM_BUFFER_MAX];     // 960 bytes
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 3271cfd..dd44aa5 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -85,9 +85,12 @@
     /* create connection with surface flinger, requires
      * ACCESS_SURFACE_FLINGER permission
      */
-
     virtual sp<ISurfaceComposerClient> createConnection() = 0;
 
+    /* create a client connection with surface flinger
+     */
+    virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
+
     /* retrieve the control block */
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
@@ -123,6 +126,7 @@
         // Java by ActivityManagerService.
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
+        CREATE_CLIENT_CONNECTION,
         GET_CBLK,
         OPEN_GLOBAL_TRANSACTION,
         CLOSE_GLOBAL_TRANSACTION,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index b2a4766..a1e9e04 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -58,6 +58,7 @@
     };
 
     virtual sp<IMemoryHeap> getControlBlock() const = 0;
+    virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const = 0;
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 2957970..67dc693 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -229,7 +229,6 @@
      */
     void init();
     status_t validate() const;
-    status_t initCheck() const;
     sp<ISurface> getISurface() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
@@ -264,15 +263,15 @@
     };
 
     // constants
-    sp<SurfaceClient>           mClient;
+    GraphicBufferMapper&        mBufferMapper;
+    SurfaceClient&              mClient;
+    SharedBufferClient*         mSharedBufferClient;
+    status_t                    mInitCheck;
     sp<ISurface>                mSurface;
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
-    GraphicBufferMapper&        mBufferMapper;
-    SharedBufferClient*         mSharedBufferClient;
-    status_t                    mInitCheck;
 
     // protected by mSurfaceLock
     Rect                        mSwapRectangle;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 8e28a81..8773d713 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -22,8 +22,9 @@
 
 #include <binder/IBinder.h>
 
-#include <utils/SortedVector.h>
 #include <utils/RefBase.h>
+#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
 #include <utils/threads.h>
 
 #include <ui/PixelFormat.h>
@@ -39,6 +40,22 @@
 class SharedClient;
 class ISurfaceComposer;
 class DisplayInfo;
+class surface_flinger_cblk_t;
+
+// ---------------------------------------------------------------------------
+
+class ComposerService : public Singleton<ComposerService>
+{
+    // these are constants
+    sp<ISurfaceComposer> mComposerService;
+    sp<IMemoryHeap> mServerCblkMemory;
+    surface_flinger_cblk_t volatile* mServerCblk;
+    ComposerService();
+    friend class Singleton<ComposerService>;
+public:
+    static sp<ISurfaceComposer> getComposerService();
+    static surface_flinger_cblk_t const volatile * getControlBlock();
+};
 
 // ---------------------------------------------------------------------------
 
@@ -153,25 +170,6 @@
 };
 
 // ---------------------------------------------------------------------------
-
-class SurfaceClient : public RefBase
-{
-    // all these attributes are constants
-    status_t                    mStatus;
-    SharedClient*               mControl;
-    sp<IMemoryHeap>             mControlMemory;
-    sp<IBinder>                 mConnection;
-    sp<ISurfaceComposer>        mComposerService;
-    void init(const sp<IBinder>& conn);
-public:
-    explicit SurfaceClient(const sp<IBinder>& conn);
-    explicit SurfaceClient(const sp<SurfaceComposerClient>& client);
-    status_t initCheck() const;
-    SharedClient* getSharedClient() const;
-    void signalServer() const;
-};
-
-// ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index e72b6b3..a3e85a9 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -93,10 +93,8 @@
     
     void setIndex(int index);
     int getIndex() const;
-    void setVerticalStride(uint32_t vstride);
-    uint32_t getVerticalStride() const;
 
-protected:
+private:
     virtual ~GraphicBuffer();
 
     enum {
@@ -105,8 +103,12 @@
         ownData   = 2,
     };
 
-    inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
-    inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
+    inline const GraphicBufferMapper& getBufferMapper() const {
+        return mBufferMapper;
+    }
+    inline GraphicBufferMapper& getBufferMapper() {
+        return mBufferMapper;
+    }
     uint8_t mOwner;
 
 private:
@@ -134,7 +136,6 @@
 
     GraphicBufferMapper& mBufferMapper;
     ssize_t mInitCheck;
-    uint32_t mVStride;
     int mIndex;
 };
 
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 85149f5f5..a94fdd4 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -50,10 +50,9 @@
 Layer::Layer(SurfaceFlinger* flinger,
         DisplayID display, const sp<Client>& client)
     :   LayerBaseClient(flinger, display, client),
-        lcblk(NULL),
-        mSecure(false),
         mNeedsBlending(true),
         mNeedsDithering(false),
+        mSecure(false),
         mTextureManager(mFlags),
         mBufferManager(mTextureManager),
         mWidth(0), mHeight(0), mFixedSize(false)
@@ -66,32 +65,43 @@
     EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
     mBufferManager.destroy(dpy);
 
-    // the actual buffers will be destroyed here
-    delete lcblk;
+    // we can use getUserClientUnsafe here because we know we're
+    // single-threaded at that point.
+    sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
+    if (ourClient != 0) {
+        ourClient->detachLayer(this);
+    }
 }
 
-// TODO: get rid of this
-void Layer::setToken(int32_t token)
+status_t Layer::setToken(const sp<UserClient>& userClient,
+        SharedClient* sharedClient, int32_t token)
 {
-    sp<Client> ourClient(client.promote());
-
-    mToken = token;
-
-    // no OpenGL operation is possible here, since we might not be
-    // in the OpenGL thread.
-    lcblk = new SharedBufferServer(
-            ourClient->ctrlblk, token, mBufferManager.getDefaultBufferCount(),
+    SharedBufferServer* lcblk = new SharedBufferServer(
+            sharedClient, token, mBufferManager.getDefaultBufferCount(),
             getIdentity());
 
-   mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
+    status_t err = mUserClientRef.setToken(userClient, lcblk, token);
+    if (err != NO_ERROR) {
+        LOGE("ClientRef::setToken(%p, %p, %u) failed",
+                userClient.get(), lcblk, token);
+        delete lcblk;
+    }
+
+    return err;
+}
+
+int32_t Layer::getToken() const
+{
+    return mUserClientRef.getToken();
 }
 
 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
 // in the purgatory list
 void Layer::onRemoved()
 {
-    sp<Client> ourClient(client.promote());
-    if (ourClient != 0) {
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    if (lcblk) {
         // wake up the condition
         lcblk->setStatus(NO_INIT);
     }
@@ -237,10 +247,9 @@
 
 status_t Layer::setBufferCount(int bufferCount)
 {
-    // Ensures our client doesn't go away while we're accessing
-    // the shared area.
-    sp<Client> ourClient(client.promote());
-    if (ourClient == 0) {
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    if (!lcblk) {
         // oops, the client is already gone
         return DEAD_OBJECT;
     }
@@ -259,7 +268,7 @@
 {
     sp<GraphicBuffer> buffer;
 
-    if ((reqWidth | reqHeight | reqFormat) < 0)
+    if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
         return buffer;
 
     if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
@@ -267,8 +276,9 @@
 
     // this ensures our client doesn't go away while we're accessing
     // the shared area.
-    sp<Client> ourClient(client.promote());
-    if (ourClient == 0) {
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    if (!lcblk) {
         // oops, the client is already gone
         return buffer;
     }
@@ -403,8 +413,9 @@
             // a buffer, it'll get the new size.
             setBufferSize(temp.requested_w, temp.requested_h);
 
-            sp<Client> ourClient(client.promote());
-            if (ourClient != 0) {
+            ClientRef::Access sharedClient(mUserClientRef);
+            SharedBufferServer* lcblk(sharedClient.get());
+            if (lcblk) {
                 // all buffers need reallocation
                 lcblk->reallocateAll();
             }
@@ -442,8 +453,9 @@
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
-    sp<Client> ourClient(client.promote());
-    if (ourClient == 0) {
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    if (!lcblk) {
         // client died
         recomputeVisibleRegions = true;
         return;
@@ -458,14 +470,14 @@
     }
 
     if (buf < NO_ERROR) {
-        LOGE("retireAndLock() buffer index (%d) out of range", buf);
+        LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
         mPostedDirtyRegion.clear();
         return;
     }
 
     // we retired a buffer, which becomes the new front buffer
     if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
-        LOGE("retireAndLock() buffer index (%d) out of range", buf);
+        LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
         mPostedDirtyRegion.clear();
         return;
     }
@@ -560,11 +572,16 @@
 
 void Layer::finishPageFlip()
 {
-    sp<Client> ourClient(client.promote());
-    if (ourClient != 0) {
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    if (lcblk) {
         int buf = mBufferManager.getActiveBufferIndex();
-        status_t err = lcblk->unlock( buf );
-        LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
+        if (buf >= 0) {
+            status_t err = lcblk->unlock( buf );
+            LOGE_IF(err!=NO_ERROR,
+                    "layer %p, buffer=%d wasn't locked!",
+                    this, buf);
+        }
     }
 }
 
@@ -573,8 +590,15 @@
 {
     LayerBaseClient::dump(result, buffer, SIZE);
 
-    SharedBufferStack::Statistics stats = lcblk->getStats();
-    result.append( lcblk->dump("      ") );
+    ClientRef::Access sharedClient(mUserClientRef);
+    SharedBufferServer* lcblk(sharedClient.get());
+    uint32_t totalTime = 0;
+    if (lcblk) {
+        SharedBufferStack::Statistics stats = lcblk->getStats();
+        totalTime= stats.totalTime;
+        result.append( lcblk->dump("      ") );
+    }
+
     sp<const GraphicBuffer> buf0(getBuffer(0));
     sp<const GraphicBuffer> buf1(getBuffer(1));
     uint32_t w0=0, h0=0, s0=0;
@@ -593,18 +617,59 @@
             "      "
             "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
             " freezeLock=%p, dq-q-time=%u us\n",
-            pixelFormat(),
-            w0, h0, s0, w1, h1, s1,
-            getFreezeLock().get(), stats.totalTime);
+            mFormat, w0, h0, s0, w1, h1, s1,
+            getFreezeLock().get(), totalTime);
 
     result.append(buffer);
 }
 
 // ---------------------------------------------------------------------------
 
+Layer::ClientRef::ClientRef()
+    : mToken(-1) {
+}
+
+Layer::ClientRef::~ClientRef() {
+    delete lcblk;
+}
+
+int32_t Layer::ClientRef::getToken() const {
+    Mutex::Autolock _l(mLock);
+    return mToken;
+}
+
+status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
+        SharedBufferServer* sharedClient, int32_t token) {
+    Mutex::Autolock _l(mLock);
+    if (mToken >= 0)
+        return INVALID_OPERATION;
+    mUserClient = uc;
+    mToken = token;
+    lcblk = sharedClient;
+    return NO_ERROR;
+}
+
+sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
+    return mUserClient.promote();
+}
+
+// this class gives us access to SharedBufferServer safely
+// it makes sure the UserClient (and its associated shared memory)
+// won't go away while we're accessing it.
+Layer::ClientRef::Access::Access(const ClientRef& ref)
+    : lcblk(0)
+{
+    Mutex::Autolock _l(ref.mLock);
+    mUserClientStrongRef = ref.mUserClient.promote();
+    if (mUserClientStrongRef != 0)
+        lcblk = ref.lcblk;
+}
+
+// ---------------------------------------------------------------------------
+
 Layer::BufferManager::BufferManager(TextureManager& tm)
     : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
-      mActiveBuffer(0), mFailover(false)
+      mActiveBuffer(-1), mFailover(false)
 {
 }
 
@@ -625,7 +690,6 @@
 }
 
 status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
-    // TODO: need to validate 'index'
     mActiveBuffer = index;
     return NO_ERROR;
 }
@@ -636,7 +700,7 @@
 
 Texture Layer::BufferManager::getActiveTexture() const {
     Texture res;
-    if (mFailover) {
+    if (mFailover || mActiveBuffer<0) {
         res = mFailoverTexture;
     } else {
         static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
@@ -645,10 +709,14 @@
 }
 
 sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
-    const size_t activeBuffer = mActiveBuffer;
-    BufferData const * const buffers = mBufferData;
-    Mutex::Autolock _l(mLock);
-    return buffers[activeBuffer].buffer;
+    sp<GraphicBuffer> result;
+    const ssize_t activeBuffer = mActiveBuffer;
+    if (activeBuffer >= 0) {
+        BufferData const * const buffers = mBufferData;
+        Mutex::Autolock _l(mLock);
+        result = buffers[activeBuffer].buffer;
+    }
+    return result;
 }
 
 sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
@@ -692,19 +760,22 @@
 status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
         const sp<GraphicBuffer>& buffer)
 {
-    size_t index = mActiveBuffer;
-    Image& texture(mBufferData[index].texture);
-    status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
-    // if EGLImage fails, we switch to regular texture mode, and we
-    // free all resources associated with using EGLImages.
-    if (err == NO_ERROR) {
-        mFailover = false;
-        destroyTexture(&mFailoverTexture, dpy);
-    } else {
-        mFailover = true;
-        const size_t num = mNumBuffers;
-        for (size_t i=0 ; i<num ; i++) {
-            destroyTexture(&mBufferData[i].texture, dpy);
+    status_t err = NO_INIT;
+    ssize_t index = mActiveBuffer;
+    if (index >= 0) {
+        Image& texture(mBufferData[index].texture);
+        err = mTextureManager.initEglImage(&texture, dpy, buffer);
+        // if EGLImage fails, we switch to regular texture mode, and we
+        // free all resources associated with using EGLImages.
+        if (err == NO_ERROR) {
+            mFailover = false;
+            destroyTexture(&mFailoverTexture, dpy);
+        } else {
+            mFailover = true;
+            const size_t num = mNumBuffers;
+            for (size_t i=0 ; i<num ; i++) {
+                destroyTexture(&mBufferData[i].texture, dpy);
+            }
         }
     }
     return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index b427576..d396ecf 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -38,6 +38,7 @@
 // ---------------------------------------------------------------------------
 
 class Client;
+class UserClient;
 class FreezeLock;
 
 // ---------------------------------------------------------------------------
@@ -45,21 +46,26 @@
 class Layer : public LayerBaseClient
 {
 public:
-    // lcblk is (almost) only accessed from the main SF thread, in the places
-    // where it's not, a reference to Client must be held
-    SharedBufferServer*     lcblk;
+            Layer(SurfaceFlinger* flinger, DisplayID display,
+                    const sp<Client>& client);
 
-                 Layer(SurfaceFlinger* flinger, DisplayID display,
-                         const sp<Client>& client);
+    virtual ~Layer();
 
-        virtual ~Layer();
+    virtual const char* getTypeId() const { return "Layer"; }
 
+    // the this layer's size and format
     status_t setBuffers(uint32_t w, uint32_t h, 
             PixelFormat format, uint32_t flags=0);
 
+    // associate a UserClient to this Layer
+    status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
+    int32_t getToken() const;
+
+    // Set this Layer's buffers size
     void setBufferSize(uint32_t w, uint32_t h);
     bool isFixedSize() const;
 
+    // LayerBase interface
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t transactionFlags);
     virtual void lockPageFlip(bool& recomputeVisibleRegions);
@@ -72,28 +78,26 @@
     virtual sp<Surface> createSurface() const;
     virtual status_t ditch();
     virtual void onRemoved();
-    
-    // only for debugging
-    inline sp<GraphicBuffer> getBuffer(int i) const { return mBufferManager.getBuffer(i); }
-    // only for debugging
-    inline const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
-    // only for debugging
-    inline PixelFormat pixelFormat() const { return mFormat; }
 
-    virtual const char* getTypeId() const { return "Layer"; }
+    // only for debugging
+    inline sp<GraphicBuffer> getBuffer(int i) const {
+        return mBufferManager.getBuffer(i); }
+    // only for debugging
+    inline const sp<FreezeLock>&  getFreezeLock() const {
+        return mFreezeLock; }
 
 protected:
     virtual void dump(String8& result, char* scratch, size_t size) const;
 
 private:
     void reloadTexture(const Region& dirty);
-
     uint32_t getEffectiveUsage(uint32_t usage) const;
-
     sp<GraphicBuffer> requestBuffer(int bufferIdx,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
     status_t setBufferCount(int bufferCount);
 
+    // -----------------------------------------------------------------------
+
     class SurfaceLayer : public LayerBaseClient::Surface {
     public:
         SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
@@ -107,93 +111,120 @@
         }
     };
     friend class SurfaceLayer;
-    
-    sp<Surface>             mSurface;
 
-            bool            mSecure;
-            int32_t         mFrontBufferIndex;
-            bool            mNeedsBlending;
-            bool            mNeedsDithering;
-            Region          mPostedDirtyRegion;
-            sp<FreezeLock>  mFreezeLock;
-            PixelFormat     mFormat;
+    // -----------------------------------------------------------------------
 
-            class BufferManager {
-                static const size_t NUM_BUFFERS = 2;
-                struct BufferData {
-                    sp<GraphicBuffer>   buffer;
-                    Image               texture;
-                };
-                // this lock protect mBufferData[].buffer but since there
-                // is very little contention, we have only one like for
-                // the whole array, we also use it to protect mNumBuffers.
-                mutable Mutex mLock;
-                BufferData          mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
-                size_t              mNumBuffers;
-                Texture             mFailoverTexture;
-                TextureManager&     mTextureManager;
-                ssize_t             mActiveBuffer;
-                bool                mFailover;
-                static status_t destroyTexture(Image* tex, EGLDisplay dpy);
+    class ClientRef {
+        ClientRef(const ClientRef& rhs);
+        ClientRef& operator = (const ClientRef& rhs);
+        mutable Mutex mLock;
+        // binder thread, page-flip thread
+        SharedBufferServer* lcblk;
+        wp<UserClient> mUserClient;
+        int32_t mToken;
+    public:
+        ClientRef();
+        ~ClientRef();
+        int32_t getToken() const;
+        status_t setToken(const sp<UserClient>& uc,
+                SharedBufferServer* sharedClient, int32_t token);
+        sp<UserClient> getUserClientUnsafe() const;
+        class Access {
+            Access(const Access& rhs);
+            Access& operator = (const Access& rhs);
+            sp<UserClient> mUserClientStrongRef;
+            SharedBufferServer* lcblk;
+        public:
+            Access(const ClientRef& ref);
+            inline SharedBufferServer* get() const { return lcblk; }
+        };
+        friend class Access;
+    };
 
-            public:
-                static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
-                BufferManager(TextureManager& tm);
-                ~BufferManager();
+    // -----------------------------------------------------------------------
 
-                // detach/attach buffer from/to given index
-                sp<GraphicBuffer> detachBuffer(size_t index);
-                status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
+    class BufferManager {
+        static const size_t NUM_BUFFERS = 2;
+        struct BufferData {
+            sp<GraphicBuffer>   buffer;
+            Image               texture;
+        };
+        // this lock protect mBufferData[].buffer but since there
+        // is very little contention, we have only one like for
+        // the whole array, we also use it to protect mNumBuffers.
+        mutable Mutex mLock;
+        BufferData          mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
+        size_t              mNumBuffers;
+        Texture             mFailoverTexture;
+        TextureManager&     mTextureManager;
+        ssize_t             mActiveBuffer;
+        bool                mFailover;
+        static status_t destroyTexture(Image* tex, EGLDisplay dpy);
 
-                // resize the number of active buffers
-                status_t resize(size_t size);
+    public:
+        static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
+        BufferManager(TextureManager& tm);
+        ~BufferManager();
 
-                // ----------------------------------------------
-                // must be called from GL thread
+        // detach/attach buffer from/to given index
+        sp<GraphicBuffer> detachBuffer(size_t index);
+        status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
+        // resize the number of active buffers
+        status_t resize(size_t size);
 
-                // set/get active buffer index
-                status_t setActiveBufferIndex(size_t index);
-                size_t getActiveBufferIndex() const;
+        // ----------------------------------------------
+        // must be called from GL thread
 
-                // return the active buffer
-                sp<GraphicBuffer> getActiveBuffer() const;
+        // set/get active buffer index
+        status_t setActiveBufferIndex(size_t index);
+        size_t getActiveBufferIndex() const;
+        // return the active buffer
+        sp<GraphicBuffer> getActiveBuffer() const;
+        // return the active texture (or fail-over)
+        Texture getActiveTexture() const;
+        // frees resources associated with all buffers
+        status_t destroy(EGLDisplay dpy);
+        // load bitmap data into the active buffer
+        status_t loadTexture(const Region& dirty, const GGLSurface& t);
+        // make active buffer an EGLImage if needed
+        status_t initEglImage(EGLDisplay dpy,
+                const sp<GraphicBuffer>& buffer);
 
-                // return the active texture (or fail-over)
-                Texture getActiveTexture() const;
+        // ----------------------------------------------
+        // only for debugging
+        sp<GraphicBuffer> getBuffer(size_t index) const;
+    };
 
-                // frees resources associated with all buffers
-                status_t destroy(EGLDisplay dpy);
+    // -----------------------------------------------------------------------
 
-                // load bitmap data into the active buffer
-                status_t loadTexture(const Region& dirty, const GGLSurface& t);
+    // thread-safe
+    ClientRef mUserClientRef;
 
-                // make active buffer an EGLImage if needed
-                status_t initEglImage(EGLDisplay dpy,
-                        const sp<GraphicBuffer>& buffer);
+    // constants
+    sp<Surface> mSurface;
+    PixelFormat mFormat;
+    bool mNeedsBlending;
+    bool mNeedsDithering;
 
-                // ----------------------------------------------
-                // only for debugging
-                sp<GraphicBuffer> getBuffer(size_t index) const;
-            };
+    // page-flip thread (currently main thread)
+    bool mSecure;
+    Region mPostedDirtyRegion;
 
-            TextureManager mTextureManager;
-            BufferManager mBufferManager;
+    // page-flip thread and transaction thread (currently main thread)
+    sp<FreezeLock>  mFreezeLock;
 
-            // this lock protects mWidth and mHeight which are accessed from
-            // the main thread and requestBuffer's binder transaction thread.
-            mutable Mutex mLock;
-            uint32_t    mWidth;
-            uint32_t    mHeight;
-            uint32_t    mReqWidth;
-            uint32_t    mReqHeight;
-            uint32_t    mReqFormat;
-            bool        mFixedSize;
+    // see threading usage in declaration
+    TextureManager mTextureManager;
+    BufferManager mBufferManager;
 
-    // TODO: get rid of this
-private:
-    virtual void setToken(int32_t token);
-    virtual int32_t getToken() const { return mToken; }
-    int32_t mToken;
+    // binder thread, transaction thread
+    mutable Mutex mLock;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mReqWidth;
+    uint32_t mReqHeight;
+    uint32_t mReqFormat;
+    bool mFixedSize;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 80b001e..1f66fd0 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -151,7 +151,6 @@
     return true;
 }
 bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
-    // TODO: check the matrix has changed
     mCurrentState.sequence++;
     mCurrentState.transform.set(
             matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
@@ -159,7 +158,6 @@
     return true;
 }
 bool LayerBase::setTransparentRegionHint(const Region& transparent) {
-    // TODO: check the region has changed
     mCurrentState.sequence++;
     mCurrentState.transparentRegion = transparent;
     requestTransaction();
@@ -489,16 +487,16 @@
 
 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client)
-    : LayerBase(flinger, display), client(client),
+    : LayerBase(flinger, display), mClientRef(client),
       mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
 {
 }
 
 LayerBaseClient::~LayerBaseClient()
 {
-    sp<Client> c(client.promote());
+    sp<Client> c(mClientRef.promote());
     if (c != 0) {
-        c->free(this);
+        c->detachLayer(this);
     }
 }
 
@@ -524,7 +522,7 @@
 {
     LayerBase::dump(result, buffer, SIZE);
 
-    sp<Client> client(this->client.promote());
+    sp<Client> client(mClientRef.promote());
     snprintf(buffer, SIZE,
             "      name=%s\n"
             "      client=%p, identity=%u\n",
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index c9a516f..1a07f32 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -45,6 +45,7 @@
 class Client;
 class GraphicBuffer;
 class GraphicPlane;
+class LayerBaseClient;
 class SurfaceFlinger;
 class Texture;
 
@@ -100,6 +101,8 @@
 
             void invalidate();
 
+    virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
+
     virtual const char* getTypeId() const { return "LayerBase"; }
 
     /**
@@ -268,14 +271,14 @@
 public:
     class Surface;
 
-    const wp<Client> client;
-
             LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
                         const sp<Client>& client);
     virtual ~LayerBaseClient();
 
             sp<Surface> getSurface();
     virtual sp<Surface> createSurface() const;
+    virtual sp<LayerBaseClient> getLayerBaseClient() const {
+        return const_cast<LayerBaseClient*>(this); }
     virtual const char* getTypeId() const { return "LayerBaseClient"; }
 
     uint32_t getIdentity() const { return mIdentity; }
@@ -318,14 +321,10 @@
 private:
     mutable Mutex mLock;
     mutable wp<Surface> mClientSurface;
+    const wp<Client> mClientRef;
     // only read
     const uint32_t mIdentity;
     static int32_t sIdentity;
-
-    // TODO: get rid of this
-public:
-    virtual void setToken(int32_t token) { }
-    virtual int32_t getToken() const { return -1; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index e8d0d5b..0f73774 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -236,6 +236,18 @@
     return bclient;
 }
 
+sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
+{
+    sp<ISurfaceComposerClient> bclient;
+    sp<UserClient> client(new UserClient(this));
+    status_t err = client->initCheck();
+    if (err == NO_ERROR) {
+        bclient = client;
+    }
+    return bclient;
+}
+
+
 const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
 {
     LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
@@ -772,7 +784,8 @@
 void SurfaceFlinger::handlePageFlip()
 {
     bool visibleRegions = mVisibleRegionsDirty;
-    LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
+    LayerVector& currentLayers = const_cast<LayerVector&>(
+            mDrawingState.layersSortedByZ);
     visibleRegions |= lockPageFlip(currentLayers);
 
         const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -794,7 +807,7 @@
     size_t count = currentLayers.size();
     sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer = layers[i];
+        const sp<LayerBase>& layer(layers[i]);
         layer->lockPageFlip(recomputeVisibleRegions);
     }
     return recomputeVisibleRegions;
@@ -807,7 +820,7 @@
     size_t count = currentLayers.size();
     sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer = layers[i];
+        const sp<LayerBase>& layer(layers[i]);
         layer->unlockPageFlip(planeTransform, mDirtyRegion);
     }
 }
@@ -839,7 +852,7 @@
         // takes a rectangle, we must make sure to update that whole
         // rectangle in that case
         if (flags & DisplayHardware::SWAP_RECTANGLE) {
-            // FIXME: we really should be able to pass a region to
+            // TODO: we really should be able to pass a region to
             // SWAP_RECTANGLE so that we don't have to redraw all this.
             mDirtyRegion.set(mInvalidRegion.bounds());
         } else {
@@ -1060,6 +1073,10 @@
 
 status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
 {
+    sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient());
+    if (lbc != 0) {
+        mLayerMap.removeItem( lbc->getSurface()->asBinder() );
+    }
     ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
     if (index >= 0) {
         mLayersRemoved = true;
@@ -1192,12 +1209,14 @@
     }
     
     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
+    sp<Layer> normalLayer;
     switch (flags & eFXSurfaceMask) {
         case eFXSurfaceNormal:
             if (UNLIKELY(flags & ePushBuffers)) {
                 layer = createPushBuffersSurface(client, d, w, h, flags);
             } else {
-                layer = createNormalSurface(client, d, w, h, flags, format);
+                normalLayer = createNormalSurface(client, d, w, h, flags, format);
+                layer = normalLayer;
             }
             break;
         case eFXSurfaceBlur:
@@ -1212,6 +1231,7 @@
         layer->initStates(w, h, flags);
         layer->setName(name);
         ssize_t token = addClientLayer(client, layer);
+
         surfaceHandle = layer->getSurface();
         if (surfaceHandle != 0) { 
             params->token = token;
@@ -1219,14 +1239,19 @@
             params->width = w;
             params->height = h;
             params->format = format;
+            if (normalLayer != 0) {
+                Mutex::Autolock _l(mStateLock);
+                mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
+            }
         }
+
         setTransactionFlags(eTransactionNeeded);
     }
 
     return surfaceHandle;
 }
 
-sp<LayerBaseClient> SurfaceFlinger::createNormalSurface(
+sp<Layer> SurfaceFlinger::createNormalSurface(
         const sp<Client>& client, DisplayID display,
         uint32_t w, uint32_t h, uint32_t flags,
         PixelFormat& format)
@@ -1251,7 +1276,7 @@
     return layer;
 }
 
-sp<LayerBaseClient> SurfaceFlinger::createBlurSurface(
+sp<LayerBlur> SurfaceFlinger::createBlurSurface(
         const sp<Client>& client, DisplayID display,
         uint32_t w, uint32_t h, uint32_t flags)
 {
@@ -1260,7 +1285,7 @@
     return layer;
 }
 
-sp<LayerBaseClient> SurfaceFlinger::createDimSurface(
+sp<LayerDim> SurfaceFlinger::createDimSurface(
         const sp<Client>& client, DisplayID display,
         uint32_t w, uint32_t h, uint32_t flags)
 {
@@ -1269,7 +1294,7 @@
     return layer;
 }
 
-sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurface(
+sp<LayerBuffer> SurfaceFlinger::createPushBuffersSurface(
         const sp<Client>& client, DisplayID display,
         uint32_t w, uint32_t h, uint32_t flags)
 {
@@ -1567,32 +1592,24 @@
 }
 
 // ---------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#endif
+
+sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
+{
+    sp<Layer> result;
+    Mutex::Autolock _l(mStateLock);
+    result = mLayerMap.valueFor( sur->asBinder() ).promote();
+    return result;
+}
+
+// ---------------------------------------------------------------------------
 
 Client::Client(const sp<SurfaceFlinger>& flinger)
-    : ctrlblk(0), mBitmap(0), mFlinger(flinger)
+    : mFlinger(flinger), mNameGenerator(1)
 {
-    const int pgsize = getpagesize();
-    const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
-
-    mCblkHeap = new MemoryHeapBase(cblksize, 0,
-            "SurfaceFlinger Client control-block");
-
-    ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
-    if (ctrlblk) { // construct the shared structure in-place.
-        new(ctrlblk) SharedClient;
-    }
-
 }
 
 Client::~Client()
 {
-    if (ctrlblk) {
-        ctrlblk->~SharedClient();  // destroy our shared-structure.
-    }
-
     const size_t count = mLayers.size();
     for (size_t i=0 ; i<count ; i++) {
         sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
@@ -1603,32 +1620,18 @@
 }
 
 status_t Client::initCheck() const {
-    return ctrlblk == 0 ? NO_INIT : NO_ERROR;
+    return NO_ERROR;
 }
 
 ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
 {
-    // TODO: get rid of this
-    int32_t name = 0;
-    while (mBitmap & (1LU<<name)) {
-        name++;
-        if (name >= 31)
-            return NO_MEMORY;
-    }
-    mBitmap |= 1LU<<name;
-    layer->setToken(name);
+    int32_t name = android_atomic_inc(&mNameGenerator);
     mLayers.add(name, layer);
     return name;
 }
 
-void Client::free(LayerBaseClient const* layer)
+void Client::detachLayer(const LayerBaseClient* layer)
 {
-    // TODO: get rid of this
-    int32_t name = layer->getToken();
-    if (name >= 0) {
-        mBitmap &= ~(1LU<<name);
-    }
-
     // we do a linear search here, because this doesn't happen often
     const size_t count = mLayers.size();
     for (size_t i=0 ; i<count ; i++) {
@@ -1649,12 +1652,15 @@
 }
 
 sp<IMemoryHeap> Client::getControlBlock() const {
-    return mCblkHeap;
+    return 0;
+}
+ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
+    return -1;
 }
 sp<ISurface> Client::createSurface(
-        ISurfaceComposerClient::surface_data_t* params,
-        int pid, const String8& name,
-        DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
+        ISurfaceComposerClient::surface_data_t* params, int pid,
+        const String8& name,
+        DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags)
 {
     return mFlinger->createSurface(this, pid, name, params,
@@ -1669,6 +1675,100 @@
 
 // ---------------------------------------------------------------------------
 
+UserClient::UserClient(const sp<SurfaceFlinger>& flinger)
+    : ctrlblk(0), mBitmap(0), mFlinger(flinger)
+{
+    const int pgsize = getpagesize();
+    const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
+
+    mCblkHeap = new MemoryHeapBase(cblksize, 0,
+            "SurfaceFlinger Client control-block");
+
+    ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
+    if (ctrlblk) { // construct the shared structure in-place.
+        new(ctrlblk) SharedClient;
+    }
+}
+
+UserClient::~UserClient()
+{
+    if (ctrlblk) {
+        ctrlblk->~SharedClient();  // destroy our shared-structure.
+    }
+
+    /*
+     * When a UserClient dies, it's unclear what to do exactly.
+     * We could go ahead and destroy all surfaces linked to that client
+     * however, it wouldn't be fair to the main Client
+     * (usually the the window-manager), which might want to re-target
+     * the layer to another UserClient.
+     * I think the best is to do nothing, or not much; in most cases the
+     * WM itself will go ahead and clean things up when it detects a client of
+     * his has died.
+     * The remaining question is what to display? currently we keep
+     * just keep the current buffer.
+     */
+}
+
+status_t UserClient::initCheck() const {
+    return ctrlblk == 0 ? NO_INIT : NO_ERROR;
+}
+
+void UserClient::detachLayer(const Layer* layer)
+{
+    int32_t name = layer->getToken();
+    if (name >= 0) {
+        android_atomic_and(~(1LU<<name), &mBitmap);
+    }
+}
+
+sp<IMemoryHeap> UserClient::getControlBlock() const {
+    return mCblkHeap;
+}
+
+ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
+{
+    int32_t name = NAME_NOT_FOUND;
+    sp<Layer> layer(mFlinger->getLayer(sur));
+    if (layer == 0) return name;
+
+    // this layer already has a token, just return it
+    // FIXME: we should check that this token is for the same client
+    name = layer->getToken();
+    if (name >= 0) return name;
+
+    name = 0;
+    do {
+        int32_t mask = 1LU<<name;
+        if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
+            // we found and locked that name
+            layer->setToken(const_cast<UserClient*>(this), ctrlblk, name);
+            break;
+        }
+        if (++name > 31)
+            name = NO_MEMORY;
+    } while(name >= 0);
+
+    //LOGD("getTokenForSurface(%p) => %d", sur->asBinder().get(), name);
+    return name;
+}
+
+sp<ISurface> UserClient::createSurface(
+        ISurfaceComposerClient::surface_data_t* params, int pid,
+        const String8& name,
+        DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t flags) {
+    return 0;
+}
+status_t UserClient::destroySurface(SurfaceID sid) {
+    return INVALID_OPERATION;
+}
+status_t UserClient::setState(int32_t count, const layer_state_t* states) {
+    return INVALID_OPERATION;
+}
+
+// ---------------------------------------------------------------------------
+
 GraphicPlane::GraphicPlane()
     : mHw(0)
 {
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 84134e0..0bfc170 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,8 @@
 class DisplayHardware;
 class FreezeLock;
 class Layer;
+class LayerBlur;
+class LayerDim;
 class LayerBuffer;
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
@@ -60,10 +62,6 @@
 class Client : public BnSurfaceComposerClient
 {
 public:
-    // pointer to this client's control block
-    SharedClient* ctrlblk;
-
-public:
         Client(const sp<SurfaceFlinger>& flinger);
         ~Client();
 
@@ -71,13 +69,14 @@
 
     // protected by SurfaceFlinger::mStateLock
     ssize_t attachLayer(const sp<LayerBaseClient>& layer);
+    void detachLayer(const LayerBaseClient* layer);
     sp<LayerBaseClient> getLayerUser(int32_t i) const;
-    void free(LayerBaseClient const* layer);
 
 private:
 
     // ISurfaceComposerClient interface
     virtual sp<IMemoryHeap> getControlBlock() const;
+    virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
     virtual sp<ISurface> createSurface(
             surface_data_t* params, int pid, const String8& name,
             DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
@@ -85,8 +84,41 @@
     virtual status_t destroySurface(SurfaceID surfaceId);
     virtual status_t setState(int32_t count, const layer_state_t* states);
 
-    uint32_t mBitmap;
     DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+    sp<SurfaceFlinger> mFlinger;
+    int32_t mNameGenerator;
+};
+
+class UserClient : public BnSurfaceComposerClient
+{
+public:
+    // pointer to this client's control block
+    SharedClient* ctrlblk;
+
+public:
+        UserClient(const sp<SurfaceFlinger>& flinger);
+        ~UserClient();
+
+    status_t initCheck() const;
+
+    // protected by SurfaceFlinger::mStateLock
+    void detachLayer(const Layer* layer);
+
+private:
+
+    // ISurfaceComposerClient interface
+    virtual sp<IMemoryHeap> getControlBlock() const;
+    virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
+    virtual sp<ISurface> createSurface(
+            surface_data_t* params, int pid, const String8& name,
+            DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
+            uint32_t flags);
+    virtual status_t destroySurface(SurfaceID surfaceId);
+    virtual status_t setState(int32_t count, const layer_state_t* states);
+
+    // atomic-ops
+    mutable volatile int32_t mBitmap;
+
     sp<IMemoryHeap> mCblkHeap;
     sp<SurfaceFlinger> mFlinger;
 };
@@ -152,6 +184,7 @@
 
     // ISurfaceComposer interface
     virtual sp<ISurfaceComposerClient>  createConnection();
+    virtual sp<ISurfaceComposerClient>  createClientConnection();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
     virtual void                        openGlobalTransaction();
@@ -166,11 +199,12 @@
 
             overlay_control_device_t* getOverlayEngine() const;
 
-            
     status_t removeLayer(const sp<LayerBase>& layer);
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
-    
+
+    sp<Layer> getLayer(const sp<ISurface>& sur) const;
+
 private:
     friend class Client;
     friend class LayerBase;
@@ -187,20 +221,20 @@
             DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
             uint32_t flags);
 
-    sp<LayerBaseClient> createNormalSurface(
+    sp<Layer> createNormalSurface(
             const sp<Client>& client, DisplayID display,
             uint32_t w, uint32_t h, uint32_t flags,
             PixelFormat& format);
 
-    sp<LayerBaseClient> createBlurSurface(
+    sp<LayerBlur> createBlurSurface(
             const sp<Client>& client, DisplayID display,
             uint32_t w, uint32_t h, uint32_t flags);
 
-    sp<LayerBaseClient> createDimSurface(
+    sp<LayerDim> createDimSurface(
             const sp<Client>& client, DisplayID display,
             uint32_t w, uint32_t h, uint32_t flags);
 
-    sp<LayerBaseClient> createPushBuffersSurface(
+    sp<LayerBuffer> createPushBuffersSurface(
             const sp<Client>& client, DisplayID display,
             uint32_t w, uint32_t h, uint32_t flags);
 
@@ -307,8 +341,7 @@
 
     status_t postMessageSync(const sp<MessageBase>& msg,
             nsecs_t reltime=0, uint32_t flags = 0);
-                
-                
+
                 // access must be protected by mStateLock
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
@@ -321,6 +354,7 @@
                 // protected by mStateLock (but we could use another lock)
                 GraphicPlane                mGraphicPlanes[1];
                 bool                        mLayersRemoved;
+                DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayerMap;
 
                 // constant members (no synchronization needed for access)
                 sp<IMemoryHeap>             mServerHeap;
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 50495c1..5c111f6 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -55,6 +55,15 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
+    virtual sp<ISurfaceComposerClient> createClientConnection()
+    {
+        uint32_t n;
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::CREATE_CLIENT_CONNECTION, data, &reply);
+        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
+    }
+
     virtual sp<IMemoryHeap> getCblk() const
     {
         Parcel data, reply;
@@ -136,6 +145,11 @@
             sp<IBinder> b = createConnection()->asBinder();
             reply->writeStrongBinder(b);
         } break;
+        case CREATE_CLIENT_CONNECTION: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> b = createClientConnection()->asBinder();
+            reply->writeStrongBinder(b);
+        } break;
         case OPEN_GLOBAL_TRANSACTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             openGlobalTransaction();
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
index 67c7df81..2cc1f8e 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
@@ -51,6 +51,7 @@
 
 enum {
     GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+    GET_TOKEN,
     CREATE_SURFACE,
     DESTROY_SURFACE,
     SET_STATE
@@ -72,6 +73,15 @@
         return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
+    virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
+        data.writeStrongBinder(sur->asBinder());
+        remote()->transact(GET_TOKEN, data, &reply);
+        return reply.readInt32();
+    }
+
     virtual sp<ISurface> createSurface( surface_data_t* params,
                                         int pid,
                                         const String8& name,
@@ -132,6 +142,13 @@
             reply->writeStrongBinder(ctl->asBinder());
             return NO_ERROR;
         } break;
+        case GET_TOKEN: {
+            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
+            sp<ISurface> sur = interface_cast<ISurface>(data.readStrongBinder());
+            ssize_t token = getTokenForSurface(sur);
+            reply->writeInt32(token);
+            return NO_ERROR;
+        } break;
     }
 
     // these must be checked
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8d03145..1dd8642 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -58,7 +58,7 @@
 
 void SharedBufferStack::init(int32_t i)
 {
-    inUse = -1;
+    inUse = -2;
     status = NO_ERROR;
     identity = i;
 }
@@ -282,8 +282,10 @@
 }
 ssize_t SharedBufferServer::UnlockUpdate::operator()() {
     if (stack.inUse != lockedBuffer) {
-        LOGE("unlocking %d, but currently locked buffer is %d",
-                lockedBuffer, stack.inUse);
+        LOGE("unlocking %d, but currently locked buffer is %d "
+             "(identity=%d, token=%d)",
+                lockedBuffer, stack.inUse,
+                stack.identity, stack.token);
         return BAD_VALUE;
     }
     android_atomic_write(-1, &stack.inUse);
@@ -480,6 +482,7 @@
       mNumBuffers(num)
 {
     mSharedStack->init(identity);
+    mSharedStack->token = surface;
     mSharedStack->head = num-1;
     mSharedStack->available = num;
     mSharedStack->queued = 0;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index ac4b198..01420fe 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -238,14 +238,12 @@
 {
     uint32_t flags = 0;
     uint32_t format = 0;
-    SurfaceID token = -1;
     uint32_t identity = 0;
     uint32_t width = 0;
     uint32_t height = 0;
     sp<SurfaceComposerClient> client;
     sp<ISurface> sur;
     if (SurfaceControl::isValid(control)) {
-        token    = control->mToken;
         identity = control->mIdentity;
         client   = control->mClient;
         sur      = control->mSurface;
@@ -254,9 +252,7 @@
         format   = control->mFormat;
         flags    = control->mFlags;
     }
-    parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
-    parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
-    parcel->writeInt32(token);
+    parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
     parcel->writeInt32(identity);
     parcel->writeInt32(width);
     parcel->writeInt32(height);
@@ -278,31 +274,78 @@
 //  Surface
 // ============================================================================
 
+class SurfaceClient : public Singleton<SurfaceClient>
+{
+    // all these attributes are constants
+    sp<ISurfaceComposer> mComposerService;
+    sp<ISurfaceComposerClient> mClient;
+    status_t mStatus;
+    SharedClient* mControl;
+    sp<IMemoryHeap> mControlMemory;
+
+    SurfaceClient()
+        : Singleton<SurfaceClient>(), mStatus(NO_INIT)
+    {
+        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+        mComposerService = sf;
+        mClient = sf->createClientConnection();
+        if (mClient != NULL) {
+            mControlMemory = mClient->getControlBlock();
+            if (mControlMemory != NULL) {
+                mControl = static_cast<SharedClient *>(
+                        mControlMemory->getBase());
+                if (mControl) {
+                    mStatus = NO_ERROR;
+                }
+            }
+        }
+    }
+    friend class Singleton<SurfaceClient>;
+public:
+    status_t initCheck() const {
+        return mStatus;
+    }
+    SharedClient* getSharedClient() const {
+        return mControl;
+    }
+    ssize_t getTokenForSurface(const sp<ISurface>& sur) const {
+        // TODO: we could cache a few tokens here to avoid an IPC
+        return mClient->getTokenForSurface(sur);
+    }
+    void signalServer() const {
+        mComposerService->signal();
+    }
+};
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient);
+
+// ---------------------------------------------------------------------------
+
 Surface::Surface(const sp<SurfaceControl>& surface)
-    : mSurface(surface->mSurface),
-      mToken(surface->mToken), mIdentity(surface->mIdentity),
-      mFormat(surface->mFormat), mFlags(surface->mFlags),
-      mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
+    : mBufferMapper(GraphicBufferMapper::get()),
+      mClient(SurfaceClient::getInstance()),
+      mSharedBufferClient(NULL),
       mInitCheck(NO_INIT),
+      mSurface(surface->mSurface),
+      mIdentity(surface->mIdentity),
+      mFormat(surface->mFormat), mFlags(surface->mFlags),
       mWidth(surface->mWidth), mHeight(surface->mHeight)
 {
-    mClient = new SurfaceClient(surface->mClient);
     init();
 }
 
 Surface::Surface(const Parcel& parcel)
-    :  mBufferMapper(GraphicBufferMapper::get()),
-       mSharedBufferClient(NULL), mInitCheck(NO_INIT)
+    : mBufferMapper(GraphicBufferMapper::get()),
+      mClient(SurfaceClient::getInstance()),
+      mSharedBufferClient(NULL),
+      mInitCheck(NO_INIT)
 {
-    sp<IBinder> conn = parcel.readStrongBinder();
     mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
-    mToken      = parcel.readInt32();
     mIdentity   = parcel.readInt32();
     mWidth      = parcel.readInt32();
     mHeight     = parcel.readInt32();
     mFormat     = parcel.readInt32();
     mFlags      = parcel.readInt32();
-    mClient = new SurfaceClient(conn);
     init();
 }
 
@@ -330,12 +373,14 @@
     mBuffers.setCapacity(2);
     mBuffers.insertAt(0, 2);
 
-    if (mClient != 0 && mClient->initCheck() == NO_ERROR) {
-        mSharedBufferClient = new SharedBufferClient(
-                mClient->getSharedClient(), mToken, 2, mIdentity);
+    if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
+        mToken = mClient.getTokenForSurface(mSurface);
+        if (mToken >= 0) {
+            mSharedBufferClient = new SharedBufferClient(
+                    mClient.getSharedClient(), mToken, 2, mIdentity);
+            mInitCheck = mClient.getSharedClient()->validate(mToken);
+        }
     }
-
-    mInitCheck = initCheck();
 }
 
 Surface::~Surface()
@@ -352,25 +397,11 @@
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
     mBuffers.clear();
-    mClient.clear();
     mSurface.clear();
     delete mSharedBufferClient;
     IPCThreadState::self()->flushCommands();
 }
 
-status_t Surface::initCheck() const
-{
-    if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) {
-        return NO_INIT;
-    }
-    SharedClient const* cblk = mClient->getSharedClient();
-    if (cblk == 0) {
-        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
-        return NO_INIT;
-    }
-    return cblk->validate(mToken);
-}
-
 bool Surface::isValid() {
     return mInitCheck == NO_ERROR;
 }
@@ -379,8 +410,7 @@
 {
     // check that we initialized ourself properly
     if (mInitCheck != NO_ERROR) {
-        LOGE("invalid token (%d, identity=%u) or client (%p)",
-                mToken, mIdentity, mClient.get());
+        LOGE("invalid token (%d, identity=%u)", mToken, mIdentity);
         return mInitCheck;
     }
 
@@ -558,8 +588,8 @@
     LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
 
     if (err == NO_ERROR) {
-        // FIXME: can we avoid this IPC if we know there is one pending?
-        mClient->signalServer();
+        // TODO: can we avoid this IPC if we know there is one pending?
+        mClient.signalServer();
     }
     return err;
 }
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index 0670d20..5ac0d5d 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -42,36 +42,26 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class ComposerService : public Singleton<ComposerService>
-{
-    // these are constants
-    sp<ISurfaceComposer> mComposerService;
-    sp<IMemoryHeap> mServerCblkMemory;
-    surface_flinger_cblk_t volatile* mServerCblk;
-
-    ComposerService() : Singleton<ComposerService>() {
-        const String16 name("SurfaceFlinger");
-        while (getService(name, &mComposerService) != NO_ERROR) {
-            usleep(250000);
-        }
-        mServerCblkMemory = mComposerService->getCblk();
-        mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
-                mServerCblkMemory->getBase());
-    }
-
-    friend class Singleton<ComposerService>;
-
-public:
-    static sp<ISurfaceComposer> getComposerService() {
-        return ComposerService::getInstance().mComposerService;
-    }
-    static surface_flinger_cblk_t const volatile * getControlBlock() {
-        return ComposerService::getInstance().mServerCblk;
-    }
-};
-
 ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
 
+ComposerService::ComposerService()
+: Singleton<ComposerService>() {
+    const String16 name("SurfaceFlinger");
+    while (getService(name, &mComposerService) != NO_ERROR) {
+        usleep(250000);
+    }
+    mServerCblkMemory = mComposerService->getCblk();
+    mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
+            mServerCblkMemory->getBase());
+}
+
+sp<ISurfaceComposer> ComposerService::getComposerService() {
+    return ComposerService::getInstance().mComposerService;
+}
+
+surface_flinger_cblk_t const volatile * ComposerService::getControlBlock() {
+    return ComposerService::getInstance().mServerCblk;
+}
 
 static inline sp<ISurfaceComposer> getComposerService() {
     return ComposerService::getComposerService();
@@ -557,41 +547,5 @@
 }
 
 // ----------------------------------------------------------------------------
-
-SurfaceClient::SurfaceClient(const sp<SurfaceComposerClient>& client)
-    : mStatus(NO_INIT), mControl(0)
-{
-    if (client != 0) {
-        sp<IBinder> conn = client->connection();
-        init(conn);
-    }
-}
-SurfaceClient::SurfaceClient(const sp<IBinder>& conn)
-    : mStatus(NO_INIT), mControl(0)
-{
-    init(conn);
-}
-void SurfaceClient::init(const sp<IBinder>& conn)
-{
-    mComposerService = getComposerService();
-    sp<ISurfaceComposerClient> sf(interface_cast<ISurfaceComposerClient>(conn));
-    if (sf != 0) {
-        mConnection = conn;
-        mControlMemory = sf->getControlBlock();
-        mControl = static_cast<SharedClient *>(mControlMemory->getBase());
-        mStatus = NO_ERROR;
-    }
-}
-status_t SurfaceClient::initCheck() const {
-    return mStatus;
-}
-SharedClient* SurfaceClient::getSharedClient() const {
-    return mControl;
-}
-void SurfaceClient::signalServer() const {
-    mComposerService->signal();
-}
-
-// ----------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 35e4af3..3ddde38 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -38,7 +38,7 @@
 
 GraphicBuffer::GraphicBuffer()
     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+      mInitCheck(NO_ERROR), mIndex(-1)
 {
     width  = 
     height = 
@@ -51,7 +51,7 @@
 GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 
         PixelFormat reqFormat, uint32_t reqUsage)
     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+      mInitCheck(NO_ERROR), mIndex(-1)
 {
     width  = 
     height = 
@@ -67,7 +67,7 @@
         uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
       mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+      mInitCheck(NO_ERROR), mIndex(-1)
 {
     width  = w;
     height = h;
@@ -141,7 +141,6 @@
         this->height = h;
         this->format = format;
         this->usage  = reqUsage;
-        mVStride = 0;
     }
     return err;
 }
@@ -182,7 +181,6 @@
         sur->height = height;
         sur->stride = stride;
         sur->format = format;
-        sur->vstride = mVStride;
         sur->data = static_cast<GGLubyte*>(vaddr);
     }
     return res;
@@ -276,14 +274,6 @@
     return mIndex;
 }
 
-void GraphicBuffer::setVerticalStride(uint32_t vstride) {
-    mVStride = vstride;
-}
-
-uint32_t GraphicBuffer::getVerticalStride() const {
-    return mVStride;
-}
-
 // ---------------------------------------------------------------------------
 
 }; // namespace android