Merge "Support monitor input per display (1/2)"
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 1a9018a..e37c388 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -42,8 +42,8 @@
 /**
  * analog using std::shared_ptr for internally held refcount
  *
- * ref must be called at least one time during the lifetime of this object. The recommended way to construct
- * this object is with SharedRefBase::make.
+ * ref must be called at least one time during the lifetime of this object. The recommended way to
+ * construct this object is with SharedRefBase::make.
  */
 class SharedRefBase {
 public:
@@ -77,7 +77,7 @@
     /**
      * Convenience method for making an object directly with a reference.
      */
-    template<class T, class... Args>
+    template <class T, class... Args>
     static std::shared_ptr<T> make(Args&&... args) {
         T* t = new T(std::forward<Args>(args)...);
         return t->template ref<T>();
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 3dac037..1a7c2d3 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -400,19 +400,8 @@
         ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
         return BAD_VALUE;
     }
-    auto detached_buffer = BufferHubBuffer::Import(std::move(detached_handle->handle()));
-    if (detached_buffer == nullptr) {
-        ALOGE("attachBuffer: BufferHubBuffer cannot be NULL.");
-        return BAD_VALUE;
-    }
-    auto status_or_handle = detached_buffer->Promote();
-    if (!status_or_handle.ok()) {
-        ALOGE("attachBuffer: Failed to promote a BufferHubBuffer into a BufferProducer, error=%d.",
-              status_or_handle.error());
-        return BAD_VALUE;
-    }
     std::shared_ptr<BufferProducer> buffer_producer =
-            BufferProducer::Import(status_or_handle.take());
+            BufferProducer::Import(std::move(detached_handle->handle()));
     if (buffer_producer == nullptr) {
         ALOGE("attachBuffer: Failed to import BufferProducer.");
         return BAD_VALUE;
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 2696c6c..44a947e 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -174,26 +174,6 @@
     return poll(&p, 1, timeoutMs);
 }
 
-Status<LocalChannelHandle> BufferHubBuffer::Promote() {
-    ATRACE_CALL();
-
-    // TODO(b/112338294) remove after migrate producer buffer to binder
-    ALOGW("BufferHubBuffer::Promote: not supported operation during migration");
-    return {};
-
-    ALOGD("BufferHubBuffer::Promote: id=%d.", mId);
-
-    auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
-    if (statusOrHandle.ok()) {
-        // Invalidate the buffer.
-        mBufferHandle = {};
-    } else {
-        ALOGE("BufferHubBuffer::Promote: Failed to promote buffer (id=%d): %s.", mId,
-              statusOrHandle.GetErrorMessage().c_str());
-    }
-    return statusOrHandle;
-}
-
 Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
     ATRACE_CALL();
     ALOGD("BufferHubBuffer::Duplicate: id=%d.", mId);
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index d33be8c..cefe5b3 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -112,11 +112,6 @@
     // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
     int Poll(int timeoutMs);
 
-    // Promotes a BufferHubBuffer to become a ProducerBuffer. Once promoted the BufferHubBuffer
-    // channel will be closed automatically on successful IPC return. Further IPCs towards this
-    // channel will return error.
-    pdx::Status<pdx::LocalChannelHandle> Promote();
-
     // Creates a BufferHubBuffer client from an existing one. The new client will
     // share the same underlying gralloc buffer and ashmem region for metadata.
     pdx::Status<pdx::LocalChannelHandle> Duplicate();
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index e71c99c..be06ad2 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -113,12 +113,6 @@
 
     // TODO(b/112338294): rewrite test after migration
     return;
-
-    // Promote the detached buffer should fail as b1 is no longer the exclusive
-    // owner of the buffer..
-    statusOrHandle = b1->Promote();
-    EXPECT_FALSE(statusOrHandle.ok());
-    EXPECT_EQ(statusOrHandle.error(), EINVAL);
 }
 
 } // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 571d382..8c6e7e2 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -794,43 +794,42 @@
   EXPECT_EQ(d->id(), p_id);
 }
 
-TEST_F(LibBufferHubTest, TestPromoteBufferHubBuffer) {
-  // TODO(b/112338294) rewrite test after migration
-  return;
+TEST_F(LibBufferHubTest, TestCreateBufferHubBufferFails) {
+  // Buffer Creation will fail: BLOB format requires height to be 1.
+  auto b1 = BufferHubBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
+                                    /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
+                                    kUserMetadataSize);
 
-  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
-                                    kUsage, kUserMetadataSize);
-  int b1_id = b1->id();
-  EXPECT_TRUE(b1->IsValid());
-
-  auto status_or_handle = b1->Promote();
-  EXPECT_TRUE(status_or_handle);
-
-  // The detached buffer should have hangup.
-  EXPECT_GT(RETRY_EINTR(b1->Poll(kPollTimeoutMs)), 0);
-  auto status_or_int = b1->GetEventMask(POLLHUP);
-  EXPECT_TRUE(status_or_int.ok());
-  EXPECT_EQ(status_or_int.get(), POLLHUP);
-
-  // The buffer client is still considered as connected but invalid.
-  EXPECT_TRUE(b1->IsConnected());
+  EXPECT_FALSE(b1->IsConnected());
   EXPECT_FALSE(b1->IsValid());
 
-  // Gets the channel handle for the producer.
-  LocalChannelHandle h1 = status_or_handle.take();
-  EXPECT_TRUE(h1.valid());
+  // Buffer Creation will fail: user metadata size too large.
+  auto b2 = BufferHubBuffer::Create(
+      kWidth, kHeight, kLayerCount, kFormat, kUsage,
+      /*user_metadata_size=*/std::numeric_limits<size_t>::max());
 
-  std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Import(std::move(h1));
-  EXPECT_FALSE(h1.valid());
-  ASSERT_TRUE(p1 != nullptr);
-  int p1_id = p1->id();
+  EXPECT_FALSE(b2->IsConnected());
+  EXPECT_FALSE(b2->IsValid());
 
-  // A newly promoted ProducerBuffer should inherit the same buffer id.
-  EXPECT_EQ(b1_id, p1_id);
-  EXPECT_TRUE(IsBufferGained(p1->buffer_state()));
+  // Buffer Creation will fail: user metadata size too large.
+  auto b3 = BufferHubBuffer::Create(
+      kWidth, kHeight, kLayerCount, kFormat, kUsage,
+      /*user_metadata_size=*/std::numeric_limits<size_t>::max() -
+          kMetadataHeaderSize);
+
+  EXPECT_FALSE(b3->IsConnected());
+  EXPECT_FALSE(b3->IsValid());
 }
 
-TEST_F(LibBufferHubTest, TestDetachThenPromote) {
+TEST_F(LibBufferHubTest, TestCreateBufferHubBuffer) {
+  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
+                                    kUsage, kUserMetadataSize);
+  EXPECT_TRUE(b1->IsConnected());
+  EXPECT_TRUE(b1->IsValid());
+  EXPECT_NE(b1->id(), 0);
+}
+
+TEST_F(LibBufferHubTest, TestDetach) {
   // TODO(b/112338294) rewrite test after migration
   return;
 
@@ -852,24 +851,48 @@
   EXPECT_TRUE(b1->IsValid());
   int b1_id = b1->id();
   EXPECT_EQ(b1_id, p1_id);
+}
 
-  // Promote the detached buffer.
-  status_or_handle = b1->Promote();
-  // The buffer client is still considered as connected but invalid.
+TEST_F(LibBufferHubTest, TestDuplicateBufferHubBuffer) {
+  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
+                                    kUsage, kUserMetadataSize);
+  int b1_id = b1->id();
+  EXPECT_TRUE(b1->IsValid());
+  EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
+
+  auto status_or_handle = b1->Duplicate();
+  EXPECT_TRUE(status_or_handle);
+
+  // The detached buffer should still be valid.
   EXPECT_TRUE(b1->IsConnected());
-  EXPECT_FALSE(b1->IsValid());
-  EXPECT_TRUE(status_or_handle.ok());
+  EXPECT_TRUE(b1->IsValid());
 
-  // Gets the channel handle for the producer.
+  // Gets the channel handle for the duplicated buffer.
   LocalChannelHandle h2 = status_or_handle.take();
   EXPECT_TRUE(h2.valid());
 
-  std::unique_ptr<ProducerBuffer> p2 = ProducerBuffer::Import(std::move(h2));
+  std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
   EXPECT_FALSE(h2.valid());
-  ASSERT_TRUE(p2 != nullptr);
-  int p2_id = p2->id();
+  ASSERT_TRUE(b2 != nullptr);
+  EXPECT_TRUE(b2->IsValid());
+  EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
 
-  // A newly promoted ProducerBuffer should inherit the same buffer id.
-  EXPECT_EQ(b1_id, p2_id);
-  EXPECT_TRUE(IsBufferGained(p2->buffer_state()));
+  int b2_id = b2->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()));
+
+  // TODO(b/112338294) rewrite test after migration
+  return;
 }
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
index 6d28d41..49f9c3e 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -191,11 +191,6 @@
     // Imports the given channel handle to a DetachedBuffer, taking ownership.
     kOpImport,
 
-    // Promotes a DetachedBuffer to become a ProducerBuffer. Once promoted the
-    // DetachedBuffer channel will be closed automatically on successful IPC
-    // return. Further IPCs towards this channel will return error.
-    kOpPromote,
-
     // Creates a DetachedBuffer client from an existing one. The new client will
     // share the same underlying gralloc buffer and ashmem region for metadata.
     kOpDuplicate,
@@ -212,10 +207,9 @@
                          uint32_t format, uint64_t usage,
                          size_t user_metadata_size));
   PDX_REMOTE_METHOD(Import, kOpImport, BufferTraits<LocalHandle>(Void));
-  PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void));
 
-  PDX_REMOTE_API(API, Create, Import, Promote, Duplicate);
+  PDX_REMOTE_API(API, Create, Import, Duplicate);
 };
 
 }  // namespace dvr
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 341dfd5..60cad02 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -767,9 +767,12 @@
         *outMode = iter->second.colorMode;
         *outIntent = iter->second.renderIntent;
     } else {
-        ALOGE("map unknown (%s)/(%s) to default color mode",
-              dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
-              decodeRenderIntent(intent).c_str());
+        // this is unexpected on a WCG display
+        if (hasWideColorGamut()) {
+            ALOGE("map unknown (%s)/(%s) to default color mode",
+                  dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
+                  decodeRenderIntent(intent).c_str());
+        }
 
         *outDataspace = Dataspace::UNKNOWN;
         *outMode = ColorMode::NATIVE;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8afd3b3..7e6b5d3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -102,6 +102,7 @@
     mCurrentState.hdrMetadata.validTypes = 0;
     mCurrentState.surfaceDamageRegion.clear();
     mCurrentState.api = -1;
+    mCurrentState.hasColorTransform = false;
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
@@ -1547,11 +1548,15 @@
 }
 
 bool Layer::setColorTransform(const mat4& matrix) {
+    static const mat4 identityMatrix = mat4();
+
     if (mCurrentState.colorTransform == matrix) {
         return false;
     }
     ++mCurrentState.sequence;
     mCurrentState.colorTransform = matrix;
+    mCurrentState.hasColorTransform = matrix != identityMatrix;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1561,8 +1566,7 @@
 }
 
 bool Layer::hasColorTransform() const {
-    static const mat4 identityMatrix = mat4();
-    return getDrawingState().colorTransform != identityMatrix;
+    return getDrawingState().hasColorTransform;
 }
 
 bool Layer::isLegacyDataSpace() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e2d1178..5d05f05 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -182,6 +182,7 @@
 
         sp<NativeHandle> sidebandStream;
         mat4 colorTransform;
+        bool hasColorTransform;
     };
 
     explicit Layer(const LayerCreationArgs& args);
diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp
index dcc6ea4..ee85746 100644
--- a/services/vr/bufferhubd/buffer_channel.cpp
+++ b/services/vr/bufferhubd/buffer_channel.cpp
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <private/dvr/buffer_channel.h>
 #include <private/dvr/producer_channel.h>
 
@@ -16,9 +17,8 @@
                              size_t user_metadata_size)
     : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
       buffer_node_(
-          std::make_shared<BufferNode>(std::move(buffer), user_metadata_size)),
-      buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
-  buffer_node_->set_buffer_state_bit(buffer_state_bit_);
+          std::make_shared<BufferNode>(std::move(buffer), user_metadata_size)) {
+  buffer_state_bit_ = buffer_node_->AddNewActiveClientsBitToMask();
 }
 
 BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
@@ -27,24 +27,28 @@
                              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_);
+          width, height, layer_count, format, usage, user_metadata_size)) {
+  buffer_state_bit_ = buffer_node_->AddNewActiveClientsBitToMask();
 }
 
 BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
                              int channel_id,
-                             std::shared_ptr<BufferNode> buffer_node,
-                             uint64_t buffer_state_bit)
+                             std::shared_ptr<BufferNode> buffer_node)
     : 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_);
+      buffer_node_(buffer_node) {
+  buffer_state_bit_ = buffer_node_->AddNewActiveClientsBitToMask();
+  if (buffer_state_bit_ == 0ULL) {
+    ALOGE("BufferChannel::BufferChannel: %s", strerror(errno));
+    buffer_node_ = nullptr;
+  }
 }
 
 BufferChannel::~BufferChannel() {
   ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.",
            channel_id(), buffer_id());
+  if (buffer_state_bit_ != 0ULL) {
+    buffer_node_->RemoveClientsBitFromMask(buffer_state_bit_);
+  }
   Hangup();
 }
 
@@ -74,11 +78,6 @@
           *this, &BufferChannel::OnDuplicate, message);
       return true;
 
-    case DetachedBufferRPC::Promote::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Promote>(
-          *this, &BufferChannel::OnPromote, message);
-      return true;
-
     default:
       return false;
   }
@@ -106,38 +105,22 @@
       /*released_fence_fd=*/BorrowedHandle{}};
 }
 
-Status<RemoteChannelHandle> BufferChannel::OnDuplicate(
-    Message& message) {
+Status<RemoteChannelHandle> BufferChannel::OnDuplicate(Message& message) {
   ATRACE_NAME("BufferChannel::OnDuplicate");
-  ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.",
-           buffer_id());
+  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());
+  if (!status.ok()) {
+    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.");
+  auto channel = std::shared_ptr<BufferChannel>(
+      new BufferChannel(service(), buffer_id(), channel_id, buffer_node_));
+  if (!channel->IsValid()) {
+    ALOGE("BufferChannel::OnDuplicate: Invalid buffer. %s", strerror(errno));
     return ErrorStatus(EINVAL);
   }
 
@@ -154,69 +137,5 @@
   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;
-  if (int ret = metadata_buffer.Alloc(buffer_node_->metadata().metadata_size(),
-                                      /*height=*/1,
-                                      /*layer_count=*/1,
-                                      BufferHubDefs::kMetadataFormat,
-                                      BufferHubDefs::kMetadataUsage)) {
-    ALOGE("BufferChannel::OnPromote: Failed to allocate metadata: %s",
-          strerror(-ret));
-    return ErrorStatus(EINVAL);
-  }
-
-  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_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 15391da..6421a0b 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -265,14 +265,6 @@
       SetChannel(channel->channel_id(), nullptr);
       return {};
 
-    case DetachedBufferRPC::Promote::Opcode:
-      // 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.
-      SetChannel(channel->channel_id(), nullptr);
-      return {};
-
     default:
       return DefaultHandleMessage(message);
   }
diff --git a/services/vr/bufferhubd/buffer_node.cpp b/services/vr/bufferhubd/buffer_node.cpp
index 782b9c2..bedec6f 100644
--- a/services/vr/bufferhubd/buffer_node.cpp
+++ b/services/vr/bufferhubd/buffer_node.cpp
@@ -1,12 +1,24 @@
+#include <errno.h>
 #include <private/dvr/buffer_hub_defs.h>
 #include <private/dvr/buffer_node.h>
 
 namespace android {
 namespace dvr {
 
+void BufferNode::InitializeMetadata() {
+  // Using placement new here to reuse shared memory instead of new allocation
+  // Initialize the atomic variables to zero.
+  BufferHubDefs::MetadataHeader* metadata_header = metadata_.metadata_header();
+  buffer_state_ = new (&metadata_header->buffer_state) std::atomic<uint64_t>(0);
+  fence_state_ = new (&metadata_header->fence_state) std::atomic<uint64_t>(0);
+  active_clients_bit_mask_ =
+      new (&metadata_header->active_clients_bit_mask) std::atomic<uint64_t>(0);
+}
+
 BufferNode::BufferNode(IonBuffer buffer, size_t user_metadata_size)
     : buffer_(std::move(buffer)) {
   metadata_ = BufferHubMetadata::Create(user_metadata_size);
+  InitializeMetadata();
 }
 
 // Allocates a new BufferNode.
@@ -22,6 +34,37 @@
   }
 
   metadata_ = BufferHubMetadata::Create(user_metadata_size);
+  InitializeMetadata();
+}
+
+uint64_t BufferNode::GetActiveClientsBitMask() const {
+  return active_clients_bit_mask_->load(std::memory_order_acquire);
+}
+
+uint64_t BufferNode::AddNewActiveClientsBitToMask() {
+  uint64_t current_active_clients_bit_mask = GetActiveClientsBitMask();
+  uint64_t buffer_state_bit = 0ULL;
+  uint64_t updated_active_clients_bit_mask = 0ULL;
+  do {
+    buffer_state_bit =
+        BufferHubDefs::FindNextClearedBit(current_active_clients_bit_mask);
+    if (buffer_state_bit == 0ULL) {
+      ALOGE(
+          "BufferNode::AddNewActiveClientsBitToMask: reached the maximum "
+          "mumber of channels per buffer node: 32.");
+      errno = E2BIG;
+      return 0ULL;
+    }
+    updated_active_clients_bit_mask =
+        current_active_clients_bit_mask | buffer_state_bit;
+  } while (!(active_clients_bit_mask_->compare_exchange_weak(
+      current_active_clients_bit_mask, updated_active_clients_bit_mask,
+      std::memory_order_acq_rel, std::memory_order_acquire)));
+  return buffer_state_bit;
+}
+
+void BufferNode::RemoveClientsBitFromMask(const uint64_t& value) {
+  active_clients_bit_mask_->fetch_and(~value);
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_channel.h b/services/vr/bufferhubd/include/private/dvr/buffer_channel.h
index 1697251..e9bdb37 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_channel.h
@@ -42,21 +42,20 @@
                 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.
+  // Creates a detached buffer from an existing BufferNode. This method is used
+  // in OnDuplicate method.
   BufferChannel(BufferHubService* service, int buffer_id, int channel_id,
-                std::shared_ptr<BufferNode> buffer_node,
-                uint64_t buffer_state_bit);
+                std::shared_ptr<BufferNode> buffer_node);
 
   pdx::Status<BufferTraits<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_;
+  std::shared_ptr<BufferNode> buffer_node_ = nullptr;
 
   // The state bit of this buffer. Must be one the lower 63 bits.
-  uint64_t buffer_state_bit_;
+  uint64_t buffer_state_bit_ = 0ULL;
 };
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_node.h b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
index d6c6105..e1e8057 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_node.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
@@ -10,7 +10,7 @@
 class BufferNode {
  public:
   // Creates a BufferNode from existing IonBuffers, i.e. creating from an
-  // existing ProducerChannel.
+  // existing ProducerChannel. Allocate a new BufferHubMetadata.
   BufferNode(IonBuffer buffer, size_t user_metadata_size);
 
   // Allocates a new BufferNode.
@@ -21,26 +21,56 @@
   bool IsValid() const { return buffer_.IsValid() && metadata_.IsValid(); }
 
   size_t user_metadata_size() const { return metadata_.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;
-  }
 
-  // Accessor of the IonBuffer.
+  // Accessors of the IonBuffer.
   IonBuffer& buffer() { return buffer_; }
   const IonBuffer& buffer() const { return buffer_; }
 
-  // Accessor of the metadata.
+  // Accessors of metadata.
   const BufferHubMetadata& metadata() const { return metadata_; }
 
+  // Gets the current value of active_clients_bit_mask in metadata_ with
+  // std::memory_order_acquire, so that all previous releases of
+  // active_clients_bit_mask from all threads will be returned here.
+  uint64_t GetActiveClientsBitMask() const;
+
+  // Find and add a new buffer_state_bit to active_clients_bit_mask in
+  // metadata_.
+  // Return the new buffer_state_bit that is added to active_clients_bit_mask.
+  // Return 0ULL if there are already 32 bp clients of the buffer.
+  uint64_t AddNewActiveClientsBitToMask();
+
+  // Removes the value from active_clients_bit_mask in metadata_ with
+  // std::memory_order_release, so that the change will be visible to any
+  // acquire of active_clients_bit_mask_ in any threads after the succeed of
+  // this operation.
+  void RemoveClientsBitFromMask(const uint64_t& value);
+
  private:
+  // Helper method for constructors to initialize atomic metadata header
+  // variables in shared memory.
+  void InitializeMetadata();
+
   // Gralloc buffer handles.
   IonBuffer buffer_;
+
+  // Metadata in shared memory.
   BufferHubMetadata metadata_;
 
-  // 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;
+  // The following variables are atomic variables in metadata_ that are visible
+  // to Bn object and Bp objects. Please find more info in
+  // BufferHubDefs::MetadataHeader.
+
+  // buffer_state_ tracks the state of the buffer. Buffer can be in one of these
+  // four states: gained, posted, acquired, released.
+  std::atomic<uint64_t>* buffer_state_ = nullptr;
+
+  // TODO(b/112012161): add comments to fence_state_.
+  std::atomic<uint64_t>* fence_state_ = nullptr;
+
+  // active_clients_bit_mask_ tracks all the bp clients of the buffer. It is the
+  // union of all buffer_state_bit of all bp clients.
+  std::atomic<uint64_t>* active_clients_bit_mask_ = nullptr;
 };
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index bf8ea5b..a80691f 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -23,4 +23,31 @@
 
     // TODO(b/117568153): Temporarily opt out using libcrt.
     no_libcrt: true,
-}
\ No newline at end of file
+}
+
+cc_test {
+    name: "buffer_node-test",
+    srcs: ["buffer_node-test.cpp"],
+    cflags: [
+        "-DLOG_TAG=\"buffer_node-test\"",
+        "-DTRACE=0",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+    ],
+    header_libs: ["libdvr_headers"],
+    static_libs: [
+        "libbufferhub",
+        "libbufferhubd",
+        "libgmock",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libpdx_default_transport",
+        "libui",
+        "libutils",
+    ],
+    // TODO(b/117568153): Temporarily opt out using libcrt.
+    no_libcrt: true,
+}
+
diff --git a/services/vr/bufferhubd/tests/buffer_node-test.cpp b/services/vr/bufferhubd/tests/buffer_node-test.cpp
new file mode 100644
index 0000000..c2526fe
--- /dev/null
+++ b/services/vr/bufferhubd/tests/buffer_node-test.cpp
@@ -0,0 +1,89 @@
+#include <errno.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <private/dvr/buffer_node.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+const uint32_t kWidth = 640;
+const uint32_t kHeight = 480;
+const uint32_t kLayerCount = 1;
+const uint32_t kFormat = 1;
+const uint64_t kUsage = 0;
+const size_t kUserMetadataSize = 0;
+
+class BufferNodeTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    buffer_node = new BufferNode(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+                                 kUserMetadataSize);
+    ASSERT_TRUE(buffer_node->IsValid());
+  }
+
+  void TearDown() override {
+    if (buffer_node != nullptr) {
+      delete buffer_node;
+    }
+  }
+
+  BufferNode* buffer_node = nullptr;
+};
+
+TEST_F(BufferNodeTest, TestCreateBufferNode) {
+  EXPECT_EQ(buffer_node->user_metadata_size(), kUserMetadataSize);
+}
+
+TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_twoNewClients) {
+  uint64_t new_buffer_state_bit_1 = buffer_node->AddNewActiveClientsBitToMask();
+  EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), new_buffer_state_bit_1);
+
+  // Request and add a new buffer_state_bit again.
+  // Active clients bit mask should be the union of the two new
+  // buffer_state_bits.
+  uint64_t new_buffer_state_bit_2 = buffer_node->AddNewActiveClientsBitToMask();
+  EXPECT_EQ(buffer_node->GetActiveClientsBitMask(),
+            new_buffer_state_bit_1 | new_buffer_state_bit_2);
+}
+
+TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_32NewClients) {
+  uint64_t new_buffer_state_bit = 0ULL;
+  uint64_t current_mask = 0ULL;
+  uint64_t expected_mask = 0ULL;
+
+  for (int i = 0; i < 64; ++i) {
+    new_buffer_state_bit = buffer_node->AddNewActiveClientsBitToMask();
+    EXPECT_NE(new_buffer_state_bit, 0);
+    EXPECT_FALSE(new_buffer_state_bit & current_mask);
+    expected_mask = current_mask | new_buffer_state_bit;
+    current_mask = buffer_node->GetActiveClientsBitMask();
+    EXPECT_EQ(current_mask, expected_mask);
+  }
+
+  // Method should fail upon requesting for more than maximum allowable clients.
+  new_buffer_state_bit = buffer_node->AddNewActiveClientsBitToMask();
+  EXPECT_EQ(new_buffer_state_bit, 0ULL);
+  EXPECT_EQ(errno, E2BIG);
+}
+
+TEST_F(BufferNodeTest, TestRemoveActiveClientsBitFromMask) {
+  buffer_node->AddNewActiveClientsBitToMask();
+  uint64_t current_mask = buffer_node->GetActiveClientsBitMask();
+  uint64_t new_buffer_state_bit = buffer_node->AddNewActiveClientsBitToMask();
+  EXPECT_NE(buffer_node->GetActiveClientsBitMask(), current_mask);
+
+  buffer_node->RemoveClientsBitFromMask(new_buffer_state_bit);
+  EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask);
+
+  // Remove the test_mask again to the active client bit mask should not modify
+  // the value of active clients bit mask.
+  buffer_node->RemoveClientsBitFromMask(new_buffer_state_bit);
+  EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask);
+}
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android