allow re-targetting of surfaces

Surfaces can now be parcelized and sent to remote
processes. When a surface crosses a process
boundary, it looses its connection with the
current process and gets attached to the new one.

Change-Id: I39c7b055bcd3ea1162ef2718d3d4b866bf7c81c0
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index a94fdd4..e7247bd 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -76,15 +76,18 @@
 status_t Layer::setToken(const sp<UserClient>& userClient,
         SharedClient* sharedClient, int32_t token)
 {
-    SharedBufferServer* lcblk = new SharedBufferServer(
+    sp<SharedBufferServer> lcblk = new SharedBufferServer(
             sharedClient, token, mBufferManager.getDefaultBufferCount(),
             getIdentity());
 
     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;
+
+    LOGE_IF(err != NO_ERROR,
+            "ClientRef::setToken(%p, %p, %u) failed",
+            userClient.get(), lcblk.get(), token);
+
+    if (err == NO_ERROR) {
+        // we need to free the buffers associated with this surface
     }
 
     return err;
@@ -95,6 +98,11 @@
     return mUserClientRef.getToken();
 }
 
+sp<UserClient> Layer::getClient() const
+{
+    return mUserClientRef.getClient();
+}
+
 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
 // in the purgatory list
 void Layer::onRemoved()
@@ -626,11 +634,10 @@
 // ---------------------------------------------------------------------------
 
 Layer::ClientRef::ClientRef()
-    : mToken(-1) {
+    : mControlBlock(0), mToken(-1) {
 }
 
 Layer::ClientRef::~ClientRef() {
-    delete lcblk;
 }
 
 int32_t Layer::ClientRef::getToken() const {
@@ -638,14 +645,25 @@
     return mToken;
 }
 
-status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
-        SharedBufferServer* sharedClient, int32_t token) {
+sp<UserClient> Layer::ClientRef::getClient() const {
     Mutex::Autolock _l(mLock);
-    if (mToken >= 0)
-        return INVALID_OPERATION;
+    return mUserClient.promote();
+}
+
+status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
+        const sp<SharedBufferServer>& sharedClient, int32_t token) {
+    Mutex::Autolock _l(mLock);
+
+    { // scope for strong mUserClient reference
+        sp<UserClient> userClient(mUserClient.promote());
+        if (mUserClient != 0 && mControlBlock != 0) {
+            mControlBlock->setStatus(NO_INIT);
+        }
+    }
+
     mUserClient = uc;
     mToken = token;
-    lcblk = sharedClient;
+    mControlBlock = sharedClient;
     return NO_ERROR;
 }
 
@@ -657,12 +675,16 @@
 // 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)
+    : mControlBlock(0)
 {
     Mutex::Autolock _l(ref.mLock);
     mUserClientStrongRef = ref.mUserClient.promote();
     if (mUserClientStrongRef != 0)
-        lcblk = ref.lcblk;
+        mControlBlock = ref.mControlBlock;
+}
+
+Layer::ClientRef::Access::~Access()
+{
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index d396ecf..dcb27a0 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -60,6 +60,7 @@
     // associate a UserClient to this Layer
     status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
     int32_t getToken() const;
+    sp<UserClient> getClient() const;
 
     // Set this Layer's buffers size
     void setBufferSize(uint32_t w, uint32_t h);
@@ -119,24 +120,26 @@
         ClientRef& operator = (const ClientRef& rhs);
         mutable Mutex mLock;
         // binder thread, page-flip thread
-        SharedBufferServer* lcblk;
+        sp<SharedBufferServer> mControlBlock;
         wp<UserClient> mUserClient;
         int32_t mToken;
     public:
         ClientRef();
         ~ClientRef();
         int32_t getToken() const;
+        sp<UserClient> getClient() const;
         status_t setToken(const sp<UserClient>& uc,
-                SharedBufferServer* sharedClient, int32_t token);
+                const sp<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;
+            sp<SharedBufferServer> mControlBlock;
         public:
             Access(const ClientRef& ref);
-            inline SharedBufferServer* get() const { return lcblk; }
+            ~Access();
+            inline SharedBufferServer* get() const { return mControlBlock.get(); }
         };
         friend class Access;
     };
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 4926858..4dea62f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1718,7 +1718,10 @@
 {
     int32_t name = layer->getToken();
     if (name >= 0) {
-        android_atomic_and(~(1LU<<name), &mBitmap);
+        int32_t mask = 1LU<<name;
+        if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
+            LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
+        }
     }
 }
 
@@ -1732,17 +1735,23 @@
     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
+    // if this layer already has a token, just return it
     name = layer->getToken();
-    if (name >= 0) return name;
+    if ((name >= 0) && (layer->getClient() == this))
+        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);
+            status_t err = layer->setToken(
+                    const_cast<UserClient*>(this), ctrlblk, name);
+            if (err != NO_ERROR) {
+                // free the name
+                android_atomic_and(~mask, &mBitmap);
+                name = err;
+            }
             break;
         }
         if (++name > 31)