Merge "Android doesn't support Pixmaps"
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/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 3328ad7..e53f7fd 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -68,7 +68,9 @@
 }
 
 void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
-                               const std::string appPref, bool developerOptIn) {
+                               const std::string appPref, bool developerOptIn,
+                               const int rulesFd, const long rulesOffset,
+                               const long rulesLength) {
     if (!mAnglePath.empty()) {
         ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
               path.c_str());
@@ -94,6 +96,13 @@
     }
 
     mAngleDeveloperOptIn = developerOptIn;
+
+    ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd);
+    mAngleRulesFd = rulesFd;
+    ALOGV("setting ANGLE rules offset to '%li'", rulesOffset);
+    mAngleRulesOffset = rulesOffset;
+    ALOGV("setting ANGLE rules length to '%li'", rulesLength);
+    mAngleRulesLength = rulesLength;
 }
 
 void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
@@ -124,6 +133,18 @@
     return mAngleAppPref.c_str();
 }
 
+int GraphicsEnv::getAngleRulesFd() {
+    return mAngleRulesFd;
+}
+
+long GraphicsEnv::getAngleRulesOffset() {
+    return mAngleRulesOffset;
+}
+
+long GraphicsEnv::getAngleRulesLength() {
+    return mAngleRulesLength;
+}
+
 const std::string GraphicsEnv::getLayerPaths(){
     return mLayerPaths;
 }
@@ -192,6 +213,15 @@
 const char* android_getAngleAppPref() {
     return android::GraphicsEnv::getInstance().getAngleAppPref();
 }
+int android_getAngleRulesFd() {
+   return android::GraphicsEnv::getInstance().getAngleRulesFd();
+}
+long android_getAngleRulesOffset() {
+   return android::GraphicsEnv::getInstance().getAngleRulesOffset();
+}
+long android_getAngleRulesLength() {
+   return android::GraphicsEnv::getInstance().getAngleRulesLength();
+}
 const char* android_getLayerPaths() {
     return android::GraphicsEnv::getInstance().getLayerPaths().c_str();
 }
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 1783429..404823a 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -45,11 +45,15 @@
     // in the search path must have a '!' after the zip filename, e.g.
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
     void setAngleInfo(const std::string path, const std::string appName, const std::string appPref,
-                      bool devOptIn);
+                      bool devOptIn, const int rulesFd, const long rulesOffset,
+                      const long rulesLength);
     android_namespace_t* getAngleNamespace();
     const char* getAngleAppName();
     const char* getAngleAppPref();
     bool getAngleDeveloperOptIn();
+    int getAngleRulesFd();
+    long getAngleRulesOffset();
+    long getAngleRulesLength();
 
     void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
     NativeLoaderNamespace* getAppNamespace();
@@ -66,6 +70,9 @@
     std::string mAngleAppName;
     std::string mAngleAppPref;
     bool mAngleDeveloperOptIn;
+    int mAngleRulesFd;
+    long mAngleRulesOffset;
+    long mAngleRulesLength;
     std::string mDebugLayers;
     std::string mLayerPaths;
     android_namespace_t* mDriverNamespace = nullptr;
@@ -92,6 +99,9 @@
     const char* android_getAngleAppName();
     const char* android_getAngleAppPref();
     bool android_getAngleDeveloperOptIn();
+    int android_getAngleRulesFd();
+    long android_getAngleRulesOffset();
+    long android_getAngleRulesLength();
     const char* android_getLayerPaths();
     const char* android_getDebugLayers();
 }
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/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 31712fc..6f792ec 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -51,6 +51,14 @@
   typedef bool (*fpANGLEUseForApplication)(const char* appName, const char* deviceMfr,
                                            const char* deviceModel, ANGLEPreference developerOption,
                                            ANGLEPreference appPreference);
+
+  // TODO(ianelliott@): Get this from an ANGLE header:
+  typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse);
+
+  // TODO(ianelliott@): Get this from an ANGLE header:
+  typedef bool (*fpAndroidUseANGLEForApplication)(int fd, long offset, long length,
+                                                  const char* appName, const char* deviceMfr,
+                                                  const char* deviceModel);
 }
 
 // ----------------------------------------------------------------------------
@@ -511,7 +519,7 @@
     return ANGLE_NO_PREFERENCE;
 }
 
-static void* load_angle(const char* kind, egl_connection_t* cnx) {
+static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) {
     // Only attempt to load ANGLE libs
     if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0)
         return nullptr;
@@ -520,10 +528,12 @@
     std::string name;
     char prop[PROPERTY_VALUE_MAX];
 
-    android_namespace_t* ns = android_getAngleNamespace();
     const char* app_name = android_getAngleAppName();
     const char* app_pref = android_getAngleAppPref();
     bool developer_opt_in = android_getAngleDeveloperOptIn();
+    const int rules_fd = android_getAngleRulesFd();
+    const long rules_offset = android_getAngleRulesOffset();
+    const long rules_length = android_getAngleRulesLength();
 
     // Determine whether or not to use ANGLE:
     ANGLEPreference developer_option = developer_opt_in ? ANGLE_PREFER_ANGLE : ANGLE_NO_PREFERENCE;
@@ -539,21 +549,51 @@
         char model[PROPERTY_VALUE_MAX];
         property_get("ro.product.manufacturer", manufacturer, "UNSET");
         property_get("ro.product.model", model, "UNSET");
-        ANGLEPreference app_preference = getAnglePref(android_getAngleAppPref());
-
         so = load_angle_from_namespace("feature_support", ns);
         if (so) {
             ALOGV("Temporarily loaded ANGLE's opt-in/out logic from namespace");
-            fpANGLEUseForApplication fp =
-                    (fpANGLEUseForApplication)dlsym(so, "ANGLEUseForApplication");
-            if (fp) {
-                use_angle = (fp)(app_name_str.c_str(), manufacturer, model, developer_option,
-                                 app_preference);
-                ALOGV("Result of opt-in/out logic is %s", use_angle ? "true" : "false");
+            bool use_version0_API = false;
+            bool use_version1_API = false;
+            fpANGLEGetUtilityAPI ANGLEGetUtilityAPI =
+                    (fpANGLEGetUtilityAPI)dlsym(so, "ANGLEGetUtilityAPI");
+            if (ANGLEGetUtilityAPI) {
+                unsigned int versionToUse = 1;
+                if ((ANGLEGetUtilityAPI)(&versionToUse)) {
+                    if (versionToUse == 1) {
+                        use_version1_API = true;
+                    } else {
+                        use_version0_API = true;
+                    }
+                }
             } else {
-                ALOGW("Cannot find ANGLEUseForApplication in library");
+                use_version0_API = true;
             }
-
+            if (use_version1_API) {
+                // Use the new version 1 API to determine if the
+                // application should use the ANGLE or the native driver.
+                fpAndroidUseANGLEForApplication AndroidUseANGLEForApplication =
+                        (fpAndroidUseANGLEForApplication)dlsym(so, "AndroidUseANGLEForApplication");
+                if (AndroidUseANGLEForApplication) {
+                    use_angle = (AndroidUseANGLEForApplication)(rules_fd, rules_offset,
+                                                                rules_length, app_name_str.c_str(),
+                                                                manufacturer, model);
+                } else {
+                    ALOGW("Cannot find AndroidUseANGLEForApplication in library");
+                }
+            } else if (use_version0_API) {
+                // Use the old version 0 API to determine if the
+                // application should use the ANGLE or the native driver.
+                fpANGLEUseForApplication ANGLEUseForApplication =
+                        (fpANGLEUseForApplication)dlsym(so, "ANGLEUseForApplication");
+                if (ANGLEUseForApplication) {
+                    ANGLEPreference app_preference = getAnglePref(android_getAngleAppPref());
+                    use_angle = (ANGLEUseForApplication)(app_name_str.c_str(), manufacturer, model,
+                                                         developer_option, app_preference);
+                    ALOGV("Result of opt-in/out logic is %s", use_angle ? "true" : "false");
+                } else {
+                    ALOGW("Cannot find ANGLEUseForApplication in library");
+                }
+            }
             ALOGV("Close temporarily-loaded ANGLE opt-in/out logic");
             dlclose(so);
             so = nullptr;
@@ -620,7 +660,10 @@
     ATRACE_CALL();
 
     void* dso = nullptr;
-    dso = load_angle(kind, cnx);
+    android_namespace_t* ns = android_getAngleNamespace();
+    if (ns) {
+        dso = load_angle(kind, ns, cnx);
+    }
 #ifndef __ANDROID_VNDK__
     if (!dso) {
         android_namespace_t* ns = android_getDriverNamespace();
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 38104c4..2cad986 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -852,7 +852,8 @@
         return true;
     }
 
-    addMonitoringTargetsLocked(inputTargets);
+    // Add monitor channels from event's or focused display.
+    addMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
 
     // Dispatch the key.
     dispatchEventLocked(currentTime, entry, inputTargets);
@@ -919,7 +920,8 @@
         return true;
     }
 
-    addMonitoringTargetsLocked(inputTargets);
+    // Add monitor channels from event's or focused display.
+    addMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
 
     // Dispatch the motion.
     if (conflictingPointerActions) {
@@ -1665,17 +1667,29 @@
     target.pointerIds = pointerIds;
 }
 
-void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {
-    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-        inputTargets.push();
+void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets,
+        int32_t displayId) {
+    std::unordered_map<int32_t, Vector<sp<InputChannel>>>::const_iterator it =
+            mMonitoringChannelsByDisplay.find(displayId);
 
-        InputTarget& target = inputTargets.editTop();
-        target.inputChannel = mMonitoringChannels[i];
-        target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-        target.xOffset = 0;
-        target.yOffset = 0;
-        target.pointerIds.clear();
-        target.scaleFactor = 1.0f;
+    if (it != mMonitoringChannelsByDisplay.end()) {
+        const Vector<sp<InputChannel>>& monitoringChannels = it->second;
+        const size_t numChannels = monitoringChannels.size();
+        for (size_t i = 0; i < numChannels; i++) {
+            inputTargets.push();
+
+            InputTarget& target = inputTargets.editTop();
+            target.inputChannel = monitoringChannels[i];
+            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+            target.xOffset = 0;
+            target.yOffset = 0;
+            target.pointerIds.clear();
+            target.scaleFactor = 1.0f;
+        }
+    } else {
+        // If there is no monitor channel registered or all monitor channel unregistered,
+        // the display can't detect the extra system gesture by a copy of input events.
+        ALOGW("There is no monitor channel found in display=%" PRId32, displayId);
     }
 }
 
@@ -2294,8 +2308,12 @@
 
 void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
         const CancelationOptions& options) {
-    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-        synthesizeCancelationEventsForInputChannelLocked(mMonitoringChannels[i], options);
+    for (auto& it : mMonitoringChannelsByDisplay) {
+        const Vector<sp<InputChannel>>& monitoringChannels = it.second;
+        const size_t numChannels = monitoringChannels.size();
+        for (size_t i = 0; i < numChannels; i++) {
+            synthesizeCancelationEventsForInputChannelLocked(monitoringChannels[i], options);
+        }
     }
 }
 
@@ -3486,12 +3504,16 @@
         dump += INDENT "Displays: <none>\n";
     }
 
-    if (!mMonitoringChannels.isEmpty()) {
-        dump += INDENT "MonitoringChannels:\n";
-        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-            const sp<InputChannel>& channel = mMonitoringChannels[i];
-            dump += StringPrintf(INDENT2 "%zu: '%s'\n", i, channel->getName().c_str());
-        }
+    if (!mMonitoringChannelsByDisplay.empty()) {
+       for (auto& it : mMonitoringChannelsByDisplay) {
+            const Vector<sp<InputChannel>>& monitoringChannels = it.second;
+            dump += INDENT "MonitoringChannels in Display %d:\n";
+            const size_t numChannels = monitoringChannels.size();
+            for (size_t i = 0; i < numChannels; i++) {
+                const sp<InputChannel>& channel = monitoringChannels[i];
+                dump += StringPrintf(INDENT2 "%zu: '%s'\n", i, channel->getName().c_str());
+            }
+       }
     } else {
         dump += INDENT "MonitoringChannels: <none>\n";
     }
@@ -3609,10 +3631,10 @@
 }
 
 status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+        const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) {
 #if DEBUG_REGISTRATION
-    ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().c_str(),
-            toString(monitor));
+    ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
+            inputChannel->getName().c_str(), displayId);
 #endif
 
     { // acquire lock
@@ -3624,13 +3646,20 @@
             return BAD_VALUE;
         }
 
+        // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
+        // treat inputChannel as monitor channel for displayId.
+        bool monitor = inputWindowHandle == nullptr && displayId != ADISPLAY_ID_NONE;
+
         sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
 
         int fd = inputChannel->getFd();
         mConnectionsByFd.add(fd, connection);
 
+        // Store monitor channel by displayId.
         if (monitor) {
-            mMonitoringChannels.push(inputChannel);
+            Vector<sp<InputChannel>>& monitoringChannels =
+                    mMonitoringChannelsByDisplay[displayId];
+            monitoringChannels.push(inputChannel);
         }
 
         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
@@ -3687,11 +3716,21 @@
 }
 
 void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
-    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-         if (mMonitoringChannels[i] == inputChannel) {
-             mMonitoringChannels.removeAt(i);
-             break;
-         }
+    for (auto it = mMonitoringChannelsByDisplay.begin();
+            it != mMonitoringChannelsByDisplay.end(); ) {
+        Vector<sp<InputChannel>>& monitoringChannels = it->second;
+        const size_t numChannels = monitoringChannels.size();
+        for (size_t i = 0; i < numChannels; i++) {
+             if (monitoringChannels[i] == inputChannel) {
+                 monitoringChannels.removeAt(i);
+                 break;
+             }
+        }
+        if (monitoringChannels.empty()) {
+            it = mMonitoringChannelsByDisplay.erase(it);
+        } else {
+            ++it;
+        }
     }
 }
 
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index aedad2f..5efb2fa 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -346,13 +346,19 @@
     virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
             const sp<InputChannel>& toChannel) = 0;
 
-    /* Registers or unregister input channels that may be used as targets for input events.
-     * If monitor is true, the channel will receive a copy of all input events.
+    /* Registers input channels that may be used as targets for input events.
+     * If inputWindowHandle is null, and displayId is not ADISPLAY_ID_NONE,
+     * the channel will receive a copy of all input events form the specific displayId.
      *
-     * These methods may be called on any thread (usually by the input manager).
+     * This method may be called on any thread (usually by the input manager).
      */
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
+            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) = 0;
+
+    /* Unregister input channels that will no longer receive input events.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
 };
 
@@ -407,7 +413,7 @@
             const sp<InputChannel>& toChannel);
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
 private:
@@ -914,8 +920,8 @@
 
     ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
 
-    // Input channels that will receive a copy of all input events.
-    Vector<sp<InputChannel> > mMonitoringChannels;
+    // Input channels that will receive a copy of all input events sent to the provided display.
+    std::unordered_map<int32_t, Vector<sp<InputChannel>>> mMonitoringChannelsByDisplay;
 
     // Event injection and synchronization.
     Condition mInjectionResultAvailableCondition;
@@ -1070,7 +1076,7 @@
 
     void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
             int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets);
-    void addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets);
+    void addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets, int32_t displayId);
 
     void pokeUserActivityLocked(const EventEntry* eventEntry);
     bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index f75b0b6..c6eaf9f 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -278,68 +278,8 @@
     }
 };
 
-class FakeWindowHandle : public InputWindowHandle {
+class FakeInputReceiver {
 public:
-    static const int32_t WIDTH = 600;
-    static const int32_t HEIGHT = 800;
-
-    FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
-        const sp<InputDispatcher>& dispatcher, const std::string name) :
-            InputWindowHandle(inputApplicationHandle), mDispatcher(dispatcher),
-            mName(name), mFocused(false), mDisplayId(ADISPLAY_ID_DEFAULT) {
-        InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
-        mConsumer = new InputConsumer(mClientChannel);
-        mDispatcher->registerInputChannel(mServerChannel, this, false);
-    }
-
-    virtual ~FakeWindowHandle() {
-        mDispatcher->unregisterInputChannel(mServerChannel);
-        mServerChannel.clear();
-        mClientChannel.clear();
-        mDispatcher.clear();
-
-        if (mConsumer != nullptr) {
-            delete mConsumer;
-        }
-    }
-
-    virtual bool updateInfo() {
-        if (!mInfo) {
-            mInfo = new InputWindowInfo();
-        }
-        mInfo->inputChannel = mServerChannel;
-        mInfo->name = mName;
-        mInfo->layoutParamsFlags = 0;
-        mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
-        mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
-        mInfo->frameLeft = 0;
-        mInfo->frameTop = 0;
-        mInfo->frameRight = WIDTH;
-        mInfo->frameBottom = HEIGHT;
-        mInfo->scaleFactor = 1.0;
-        mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
-        mInfo->visible = true;
-        mInfo->canReceiveKeys = true;
-        mInfo->hasFocus = mFocused;
-        mInfo->hasWallpaper = false;
-        mInfo->paused = false;
-        mInfo->layer = 0;
-        mInfo->ownerPid = INJECTOR_PID;
-        mInfo->ownerUid = INJECTOR_UID;
-        mInfo->inputFeatures = 0;
-        mInfo->displayId = mDisplayId;
-
-        return true;
-    }
-
-    void setFocus() {
-        mFocused = true;
-    }
-
-    void setDisplayId(int32_t displayId) {
-        mDisplayId = displayId;
-    }
-
     void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
             int32_t expectedFlags = 0) {
         uint32_t consumeSeq;
@@ -376,7 +316,7 @@
         ASSERT_EQ(expectedFlags, flags)
                 << mName.c_str() << ": event flags should be the same as expected.";
 
-        status = mConsumer->sendFinishedSignal(consumeSeq, true /*handled*/);
+        status = mConsumer->sendFinishedSignal(consumeSeq, handled());
         ASSERT_EQ(OK, status)
                 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
     }
@@ -391,17 +331,94 @@
                 << ": should not have received any events, so consume(..) should not return OK.";
     }
 
-    private:
+protected:
+        explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
+            const std::string name, int32_t displayId) :
+                mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
+            InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+            mConsumer = new InputConsumer(mClientChannel);
+        }
+
+        virtual ~FakeInputReceiver() {
+        }
+
+        // return true if the event has been handled.
+        virtual bool handled() {
+            return false;
+        }
+
         sp<InputDispatcher> mDispatcher;
         sp<InputChannel> mServerChannel, mClientChannel;
         InputConsumer *mConsumer;
         PreallocatedInputEventFactory mEventFactory;
 
         std::string mName;
-        bool mFocused;
         int32_t mDisplayId;
 };
 
+class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
+public:
+    static const int32_t WIDTH = 600;
+    static const int32_t HEIGHT = 800;
+
+    FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+        const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
+            InputWindowHandle(inputApplicationHandle),
+            FakeInputReceiver(dispatcher, name, displayId),
+            mFocused(false) {
+            mDispatcher->registerInputChannel(mServerChannel, this, displayId);
+    }
+
+    virtual bool updateInfo() {
+        if (!mInfo) {
+            mInfo = new InputWindowInfo();
+        }
+        mInfo->inputChannel = mServerChannel;
+        mInfo->name = mName;
+        mInfo->layoutParamsFlags = 0;
+        mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
+        mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
+        mInfo->frameLeft = 0;
+        mInfo->frameTop = 0;
+        mInfo->frameRight = WIDTH;
+        mInfo->frameBottom = HEIGHT;
+        mInfo->scaleFactor = 1.0;
+        mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
+        mInfo->visible = true;
+        mInfo->canReceiveKeys = true;
+        mInfo->hasFocus = mFocused;
+        mInfo->hasWallpaper = false;
+        mInfo->paused = false;
+        mInfo->layer = 0;
+        mInfo->ownerPid = INJECTOR_PID;
+        mInfo->ownerUid = INJECTOR_UID;
+        mInfo->inputFeatures = 0;
+        mInfo->displayId = mDisplayId;
+
+        return true;
+    }
+
+    void setFocus() {
+        mFocused = true;
+    }
+
+    void assertNoEvents() {
+        uint32_t consumeSeq;
+        InputEvent* event;
+        status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
+            &consumeSeq, &event);
+        ASSERT_NE(OK, status)
+                << mName.c_str()
+                << ": should not have received any events, so consume(..) should not return OK.";
+    }
+protected:
+    virtual bool handled() {
+        return true;
+    }
+
+    bool mFocused;
+};
+
 static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
         int32_t displayId = ADISPLAY_ID_NONE) {
     KeyEvent event;
@@ -419,7 +436,8 @@
             INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
 }
 
-static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t displayId) {
+static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
+        int32_t displayId) {
     MotionEvent event;
     PointerProperties pointerProperties[1];
     PointerCoords pointerCoords[1];
@@ -434,7 +452,7 @@
 
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid motion down event.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, displayId,
+    event.initialize(DEVICE_ID, source, displayId,
             AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
             AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
             /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
@@ -449,13 +467,15 @@
 
 TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
     sp<FakeApplicationHandle> application = new FakeApplicationHandle();
-    sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window");
+    sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
+            ADISPLAY_ID_DEFAULT);
 
     Vector<sp<InputWindowHandle>> inputWindowHandles;
     inputWindowHandles.add(window);
 
     mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
 
     // Window should receive motion event.
@@ -465,15 +485,18 @@
 // The foreground window should receive the first touch down event.
 TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
     sp<FakeApplicationHandle> application = new FakeApplicationHandle();
-    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
-    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
+    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
+            ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
+            ADISPLAY_ID_DEFAULT);
 
     Vector<sp<InputWindowHandle>> inputWindowHandles;
     inputWindowHandles.add(windowTop);
     inputWindowHandles.add(windowSecond);
 
     mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
 
     // Top window should receive the touch down event. Second window should not receive anything.
@@ -483,8 +506,10 @@
 
 TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
     sp<FakeApplicationHandle> application = new FakeApplicationHandle();
-    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
-    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
+    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
+            ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
+            ADISPLAY_ID_DEFAULT);
 
     // Set focus application.
     mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -504,61 +529,70 @@
     windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 }
 
-TEST_F(InputDispatcherTest, SetInputWindow_MultiDisplayTouch) {
-    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
-    sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
-    sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application, mDispatcher, "D_2");
+/* Test InputDispatcher for MultiDisplay */
+class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
+public:
+    static constexpr int32_t SECOND_DISPLAY_ID = 1;
+    virtual void SetUp() {
+        InputDispatcherTest::SetUp();
 
-    // Test the primary display touch down.
-    Vector<sp<InputWindowHandle>> inputWindowHandles;
-    inputWindowHandles.push(windowInPrimary);
+        application1 = new FakeApplicationHandle();
+        windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
+                ADISPLAY_ID_DEFAULT);
+        Vector<sp<InputWindowHandle>> inputWindowHandles;
+        inputWindowHandles.push(windowInPrimary);
+        // Set focus window for primary display, but focused display would be second one.
+        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
+        windowInPrimary->setFocus();
+        mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
 
-    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+        application2 = new FakeApplicationHandle();
+        windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
+                SECOND_DISPLAY_ID);
+        // Set focus to second display window.
+        Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
+        inputWindowHandles_Second.push(windowInSecondary);
+        // Set focus display to second one.
+        mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
+        // Set focus window for second display.
+        mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
+        windowInSecondary->setFocus();
+        mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
+    }
+
+    virtual void TearDown() {
+        InputDispatcherTest::TearDown();
+
+        application1.clear();
+        windowInPrimary.clear();
+        application2.clear();
+        windowInSecondary.clear();
+    }
+
+protected:
+    sp<FakeApplicationHandle> application1;
+    sp<FakeWindowHandle> windowInPrimary;
+    sp<FakeApplicationHandle> application2;
+    sp<FakeWindowHandle> windowInSecondary;
+};
+
+TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
+    // Test touch down on primary display.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
     windowInSecondary->assertNoEvents();
 
-    // Test the second display touch down.
-    constexpr int32_t SECOND_DISPLAY_ID = 1;
-    windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
-    Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
-    inputWindowHandles_Second.push(windowInSecondary);
-
-    mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, SECOND_DISPLAY_ID))
+    // Test touch down on second display.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
             << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     windowInPrimary->assertNoEvents();
     windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
 }
 
-TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
-    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
-    sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
-    sp<FakeApplicationHandle> application2 = new FakeApplicationHandle();
-    sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2");
-
-    constexpr int32_t SECOND_DISPLAY_ID = 1;
-
-    // Set focus to primary display window.
-    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
-    windowInPrimary->setFocus();
-
-    // Set focus to second display window.
-    mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
-    mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
-    windowInSecondary->setFocus();
-
-    // Update all windows per displays.
-    Vector<sp<InputWindowHandle>> inputWindowHandles;
-    inputWindowHandles.push(windowInPrimary);
-    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
-
-    windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
-    Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
-    inputWindowHandles_Second.push(windowInSecondary);
-    mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
-
+TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
     // Test inject a key down with display id specified.
     ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
             << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
@@ -572,8 +606,8 @@
     windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 
     // Remove secondary display.
-    inputWindowHandles_Second.clear();
-    mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
+    Vector<sp<InputWindowHandle>> noWindows;
+    mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
 
     // Expect old focus should receive a cancel event.
     windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
@@ -586,4 +620,66 @@
     windowInSecondary->assertNoEvents();
 }
 
+class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
+public:
+    FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
+            int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
+        mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
+    }
+};
+
+// Test per-display input monitors for motion event.
+TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
+    sp<FakeMonitorReceiver> monitorInPrimary =
+            new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    sp<FakeMonitorReceiver> monitorInSecondary =
+            new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
+
+    // Test touch down on primary display.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+    monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+    windowInSecondary->assertNoEvents();
+    monitorInSecondary->assertNoEvents();
+
+    // Test touch down on second display.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    windowInPrimary->assertNoEvents();
+    monitorInPrimary->assertNoEvents();
+    windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
+    monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
+
+    // Test inject a non-pointer motion event.
+    // If specific a display, it will dispatch to the focused window of particular display,
+    // or it will dispatch to the focused window of focused display.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+        AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    windowInPrimary->assertNoEvents();
+    monitorInPrimary->assertNoEvents();
+    windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
+    monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
+}
+
+// Test per-display input monitors for key event.
+TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
+    //Input monitor per display.
+    sp<FakeMonitorReceiver> monitorInPrimary =
+            new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+    sp<FakeMonitorReceiver> monitorInSecondary =
+            new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
+
+    // Test inject a key down.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
+            << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    windowInPrimary->assertNoEvents();
+    monitorInPrimary->assertNoEvents();
+    windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+    monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+}
+
 } // namespace android
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