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/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index c11c855..633b543 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -43,15 +43,6 @@
  * unless they are in use by the server, which is only the case for the last 
  * dequeue-able buffer. When these various conditions are not met, the caller
  * waits until the condition is met.
- *
- * 
- * CAVEATS:
- * 
- * In the current implementation there are several limitations:
- * - buffers must be locked in the same order they've been dequeued
- * - buffers must be enqueued in the same order they've been locked
- * - dequeue() is not reentrant
- * - no error checks are done on the condition above
  * 
  */
 
@@ -269,7 +260,9 @@
 
 // ----------------------------------------------------------------------------
 
-class SharedBufferServer : public SharedBufferBase
+class SharedBufferServer
+    : public SharedBufferBase,
+      public LightRefBase<SharedBufferServer>
 {
 public:
     SharedBufferServer(SharedClient* sharedClient, int surface, int num,
@@ -290,6 +283,9 @@
     
 
 private:
+    friend class LightRefBase<SharedBufferServer>;
+    ~SharedBufferServer();
+
     /*
      * BufferList is basically a fixed-capacity sorted-vector of
      * unsigned 5-bits ints using a 32-bits int as storage.
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index ac01ce5..f333911 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -60,7 +60,6 @@
     static bool isSameSurface(
             const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
         
-    SurfaceID   ID() const      { return mToken; }
     uint32_t    getFlags() const { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
 
@@ -145,6 +144,9 @@
         uint32_t    reserved[2];
     };
 
+    static status_t writeToParcel(
+            const sp<Surface>& control, Parcel* parcel);
+
     static sp<Surface> readFromParcel(
             const Parcel& data, const sp<Surface>& other);
 
@@ -153,7 +155,6 @@
     }
 
     bool        isValid();
-    SurfaceID   ID() const          { return mToken; }
     uint32_t    getFlags() const    { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
 
@@ -267,7 +268,6 @@
     SharedBufferClient*         mSharedBufferClient;
     status_t                    mInitCheck;
     sp<ISurface>                mSurface;
-    SurfaceID                   mToken;
     uint32_t                    mIdentity;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
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)
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 1dd8642..d67a589 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -494,6 +494,10 @@
     }
 }
 
+SharedBufferServer::~SharedBufferServer()
+{
+}
+
 ssize_t SharedBufferServer::retireAndLock()
 {
     RWLock::AutoRLock _l(mLock);
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 6fe4c4a..8617d94 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -236,17 +236,15 @@
 status_t SurfaceControl::writeSurfaceToParcel(
         const sp<SurfaceControl>& control, Parcel* parcel)
 {
-    uint32_t flags = 0;
-    uint32_t format = 0;
+    sp<ISurface> sur;
     uint32_t identity = 0;
     uint32_t width = 0;
     uint32_t height = 0;
-    sp<SurfaceComposerClient> client;
-    sp<ISurface> sur;
+    uint32_t format = 0;
+    uint32_t flags = 0;
     if (SurfaceControl::isValid(control)) {
-        identity = control->mIdentity;
-        client   = control->mClient;
         sur      = control->mSurface;
+        identity = control->mIdentity;
         width    = control->mWidth;
         height   = control->mHeight;
         format   = control->mFormat;
@@ -349,6 +347,33 @@
     init();
 }
 
+status_t Surface::writeToParcel(
+        const sp<Surface>& surface, Parcel* parcel)
+{
+    sp<ISurface> sur;
+    uint32_t identity = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint32_t flags = 0;
+    if (Surface::isValid(surface)) {
+        sur      = surface->mSurface;
+        identity = surface->mIdentity;
+        width    = surface->mWidth;
+        height   = surface->mHeight;
+        format   = surface->mFormat;
+        flags    = surface->mFlags;
+    }
+    parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+    parcel->writeInt32(identity);
+    parcel->writeInt32(width);
+    parcel->writeInt32(height);
+    parcel->writeInt32(format);
+    parcel->writeInt32(flags);
+    return NO_ERROR;
+
+}
+
 sp<Surface> Surface::readFromParcel(
         const Parcel& data, const sp<Surface>& other)
 {
@@ -385,11 +410,11 @@
     mBuffers.insertAt(0, 2);
 
     if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
-        mToken = mClient.getTokenForSurface(mSurface);
-        if (mToken >= 0) {
+        int32_t token = mClient.getTokenForSurface(mSurface);
+        if (token >= 0) {
             mSharedBufferClient = new SharedBufferClient(
-                    mClient.getSharedClient(), mToken, 2, mIdentity);
-            mInitCheck = mClient.getSharedClient()->validate(mToken);
+                    mClient.getSharedClient(), token, 2, mIdentity);
+            mInitCheck = mClient.getSharedClient()->validate(token);
         }
     }
 }
@@ -421,7 +446,7 @@
 {
     // check that we initialized ourself properly
     if (mInitCheck != NO_ERROR) {
-        LOGE("invalid token (%d, identity=%u)", mToken, mIdentity);
+        LOGE("invalid token (identity=%u)", mIdentity);
         return mInitCheck;
     }
 
@@ -437,17 +462,17 @@
     }
 
     if (mIdentity != identity) {
-        LOGE("[Surface] using an invalid surface id=%d, "
+        LOGE("[Surface] using an invalid surface, "
                 "identity=%u should be %d",
-                mToken, mIdentity, identity);
+                mIdentity, identity);
         return NO_INIT;
     }
 
     // check the surface didn't become invalid
     status_t err = mSharedBufferClient->getStatus();
     if (err != NO_ERROR) {
-        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
-                mToken, mIdentity, err, strerror(-err));
+        LOGE("surface (identity=%u) is invalid, err=%d (%s)",
+                mIdentity, err, strerror(-err));
         return err;
     }
 
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3ddde38..4b5f025 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -111,6 +111,9 @@
     if (mOwner != ownData)
         return INVALID_OPERATION;
 
+    if (handle && w==width && h==height && f==format && reqUsage==usage)
+        return NO_ERROR;
+
     if (handle) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);