Move core data structure of DetachedBuffer into BufferNode

1/ Supports mutiple DetachedBuffer(s) to be created from a single
BufferNode.
2/ Separate core data structure and logic (i.e. BufferNode) out of the
IPC layer (i.e. DetachedBufferChannel).
3/ DetachedBufferChannel will be renamed to BufferChannel in future
and becomes the universal backend of GraphicBuffer. Thus we are naming
the new class BufferNode instead of DetachedBufferNode.
4/ Move BufferHubDefs out of bufferhub_rpc.h, as BufferHubDefs is not
directly related to the PDX IPCm echanism.

Bug: 112011098
Bug: 112012812
Bug: 111976433
Bug: 70046255
Test: buffer_hub-test
Change-Id: Ieba19329a0e823c78f21611462dedacdad3aab85
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 6122846..499a8f6 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -13,11 +13,12 @@
 // limitations under the License.
 
 sourceFiles = [
+    "buffer_channel.cpp",
     "buffer_hub.cpp",
+    "buffer_node.cpp",
     "bufferhubd.cpp",
     "consumer_channel.cpp",
     "producer_channel.cpp",
-    "detached_buffer_channel.cpp",
     "consumer_queue_channel.cpp",
     "producer_queue_channel.cpp",
 ]
diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp
new file mode 100644
index 0000000..2150d62
--- /dev/null
+++ b/services/vr/bufferhubd/buffer_channel.cpp
@@ -0,0 +1,206 @@
+#include "buffer_channel.h"
+#include "producer_channel.h"
+
+using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
+using android::pdx::Message;
+using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
+using android::pdx::rpc::DispatchRemoteMethod;
+
+namespace android {
+namespace dvr {
+
+BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
+                             int channel_id, IonBuffer buffer,
+                             IonBuffer metadata_buffer,
+                             size_t user_metadata_size)
+    : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
+      buffer_node_(std::make_shared<BufferNode>(
+          std::move(buffer), std::move(metadata_buffer), user_metadata_size)),
+      buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
+  buffer_node_->set_buffer_state_bit(buffer_state_bit_);
+}
+
+BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
+                             uint32_t width, uint32_t height,
+                             uint32_t layer_count, uint32_t format,
+                             uint64_t usage, size_t user_metadata_size)
+    : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
+      buffer_node_(std::make_shared<BufferNode>(
+          width, height, layer_count, format, usage, user_metadata_size)),
+      buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
+  buffer_node_->set_buffer_state_bit(buffer_state_bit_);
+}
+
+BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
+                             int channel_id,
+                             std::shared_ptr<BufferNode> buffer_node,
+                             uint64_t buffer_state_bit)
+    : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
+      buffer_node_(buffer_node),
+      buffer_state_bit_(buffer_state_bit) {
+  buffer_node_->set_buffer_state_bit(buffer_state_bit_);
+}
+
+BufferChannel::~BufferChannel() {
+  ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.",
+           channel_id(), buffer_id());
+  Hangup();
+}
+
+BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const {
+  return BufferInfo(
+      buffer_id(), /*consumer_count=*/0, buffer_node_->buffer().width(),
+      buffer_node_->buffer().height(), buffer_node_->buffer().layer_count(),
+      buffer_node_->buffer().format(), buffer_node_->buffer().usage(),
+      /*pending_count=*/0, /*state=*/0, /*signaled_mask=*/0,
+      /*index=*/0);
+}
+
+void BufferChannel::HandleImpulse(Message& /*message*/) {
+  ATRACE_NAME("BufferChannel::HandleImpulse");
+}
+
+bool BufferChannel::HandleMessage(Message& message) {
+  ATRACE_NAME("BufferChannel::HandleMessage");
+  switch (message.GetOp()) {
+    case DetachedBufferRPC::Import::Opcode:
+      DispatchRemoteMethod<DetachedBufferRPC::Import>(
+          *this, &BufferChannel::OnImport, message);
+      return true;
+
+    case DetachedBufferRPC::Duplicate::Opcode:
+      DispatchRemoteMethod<DetachedBufferRPC::Duplicate>(
+          *this, &BufferChannel::OnDuplicate, message);
+      return true;
+
+    case DetachedBufferRPC::Promote::Opcode:
+      DispatchRemoteMethod<DetachedBufferRPC::Promote>(
+          *this, &BufferChannel::OnPromote, message);
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+Status<BufferDescription<BorrowedHandle>> BufferChannel::OnImport(
+    Message& /*message*/) {
+  ATRACE_NAME("BufferChannel::OnImport");
+  ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.",
+           buffer_id());
+
+  return BufferDescription<BorrowedHandle>{buffer_node_->buffer(),
+                                           buffer_node_->metadata_buffer(),
+                                           buffer_id(),
+                                           channel_id(),
+                                           buffer_state_bit_,
+                                           BorrowedHandle{},
+                                           BorrowedHandle{}};
+}
+
+Status<RemoteChannelHandle> BufferChannel::OnDuplicate(
+    Message& message) {
+  ATRACE_NAME("BufferChannel::OnDuplicate");
+  ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.",
+           buffer_id());
+
+  int channel_id;
+  auto status = message.PushChannel(0, nullptr, &channel_id);
+  if (!status) {
+    ALOGE(
+        "BufferChannel::OnDuplicate: Failed to push buffer channel: %s",
+        status.GetErrorMessage().c_str());
+    return ErrorStatus(ENOMEM);
+  }
+
+  // Try find the next buffer state bit which has not been claimed by any
+  // other buffers yet.
+  uint64_t buffer_state_bit =
+      BufferHubDefs::FindNextClearedBit(buffer_node_->active_buffer_bit_mask() |
+                                        BufferHubDefs::kProducerStateBit);
+  if (buffer_state_bit == 0ULL) {
+    ALOGE(
+        "BufferChannel::OnDuplicate: reached the maximum mumber of channels "
+        "per buffer node: 63.");
+    return ErrorStatus(E2BIG);
+  }
+
+  auto channel =
+      std::shared_ptr<BufferChannel>(new BufferChannel(
+          service(), buffer_id(), channel_id, buffer_node_, buffer_state_bit));
+  if (!channel) {
+    ALOGE("BufferChannel::OnDuplicate: Invalid buffer.");
+    return ErrorStatus(EINVAL);
+  }
+
+  const auto channel_status =
+      service()->SetChannel(channel_id, std::move(channel));
+  if (!channel_status) {
+    // Technically, this should never fail, as we just pushed the channel. Note
+    // that LOG_FATAL will be stripped out in non-debug build.
+    LOG_FATAL(
+        "BufferChannel::OnDuplicate: Failed to set new buffer channel: %s.",
+        channel_status.GetErrorMessage().c_str());
+  }
+
+  return status;
+}
+
+Status<RemoteChannelHandle> BufferChannel::OnPromote(
+    Message& message) {
+  ATRACE_NAME("BufferChannel::OnPromote");
+  ALOGD_IF(TRACE, "BufferChannel::OnPromote: buffer_id=%d", buffer_id());
+
+  // Check whether this is the channel exclusive owner of the buffer_node_.
+  if (buffer_state_bit_ != buffer_node_->active_buffer_bit_mask()) {
+    ALOGE(
+        "BufferChannel::OnPromote: Cannot promote this BufferChannel as its "
+        "BufferNode is shared between multiple channels. This channel's  state "
+        "bit=0x%" PRIx64 ", acitve_buffer_bit_mask=0x%" PRIx64 ".",
+        buffer_state_bit_, buffer_node_->active_buffer_bit_mask());
+    return ErrorStatus(EINVAL);
+  }
+
+  // Note that the new ProducerChannel will have different channel_id, but
+  // inherits the buffer_id from the DetachedBuffer.
+  int channel_id;
+  auto status = message.PushChannel(0, nullptr, &channel_id);
+  if (!status) {
+    ALOGE(
+        "BufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
+        status.GetErrorMessage().c_str());
+    return ErrorStatus(ENOMEM);
+  }
+
+  IonBuffer buffer = std::move(buffer_node_->buffer());
+  IonBuffer metadata_buffer = std::move(buffer_node_->metadata_buffer());
+  size_t user_metadata_size = buffer_node_->user_metadata_size();
+
+  std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
+      service(), buffer_id(), channel_id, std::move(buffer),
+      std::move(metadata_buffer), user_metadata_size);
+  if (!channel) {
+    ALOGE(
+        "BufferChannel::OnPromote: Failed to create ProducerChannel from a "
+        "BufferChannel, buffer_id=%d.",
+        buffer_id());
+  }
+
+  const auto channel_status =
+      service()->SetChannel(channel_id, std::move(channel));
+  if (!channel_status) {
+    // Technically, this should never fail, as we just pushed the channel. Note
+    // that LOG_FATAL will be stripped out in non-debug build.
+    LOG_FATAL(
+        "BufferChannel::OnPromote: Failed to set new producer buffer channel: "
+        "%s.",
+        channel_status.GetErrorMessage().c_str());
+  }
+
+  return status;
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/services/vr/bufferhubd/buffer_channel.h b/services/vr/bufferhubd/buffer_channel.h
new file mode 100644
index 0000000..ac99a73
--- /dev/null
+++ b/services/vr/bufferhubd/buffer_channel.h
@@ -0,0 +1,66 @@
+#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
+#define ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
+
+#include "buffer_hub.h"
+#include "buffer_node.h"
+
+#include <pdx/channel_handle.h>
+#include <pdx/file_handle.h>
+
+namespace android {
+namespace dvr {
+
+class BufferChannel : public BufferHubChannel {
+ public:
+  ~BufferChannel() override;
+
+  template <typename... Args>
+  static std::unique_ptr<BufferChannel> Create(Args&&... args) {
+    auto buffer = std::unique_ptr<BufferChannel>(
+        new BufferChannel(std::forward<Args>(args)...));
+    return buffer->IsValid() ? std::move(buffer) : nullptr;
+  }
+
+  // Returns whether the object holds a valid graphic buffer.
+  bool IsValid() const {
+    return buffer_node_ != nullptr && buffer_node_->IsValid();
+  }
+
+  // Captures buffer info for use by BufferHubService::DumpState().
+  BufferInfo GetBufferInfo() const override;
+
+  bool HandleMessage(pdx::Message& message) override;
+  void HandleImpulse(pdx::Message& message) override;
+
+ private:
+  // Creates a detached buffer from existing IonBuffers.
+  BufferChannel(BufferHubService* service, int buffer_id, int channel_id,
+                IonBuffer buffer, IonBuffer metadata_buffer,
+                size_t user_metadata_size);
+
+  // Allocates a new detached buffer.
+  BufferChannel(BufferHubService* service, int buffer_id, uint32_t width,
+                uint32_t height, uint32_t layer_count, uint32_t format,
+                uint64_t usage, size_t user_metadata_size);
+
+  // Creates a detached buffer from an existing BufferNode.
+  BufferChannel(BufferHubService* service, int buffer_id, int channel_id,
+                std::shared_ptr<BufferNode> buffer_node,
+                uint64_t buffer_state_bit);
+
+  pdx::Status<BufferDescription<pdx::BorrowedHandle>> OnImport(
+      pdx::Message& message);
+  pdx::Status<pdx::RemoteChannelHandle> OnDuplicate(pdx::Message& message);
+  pdx::Status<pdx::RemoteChannelHandle> OnPromote(pdx::Message& message);
+
+  // The concrete implementation of the Buffer object.
+  std::shared_ptr<BufferNode> buffer_node_;
+
+  // The state bit of this buffer. Must be one the lower 63 bits.
+  uint64_t buffer_state_bit_;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index e57c8ed..c0ee31b 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -13,8 +13,8 @@
 
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/dvr/bufferhub_rpc.h>
+#include "buffer_channel.h"
 #include "consumer_channel.h"
-#include "detached_buffer_channel.h"
 #include "producer_channel.h"
 #include "producer_queue_channel.h"
 
@@ -267,7 +267,7 @@
       return {};
 
     case DetachedBufferRPC::Promote::Opcode:
-      // In addition to the message handler in the DetachedBufferChannel's
+      // In addition to the message handler in the BufferChannel's
       // HandleMessage method, we also need to invalid the channel. Note that
       // this has to be done after HandleMessage returns to make sure the IPC
       // request has went back to the client first.
@@ -332,9 +332,9 @@
     return ErrorStatus(EALREADY);
   }
 
-  std::unique_ptr<DetachedBufferChannel> channel =
-      DetachedBufferChannel::Create(this, buffer_id, width, height, layer_count,
-                                    format, usage, user_metadata_size);
+  std::unique_ptr<BufferChannel> channel =
+      BufferChannel::Create(this, buffer_id, width, height, layer_count, format,
+                            usage, user_metadata_size);
   if (!channel) {
     ALOGE(
         "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, "
diff --git a/services/vr/bufferhubd/buffer_node.cpp b/services/vr/bufferhubd/buffer_node.cpp
new file mode 100644
index 0000000..de22bba
--- /dev/null
+++ b/services/vr/bufferhubd/buffer_node.cpp
@@ -0,0 +1,53 @@
+#include "buffer_node.h"
+
+#include <private/dvr/buffer_hub_defs.h>
+
+namespace android {
+namespace dvr {
+
+BufferNode::BufferNode(IonBuffer buffer, IonBuffer metadata_buffer,
+                       size_t user_metadata_size)
+    : buffer_(std::move(buffer)),
+      metadata_buffer_(std::move(metadata_buffer)),
+      user_metadata_size_(user_metadata_size) {}
+
+// Allocates a new BufferNode.
+BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count,
+                       uint32_t format, uint64_t usage,
+                       size_t user_metadata_size)
+    : user_metadata_size_(user_metadata_size) {
+  // The size the of metadata buffer is used as the "width" parameter during
+  // allocation. Thus it cannot overflow uint32_t.
+  if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() -
+                              BufferHubDefs::kMetadataHeaderSize)) {
+    ALOGE(
+        "DetachedBufferChannel::DetachedBufferChannel: metadata size too big.");
+    return;
+  }
+
+  if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
+    ALOGE(
+        "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
+        "buffer: %s",
+        strerror(-ret));
+    return;
+  }
+
+  // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2)
+  // user requested metadata.
+  const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_;
+  if (int ret = metadata_buffer_.Alloc(size,
+                                       /*height=*/1,
+                                       /*layer_count=*/1,
+                                       BufferHubDefs::kMetadataFormat,
+                                       BufferHubDefs::kMetadataUsage)) {
+    ALOGE(
+        "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
+        "metadata: %s",
+        strerror(-ret));
+    return;
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/services/vr/bufferhubd/buffer_node.h b/services/vr/bufferhubd/buffer_node.h
new file mode 100644
index 0000000..4bcf4e3
--- /dev/null
+++ b/services/vr/bufferhubd/buffer_node.h
@@ -0,0 +1,55 @@
+#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
+#define ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
+
+#include <private/dvr/ion_buffer.h>
+
+namespace android {
+namespace dvr {
+
+class BufferNode {
+ public:
+  // Creates a BufferNode from existing IonBuffers, i.e. creating from an
+  // existing ProducerChannel.
+  BufferNode(IonBuffer buffer, IonBuffer metadata_buffer,
+             size_t user_metadata_size);
+
+  // Allocates a new BufferNode.
+  BufferNode(uint32_t width, uint32_t height, uint32_t layer_count,
+             uint32_t format, uint64_t usage, size_t user_metadata_size);
+
+  // Returns whether the object holds a valid graphic buffer.
+  bool IsValid() const {
+    return buffer_.IsValid() && metadata_buffer_.IsValid();
+  }
+
+  size_t user_metadata_size() const { return user_metadata_size_; }
+  uint64_t active_buffer_bit_mask() const { return active_buffer_bit_mask_; }
+  void set_buffer_state_bit(uint64_t buffer_state_bit) {
+    active_buffer_bit_mask_ |= buffer_state_bit;
+  }
+
+  // Used to take out IonBuffers.
+  IonBuffer& buffer() { return buffer_; }
+  IonBuffer& metadata_buffer() { return metadata_buffer_; }
+
+  // Used to access IonBuffers.
+  const IonBuffer& buffer() const { return buffer_; }
+  const IonBuffer& metadata_buffer() const { return metadata_buffer_; }
+
+ private:
+  // Gralloc buffer handles.
+  IonBuffer buffer_;
+  IonBuffer metadata_buffer_;
+
+  // Size of user requested metadata.
+  const size_t user_metadata_size_;
+
+  // All active buffer bits. Valid bits are the lower 63 bits, while the
+  // highest bit is reserved for the exclusive writing and should not be set.
+  uint64_t active_buffer_bit_mask_ = 0ULL;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
diff --git a/services/vr/bufferhubd/detached_buffer_channel.cpp b/services/vr/bufferhubd/detached_buffer_channel.cpp
deleted file mode 100644
index 3061805..0000000
--- a/services/vr/bufferhubd/detached_buffer_channel.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "detached_buffer_channel.h"
-#include "producer_channel.h"
-
-using android::pdx::BorrowedHandle;
-using android::pdx::ErrorStatus;
-using android::pdx::Message;
-using android::pdx::RemoteChannelHandle;
-using android::pdx::Status;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
-                                             int buffer_id, int channel_id,
-                                             IonBuffer buffer,
-                                             IonBuffer metadata_buffer,
-                                             size_t user_metadata_size)
-    : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
-      buffer_(std::move(buffer)),
-      metadata_buffer_(std::move(metadata_buffer)),
-      user_metadata_size_(user_metadata_size) {
-}
-
-DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
-                                             int buffer_id, uint32_t width,
-                                             uint32_t height,
-                                             uint32_t layer_count,
-                                             uint32_t format, uint64_t usage,
-                                             size_t user_metadata_size)
-    : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
-      user_metadata_size_(user_metadata_size) {
-  // The size the of metadata buffer is used as the "width" parameter during
-  // allocation. Thus it cannot overflow uint32_t.
-  if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() -
-                              BufferHubDefs::kMetadataHeaderSize)) {
-    ALOGE(
-        "DetachedBufferChannel::DetachedBufferChannel: metadata size too big.");
-    return;
-  }
-
-  if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
-    ALOGE(
-        "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
-        "buffer: %s",
-        strerror(-ret));
-    return;
-  }
-
-  // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2)
-  // user requested metadata.
-  const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_;
-  if (int ret = metadata_buffer_.Alloc(size,
-                                       /*height=*/1,
-                                       /*layer_count=*/1,
-                                       BufferHubDefs::kMetadataFormat,
-                                       BufferHubDefs::kMetadataUsage)) {
-    ALOGE(
-        "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
-        "metadata: %s",
-        strerror(-ret));
-    return;
-  }
-}
-
-DetachedBufferChannel::~DetachedBufferChannel() {
-  ALOGD_IF(TRACE,
-           "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d "
-           "buffer_id=%d.",
-           channel_id(), buffer_id());
-  Hangup();
-}
-
-BufferHubChannel::BufferInfo DetachedBufferChannel::GetBufferInfo() const {
-  return BufferInfo(buffer_id(), /*consumer_count=*/0, buffer_.width(),
-                    buffer_.height(), buffer_.layer_count(), buffer_.format(),
-                    buffer_.usage(), /*pending_count=*/0, /*state=*/0,
-                    /*signaled_mask=*/0, /*index=*/0);
-}
-
-void DetachedBufferChannel::HandleImpulse(Message& /*message*/) {
-  ATRACE_NAME("DetachedBufferChannel::HandleImpulse");
-}
-
-bool DetachedBufferChannel::HandleMessage(Message& message) {
-  ATRACE_NAME("DetachedBufferChannel::HandleMessage");
-  switch (message.GetOp()) {
-    case DetachedBufferRPC::Import::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Import>(
-          *this, &DetachedBufferChannel::OnImport, message);
-      return true;
-
-    case DetachedBufferRPC::Promote::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Promote>(
-          *this, &DetachedBufferChannel::OnPromote, message);
-      return true;
-
-    default:
-      return false;
-  }
-}
-
-Status<BufferDescription<BorrowedHandle>> DetachedBufferChannel::OnImport(
-    Message& /*message*/) {
-  ATRACE_NAME("DetachedBufferChannel::OnGetBuffer");
-  ALOGD_IF(TRACE, "DetachedBufferChannel::OnGetBuffer: buffer=%d.",
-           buffer_id());
-
-  return BufferDescription<BorrowedHandle>{buffer_,
-                                           metadata_buffer_,
-                                           buffer_id(),
-                                           channel_id(),
-                                           /*buffer_state_bit=*/0,
-                                           BorrowedHandle{},
-                                           BorrowedHandle{}};
-}
-
-Status<RemoteChannelHandle> DetachedBufferChannel::OnPromote(
-    Message& message) {
-  ATRACE_NAME("DetachedBufferChannel::OnPromote");
-  ALOGD_IF(TRACE, "DetachedBufferChannel::OnPromote: buffer_id=%d",
-           buffer_id());
-
-  // Note that the new ProducerChannel will have different channel_id, but
-  // inherits the buffer_id from the DetachedBuffer.
-  int channel_id;
-  auto status = message.PushChannel(0, nullptr, &channel_id);
-  if (!status) {
-    ALOGE(
-        "DetachedBufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
-        status.GetErrorMessage().c_str());
-    return ErrorStatus(ENOMEM);
-  }
-
-  std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
-      service(), buffer_id(), channel_id, std::move(buffer_),
-      std::move(metadata_buffer_), user_metadata_size_);
-  if (!channel) {
-    ALOGE(
-        "DetachedBufferChannel::OnPromote: Failed to create ProducerChannel "
-        "from a DetachedBufferChannel, buffer_id=%d.",
-        buffer_id());
-  }
-
-  const auto channel_status =
-      service()->SetChannel(channel_id, std::move(channel));
-  if (!channel_status) {
-    // Technically, this should never fail, as we just pushed the channel. Note
-    // that LOG_FATAL will be stripped out in non-debug build.
-    LOG_FATAL(
-        "DetachedBufferChannel::OnPromote: Failed to set new producer buffer "
-        "channel: %s.",
-        channel_status.GetErrorMessage().c_str());
-  }
-
-  return status;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/bufferhubd/detached_buffer_channel.h b/services/vr/bufferhubd/detached_buffer_channel.h
deleted file mode 100644
index 8b6dab8..0000000
--- a/services/vr/bufferhubd/detached_buffer_channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_
-#define ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_
-
-#include "buffer_hub.h"
-
-#include <pdx/channel_handle.h>
-#include <pdx/file_handle.h>
-
-namespace android {
-namespace dvr {
-
-class DetachedBufferChannel : public BufferHubChannel {
- public:
-  ~DetachedBufferChannel() override;
-
-  template <typename... Args>
-  static std::unique_ptr<DetachedBufferChannel> Create(Args&&... args) {
-    auto buffer = std::unique_ptr<DetachedBufferChannel>(
-        new DetachedBufferChannel(std::forward<Args>(args)...));
-    return buffer->IsValid() ? std::move(buffer) : nullptr;
-  }
-
-  // Returns whether the object holds a valid graphic buffer.
-  bool IsValid() const {
-    return buffer_.IsValid() && metadata_buffer_.IsValid();
-  }
-
-  size_t user_metadata_size() const { return user_metadata_size_; }
-
-  // Captures buffer info for use by BufferHubService::DumpState().
-  BufferInfo GetBufferInfo() const override;
-
-  bool HandleMessage(pdx::Message& message) override;
-  void HandleImpulse(pdx::Message& message) override;
-
- private:
-  // Creates a detached buffer from existing IonBuffers.
-  DetachedBufferChannel(BufferHubService* service, int buffer_id,
-                        int channel_id, IonBuffer buffer,
-                        IonBuffer metadata_buffer, size_t user_metadata_size);
-
-  // Allocates a new detached buffer.
-  DetachedBufferChannel(BufferHubService* service, int buffer_id,
-                        uint32_t width, uint32_t height, uint32_t layer_count,
-                        uint32_t format, uint64_t usage,
-                        size_t user_metadata_size);
-
-  pdx::Status<BufferDescription<pdx::BorrowedHandle>> OnImport(
-      pdx::Message& message);
-  pdx::Status<pdx::RemoteChannelHandle> OnPromote(pdx::Message& message);
-
-  // Gralloc buffer handles.
-  IonBuffer buffer_;
-  IonBuffer metadata_buffer_;
-
-  // Size of user requested metadata.
-  const size_t user_metadata_size_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_BUFFERHUBD_DETACHED_BUFFER_CHANNEL_H_
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 97af660..19d48f2 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -12,8 +12,8 @@
 #include <thread>
 
 #include <private/dvr/bufferhub_rpc.h>
+#include "buffer_channel.h"
 #include "consumer_channel.h"
-#include "detached_buffer_channel.h"
 
 using android::pdx::BorrowedHandle;
 using android::pdx::ErrorStatus;
@@ -27,14 +27,6 @@
 namespace android {
 namespace dvr {
 
-namespace {
-
-static inline uint64_t FindNextClearedBit(uint64_t bits) {
-  return ~bits - (~bits & (~bits - 1));
-}
-
-}  // namespace
-
 ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id,
                                  int channel_id, IonBuffer buffer,
                                  IonBuffer metadata_buffer,
@@ -270,7 +262,7 @@
 
   // Try find the next consumer state bit which has not been claimed by any
   // consumer yet.
-  uint64_t consumer_state_bit = FindNextClearedBit(
+  uint64_t consumer_state_bit = BufferHubDefs::FindNextClearedBit(
       active_consumer_bit_mask_ | orphaned_consumer_bit_mask_ |
       BufferHubDefs::kProducerStateBit);
   if (consumer_state_bit == 0ULL) {
@@ -419,10 +411,9 @@
     return ErrorStatus(-ret);
   };
 
-  std::unique_ptr<DetachedBufferChannel> channel =
-      DetachedBufferChannel::Create(
-          service(), buffer_id(), channel_id, std::move(buffer_),
-          std::move(metadata_buffer_), user_metadata_size_);
+  std::unique_ptr<BufferChannel> channel = BufferChannel::Create(
+      service(), buffer_id(), channel_id, std::move(buffer_),
+      std::move(metadata_buffer_), user_metadata_size_);
   if (!channel) {
     ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer.");
     return ErrorStatus(EINVAL);