split surface management from surface's buffers management

Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
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)
 {