Merge "vkjson: report VkPhysicalDeviceDriverPropertiesKHR"
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 73098f8..28c7658 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -361,12 +361,11 @@
         }
 
         std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
-        if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
-          return PatchoatBootImage(isa_path, isa);
-        } else {
+        if (access(preopted_boot_art_path.c_str(), F_OK) != 0) {
           // No preopted boot image. Try to compile.
           return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
         }
+        return true;
     }
 
     static bool CreatePath(const std::string& path) {
@@ -431,29 +430,6 @@
         CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
     }
 
-    bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
-        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
-
-        std::vector<std::string> cmd;
-        cmd.push_back("/system/bin/patchoat");
-
-        cmd.push_back("--input-image-location=/system/framework/boot.art");
-        cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
-
-        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
-
-        int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
-                                                          art::GetImageMaxBaseAddressDelta());
-        cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
-
-        std::string error_msg;
-        bool result = Exec(cmd, &error_msg);
-        if (!result) {
-            LOG(ERROR) << "Could not generate boot image: " << error_msg;
-        }
-        return result;
-    }
-
     bool Dex2oatBootImage(const std::string& boot_cp,
                           const std::string& art_path,
                           const std::string& oat_path,
diff --git a/services/inputflinger/InputApplication.h b/include/input/InputApplication.h
similarity index 100%
rename from services/inputflinger/InputApplication.h
rename to include/input/InputApplication.h
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 5fd86b4..4782c9b 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -37,6 +37,7 @@
 #include <utils/BitSet.h>
 
 namespace android {
+class Parcel;
 
 /*
  * Intermediate representation used to send input events and related signals.
@@ -143,6 +144,7 @@
     virtual ~InputChannel();
 
 public:
+    InputChannel() = default;
     InputChannel(const std::string& name, int fd);
 
     /* Creates a pair of input channels.
@@ -183,9 +185,14 @@
     /* Returns a new object that has a duplicate of this channel's fd. */
     sp<InputChannel> dup() const;
 
+    status_t write(Parcel& out) const;
+    status_t read(const Parcel& from);
+
 private:
+    void setFd(int fd);
+
     std::string mName;
-    int mFd;
+    int mFd = -1;
 };
 
 /*
diff --git a/services/inputflinger/InputWindow.h b/include/input/InputWindow.h
similarity index 97%
rename from services/inputflinger/InputWindow.h
rename to include/input/InputWindow.h
index c481853..7c284dd 100644
--- a/services/inputflinger/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -27,7 +27,7 @@
 #include "InputApplication.h"
 
 namespace android {
-
+class Parcel;
 
 /*
  * Describes the properties of a window that can receive input.
@@ -151,6 +151,9 @@
     bool supportsSplitTouch() const;
 
     bool overlaps(const InputWindowInfo* other) const;
+
+    status_t write(Parcel& output) const;
+    static InputWindowInfo read(const Parcel& from);
 };
 
 
@@ -168,9 +171,7 @@
         return mInfo;
     }
 
-    inline sp<InputChannel> getInputChannel() const {
-        return mInfo ? mInfo->inputChannel : nullptr;
-    }
+    sp<InputChannel> getInputChannel() const;
 
     inline std::string getName() const {
         return mInfo ? mInfo->name : "<invalid>";
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 02064c6..7ecadf8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -44,6 +44,7 @@
         "libgui",
         "libhidlbase",
         "libhidltransport",
+        "libinput",
         "libui",
         "libutils",
         "libnativewindow"
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index a2d6a8a..72558a6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -47,11 +47,14 @@
                 "InputTransport.cpp",
                 "VelocityControl.cpp",
                 "VelocityTracker.cpp",
+                "InputApplication.cpp",
+                "InputWindow.cpp"
             ],
 
             shared_libs: [
                 "libutils",
                 "libbinder",
+                "libui"
             ],
 
             sanitize: {
diff --git a/services/inputflinger/InputApplication.cpp b/libs/input/InputApplication.cpp
similarity index 96%
rename from services/inputflinger/InputApplication.cpp
rename to libs/input/InputApplication.cpp
index c56dfe6..a0d1668 100644
--- a/services/inputflinger/InputApplication.cpp
+++ b/libs/input/InputApplication.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "InputApplication"
 
-#include "InputApplication.h"
+#include <input/InputApplication.h>
 
 #include <android/log.h>
 
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 770d483..32444f9 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -30,6 +30,7 @@
 #include <cutils/properties.h>
 #include <log/log.h>
 
+#include <binder/Parcel.h>
 #include <input/InputTransport.h>
 
 namespace android {
@@ -100,15 +101,13 @@
 // --- InputChannel ---
 
 InputChannel::InputChannel(const std::string& name, int fd) :
-        mName(name), mFd(fd) {
+        mName(name) {
 #if DEBUG_CHANNEL_LIFECYCLE
     ALOGD("Input channel constructed: name='%s', fd=%d",
             mName.c_str(), fd);
 #endif
 
-    int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
-    LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
-            "non-blocking.  errno=%d", mName.c_str(), errno);
+    setFd(fd);
 }
 
 InputChannel::~InputChannel() {
@@ -120,6 +119,18 @@
     ::close(mFd);
 }
 
+void InputChannel::setFd(int fd) {
+    if (mFd > 0) {
+        ::close(mFd);
+    }
+    mFd = fd;
+    if (mFd > 0) {
+        int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
+        LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
+            "non-blocking.  errno=%d", mName.c_str(), errno);
+    }
+}
+
 status_t InputChannel::openInputChannelPair(const std::string& name,
         sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
     int sockets[2];
@@ -230,6 +241,31 @@
 }
 
 
+status_t InputChannel::write(Parcel& out) const {
+    status_t s = out.writeString8(String8(getName().c_str()));
+
+    if (s != OK) {
+        return s;
+    }
+
+    s = out.writeDupFileDescriptor(getFd());
+
+    return s;
+}
+
+status_t InputChannel::read(const Parcel& from) {
+    mName = from.readString8();
+
+    int rawFd = from.readFileDescriptor();
+    setFd(::dup(rawFd));
+
+    if (mFd < 0) {
+        return BAD_VALUE;
+    }
+
+    return OK;
+}
+
 // --- InputPublisher ---
 
 InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
new file mode 100644
index 0000000..f94faba
--- /dev/null
+++ b/libs/input/InputWindow.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+#include <log/log.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+namespace android {
+
+// --- InputWindowInfo ---
+void InputWindowInfo::addTouchableRegion(const Rect& region) {
+    touchableRegion.orSelf(region);
+}
+
+bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+    return touchableRegion.contains(x,y);
+}
+
+bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
+    return x >= frameLeft && x < frameRight
+            && y >= frameTop && y < frameBottom;
+}
+
+bool InputWindowInfo::isTrustedOverlay() const {
+    return layoutParamsType == TYPE_INPUT_METHOD
+            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+            || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
+            || layoutParamsType == TYPE_STATUS_BAR
+            || layoutParamsType == TYPE_NAVIGATION_BAR
+            || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
+            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
+            || layoutParamsType == TYPE_DOCK_DIVIDER
+            || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
+            || layoutParamsType == TYPE_INPUT_CONSUMER;
+}
+
+bool InputWindowInfo::supportsSplitTouch() const {
+    return layoutParamsFlags & FLAG_SPLIT_TOUCH;
+}
+
+bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
+    return frameLeft < other->frameRight && frameRight > other->frameLeft
+            && frameTop < other->frameBottom && frameBottom > other->frameTop;
+}
+
+status_t InputWindowInfo::write(Parcel& output) const {
+    if (inputChannel == nullptr) {
+        output.writeInt32(0);
+        return OK;
+    }
+    output.writeInt32(1);
+    status_t s = inputChannel->write(output);
+    if (s != OK) return s;
+
+    output.writeString8(String8(name.c_str()));
+    output.writeInt32(layoutParamsFlags);
+    output.writeInt32(layoutParamsType);
+    output.writeInt64(dispatchingTimeout);
+    output.writeInt32(frameLeft);
+    output.writeInt32(frameTop);
+    output.writeInt32(frameRight);
+    output.writeInt32(frameBottom);
+    output.writeFloat(scaleFactor);
+    output.writeBool(visible);
+    output.writeBool(canReceiveKeys);
+    output.writeBool(hasFocus);
+    output.writeBool(hasWallpaper);
+    output.writeBool(paused);
+    output.writeInt32(layer);
+    output.writeInt32(ownerPid);
+    output.writeInt32(ownerUid);
+    output.writeInt32(inputFeatures);
+    output.writeInt32(displayId);
+    output.write(touchableRegion);
+
+    return OK;
+}
+
+InputWindowInfo InputWindowInfo::read(const Parcel& from) {
+    InputWindowInfo ret;
+
+    if (from.readInt32() == 0) {
+        return ret;
+
+    }
+    sp<InputChannel> inputChannel = new InputChannel();
+    status_t s = inputChannel->read(from);
+    if (s != OK) {
+        return ret;
+    }
+
+    ret.inputChannel = inputChannel;
+    ret.name = from.readString8().c_str();
+    ret.layoutParamsFlags = from.readInt32();
+    ret.layoutParamsType = from.readInt32();
+    ret.dispatchingTimeout = from.readInt64();
+    ret.frameLeft = from.readInt32();
+    ret.frameTop = from.readInt32();
+    ret.frameRight = from.readInt32();
+    ret.frameBottom = from.readInt32();
+    ret.scaleFactor = from.readFloat();
+    ret.visible = from.readBool();
+    ret.canReceiveKeys = from.readBool();
+    ret.hasFocus = from.readBool();
+    ret.hasWallpaper = from.readBool();
+    ret.paused = from.readBool();
+    ret.layer = from.readInt32();
+    ret.ownerPid = from.readInt32();
+    ret.ownerUid = from.readInt32();
+    ret.inputFeatures = from.readInt32();
+    ret.displayId = from.readInt32();
+    from.read(ret.touchableRegion);
+
+    return ret;
+}
+
+// --- InputWindowHandle ---
+
+InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+    inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
+}
+
+InputWindowHandle::~InputWindowHandle() {
+    delete mInfo;
+}
+
+void InputWindowHandle::releaseInfo() {
+    if (mInfo) {
+        delete mInfo;
+        mInfo = nullptr;
+    }
+}
+
+sp<InputChannel> InputWindowHandle::getInputChannel() const {
+    return mInfo ? mInfo->inputChannel : nullptr;
+}
+
+} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index f06119f..fdd945e 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -6,6 +6,7 @@
         "InputEvent_test.cpp",
         "InputPublisherAndConsumer_test.cpp",
         "VelocityTracker_test.cpp",
+        "InputWindow_test.cpp"
     ],
     cflags: [
         "-Wall",
@@ -34,4 +35,12 @@
         "-Wall",
         "-Werror",
     ],
+    shared_libs: [
+        "libinput",
+        "libcutils",
+        "libutils",
+        "libbinder",
+        "libui",
+        "libbase",
+    ]
 }
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
new file mode 100644
index 0000000..39ad26e
--- /dev/null
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+namespace android {
+namespace test {
+
+TEST(InputWindowInfo, ParcellingWithoutChannel) {
+    InputWindowInfo i;
+    i.inputChannel = nullptr;
+
+    Parcel p;
+    ASSERT_EQ(OK, i.write(p));
+    p.setDataPosition(0);
+    InputWindowInfo i2 = InputWindowInfo::read(p);
+    ASSERT_TRUE(i2.inputChannel == nullptr);
+}
+
+TEST(InputWindowInfo, Parcelling) {
+    sp<InputChannel> channel, junkChannel;
+    status_t result = InputChannel::openInputChannelPair("name", channel, junkChannel);
+    ASSERT_EQ(OK, result) << "openInputChannelPair should have returned valid channels";
+
+    InputWindowInfo i;
+    i.inputChannel = channel;
+    i.name = "Foobar";
+    i.layoutParamsFlags = 7;
+    i.layoutParamsType = 39;
+    i.dispatchingTimeout = 12;
+    i.frameLeft = 93;
+    i.frameTop = 34;
+    i.frameRight = 16;
+    i.frameBottom = 19;
+    i.scaleFactor = 0.3;
+    i.visible = false;
+    i.canReceiveKeys = false;
+    i.hasFocus = false;
+    i.hasWallpaper = false;
+    i.paused = false;
+    i.layer = 7;
+    i.ownerPid = 19;
+    i.ownerUid = 24;
+    i.inputFeatures = 29;
+    i.displayId = 34;
+
+    Parcel p;
+    i.write(p);
+
+    p.setDataPosition(0);
+    InputWindowInfo i2 = InputWindowInfo::read(p);
+    ASSERT_EQ(i.inputChannel->getName(), i2.inputChannel->getName());
+    ASSERT_EQ(i.name, i2.name);
+    ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
+    ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+    ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
+    ASSERT_EQ(i.frameLeft, i2.frameLeft);
+    ASSERT_EQ(i.frameTop, i2.frameTop);
+    ASSERT_EQ(i.frameRight, i2.frameRight);
+    ASSERT_EQ(i.frameBottom, i2.frameBottom);
+    ASSERT_EQ(i.scaleFactor, i2.scaleFactor);
+    ASSERT_EQ(i.visible, i2.visible);
+    ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys);
+    ASSERT_EQ(i.hasFocus, i2.hasFocus);
+    ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper);
+    ASSERT_EQ(i.paused, i2.paused);
+    ASSERT_EQ(i.layer, i2.layer);
+    ASSERT_EQ(i.ownerPid, i2.ownerPid);
+    ASSERT_EQ(i.ownerUid, i2.ownerUid);
+    ASSERT_EQ(i.inputFeatures, i2.inputFeatures);
+    ASSERT_EQ(i.displayId, i2.displayId);
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 4e8c36b..c9d8554 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -174,10 +174,5 @@
 
 int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
 
-int ConsumerBuffer::SetIgnore(bool ignore) {
-  return ReturnStatusOrError(
-      InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
-}
-
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 1483e16..0c7fc90 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -314,7 +314,6 @@
     kOpProducerGain,
     kOpConsumerAcquire,
     kOpConsumerRelease,
-    kOpConsumerSetIgnore,
     kOpProducerBufferDetach,
     kOpConsumerBufferDetach,
     kOpDetachedBufferCreate,
@@ -348,7 +347,6 @@
   PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void));
   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
                     void(LocalFence release_fence));
-  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
   PDX_REMOTE_METHOD(ProducerBufferDetach, kOpProducerBufferDetach,
                     LocalChannelHandle(Void));
 
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
index 089eff8..2044c53 100644
--- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -76,13 +76,6 @@
   // negative unix error code.
   int Discard();
 
-  // When set, this consumer is no longer notified when this buffer is
-  // available. The system behaves as if Discard() is immediately called
-  // whenever the buffer is posted. If ignore is set to true while a buffer is
-  // pending, it will act as if Discard() was also called.
-  // This returns zero or a negative unix error code.
-  int SetIgnore(bool ignore);
-
  private:
   friend BASE;
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1ed9850..d2dc514 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -562,6 +562,15 @@
                     break;
                 }
             }
+
+            // If the driver doesn't understand it, we should map sRGB-encoded P3 to
+            // sRGB rather than just dropping the colorspace on the floor.
+            // For this format, the driver is expected to apply the sRGB
+            // transfer function during framebuffer operations.
+            if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+                strippedAttribList->push_back(attr[0]);
+                strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+            }
         }
         if (copyAttribute) {
             strippedAttribList->push_back(attr[0]);
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 45efb9f..9a65452 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -19,12 +19,10 @@
 
     srcs: [
         "EventHub.cpp",
-        "InputApplication.cpp",
         "InputDispatcher.cpp",
         "InputListener.cpp",
         "InputManager.cpp",
         "InputReader.cpp",
-        "InputWindow.cpp",
     ],
 
     shared_libs: [
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index d609573..38104c4 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -235,6 +235,12 @@
     }
 }
 
+template<typename T, typename U>
+static T getValueByKey(std::unordered_map<U, T>& map, U key) {
+    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
+    return it != map.end() ? it->second : T{};
+}
+
 
 // --- InputDispatcher ---
 
@@ -244,6 +250,7 @@
     mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
     mNextUnblockedEvent(nullptr),
     mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
+    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
     mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
 
@@ -808,8 +815,10 @@
         if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             CommandEntry* commandEntry = postCommandLocked(
                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (mFocusedWindowHandle != nullptr) {
-                commandEntry->inputWindowHandle = mFocusedWindowHandle;
+            sp<InputWindowHandle> focusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
+            if (focusedWindowHandle != nullptr) {
+                commandEntry->inputWindowHandle = focusedWindowHandle;
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -1108,17 +1117,49 @@
     mInputTargetWaitApplicationHandle.clear();
 }
 
+/**
+ * Get the display id that the given event should go to. If this event specifies a valid display id,
+ * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
+ * Focused display is the display that the user most recently interacted with.
+ */
+int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
+    int32_t displayId;
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
+        displayId = typedEntry->displayId;
+        break;
+    }
+    case EventEntry::TYPE_MOTION: {
+        const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
+        displayId = typedEntry->displayId;
+        break;
+    }
+    default: {
+        ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
+        return ADISPLAY_ID_NONE;
+    }
+    }
+    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
+}
+
 int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
         const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
     int32_t injectionResult;
     std::string reason;
 
+    int32_t displayId = getTargetDisplayId(entry);
+    sp<InputWindowHandle> focusedWindowHandle =
+            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+    sp<InputApplicationHandle> focusedApplicationHandle =
+            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+
     // If there is no currently focused window and no focused application
     // then drop the event.
-    if (mFocusedWindowHandle == nullptr) {
-        if (mFocusedApplicationHandle != nullptr) {
+    if (focusedWindowHandle == nullptr) {
+        if (focusedApplicationHandle != nullptr) {
             injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplicationHandle, nullptr, nextWakeupTime,
+                    focusedApplicationHandle, nullptr, nextWakeupTime,
                     "Waiting because no window has focus but there is a "
                     "focused application that may eventually add a window "
                     "when it finishes starting up.");
@@ -1131,23 +1172,23 @@
     }
 
     // Check permissions.
-    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
+    if (!checkInjectionPermission(focusedWindowHandle, entry->injectionState)) {
         injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
         goto Failed;
     }
 
     // Check whether the window is ready for more input.
     reason = checkWindowReadyForMoreInputLocked(currentTime,
-            mFocusedWindowHandle, entry, "focused");
+            focusedWindowHandle, entry, "focused");
     if (!reason.empty()) {
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.c_str());
+                focusedApplicationHandle, focusedWindowHandle, nextWakeupTime, reason.c_str());
         goto Unresponsive;
     }
 
     // Success!  Output targets.
     injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(mFocusedWindowHandle,
+    addWindowTargetLocked(focusedWindowHandle,
             InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
             inputTargets);
 
@@ -1802,8 +1843,11 @@
 }
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    if (mFocusedWindowHandle != nullptr) {
-        const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
+    int32_t displayId = getTargetDisplayId(eventEntry);
+    sp<InputWindowHandle> focusedWindowHandle =
+            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+    if (focusedWindowHandle != nullptr) {
+        const InputWindowInfo* info = focusedWindowHandle->getInfo();
         if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
 #if DEBUG_DISPATCH_CYCLE
             ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
@@ -2978,18 +3022,7 @@
         // Copy old handles for release if they are no longer present.
         const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
 
-        // TODO(b/111361570): multi-display focus, one focus window per display.
-        sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
-        // Reset newFocusedWindowHandle to nullptr if current display own the focus window,
-        // that will be updated below when going through all window handles in current display.
-        // And if list of window handles becomes empty then it will be updated by other display.
-        if (mFocusedWindowHandle != nullptr) {
-            const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
-            if (info == nullptr || info->displayId == displayId) {
-                newFocusedWindowHandle = nullptr;
-            }
-        }
-
+        sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
         bool foundHoveredWindow = false;
 
         if (inputWindowHandles.isEmpty()) {
@@ -3026,28 +3059,31 @@
             mLastHoverWindowHandle = nullptr;
         }
 
-        // TODO(b/111361570): multi-display focus, one focus in all display in current.
-        if (mFocusedWindowHandle != newFocusedWindowHandle) {
-            if (mFocusedWindowHandle != nullptr) {
+        sp<InputWindowHandle> oldFocusedWindowHandle =
+                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+
+        if (oldFocusedWindowHandle != newFocusedWindowHandle) {
+            if (oldFocusedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
                 ALOGD("Focus left window: %s",
-                        mFocusedWindowHandle->getName().c_str());
+                        oldFocusedWindowHandle->getName().c_str());
 #endif
-                sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
+                sp<InputChannel> focusedInputChannel = oldFocusedWindowHandle->getInputChannel();
                 if (focusedInputChannel != nullptr) {
                     CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                             "focus left window");
                     synthesizeCancelationEventsForInputChannelLocked(
                             focusedInputChannel, options);
                 }
+                mFocusedWindowHandlesByDisplay.erase(displayId);
             }
             if (newFocusedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
                 ALOGD("Focus entered window: %s",
                         newFocusedWindowHandle->getName().c_str());
 #endif
+                mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
             }
-            mFocusedWindowHandle = newFocusedWindowHandle;
         }
 
         ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
@@ -3096,25 +3132,28 @@
 }
 
 void InputDispatcher::setFocusedApplication(
-        const sp<InputApplicationHandle>& inputApplicationHandle) {
+        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
 #if DEBUG_FOCUS
     ALOGD("setFocusedApplication");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
+        sp<InputApplicationHandle> oldFocusedApplicationHandle =
+                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
         if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
-            if (mFocusedApplicationHandle != inputApplicationHandle) {
-                if (mFocusedApplicationHandle != nullptr) {
+            if (oldFocusedApplicationHandle != inputApplicationHandle) {
+                if (oldFocusedApplicationHandle != nullptr) {
                     resetANRTimeoutsLocked();
-                    mFocusedApplicationHandle->releaseInfo();
+                    oldFocusedApplicationHandle->releaseInfo();
                 }
-                mFocusedApplicationHandle = inputApplicationHandle;
+                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
             }
-        } else if (mFocusedApplicationHandle != nullptr) {
+        } else if (oldFocusedApplicationHandle != nullptr) {
             resetANRTimeoutsLocked();
-            mFocusedApplicationHandle->releaseInfo();
-            mFocusedApplicationHandle.clear();
+            oldFocusedApplicationHandle->releaseInfo();
+            oldFocusedApplicationHandle.clear();
+            mFocusedApplicationHandlesByDisplay.erase(displayId);
         }
 
 #if DEBUG_FOCUS
@@ -3126,6 +3165,62 @@
     mLooper->wake();
 }
 
+/**
+ * Sets the focused display, which is responsible for receiving focus-dispatched input events where
+ * the display not specified.
+ *
+ * We track any unreleased events for each window. If a window loses the ability to receive the
+ * released event, we will send a cancel event to it. So when the focused display is changed, we
+ * cancel all the unreleased display-unspecified events for the focused window on the old focused
+ * display. The display-specified events won't be affected.
+ */
+void InputDispatcher::setFocusedDisplay(int32_t displayId) {
+#if DEBUG_FOCUS
+    ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
+#endif
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mFocusedDisplayId != displayId) {
+            sp<InputWindowHandle> oldFocusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
+            if (oldFocusedWindowHandle != nullptr) {
+                sp<InputChannel> inputChannel = oldFocusedWindowHandle->getInputChannel();
+                if (inputChannel != nullptr) {
+                    CancelationOptions options(
+                            CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS,
+                            "The display which contains this window no longer has focus.");
+                    synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
+                }
+            }
+            mFocusedDisplayId = displayId;
+
+            // Sanity check
+            sp<InputWindowHandle> newFocusedWindowHandle =
+                    getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+            if (newFocusedWindowHandle == nullptr) {
+                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
+                if (!mFocusedWindowHandlesByDisplay.empty()) {
+                    ALOGE("But another display has a focused window:");
+                    for (auto& it : mFocusedWindowHandlesByDisplay) {
+                        const int32_t displayId = it.first;
+                        const sp<InputWindowHandle>& windowHandle = it.second;
+                        ALOGE("Display #%" PRId32 " has focused window: '%s'\n",
+                                displayId, windowHandle->getName().c_str());
+                    }
+                }
+            }
+        }
+
+#if DEBUG_FOCUS
+        logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
 void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
 #if DEBUG_FOCUS
     ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3152,7 +3247,7 @@
         }
 
 #if DEBUG_FOCUS
-        //logDispatchStateLocked();
+        logDispatchStateLocked();
 #endif
     } // release lock
 
@@ -3297,17 +3392,35 @@
 void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
     dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
     dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
+    dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
 
-    if (mFocusedApplicationHandle != nullptr) {
-        dump += StringPrintf(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
-                mFocusedApplicationHandle->getName().c_str(),
-                mFocusedApplicationHandle->getDispatchingTimeout(
-                        DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
+    if (!mFocusedApplicationHandlesByDisplay.empty()) {
+        dump += StringPrintf(INDENT "FocusedApplications:\n");
+        for (auto& it : mFocusedApplicationHandlesByDisplay) {
+            const int32_t displayId = it.first;
+            const sp<InputApplicationHandle>& applicationHandle = it.second;
+            dump += StringPrintf(
+                    INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%0.3fms\n",
+                    displayId,
+                    applicationHandle->getName().c_str(),
+                    applicationHandle->getDispatchingTimeout(
+                            DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
+        }
     } else {
-        dump += StringPrintf(INDENT "FocusedApplication: <null>\n");
+        dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
     }
-    dump += StringPrintf(INDENT "FocusedWindow: name='%s'\n",
-            mFocusedWindowHandle != nullptr ? mFocusedWindowHandle->getName().c_str() : "<null>");
+
+    if (!mFocusedWindowHandlesByDisplay.empty()) {
+        dump += StringPrintf(INDENT "FocusedWindows:\n");
+        for (auto& it : mFocusedWindowHandlesByDisplay) {
+            const int32_t displayId = it.first;
+            const sp<InputWindowHandle>& windowHandle = it.second;
+            dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n",
+                    displayId, windowHandle->getName().c_str());
+        }
+    } else {
+        dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
+    }
 
     if (!mTouchStatesByDisplay.isEmpty()) {
         dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
@@ -4527,6 +4640,8 @@
         return true;
     case CancelationOptions::CANCEL_FALLBACK_EVENTS:
         return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
+        return memento.displayId == ADISPLAY_ID_NONE;
     default:
         return false;
     }
@@ -4545,6 +4660,8 @@
         return memento.source & AINPUT_SOURCE_CLASS_POINTER;
     case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
         return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
+        return memento.displayId == ADISPLAY_ID_NONE;
     default:
         return false;
     }
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index fdf75f6..aedad2f 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -18,7 +18,9 @@
 #define _UI_INPUT_DISPATCHER_H
 
 #include <input/Input.h>
+#include <input/InputApplication.h>
 #include <input/InputTransport.h>
+#include <input/InputWindow.h>
 #include <utils/KeyedVector.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
@@ -33,8 +35,6 @@
 #include <limits.h>
 #include <unordered_map>
 
-#include "InputWindow.h"
-#include "InputApplication.h"
 #include "InputListener.h"
 
 
@@ -311,12 +311,18 @@
     virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
             int32_t displayId) = 0;
 
-    /* Sets the focused application.
+    /* Sets the focused application on the given display.
      *
      * This method may be called on any thread (usually by the input manager).
      */
     virtual void setFocusedApplication(
-            const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+            int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+
+    /* Sets the focused display.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setFocusedDisplay(int32_t displayId) = 0;
 
     /* Sets the input dispatching mode.
      *
@@ -391,7 +397,9 @@
 
     virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
             int32_t displayId);
-    virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
+    virtual void setFocusedApplication(int32_t displayId,
+            const sp<InputApplicationHandle>& inputApplicationHandle);
+    virtual void setFocusedDisplay(int32_t displayId);
     virtual void setInputDispatchMode(bool enabled, bool frozen);
     virtual void setInputFilterEnabled(bool enabled);
 
@@ -686,6 +694,10 @@
             CANCEL_POINTER_EVENTS = 1,
             CANCEL_NON_POINTER_EVENTS = 2,
             CANCEL_FALLBACK_EVENTS = 3,
+
+            /* Cancel events where the display not specified. These events would go to the focused
+             * display. */
+            CANCEL_DISPLAY_UNSPECIFIED_EVENTS = 4,
         };
 
         // The criterion to use to determine which events should be canceled.
@@ -966,7 +978,7 @@
     bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
 
     // Focus tracking for keys, trackball, etc.
-    sp<InputWindowHandle> mFocusedWindowHandle;
+    std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay;
 
     // Focus tracking for touch.
     struct TouchedWindow {
@@ -997,8 +1009,11 @@
     KeyedVector<int32_t, TouchState> mTouchStatesByDisplay;
     TouchState mTempTouchState;
 
-    // Focused application.
-    sp<InputApplicationHandle> mFocusedApplicationHandle;
+    // Focused applications.
+    std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay;
+
+    // Top focused display.
+    int32_t mFocusedDisplayId;
 
     // Dispatcher state at time of last ANR.
     std::string mLastANRState;
@@ -1046,6 +1061,7 @@
     nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
     void resetANRTimeoutsLocked();
 
+    int32_t getTargetDisplayId(const EventEntry* entry);
     int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
             Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime);
     int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
deleted file mode 100644
index 0d1dfdd..0000000
--- a/services/inputflinger/InputWindow.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputWindow"
-#define LOG_NDEBUG 0
-
-#include "InputWindow.h"
-
-#include <log/log.h>
-
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-namespace android {
-
-// --- InputWindowInfo ---
-void InputWindowInfo::addTouchableRegion(const Rect& region) {
-    touchableRegion.orSelf(region);
-}
-
-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
-    return touchableRegion.contains(x,y);
-}
-
-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
-    return x >= frameLeft && x < frameRight
-            && y >= frameTop && y < frameBottom;
-}
-
-bool InputWindowInfo::isTrustedOverlay() const {
-    return layoutParamsType == TYPE_INPUT_METHOD
-            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
-            || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
-            || layoutParamsType == TYPE_STATUS_BAR
-            || layoutParamsType == TYPE_NAVIGATION_BAR
-            || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
-            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
-            || layoutParamsType == TYPE_DOCK_DIVIDER
-            || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
-            || layoutParamsType == TYPE_INPUT_CONSUMER;
-}
-
-bool InputWindowInfo::supportsSplitTouch() const {
-    return layoutParamsFlags & FLAG_SPLIT_TOUCH;
-}
-
-bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
-    return frameLeft < other->frameRight && frameRight > other->frameLeft
-            && frameTop < other->frameBottom && frameBottom > other->frameTop;
-}
-
-
-// --- InputWindowHandle ---
-
-InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
-    inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
-}
-
-InputWindowHandle::~InputWindowHandle() {
-    delete mInfo;
-}
-
-void InputWindowHandle::releaseInfo() {
-    if (mInfo) {
-        delete mInfo;
-        mInfo = nullptr;
-    }
-}
-
-} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 61dcdd9..2bbfb1b 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -382,12 +382,13 @@
         int32_t mDisplayId;
 };
 
-static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher) {
+static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
+        int32_t displayId = ADISPLAY_ID_NONE) {
     KeyEvent event;
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
 
     // Define a valid key down event.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
             AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
             AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
 
@@ -466,7 +467,7 @@
     sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
 
     // Set focus application.
-    mDispatcher->setFocusedApplication(application);
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
 
     // Expect one focus window exist in display.
     windowSecond->setFocus();
@@ -511,15 +512,21 @@
     windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
 }
 
-// TODO(b/111361570): multi-display focus, one focus window per display.
 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->setFocusedApplication(application2);
+    mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
+    mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
     windowInSecondary->setFocus();
 
     // Update all windows per displays.
@@ -527,13 +534,18 @@
     inputWindowHandles.push(windowInPrimary);
     mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
 
-    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);
 
-    // Test inject a key down.
+    // 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";
+    windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
+    windowInSecondary->assertNoEvents();
+
+    // Test inject a key down without display id specified.
     ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
             << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
     windowInPrimary->assertNoEvents();
@@ -545,6 +557,7 @@
 
     // Expect old focus should receive a cancel event.
     windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+    // TODO(b/111361570): Validate that the event here was marked as canceled.
 
     // Test inject a key down, should timeout because of no target window.
     ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 7c56e5c..f4e728b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -47,6 +47,7 @@
 #include "SensorRecord.h"
 #include "SensorRegistrationInfo.h"
 
+#include <ctime>
 #include <inttypes.h>
 #include <math.h>
 #include <sched.h>
@@ -423,6 +424,11 @@
         } else {
             // Default dump the sensor list and debugging information.
             //
+            timespec curTime;
+            clock_gettime(CLOCK_REALTIME, &curTime);
+            struct tm* timeinfo = localtime(&(curTime.tv_sec));
+            result.appendFormat("Captured at: %02d:%02d:%02d.%03d\n", timeinfo->tm_hour,
+                                timeinfo->tm_min, timeinfo->tm_sec, (int)ns2ms(curTime.tv_nsec));
             result.append("Sensor Device:\n");
             result.append(SensorDevice::getInstance().dump().c_str());
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8afd3b3..9be18fb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -118,12 +118,6 @@
         c->detachLayer(this);
     }
 
-    for (auto& point : mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    for (auto& point : mLocalSyncPoints) {
-        point->setFrameAvailable();
-    }
     mFrameTracker.logAndResetStats(mName);
 }
 
@@ -141,8 +135,6 @@
 void Layer::onRemovedFromCurrentState() {
     // the layer is removed from SF mCurrentState to mLayersPendingRemoval
 
-    mPendingRemoval = true;
-
     if (mCurrentState.zOrderRelativeOf != nullptr) {
         sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
         if (strongRelative != nullptr) {
@@ -151,7 +143,7 @@
         }
         mCurrentState.zOrderRelativeOf = nullptr;
     }
-
+    
     for (const auto& child : mCurrentChildren) {
         child->onRemovedFromCurrentState();
     }
@@ -163,8 +155,13 @@
 
     destroyAllHwcLayers();
 
-    for (const auto& child : mCurrentChildren) {
-        child->onRemoved();
+    mRemoved = true;
+
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    for (auto& point : mLocalSyncPoints) {
+        point->setFrameAvailable();
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3eb8327..f2cda03 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -345,7 +345,7 @@
     virtual bool isCreatedFromMainThread() const { return false; }
 
 
-    bool isPendingRemoval() const { return mPendingRemoval; }
+    bool isRemoved() const { return mRemoved; }
 
     void writeToProto(LayerProto* layerInfo,
                       LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
@@ -594,12 +594,12 @@
      */
     class LayerCleaner {
         sp<SurfaceFlinger> mFlinger;
-        wp<Layer> mLayer;
+        sp<Layer> mLayer;
 
     protected:
         ~LayerCleaner() {
             // destroy client resources
-            mFlinger->onLayerDestroyed(mLayer);
+            mFlinger->removeLayer(mLayer, true);
         }
 
     public:
@@ -744,7 +744,7 @@
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering{false};
 
-    bool mPendingRemoval{false};
+    bool mRemoved{false};
 
     // page-flip thread (currently main thread)
     bool mProtectedByApp{false}; // application requires protected path to external sink
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 9c2d312..c0174ae 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -68,7 +68,7 @@
         base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
         base::StringAppendF(&key, ",%d", layer->isProtected);
         base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
-        base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+        base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
         base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
         base::StringAppendF(&key, ",%s",
                             destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
@@ -162,8 +162,8 @@
     return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
 }
 
-const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
-    return decodePixelFormat(pixelFormat).c_str();
+std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
+    return decodePixelFormat(pixelFormat);
 }
 
 std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 944073b..9de9cce 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -50,7 +50,7 @@
     // Return the name of the composition type
     static const char* layerCompositionType(int32_t compositionType);
     // Return the name of the pixel format
-    static const char* layerPixelFormat(int32_t pixelFormat);
+    static std::string layerPixelFormat(int32_t pixelFormat);
     // Calculate scale ratios of layer's width/height with rotation information
     static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
     // Calculate scale ratio from source to destination and convert to string
diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
index 9254aa0..c118248 100644
--- a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
@@ -316,7 +316,7 @@
 
                             // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
                             if (maxInLumi <= maxOutLumi) {
-                                nits *= maxOutLumi / maxInLumi;
+                                return color * (maxOutLumi / maxInLumi);
                             } else {
                                 // three control points
                                 const float x0 = 10.0;
@@ -337,7 +337,7 @@
                                 if (nits < x0) {
                                     // scale [0.0, x0] to [0.0, y0] linearly
                                     float slope = y0 / x0;
-                                    nits *= slope;
+                                    return color * slope;
                                 } else if (nits < x1) {
                                     // scale [x0, x1] to [y0, y1] linearly
                                     float slope = (y1 - y0) / (x1 - x0);
@@ -355,7 +355,8 @@
                                 }
                             }
 
-                            return color * (nits / max(1e-6, color.y));
+                            // color.y is greater than x0 and is thus non-zero
+                            return color * (nits / color.y);
                         }
                     )__SHADER__";
                     break;
@@ -386,7 +387,7 @@
                     if (nits <= x0) {
                         // scale [0.0, x0] to [0.0, y0] linearly
                         const float slope = y0 / x0;
-                        nits *= slope;
+                        return color * slope;
                     } else if (nits <= x1) {
                         // scale [x0, x1] to [y0, y1] using a curve
                         float t = (nits - x0) / (x1 - x0);
@@ -401,7 +402,8 @@
                         nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
                     }
 
-                    return color * (nits / max(1e-6, color.y));
+                    // color.y is greater than x0 and is thus non-zero
+                    return color * (nits / color.y);
                 }
             )__SHADER__";
             break;
@@ -574,7 +576,7 @@
             fs << "uniform mat4 inputTransformMatrix;";
             fs << R"__SHADER__(
                 highp vec3 InputTransform(const highp vec3 color) {
-                    return vec3(inputTransformMatrix * vec4(color, 1.0));
+                    return clamp(vec3(inputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0);
                 }
             )__SHADER__";
         } else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 37b32ed..2199ce1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2852,6 +2852,7 @@
             recordBufferingStats(l->getName().string(),
                     l->getOccupancyHistory(true));
             l->onRemoved();
+            mNumLayers -= 1;
         }
         mLayersPendingRemoval.clear();
     }
@@ -3283,7 +3284,7 @@
         if (parent == nullptr) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else {
-            if (parent->isPendingRemoval()) {
+            if (parent->isRemoved()) {
                 ALOGE("addClientLayer called with a removed parent");
                 return NAME_NOT_FOUND;
             }
@@ -3315,7 +3316,7 @@
 
 status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer,
                                            bool topLevelOnly) {
-    if (layer->isPendingRemoval()) {
+    if (layer->isRemoved()) {
         return NO_ERROR;
     }
 
@@ -3325,39 +3326,14 @@
         if (topLevelOnly) {
             return NO_ERROR;
         }
-
-        sp<Layer> ancestor = p;
-        while (ancestor->getParent() != nullptr) {
-            ancestor = ancestor->getParent();
-        }
-        if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
-            ALOGE("removeLayer called with a layer whose parent has been removed");
-            return NAME_NOT_FOUND;
-        }
-
         index = p->removeChild(layer);
     } else {
         index = mCurrentState.layersSortedByZ.remove(layer);
     }
 
-    // As a matter of normal operation, the LayerCleaner will produce a second
-    // attempt to remove the surface. The Layer will be kept alive in mDrawingState
-    // so we will succeed in promoting it, but it's already been removed
-    // from mCurrentState. As long as we can find it in mDrawingState we have no problem
-    // otherwise something has gone wrong and we are leaking the layer.
-    if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
-        ALOGE("Failed to find layer (%s) in layer parent (%s).",
-                layer->getName().string(),
-                (p != nullptr) ? p->getName().string() : "no-parent");
-        return BAD_VALUE;
-    } else if (index < 0) {
-        return NO_ERROR;
-    }
-
     layer->onRemovedFromCurrentState();
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
-    mNumLayers -= 1 + layer->getChildrenCount();
     setTransactionFlags(eTransactionNeeded);
     return NO_ERROR;
 }
@@ -3560,7 +3536,7 @@
         return 0;
     }
 
-    if (layer->isPendingRemoval()) {
+    if (layer->isRemoved()) {
         ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
         return 0;
     }
@@ -3768,7 +3744,7 @@
         return;
     }
 
-    if (layer->isPendingRemoval()) {
+    if (layer->isRemoved()) {
         ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string());
         return;
     }
@@ -3945,19 +3921,6 @@
     return err;
 }
 
-status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
-{
-    // called by ~LayerCleaner() when all references to the IBinder (handle)
-    // are gone
-    sp<Layer> l = layer.promote();
-    if (l == nullptr) {
-        // The layer has already been removed, carry on
-        return NO_ERROR;
-    }
-    // If we have a parent, then we can continue to live as long as it does.
-    return removeLayer(l, true);
-}
-
 // ---------------------------------------------------------------------------
 
 void SurfaceFlinger::onInitializeDisplays() {
@@ -5331,7 +5294,7 @@
     auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
     auto parent = layerHandle->owner.promote();
 
-    if (parent == nullptr || parent->isPendingRemoval()) {
+    if (parent == nullptr || parent->isRemoved()) {
         ALOGE("captureLayers called with a removed parent");
         return NAME_NOT_FOUND;
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a0f7c75..9f6eb21 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -561,11 +561,6 @@
     // ISurfaceComposerClient::destroySurface()
     status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
 
-    // called when all clients have released all their references to
-    // this layer meaning it is entirely safe to destroy all
-    // resources associated to this layer.
-    status_t onLayerDestroyed(const wp<Layer>& layer);
-
     // remove a layer from SurfaceFlinger immediately
     status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
     status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3166a8c..0bf54d5 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2582,6 +2582,37 @@
     }
 }
 
+TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
+    sp<SurfaceControl> mGrandChild =
+        mClient->createSurface(String8("Grand Child"), 10, 10,
+                PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+    fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+
+    {
+        SCOPED_TRACE("Grandchild visible");
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->checkPixel(64, 64, 111, 111, 111);
+    }
+
+    mChild->clear();
+
+    {
+        SCOPED_TRACE("After destroying child");
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectFGColor(64, 64);
+    }
+
+    asTransaction([&](Transaction& t) {
+         t.reparent(mGrandChild, mFGSurfaceControl->getHandle());
+    });
+
+    {
+        SCOPED_TRACE("After reparenting grandchild");
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->checkPixel(64, 64, 111, 111, 111);
+    }
+}
+
 TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
     sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
     sp<SurfaceControl> mChildNewClient =
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
index 4ff9890..def15f1 100644
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ b/services/vr/bufferhubd/buffer_hub_binder.cpp
@@ -1,58 +1,28 @@
 #include <stdio.h>
 
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
 #include <log/log.h>
 #include <private/dvr/buffer_hub_binder.h>
 
 namespace android {
 namespace dvr {
 
-status_t BufferHubBinderService::start(
-    const std::shared_ptr<BufferHubService> &pdx_service) {
+status_t BufferHubBinderService::start() {
+  ProcessState::self()->startThreadPool();
   IPCThreadState::self()->disableBackgroundScheduling(true);
-
-  BufferHubBinderService* service = new BufferHubBinderService();
-  service->pdx_service_ = pdx_service;
-
-  // Not using BinderService::publish because need to get an instance of this
-  // class (above). Following code is the same as
-  // BinderService::publishAndJoinThreadPool
-  sp<IServiceManager> sm = defaultServiceManager();
-  status_t result = sm->addService(String16(getServiceName()), service,
-      /*allowIsolated =*/ false,
-      /*dump flags =*/ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
-  if (result != NO_ERROR) {
+  status_t result = BinderService<BufferHubBinderService>::publish();
+  if (result != OK) {
     ALOGE("Publishing bufferhubd failed with error %d", result);
     return result;
   }
 
-  sp<ProcessState> process_self(ProcessState::self());
-  process_self->startThreadPool();
-  process_self->giveThreadPoolName();
-  IPCThreadState::self()->joinThreadPool();
-
   return result;
 }
 
-status_t BufferHubBinderService::dump(int fd, const Vector<String16> &args) {
+status_t BufferHubBinderService::dump(int fd, const Vector<String16> & /* args */) {
+  // TODO(b/115435506): not implemented yet
   FILE *out = fdopen(dup(fd), "w");
 
-  // Currently not supporting args, so notify the user.
-  if (!args.isEmpty()){
-    fprintf(out, "Note: dumpsys bufferhubd currently does not support args."
-        "Input arguments are ignored.\n");
-  }
-
-  // TODO(b/116526156): output real data in this class once we have it
-  if (pdx_service_){
-    // BufferHubService::Dumpstate(size_t) is not actually using the param
-    // So just using 0 as the length
-    fprintf(out, "%s", pdx_service_->DumpState(0).c_str());
-  } else {
-    fprintf(out, "PDX service not registered or died.\n");
-  }
+  fprintf(out, "BufferHubBinderService::dump(): Not Implemented.\n");
 
   fclose(out);
   return NO_ERROR;
@@ -60,4 +30,4 @@
 
 
 }  // namespace dvr
-}  // namespace android
+}  // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index 3e10b26..0ca7edc 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -10,7 +10,7 @@
 
 int main(int, char**) {
   int ret = -1;
-  std::shared_ptr<android::dvr::BufferHubService> pdx_service;
+  std::shared_ptr<android::pdx::Service> service;
   std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher;
 
   // We need to be able to create endpoints with full perms.
@@ -33,16 +33,15 @@
   else
     ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
 
+  CHECK_ERROR(android::dvr::BufferHubBinderService::start() != android::OK,
+              error, "Failed to create bufferhub binder service\n");
+
   dispatcher = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
 
-  pdx_service = android::dvr::BufferHubService::Create();
-  CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n");
-  dispatcher->AddService(pdx_service);
-
-  ret = android::dvr::BufferHubBinderService::start(pdx_service);
-  CHECK_ERROR(ret != android::NO_ERROR, error,
-              "Failed to create bufferhub binder service\n");
+  service = android::dvr::BufferHubService::Create();
+  CHECK_ERROR(!service, error, "Failed to create bufferhubd service\n");
+  dispatcher->AddService(service);
 
   ret = dvrSetSchedulerClass(0, "graphics");
   CHECK_ERROR(ret < 0, error, "Failed to set thread priority");
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 623c9d6..4ff7adf 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -90,11 +90,6 @@
           *this, &ConsumerChannel::OnConsumerRelease, message);
       return true;
 
-    case BufferHubRPC::ConsumerSetIgnore::Opcode:
-      DispatchRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(
-          *this, &ConsumerChannel::OnConsumerSetIgnore, message);
-      return true;
-
     default:
       return false;
   }
@@ -120,9 +115,8 @@
   if (acquired_ || released_) {
     ALOGE(
         "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
-        "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
-        ignored_, acquired_, released_, message.GetChannelId(),
-        producer->buffer_id());
+        "acquired=%d released=%d channel_id=%d buffer_id=%d",
+        acquired_, released_, message.GetChannelId(), producer->buffer_id());
     return ErrorStatus(EBUSY);
   } else {
     auto status = producer->OnConsumerAcquire(message);
@@ -144,9 +138,8 @@
   if (!acquired_ || released_) {
     ALOGE(
         "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
-        "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
-        ignored_, acquired_, released_, message.GetChannelId(),
-        producer->buffer_id());
+        "acquired=%d released=%d channel_id=%d buffer_id=%d",
+        acquired_, released_, message.GetChannelId(), producer->buffer_id());
     return ErrorStatus(EBUSY);
   } else {
     auto status =
@@ -160,36 +153,11 @@
   }
 }
 
-Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
-  ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
-  auto producer = GetProducer();
-  if (!producer)
-    return ErrorStatus(EPIPE);
-
-  ignored_ = ignored;
-  if (ignored_ && acquired_) {
-    // Update the producer if ignore is set after the consumer acquires the
-    // buffer.
-    ClearAvailable();
-    producer->OnConsumerIgnored();
-    acquired_ = false;
-    released_ = true;
-  }
-
-  return {};
-}
-
 bool ConsumerChannel::OnProducerPosted() {
-  if (ignored_) {
-    acquired_ = false;
-    released_ = true;
-    return false;
-  } else {
-    acquired_ = false;
-    released_ = false;
-    SignalAvailable();
-    return true;
-  }
+  acquired_ = false;
+  released_ = false;
+  SignalAvailable();
+  return true;
 }
 
 void ConsumerChannel::OnProducerClosed() {
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
index 07f05cc..c0281fd 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
@@ -2,7 +2,6 @@
 #define ANDROID_DVR_BUFFER_HUB_BINDER_H
 
 #include <binder/BinderService.h>
-#include <private/dvr/buffer_hub.h>
 
 #include "android/dvr/BnBufferHub.h"
 
@@ -11,17 +10,14 @@
 
 class BufferHubBinderService : public BinderService<BufferHubBinderService>, public BnBufferHub {
  public:
-  static status_t start(const std::shared_ptr<BufferHubService> &pdx_service);
+  static status_t start();
   static const char* getServiceName() { return "bufferhubd"; }
   // Dump bufferhub related information to given fd (usually stdout)
   // usage: adb shell dumpsys bufferhubd
   virtual status_t dump(int fd, const Vector<String16> &args) override;
-
- private:
-  std::shared_ptr<BufferHubService> pdx_service_;
 };
 
 }  // namespace dvr
 }  // namespace android
 
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
+#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
index 0d70409..84f664d 100644
--- a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
@@ -37,12 +37,10 @@
   pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
   pdx::Status<void> OnConsumerRelease(Message& message,
                                       LocalFence release_fence);
-  pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
 
   uint64_t consumer_state_bit_{0};
   bool acquired_{false};
   bool released_{true};
-  bool ignored_{false};  // True if we are ignoring events.
   std::weak_ptr<Channel> producer_;
 
   ConsumerChannel(const ConsumerChannel&) = delete;
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
index 242198f..b4ea115 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
@@ -58,7 +58,7 @@
   pdx::Status<void> OnConsumerRelease(Message& message,
                                       LocalFence release_fence);
 
-  void OnConsumerIgnored();
+  void DecrementPendingConsumers();
   void OnConsumerOrphaned(ConsumerChannel* channel);
 
   void AddConsumer(ConsumerChannel* channel);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 057d4f4..0b5257d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -7,8 +7,8 @@
 #include <thread>
 
 #include <log/log.h>
-#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/buffer_channel.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/consumer_channel.h>
 #include <private/dvr/producer_channel.h>
 #include <sync/sync.h>
@@ -96,8 +96,7 @@
   // and also initialize the value to zero.
   buffer_state_ =
       new (&metadata_header_->buffer_state) std::atomic<uint64_t>(0);
-  fence_state_ =
-      new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
+  fence_state_ = new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
 
   acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
   release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
@@ -300,8 +299,8 @@
   return CreateConsumer(message);
 }
 
-Status<void> ProducerChannel::OnProducerPost(
-    Message&, LocalFence acquire_fence) {
+Status<void> ProducerChannel::OnProducerPost(Message&,
+                                             LocalFence acquire_fence) {
   ATRACE_NAME("ProducerChannel::OnProducerPost");
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
   if (!producer_owns_) {
@@ -315,9 +314,9 @@
   int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
                       dummy_fence_fd_.Get(), &event);
   ALOGE_IF(ret < 0,
-      "ProducerChannel::OnProducerPost: Failed to modify the shared "
-      "release fence to include the dummy fence: %s",
-      strerror(errno));
+           "ProducerChannel::OnProducerPost: Failed to modify the shared "
+           "release fence to include the dummy fence: %s",
+           strerror(errno));
 
   eventfd_t dummy_fence_count = 0ULL;
   if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
@@ -474,7 +473,7 @@
     }
   }
 
-  OnConsumerIgnored();
+  DecrementPendingConsumers();
   if (pending_consumers_ == 0) {
     // Clear the producer bit atomically to transit into released state. This
     // has to done by BufferHub as it requries synchronization among all
@@ -507,21 +506,22 @@
   return {};
 }
 
-void ProducerChannel::OnConsumerIgnored() {
+void ProducerChannel::DecrementPendingConsumers() {
   if (pending_consumers_ == 0) {
-    ALOGE("ProducerChannel::OnConsumerIgnored: no pending consumer.");
+    ALOGE("ProducerChannel::DecrementPendingConsumers: no pending consumer.");
     return;
   }
 
   --pending_consumers_;
   ALOGD_IF(TRACE,
-           "ProducerChannel::OnConsumerIgnored: buffer_id=%d %d consumers left",
+           "ProducerChannel::DecrementPendingConsumers: buffer_id=%d %d "
+           "consumers left",
            buffer_id(), pending_consumers_);
 }
 
 void ProducerChannel::OnConsumerOrphaned(ConsumerChannel* channel) {
   // Ignore the orphaned consumer.
-  OnConsumerIgnored();
+  DecrementPendingConsumers();
 
   const uint64_t consumer_state_bit = channel->consumer_state_bit();
   ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_bit,
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index 92bda78..4d1d43f 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -6,18 +6,11 @@
         "-DTRACE=0",
         "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
-    header_libs: ["libdvr_headers"],
-    static_libs: [
-        "libbufferhub",
-        "libbufferhubd",
-        "libgmock",
-    ],
+    static_libs: ["libbufferhubd"],
     shared_libs: [
         "libbase",
         "libbinder",
         "liblog",
-        "libpdx_default_transport",
-        "libui",
         "libutils",
     ],
 }
\ No newline at end of file
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
index 0b64cf0..e3f2825 100644
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
@@ -1,8 +1,7 @@
-#include <binder/IServiceManager.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
 #include <private/dvr/buffer_hub_binder.h>
 
+#include <gtest/gtest.h>
+
 namespace android {
 namespace dvr {
 
@@ -13,12 +12,8 @@
 };
 
 TEST_F(BufferHubBinderServiceTest, TestInitialize) {
-  // Create a new service will kill the current one.
-  // So just check if Binder service is running
-  sp<IServiceManager> sm = defaultServiceManager();
-  sp<IBinder> service = sm->checkService(
-      String16(BufferHubBinderService::getServiceName()));
-  EXPECT_THAT(service, ::testing::Ne(nullptr));
+  // Test if start binder server returns OK
+  EXPECT_EQ(BufferHubBinderService::start(), OK);
 }
 
 }  // namespace