bufferhubd: Implement more DetachedBuffer logic

1/ Separate DetachedBuffer related logic into a dedicated subclass of
   BufferHubRPC. This actually is the right thing to do as it utilizes
   the PDX's client/service programming pattern better.
2/ Add IsValid() check for the DetachedBufferChannel object.
3/ Add BufferHubClient to handle general PDX operations.
4/ Add DetachedBuffer which composites a BufferHubClient.
5/ Fully functional logic of allocating a DetachedBuffer, converting it
   to a BufferHub-backed GraphicBuffer, then converting it back to a
   DetachedBuffer.

Bug: 38137191
Bug: 70046255
Bug: 70912269
Test: buffer_hub-test
Change-Id: I81bf9259cbbaeb29a6df2769363b5a03464e7864
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index e4e19c7..72bf6f2 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -6,6 +6,7 @@
 #include <utils/Trace.h>
 
 #include <iomanip>
+#include <memory>
 #include <sstream>
 #include <string>
 #include <thread>
@@ -13,6 +14,7 @@
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/dvr/bufferhub_rpc.h>
 #include "consumer_channel.h"
+#include "detached_buffer_channel.h"
 #include "producer_channel.h"
 #include "producer_queue_channel.h"
 
@@ -245,6 +247,11 @@
           *this, &BufferHubService::OnCreateBuffer, message);
       return {};
 
+    case DetachedBufferRPC::Create::Opcode:
+      DispatchRemoteMethod<DetachedBufferRPC::Create>(
+          *this, &BufferHubService::OnCreateDetachedBuffer, message);
+      return {};
+
     case BufferHubRPC::CreateProducerQueue::Opcode:
       DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
           *this, &BufferHubService::OnCreateProducerQueue, message);
@@ -295,6 +302,43 @@
   }
 }
 
+pdx::Status<void> BufferHubService::OnCreateDetachedBuffer(
+    pdx::Message& message, uint32_t width, uint32_t height,
+    uint32_t layer_count, uint32_t format, uint64_t usage,
+    size_t user_metadata_size) {
+  // Use the producer channel id as the global buffer id.
+  const int buffer_id = message.GetChannelId();
+  ALOGD_IF(TRACE,
+           "BufferHubService::OnCreateDetachedBuffer: buffer_id=%d width=%u "
+           "height=%u layer_count=%u format=%u usage=%" PRIx64
+           " user_metadata_size=%zu",
+           buffer_id, width, height, layer_count, format, usage,
+           user_metadata_size);
+
+  // See if this channel is already attached to a buffer.
+  if (const auto channel = message.GetChannel<BufferHubChannel>()) {
+    ALOGE(
+        "BufferHubService::OnCreateDetachedBuffer: Buffer already created: "
+        "buffer=%d",
+        buffer_id);
+    return ErrorStatus(EALREADY);
+  }
+
+  std::unique_ptr<DetachedBufferChannel> channel =
+      DetachedBufferChannel::Create(this, buffer_id, width, height, layer_count,
+                                    format, usage, user_metadata_size);
+  if (!channel) {
+    ALOGE(
+        "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, "
+        "buffer=%d.",
+        buffer_id);
+    return ErrorStatus(ENOMEM);
+  }
+
+  message.SetChannel(std::move(channel));
+  return {};
+}
+
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
     pdx::Message& message, const ProducerQueueConfig& producer_config,
     const UsagePolicy& usage_policy) {