Add the ISurfaceComposer::createGraphicBuffer IPC.

This change adds a new binder method to the ISurfaceComposer interface.
This IPC is intended to allow SurfaceFlinger clients to allocate gralloc
buffers using SurfaceFlinger as a proxy to gralloc.

Change-Id: Ide9fc283aec5da6268ba62cfed0c3319a50b640d
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 693fbfb..1bab7d7 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -131,6 +131,13 @@
      * This is an ASYNCHRONOUS call.
      */
     virtual void signal() const = 0;
+
+    /* Create a new GraphicBuffer for the client to use.  SurfaceFlinger will
+     * not maintain a reference to the GraphicBuffer, so the underlying native
+     * handle will be freed once the client references are released.
+     */
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) const = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -144,6 +151,7 @@
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
         CREATE_CLIENT_CONNECTION,
+        CREATE_GRAPHIC_BUFFER,
         GET_CBLK,
         OPEN_GLOBAL_TRANSACTION,
         CLOSE_GLOBAL_TRANSACTION,
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index b8a7a79..a42b49d 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -26,6 +26,7 @@
 #include <binder/IServiceManager.h>
 
 #include <ui/DisplayInfo.h>
+#include <ui/GraphicBuffer.h>
 
 #include <surfaceflinger/ISurfaceComposer.h>
 
@@ -169,6 +170,25 @@
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) const {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
+        remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER, data,
+                &reply);
+        sp<GraphicBuffer> graphicBuffer;
+        bool nonNull = (bool)reply.readInt32();
+        if (nonNull) {
+            graphicBuffer = new GraphicBuffer();
+            reply.read(*graphicBuffer);
+        }
+        return graphicBuffer;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
@@ -247,6 +267,18 @@
             reply->writeInt32(f);
             reply->writeInt32(res);
         } break;
+        case CREATE_GRAPHIC_BUFFER: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            PixelFormat format = data.readInt32();
+            uint32_t usage = data.readInt32();
+            sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
+            reply->writeInt32(result != 0);
+            if (result != 0) {
+                reply->write(*result);
+            }
+        } break;
         case TURN_ELECTRON_BEAM_OFF: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             int32_t mode = data.readInt32();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 825d90b..c982ea5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2267,6 +2267,25 @@
 
 // ---------------------------------------------------------------------------
 
+sp<GraphicBuffer> SurfaceFlinger::createGraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat format, uint32_t usage) const {
+    // XXX: HACK HACK HACK!!!  This should NOT be static, but it is to fix a
+    // race between SurfaceFlinger unref'ing the buffer and the client ref'ing
+    // it.
+    static sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
+    status_t err = graphicBuffer->initCheck();
+    if (err != 0) {
+        LOGE("createGraphicBuffer: init check failed: %d", err);
+        return 0;
+    } else if (graphicBuffer->handle == 0) {
+        LOGE("createGraphicBuffer: unable to create GraphicBuffer");
+        return 0;
+    }
+    return graphicBuffer;
+}
+
+// ---------------------------------------------------------------------------
+
 Client::Client(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger), mNameGenerator(1)
 {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ca7d27d..48642d4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -322,6 +322,8 @@
             status_t electronBeamOnAnimationImplLocked();
             status_t renderScreenToTextureLocked(DisplayID dpy,
                     GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+            sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+                    PixelFormat format, uint32_t usage) const;
 
             friend class FreezeLock;
             sp<FreezeLock> getFreezeLock() const;