Move binder magic from the Surface class to GraphicBuffer.

- Register buffers with Gralloc when unflattening a GraphicBuffer (rather than
doing it in the Surface class).
- Add support for a GraphicBuffer that wraps an android_native_window_t*.

Change-Id: I029ac086111bbac800e5ca37eb505f558b718cd8
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index a3e85a9..c446633 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -72,6 +72,9 @@
     GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
             uint32_t stride, native_handle_t* handle, bool keepOwnership);
 
+    // create a buffer from an existing android_native_buffer_t
+    GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership);
+
     // return status
     status_t initCheck() const;
 
@@ -137,6 +140,10 @@
     GraphicBufferMapper& mBufferMapper;
     ssize_t mInitCheck;
     int mIndex;
+
+    // If we're wrapping another buffer then this reference will make sure it
+    // doesn't get freed.
+    sp<android_native_buffer_t> mWrappedBuffer;
 };
 
 }; // namespace android
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index ebb0cc9..0994980 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -454,15 +454,6 @@
 
 Surface::~Surface()
 {
-    // this is a client-side operation, the surface is destroyed, unmap
-    // its buffers in this process.
-    size_t size = mBuffers.size();
-    for (size_t i=0 ; i<size ; i++) {
-        if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
-            getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
-        }
-    }
-
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
     mBuffers.clear();
@@ -1021,7 +1012,20 @@
 
 int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
 {
-    return buffer->getIndex();
+    int idx = buffer->getIndex();
+    if (idx < 0) {
+        // The buffer doesn't have an index set.  See if the handle the same as
+        // one of the buffers for which we do know the index.  This can happen
+        // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that
+        // was dequeued from an ANativeWindow.
+        for (int i = 0; i < mBuffers.size(); i++) {
+            if (buffer->handle == mBuffers[i]->handle) {
+                idx = mBuffers[i]->getIndex();
+                break;
+            }
+        }
+    }
+    return idx;
 }
 
 status_t Surface::getBufferLocked(int index,
@@ -1035,7 +1039,6 @@
     // free the current buffer
     sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
     if (currentBuffer != 0) {
-        getBufferMapper().unregisterBuffer(currentBuffer->handle);
         currentBuffer.clear();
     }
 
@@ -1043,7 +1046,7 @@
     LOGE_IF(buffer==0,
             "ISurface::getBuffer(%d, %08x) returned NULL",
             index, usage);
-    if (buffer != 0) { // this should never happen by construction
+    if (buffer != 0) { // this should always happen by construction
         LOGE_IF(buffer->handle == NULL, 
                 "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
                 "returned a buffer with a null handle",
@@ -1051,13 +1054,8 @@
         err = mSharedBufferClient->getStatus();
         LOGE_IF(err,  "Surface (identity=%d) state = %d", mIdentity, err);
         if (!err && buffer->handle != NULL) {
-            err = getBufferMapper().registerBuffer(buffer->handle);
-            LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
-                    err, strerror(-err));
-            if (err == NO_ERROR) {
-                currentBuffer = buffer;
-                currentBuffer->setIndex(index);
-            }
+            currentBuffer = buffer;
+            currentBuffer->setIndex(index);
         } else {
             err = err<0 ? err : status_t(NO_MEMORY);
         }
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 519c277..436e064 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -77,6 +77,19 @@
     handle = inHandle;
 }
 
+GraphicBuffer::GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership)
+    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
+      mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR), mIndex(-1), mWrappedBuffer(buffer)
+{
+    width  = buffer->width;
+    height = buffer->height;
+    stride = buffer->stride;
+    format = buffer->format;
+    usage  = buffer->usage;
+    handle = buffer->handle;
+}
+
 GraphicBuffer::~GraphicBuffer()
 {
     if (handle) {
@@ -87,12 +100,14 @@
 void GraphicBuffer::free_handle()
 {
     if (mOwner == ownHandle) {
+        mBufferMapper.unregisterBuffer(handle);
         native_handle_close(handle);
         native_handle_delete(const_cast<native_handle*>(handle));
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
     }
+    mWrappedBuffer = 0;
 }
 
 status_t GraphicBuffer::initCheck() const {
@@ -253,6 +268,11 @@
     }
 
     mOwner = ownHandle;
+
+    if (handle != 0) {
+        mBufferMapper.registerBuffer(handle);
+    }
+
     return NO_ERROR;
 }