Add createBuffer to BufferHubBinderService

When calling createBuffer, bufferhubd will now alloc the buffer via
creating a BufferNode in the server side, and return you a
BpBufferClient object for communication. A BpBufferClient is binded with
one specific buffer.

Currently you could only call isValid() on the client. More APIs will be
added in future CL.

Test: "atest buffer_hub_binder_service-test". Passed
Bug: 116681016
Change-Id: I05ec627474303af46a792b0b6c2eaa904724d1f2
diff --git a/services/vr/bufferhubd/IBufferHub.cpp b/services/vr/bufferhubd/IBufferHub.cpp
index 9d5b91a..2f39e41 100644
--- a/services/vr/bufferhubd/IBufferHub.cpp
+++ b/services/vr/bufferhubd/IBufferHub.cpp
@@ -4,14 +4,69 @@
 namespace android {
 namespace dvr {
 
+class BpBufferHub : public BpInterface<IBufferHub> {
+ public:
+  explicit BpBufferHub(const sp<IBinder>& impl)
+      : BpInterface<IBufferHub>(impl) {}
+
+  sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
+                                 uint32_t layer_count, uint32_t format,
+                                 uint64_t usage,
+                                 uint64_t user_metadata_size) override;
+};
+
 IMPLEMENT_META_INTERFACE(BufferHub, "android.dvr.IBufferHub");
 
+// Transaction code
+enum {
+  CREATE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+sp<IBufferClient> BpBufferHub::createBuffer(uint32_t width, uint32_t height,
+                                            uint32_t layer_count,
+                                            uint32_t format, uint64_t usage,
+                                            uint64_t user_metadata_size) {
+  Parcel data, reply;
+  status_t ret = NO_ERROR;
+  ret |= data.writeInterfaceToken(IBufferHub::getInterfaceDescriptor());
+  ret |= data.writeUint32(width);
+  ret |= data.writeUint32(height);
+  ret |= data.writeUint32(layer_count);
+  ret |= data.writeUint32(format);
+  ret |= data.writeUint64(usage);
+  ret |= data.writeUint64(user_metadata_size);
+
+  if (ret != NO_ERROR) {
+    ALOGE("BpBufferHub::createBuffer: failed to write into parcel");
+    return nullptr;
+  }
+
+  ret = remote()->transact(CREATE_BUFFER, data, &reply);
+  if (ret == NO_ERROR) {
+    return interface_cast<IBufferClient>(reply.readStrongBinder());
+  } else {
+    ALOGE("BpBufferHub::createBuffer: failed to transact; errno=%d", ret);
+    return nullptr;
+  }
+}
+
 status_t BnBufferHub::onTransact(uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags) {
   switch (code) {
+    case CREATE_BUFFER: {
+      CHECK_INTERFACE(IBufferHub, data, reply);
+      uint32_t width = data.readUint32();
+      uint32_t height = data.readUint32();
+      uint32_t layer_count = data.readUint32();
+      uint32_t format = data.readUint32();
+      uint64_t usage = data.readUint64();
+      uint64_t user_metadata_size = data.readUint64();
+      sp<IBufferClient> ret = createBuffer(width, height, layer_count, format,
+                                           usage, user_metadata_size);
+      return reply->writeStrongBinder(IInterface::asBinder(ret));
+    } break;
     default:
-      // Should not reach
-      ALOGE("onTransact(): unknown code %u received!", code);
+      // Should not reach except binder defined transactions such as dumpsys
       return BBinder::onTransact(code, data, reply, flags);
   }
 }