Enabled shared memory for DetachedBuffer

Bug: 112011098
Bug: 112012812
Bug: 111976433
Bug: 70046255
Test: buffer_hub-test
Change-Id: I5111d08c1de1d1386e6896d3f7aba4e068d1adc4
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 2a962b5..2ab5b65 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -968,8 +968,19 @@
   ASSERT_TRUE(b2 != nullptr);
   int b2_id = b2->id();
 
-  // The duplicated buffer should inherit the same buffer id.
+  // These two buffer instances are based on the same physical buffer under the
+  // hood, so they should share the same id.
   EXPECT_EQ(b1_id, b2_id);
+  // We use buffer_state_bit() to tell those two instances apart.
+  EXPECT_NE(b1->buffer_state_bit(), b2->buffer_state_bit());
+  EXPECT_NE(b1->buffer_state_bit(), 0ULL);
+  EXPECT_NE(b2->buffer_state_bit(), 0ULL);
+  EXPECT_NE(b1->buffer_state_bit(), kProducerStateBit);
+  EXPECT_NE(b2->buffer_state_bit(), kProducerStateBit);
+
+  // Both buffer instances should be in gained state.
+  EXPECT_TRUE(IsBufferGained(b1->buffer_state()));
+  EXPECT_TRUE(IsBufferGained(b2->buffer_state()));
 
   // Promote the detached buffer should fail as b1 is no longer the exclusive
   // owner of the buffer..
diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp
index 60f11e2..02abd91 100644
--- a/libs/vr/libbufferhub/detached_buffer.cpp
+++ b/libs/vr/libbufferhub/detached_buffer.cpp
@@ -49,7 +49,7 @@
 }
 
 int DetachedBuffer::ImportGraphicBuffer() {
-  ATRACE_NAME("DetachedBuffer::DetachedBuffer");
+  ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
 
   auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
   if (!status) {
@@ -76,9 +76,53 @@
     return ret;
   }
 
+  // Import the metadata.
+  IonBuffer metadata_buffer;
+  if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
+    ALOGE("Failed to import metadata buffer, error=%d", ret);
+    return ret;
+  }
+  size_t metadata_buf_size = metadata_buffer.width();
+  if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
+    ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: %zu",
+          metadata_buf_size);
+    return -EINVAL;
+  }
+
   // If all imports succeed, replace the previous buffer and id.
   id_ = buffer_id;
   buffer_ = std::move(ion_buffer);
+  metadata_buffer_ = std::move(metadata_buffer);
+  user_metadata_size_ = metadata_buf_size - BufferHubDefs::kMetadataHeaderSize;
+
+  void* metadata_ptr = nullptr;
+  if (const int ret =
+          metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+                                /*y=*/0, metadata_buf_size,
+                                /*height=*/1, &metadata_ptr)) {
+    ALOGE("DetachedBuffer::ImportGraphicBuffer: Failed to lock metadata.");
+    return ret;
+  }
+
+  // TODO(b/112012161) Set up shared fences.
+
+  // Note that here the buffer state is mapped from shared memory as an atomic
+  // object. The std::atomic's constructor will not be called so that the
+  // original value stored in the memory region can be preserved.
+  metadata_header_ = static_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+  if (user_metadata_size_) {
+    user_metadata_ptr_ = static_cast<void*>(metadata_header_ + 1);
+  } else {
+    user_metadata_ptr_ = nullptr;
+  }
+
+  id_ = buffer_desc.id();
+  buffer_state_bit_ = buffer_desc.buffer_state_bit();
+
+  ALOGD_IF(TRACE,
+           "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
+           ".",
+           id(), metadata_header_->buffer_state.load());
   return 0;
 }
 
diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
index 376b53e..1fc011b 100644
--- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
@@ -30,8 +30,17 @@
 
   const sp<GraphicBuffer>& buffer() const { return buffer_.buffer(); }
 
+  // Gets ID of the buffer client. All DetachedBuffer clients derived from the
+  // same buffer in bufferhubd share the same buffer id.
   int id() const { return id_; }
 
+  // Returns the current value of MetadataHeader::buffer_state.
+  uint64_t buffer_state() { return metadata_header_->buffer_state.load(); }
+
+  // A state mask which is unique to a buffer hub client among all its siblings
+  // sharing the same concrete graphic buffer.
+  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
   // Returns true if the buffer holds an open PDX channels towards bufferhubd.
   bool IsConnected() const { return client_.IsValid(); }
 
@@ -75,7 +84,18 @@
 
   // Global id for the buffer that is consistent across processes.
   int id_;
+  uint64_t buffer_state_bit_;
+
+  // The concrete Ion buffers.
   IonBuffer buffer_;
+  IonBuffer metadata_buffer_;
+
+  // buffer metadata.
+  size_t user_metadata_size_ = 0;
+  BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
+  void* user_metadata_ptr_ = nullptr;
+
+  // PDX backend.
   BufferHubClient client_;
 };