Merge "SF: Clear mCompositionInfo before recomputing visible layers"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 4459cef..9b12a02 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -105,6 +105,8 @@
     chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable
     chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill/enable
     chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable
+    chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable
 
     # disk
     chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 72d1de9..dc7288e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1100,7 +1100,7 @@
     }
 }
 
-// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
+// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
 static void RunDumpsysCritical() {
     RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
                    /* timeout= */ 5s, /* service_timeout= */ 500ms);
@@ -1864,17 +1864,6 @@
             do_text_file = true;
         } else {
             do_text_file = false;
-            // Since zip file is already created, it needs to be renamed.
-            std::string new_path = ds.GetPath(".zip");
-            if (ds.path_ != new_path) {
-                MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
-                if (rename(ds.path_.c_str(), new_path.c_str())) {
-                    MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
-                           strerror(errno));
-                } else {
-                    ds.path_ = new_path;
-                }
-            }
         }
     }
     if (do_text_file) {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5e7f71d..35cbdb1 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -261,7 +261,7 @@
                                         std::chrono::milliseconds timeout);
 
     /*
-     * Adds a text entry entry to the existing zip file.
+     * Adds a text entry to the existing zip file.
      */
     bool AddTextZipEntry(const std::string& entry_name, const std::string& content);
 
diff --git a/include/input/Input.h b/include/input/Input.h
index d35354b..cc45aef 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -59,6 +59,12 @@
      */
     AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2,
 
+    /**
+     * This flag indicates that the event has been generated by a gesture generator. It
+     * provides a hint to the GestureDetector to not apply any touch slop.
+     */
+    AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE = 0x8,
+
     /* Motion event is inconsistent with previously sent motion events. */
     AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
 };
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index d906db3..dddbfb0 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -47,6 +47,13 @@
  *
  * Note that this structure is used for IPCs so its layout must be identical
  * on 64 and 32 bit processes. This is tested in StructLayout_test.cpp.
+ *
+ * Since the struct must be aligned to an 8-byte boundary, there could be uninitialized bytes
+ * in-between the defined fields. This padding data should be explicitly accounted for by adding
+ * "empty" fields into the struct. This data is memset to zero before sending the struct across
+ * the socket. Adding the explicit fields ensures that the memset is not optimized away by the
+ * compiler. When a new field is added to the struct, the corresponding change
+ * in StructLayout_test should be made.
  */
 struct InputMessage {
     enum {
@@ -67,6 +74,7 @@
     union Body {
         struct Key {
             uint32_t seq;
+            uint32_t empty1;
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
@@ -77,6 +85,7 @@
             int32_t scanCode;
             int32_t metaState;
             int32_t repeatCount;
+            uint32_t empty2;
             nsecs_t downTime __attribute__((aligned(8)));
 
             inline size_t size() const {
@@ -86,6 +95,7 @@
 
         struct Motion {
             uint32_t seq;
+            uint32_t empty1;
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
@@ -96,12 +106,14 @@
             int32_t metaState;
             int32_t buttonState;
             int32_t edgeFlags;
+            uint32_t empty2;
             nsecs_t downTime __attribute__((aligned(8)));
             float xOffset;
             float yOffset;
             float xPrecision;
             float yPrecision;
             uint32_t pointerCount;
+            uint32_t empty3;
             // Note that PointerCoords requires 8 byte alignment.
             struct Pointer {
                 PointerProperties properties;
@@ -132,6 +144,7 @@
 
     bool isValid(size_t actualSize) const;
     size_t size() const;
+    void getSanitizedCopy(InputMessage* msg) const;
 };
 
 /*
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index e2c0cfa..c6fcaa4 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -163,7 +163,9 @@
     ScopedAResource& operator=(ScopedAResource&&) = delete;
 
     // move-constructing is okay
-    ScopedAResource(ScopedAResource&&) = default;
+    ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) {
+      other.mT = DEFAULT;
+    }
 
    private:
     T mT;
diff --git a/libs/gui/HdrMetadata.cpp b/libs/gui/HdrMetadata.cpp
index b715e43..add3ef0 100644
--- a/libs/gui/HdrMetadata.cpp
+++ b/libs/gui/HdrMetadata.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <gui/HdrMetadata.h>
+#include <limits>
 
 namespace android {
 
@@ -26,6 +27,10 @@
     if (validTypes & CTA861_3) {
         size += sizeof(cta8613);
     }
+    if (validTypes & HDR10PLUS) {
+        size += sizeof(size_t);
+        size += hdr10plus.size();
+    }
     return size;
 }
 
@@ -41,6 +46,12 @@
     if (validTypes & CTA861_3) {
         FlattenableUtils::write(buffer, size, cta8613);
     }
+    if (validTypes & HDR10PLUS) {
+        size_t metadataSize = hdr10plus.size();
+        FlattenableUtils::write(buffer, size, metadataSize);
+        memcpy(buffer, hdr10plus.data(), metadataSize);
+        FlattenableUtils::advance(buffer, size, metadataSize);
+    }
 
     return NO_ERROR;
 }
@@ -62,6 +73,22 @@
         }
         FlattenableUtils::read(buffer, size, cta8613);
     }
+    if (validTypes & HDR10PLUS) {
+        if (size < sizeof(size_t)) {
+            return NO_MEMORY;
+        }
+
+        size_t metadataSize;
+        FlattenableUtils::read(buffer, size, metadataSize);
+
+        if (size < metadataSize) {
+            return NO_MEMORY;
+        }
+
+        hdr10plus.resize(metadataSize);
+        memcpy(hdr10plus.data(), buffer, metadataSize);
+        FlattenableUtils::advance(buffer, size, metadataSize);
+    }
 
     return NO_ERROR;
 }
@@ -91,6 +118,10 @@
         }
     }
 
+    if ((validTypes & HDR10PLUS) == HDR10PLUS) {
+        if (hdr10plus != rhs.hdr10plus) return false;
+    }
+
     return true;
 }
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b505c6f..00e23f0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -965,6 +965,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA:
         res = dispatchSetBuffersCta8613Metadata(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA:
+        res = dispatchSetBuffersHdr10PlusMetadata(args);
+        break;
     case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
         res = dispatchSetSurfaceDamage(args);
         break;
@@ -1120,6 +1123,12 @@
     return setBuffersCta8613Metadata(metadata);
 }
 
+int Surface::dispatchSetBuffersHdr10PlusMetadata(va_list args) {
+    const size_t size = va_arg(args, size_t);
+    const uint8_t* metadata = va_arg(args, const uint8_t*);
+    return setBuffersHdr10PlusMetadata(size, metadata);
+}
+
 int Surface::dispatchSetSurfaceDamage(va_list args) {
     android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
     size_t numRects = va_arg(args, size_t);
@@ -1568,6 +1577,19 @@
     return NO_ERROR;
 }
 
+int Surface::setBuffersHdr10PlusMetadata(const size_t size, const uint8_t* metadata) {
+    ALOGV("Surface::setBuffersBlobMetadata");
+    Mutex::Autolock lock(mMutex);
+    if (size > 0) {
+        mHdrMetadata.hdr10plus.assign(metadata, metadata + size);
+        mHdrMetadata.validTypes |= HdrMetadata::HDR10PLUS;
+    } else {
+        mHdrMetadata.validTypes &= ~HdrMetadata::HDR10PLUS;
+        mHdrMetadata.hdr10plus.clear();
+    }
+    return NO_ERROR;
+}
+
 Dataspace Surface::getBuffersDataSpace() {
     ALOGV("Surface::getBuffersDataSpace");
     Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/include/gui/HdrMetadata.h b/libs/gui/include/gui/HdrMetadata.h
index 9800602..1e9c3e7 100644
--- a/libs/gui/include/gui/HdrMetadata.h
+++ b/libs/gui/include/gui/HdrMetadata.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <stdint.h>
+#include <vector>
 
 #include <system/graphics.h>
 #include <utils/Flattenable.h>
@@ -26,12 +27,15 @@
 struct HdrMetadata : public LightFlattenable<HdrMetadata> {
     enum Type : uint32_t {
         SMPTE2086 = 1 << 0,
-        CTA861_3  = 1 << 1,
+        CTA861_3 = 1 << 1,
+        HDR10PLUS = 1 << 2,
     };
+
     uint32_t validTypes{0};
 
     android_smpte2086_metadata smpte2086{};
     android_cta861_3_metadata cta8613{};
+    std::vector<uint8_t> hdr10plus{};
 
     // LightFlattenable
     bool isFixedSize() const { return false; }
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 32ee595..248e105 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -218,6 +218,7 @@
     int dispatchSetBuffersDataSpace(va_list args);
     int dispatchSetBuffersSmpte2086Metadata(va_list args);
     int dispatchSetBuffersCta8613Metadata(va_list args);
+    int dispatchSetBuffersHdr10PlusMetadata(va_list args);
     int dispatchSetSurfaceDamage(va_list args);
     int dispatchSetSharedBufferMode(va_list args);
     int dispatchSetAutoRefresh(va_list args);
@@ -249,6 +250,7 @@
     virtual int setBuffersDataSpace(ui::Dataspace dataSpace);
     virtual int setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata);
     virtual int setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata);
+    virtual int setBuffersHdr10PlusMetadata(const size_t size, const uint8_t* metadata);
     virtual int setCrop(Rect const* rect);
     virtual int setUsage(uint64_t reqUsage);
     virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d0600da..4ba7da3 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -366,10 +366,17 @@
         78.0,
         62.0,
     };
+
+    std::vector<uint8_t> hdr10plus;
+    hdr10plus.push_back(0xff);
+
     int error = native_window_set_buffers_smpte2086_metadata(window.get(), &smpte2086);
     ASSERT_EQ(error, NO_ERROR);
     error = native_window_set_buffers_cta861_3_metadata(window.get(), &cta861_3);
     ASSERT_EQ(error, NO_ERROR);
+    error = native_window_set_buffers_hdr10_plus_metadata(window.get(), hdr10plus.size(),
+                                                          hdr10plus.data());
+    ASSERT_EQ(error, NO_ERROR);
 }
 
 TEST_F(SurfaceTest, DynamicSetBufferCount) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index e93f3a4..f33b210 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -97,6 +97,106 @@
     return sizeof(Header);
 }
 
+/**
+ * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire
+ * memory to zero, then only copy the valid bytes on a per-field basis.
+ */
+void InputMessage::getSanitizedCopy(InputMessage* msg) const {
+    memset(msg, 0, sizeof(*msg));
+
+    // Write the header
+    msg->header.type = header.type;
+
+    // Write the body
+    switch(header.type) {
+        case InputMessage::TYPE_KEY: {
+            // uint32_t seq
+            msg->body.key.seq = body.key.seq;
+            // nsecs_t eventTime
+            msg->body.key.eventTime = body.key.eventTime;
+            // int32_t deviceId
+            msg->body.key.deviceId = body.key.deviceId;
+            // int32_t source
+            msg->body.key.source = body.key.source;
+            // int32_t displayId
+            msg->body.key.displayId = body.key.displayId;
+            // int32_t action
+            msg->body.key.action = body.key.action;
+            // int32_t flags
+            msg->body.key.flags = body.key.flags;
+            // int32_t keyCode
+            msg->body.key.keyCode = body.key.keyCode;
+            // int32_t scanCode
+            msg->body.key.scanCode = body.key.scanCode;
+            // int32_t metaState
+            msg->body.key.metaState = body.key.metaState;
+            // int32_t repeatCount
+            msg->body.key.repeatCount = body.key.repeatCount;
+            // nsecs_t downTime
+            msg->body.key.downTime = body.key.downTime;
+            break;
+        }
+        case InputMessage::TYPE_MOTION: {
+            // uint32_t seq
+            msg->body.motion.seq = body.motion.seq;
+            // nsecs_t eventTime
+            msg->body.motion.eventTime = body.motion.eventTime;
+            // int32_t deviceId
+            msg->body.motion.deviceId = body.motion.deviceId;
+            // int32_t source
+            msg->body.motion.source = body.motion.source;
+            // int32_t displayId
+            msg->body.motion.displayId = body.motion.displayId;
+            // int32_t action
+            msg->body.motion.action = body.motion.action;
+            // int32_t actionButton
+            msg->body.motion.actionButton = body.motion.actionButton;
+            // int32_t flags
+            msg->body.motion.flags = body.motion.flags;
+            // int32_t metaState
+            msg->body.motion.metaState = body.motion.metaState;
+            // int32_t buttonState
+            msg->body.motion.buttonState = body.motion.buttonState;
+            // int32_t edgeFlags
+            msg->body.motion.edgeFlags = body.motion.edgeFlags;
+            // nsecs_t downTime
+            msg->body.motion.downTime = body.motion.downTime;
+            // float xOffset
+            msg->body.motion.xOffset = body.motion.xOffset;
+            // float yOffset
+            msg->body.motion.yOffset = body.motion.yOffset;
+            // float xPrecision
+            msg->body.motion.xPrecision = body.motion.xPrecision;
+            // float yPrecision
+            msg->body.motion.yPrecision = body.motion.yPrecision;
+            // uint32_t pointerCount
+            msg->body.motion.pointerCount = body.motion.pointerCount;
+            //struct Pointer pointers[MAX_POINTERS]
+            for (size_t i = 0; i < body.motion.pointerCount; i++) {
+                // PointerProperties properties
+                msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id;
+                msg->body.motion.pointers[i].properties.toolType =
+                        body.motion.pointers[i].properties.toolType,
+                // PointerCoords coords
+                msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits;
+                const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits);
+                memcpy(&msg->body.motion.pointers[i].coords.values[0],
+                        &body.motion.pointers[i].coords.values[0],
+                        count * (sizeof(body.motion.pointers[i].coords.values[0])));
+            }
+            break;
+        }
+        case InputMessage::TYPE_FINISHED: {
+            msg->body.finished.seq = body.finished.seq;
+            msg->body.finished.handled = body.finished.handled;
+            break;
+        }
+        default: {
+            LOG_FATAL("Unexpected message type %i", header.type);
+            break;
+        }
+    }
+}
 
 // --- InputChannel ---
 
@@ -160,10 +260,12 @@
 }
 
 status_t InputChannel::sendMessage(const InputMessage* msg) {
-    size_t msgLength = msg->size();
+    const size_t msgLength = msg->size();
+    InputMessage cleanMsg;
+    msg->getSanitizedCopy(&cleanMsg);
     ssize_t nWrite;
     do {
-        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
+        nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     } while (nWrite == -1 && errno == EINTR);
 
     if (nWrite < 0) {
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index d19f3b8..12a6782 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -65,6 +65,9 @@
   CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
   CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
   CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+
+  CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
+  CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
 }
 
 } // namespace android
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 197f73f..61590e0 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -202,7 +202,7 @@
  * ANativeWindow.
  */
 enum {
-// clang-format off
+    // clang-format off
     NATIVE_WINDOW_SET_USAGE                     =  0,   /* deprecated */
     NATIVE_WINDOW_CONNECT                       =  1,   /* deprecated */
     NATIVE_WINDOW_DISCONNECT                    =  2,   /* deprecated */
@@ -237,7 +237,8 @@
     NATIVE_WINDOW_GET_CONSUMER_USAGE64          = 31,
     NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
     NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
-// clang-format on
+    NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
+    // clang-format on
 };
 
 /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -748,6 +749,27 @@
 }
 
 /*
+ * native_window_set_buffers_hdr10_plus_metadata(..., metadata)
+ * All buffers queued after this call will be associated with the
+ * HDR10+ dynamic metadata specified.
+ *
+ * metadata specifies additional dynamic information about the
+ * contents of the buffer that may affect how it is displayed.  When
+ * it is nullptr, it means no such information is available.  No
+ * HDR10+ dynamic emtadata is associated with the buffers by default.
+ *
+ * Parameter "size" refers to the length of the metadata blob pointed to
+ * by parameter "data".  The metadata blob will adhere to the HDR10+ SEI
+ * message standard.
+ */
+static inline int native_window_set_buffers_hdr10_plus_metadata(struct ANativeWindow* window,
+                                                           const size_t size,
+                                                           const uint8_t* metadata) {
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA, size,
+                           metadata);
+}
+
+/*
  * native_window_set_buffers_transform(..., int transform)
  * All buffers queued after this call will be displayed transformed according
  * to the transform parameter specified.
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 7efc8bd..beaf9ee 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -50,7 +50,6 @@
         "gl/GLExtensions.cpp",
         "gl/GLFramebuffer.cpp",
         "gl/GLImage.cpp",
-        "gl/GLSurface.cpp",
         "gl/Program.cpp",
         "gl/ProgramCache.cpp",
     ],
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index 70a4322..d35762d 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -41,7 +41,6 @@
 #include "GLExtensions.h"
 #include "GLFramebuffer.h"
 #include "GLImage.h"
-#include "GLSurface.h"
 #include "Program.h"
 #include "ProgramCache.h"
 
@@ -275,6 +274,8 @@
 
     // now figure out what version of GL did we actually get
     // NOTE: a dummy surface is not needed if KHR_create_context is supported
+    // TODO(alecmouri): don't create this surface if EGL_KHR_surfaceless_context
+    // is supported.
 
     EGLConfig dummyConfig = config;
     if (dummyConfig == EGL_NO_CONFIG) {
@@ -301,10 +302,10 @@
             break;
         case GLES_VERSION_2_0:
         case GLES_VERSION_3_0:
-            engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+            engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
+                                                          dummy);
             break;
     }
-    engine->setEGLHandles(display, config, ctxt);
 
     ALOGI("OpenGL ES informations:");
     ALOGI("vendor    : %s", extensions.getVendor());
@@ -314,9 +315,6 @@
     ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
     ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
 
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglDestroySurface(display, dummy);
-
     return engine;
 }
 
@@ -359,11 +357,13 @@
     return config;
 }
 
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
+                                       EGLContext ctxt, EGLSurface dummy)
       : renderengine::impl::RenderEngine(featureFlags),
-        mEGLDisplay(EGL_NO_DISPLAY),
-        mEGLConfig(nullptr),
-        mEGLContext(EGL_NO_CONTEXT),
+        mEGLDisplay(display),
+        mEGLConfig(config),
+        mEGLContext(ctxt),
+        mDummySurface(dummy),
         mVpWidth(0),
         mVpHeight(0),
         mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -422,10 +422,6 @@
     return std::make_unique<GLFramebuffer>(*this);
 }
 
-std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
-    return std::make_unique<GLSurface>(*this);
-}
-
 std::unique_ptr<Image> GLES20RenderEngine::createImage() {
     return std::make_unique<GLImage>(*this);
 }
@@ -438,31 +434,6 @@
     return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
 }
 
-bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) {
-    // Surface is an abstract interface. GLES20RenderEngine only ever
-    // creates GLSurface's, so it is safe to just cast to the actual
-    // type.
-    bool success = true;
-    const GLSurface& glSurface = static_cast<const GLSurface&>(surface);
-    EGLSurface eglSurface = glSurface.getEGLSurface();
-    if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
-        success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
-        if (success && glSurface.getAsync()) {
-            eglSwapInterval(mEGLDisplay, 0);
-        }
-        if (success) {
-            mSurfaceHeight = glSurface.getHeight();
-        }
-    }
-
-    return success;
-}
-
-void GLES20RenderEngine::resetCurrentSurface() {
-    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    mSurfaceHeight = 0;
-}
-
 base::unique_fd GLES20RenderEngine::flush() {
     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
         return base::unique_fd();
@@ -576,7 +547,7 @@
 
 void GLES20RenderEngine::setScissor(const Rect& region) {
     // Invert y-coordinate to map to GL-space.
-    int32_t canvasHeight = mRenderToFbo ? mFboHeight : mSurfaceHeight;
+    int32_t canvasHeight = mFboHeight;
     int32_t glBottom = canvasHeight - region.bottom;
 
     glScissor(region.left, glBottom, region.getWidth(), region.getHeight());
@@ -619,7 +590,6 @@
     glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
 
-    mRenderToFbo = true;
     mFboHeight = glFramebuffer->getBufferHeight();
 
     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -631,17 +601,10 @@
 }
 
 void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
-    mRenderToFbo = false;
     mFboHeight = 0;
 
     // back to main framebuffer
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-    // Workaround for b/77935566 to force the EGL driver to release the
-    // screenshot buffer
-    setScissor(Rect::EMPTY_RECT);
-    clearWithColor(0.0, 0.0, 0.0, 0.0);
-    disableScissor();
 }
 
 void GLES20RenderEngine::checkErrors() const {
@@ -666,9 +629,7 @@
     int32_t r = sourceCrop.right;
     int32_t b = sourceCrop.bottom;
     int32_t t = sourceCrop.top;
-    if (mRenderToFbo) {
-        std::swap(t, b);
-    }
+    std::swap(t, b);
     mat4 m = mat4::ortho(l, r, b, t, 0, 1);
 
     // Apply custom rotation to the projection.
@@ -974,12 +935,6 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
-void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
-    mEGLDisplay = display;
-    mEGLConfig = config;
-    mEGLContext = ctxt;
-}
-
 } // namespace gl
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLES20RenderEngine.h
index 148df2f..6c50938 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -40,24 +40,21 @@
 namespace gl {
 
 class GLImage;
-class GLSurface;
 
 class GLES20RenderEngine : public impl::RenderEngine {
 public:
     static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
     static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
-    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
+    GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
+                       EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
     ~GLES20RenderEngine() override;
 
     std::unique_ptr<Framebuffer> createFramebuffer() override;
-    std::unique_ptr<Surface> createSurface() override;
     std::unique_ptr<Image> createImage() override;
 
     void primeCache() const override;
     bool isCurrent() const override;
-    bool setCurrentSurface(const Surface& surface) override;
-    void resetCurrentSurface() override;
     base::unique_fd flush() override;
     bool finish() override;
     bool waitFence(base::unique_fd fenceFd) override;
@@ -120,11 +117,12 @@
     // with PQ or HLG transfer function.
     bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
     bool needsXYZTransformMatrix() const;
-    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
     EGLContext mEGLContext;
+    EGLSurface mDummySurface;
     GLuint mProtectedTexName;
     GLint mMaxViewportDims[2];
     GLint mMaxTextureSize;
@@ -145,8 +143,6 @@
     mat4 mBt2020ToSrgb;
     mat4 mBt2020ToDisplayP3;
 
-    bool mRenderToFbo = false;
-    int32_t mSurfaceHeight = 0;
     int32_t mFboHeight = 0;
 
     // Current dataspace of layer being rendered
diff --git a/libs/renderengine/gl/GLSurface.cpp b/libs/renderengine/gl/GLSurface.cpp
deleted file mode 100644
index 2d694e9..0000000
--- a/libs/renderengine/gl/GLSurface.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 "GLSurface.h"
-
-#include <android/native_window.h>
-#include <log/log.h>
-#include <ui/PixelFormat.h>
-#include "GLES20RenderEngine.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLSurface::GLSurface(const GLES20RenderEngine& engine)
-      : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
-    // RE does not assume any config when EGL_KHR_no_config_context is supported
-    if (mEGLConfig == EGL_NO_CONFIG_KHR) {
-        mEGLConfig =
-                GLES20RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
-    }
-}
-
-GLSurface::~GLSurface() {
-    setNativeWindow(nullptr);
-}
-
-void GLSurface::setNativeWindow(ANativeWindow* window) {
-    if (mEGLSurface != EGL_NO_SURFACE) {
-        eglDestroySurface(mEGLDisplay, mEGLSurface);
-        mEGLSurface = EGL_NO_SURFACE;
-        mSurfaceWidth = 0;
-        mSurfaceHeight = 0;
-    }
-
-    mWindow = window;
-    if (mWindow) {
-        mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
-        mSurfaceWidth = ANativeWindow_getWidth(window);
-        mSurfaceHeight = ANativeWindow_getHeight(window);
-    }
-}
-
-void GLSurface::swapBuffers() const {
-    if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
-        EGLint error = eglGetError();
-
-        const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
-        if (mCritical || error == EGL_CONTEXT_LOST) {
-            LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
-        } else {
-            ALOGE(format, mEGLDisplay, mEGLSurface, error);
-        }
-    }
-}
-
-EGLint GLSurface::queryConfig(EGLint attrib) const {
-    EGLint value;
-    if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
-        value = 0;
-    }
-
-    return value;
-}
-
-int32_t GLSurface::queryRedSize() const {
-    return queryConfig(EGL_RED_SIZE);
-}
-
-int32_t GLSurface::queryGreenSize() const {
-    return queryConfig(EGL_GREEN_SIZE);
-}
-
-int32_t GLSurface::queryBlueSize() const {
-    return queryConfig(EGL_BLUE_SIZE);
-}
-
-int32_t GLSurface::queryAlphaSize() const {
-    return queryConfig(EGL_ALPHA_SIZE);
-}
-
-int32_t GLSurface::getWidth() const {
-    return mSurfaceWidth;
-}
-
-int32_t GLSurface::getHeight() const {
-    return mSurfaceHeight;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLSurface.h b/libs/renderengine/gl/GLSurface.h
deleted file mode 100644
index 092d371..0000000
--- a/libs/renderengine/gl/GLSurface.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <android-base/macros.h>
-#include <renderengine/Surface.h>
-
-struct ANativeWindow;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLES20RenderEngine;
-
-class GLSurface final : public renderengine::Surface {
-public:
-    GLSurface(const GLES20RenderEngine& engine);
-    ~GLSurface() override;
-
-    // renderengine::Surface implementation
-    void setCritical(bool enable) override { mCritical = enable; }
-    void setAsync(bool enable) override { mAsync = enable; }
-
-    void setNativeWindow(ANativeWindow* window) override;
-    void swapBuffers() const override;
-
-    int32_t queryRedSize() const override;
-    int32_t queryGreenSize() const override;
-    int32_t queryBlueSize() const override;
-    int32_t queryAlphaSize() const override;
-
-    bool getAsync() const { return mAsync; }
-    EGLSurface getEGLSurface() const { return mEGLSurface; }
-
-    int32_t getWidth() const override;
-    int32_t getHeight() const override;
-
-private:
-    EGLint queryConfig(EGLint attrib) const;
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-
-    bool mCritical = false;
-    bool mAsync = false;
-
-    int32_t mSurfaceWidth = 0;
-    int32_t mSurfaceHeight = 0;
-
-    ANativeWindow* mWindow = nullptr;
-    EGLSurface mEGLSurface = EGL_NO_SURFACE;
-
-    DISALLOW_COPY_AND_ASSIGN(GLSurface);
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index becb3c3..22891c4 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -48,7 +48,6 @@
 class BindNativeBufferAsFramebuffer;
 class Image;
 class Mesh;
-class Surface;
 class Texture;
 
 namespace impl {
@@ -72,7 +71,6 @@
     // used to support legacy behavior.
 
     virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
-    virtual std::unique_ptr<Surface> createSurface() = 0;
     virtual std::unique_ptr<Image> createImage() = 0;
 
     virtual void primeCache() const = 0;
@@ -84,8 +82,6 @@
     virtual bool useWaitSync() const = 0;
 
     virtual bool isCurrent() const = 0;
-    virtual bool setCurrentSurface(const Surface& surface) = 0;
-    virtual void resetCurrentSurface() = 0;
 
     // helpers
     // flush submits RenderEngine command stream for execution and returns a
diff --git a/libs/renderengine/include/renderengine/Surface.h b/libs/renderengine/include/renderengine/Surface.h
deleted file mode 100644
index ba7331d..0000000
--- a/libs/renderengine/include/renderengine/Surface.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017 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.
- */
-
-#pragma once
-
-#include <cstdint>
-
-struct ANativeWindow;
-
-namespace android {
-namespace renderengine {
-
-class Surface {
-public:
-    virtual ~Surface() = default;
-
-    virtual void setCritical(bool enable) = 0;
-    virtual void setAsync(bool enable) = 0;
-
-    virtual void setNativeWindow(ANativeWindow* window) = 0;
-    virtual void swapBuffers() const = 0;
-
-    virtual int32_t queryRedSize() const = 0;
-    virtual int32_t queryGreenSize() const = 0;
-    virtual int32_t queryBlueSize() const = 0;
-    virtual int32_t queryAlphaSize() const = 0;
-
-    virtual int32_t getWidth() const = 0;
-    virtual int32_t getHeight() const = 0;
-};
-
-} // namespace renderengine
-} // namespace android
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 7e0175a..297e0c4 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -16,52 +16,53 @@
 
 #if defined(__ANDROID__)
 
+#include <cutils/properties.h>
+#include "Loader.h"
 #include "egl_angle_platform.h"
-#include <time.h>
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <EGL/Platform.h>
+#pragma GCC diagnostic pop
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <graphicsenv/GraphicsEnv.h>
+#include <time.h>
 #include <log/log.h>
 
 namespace angle {
 
-GetDisplayPlatformFunc AnglePlatformImpl::angleGetDisplayPlatform = nullptr;
-ResetDisplayPlatformFunc AnglePlatformImpl::angleResetDisplayPlatform = nullptr;
-// Initialize start time
-time_t AnglePlatformImpl::startTime = time(nullptr);
+static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr;
+static ResetDisplayPlatformFunc angleResetDisplayPlatform = nullptr;
 
-void AnglePlatformImpl::assignAnglePlatformMethods(PlatformMethods* platformMethods) {
-    platformMethods->addTraceEvent = addTraceEvent;
-    platformMethods->getTraceCategoryEnabledFlag = getTraceCategoryEnabledFlag;
-    platformMethods->monotonicallyIncreasingTime = monotonicallyIncreasingTime;
-    platformMethods->logError = logError;
-    platformMethods->logWarning = logWarning;
-    platformMethods->logInfo = logInfo;
-}
+static time_t startTime = time(nullptr);
 
-const unsigned char* AnglePlatformImpl::getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
-                                                                    const char* /*categoryName*/) {
+static const unsigned char* getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
+                                                        const char* /*categoryName*/) {
     // Returning ptr to 'g' (non-zero) to ALWAYS enable tracing initially.
     // This ptr is what will be passed into "category_group_enabled" of addTraceEvent
     static const unsigned char traceEnabled = 'g';
     return &traceEnabled;
 }
 
-double AnglePlatformImpl::monotonicallyIncreasingTime(PlatformMethods* /*platform*/) {
+static double monotonicallyIncreasingTime(PlatformMethods* /*platform*/) {
     return difftime(time(nullptr), startTime);
 }
 
-void AnglePlatformImpl::logError(PlatformMethods* /*platform*/, const char* errorMessage) {
+static void logError(PlatformMethods* /*platform*/, const char* errorMessage) {
     ALOGE("ANGLE Error:%s", errorMessage);
 }
 
-void AnglePlatformImpl::logWarning(PlatformMethods* /*platform*/, const char* warningMessage) {
+static void logWarning(PlatformMethods* /*platform*/, const char* warningMessage) {
     ALOGW("ANGLE Warn:%s", warningMessage);
 }
 
-void AnglePlatformImpl::logInfo(PlatformMethods* /*platform*/, const char* infoMessage) {
+static void logInfo(PlatformMethods* /*platform*/, const char* infoMessage) {
     ALOGD("ANGLE Info:%s", infoMessage);
 }
 
-TraceEventHandle AnglePlatformImpl::addTraceEvent(
+static TraceEventHandle addTraceEvent(
         PlatformMethods* /**platform*/, char phase, const unsigned char* /*category_group_enabled*/,
         const char* name, unsigned long long /*id*/, double /*timestamp*/, int /*num_args*/,
         const char** /*arg_names*/, const unsigned char* /*arg_types*/,
@@ -88,6 +89,58 @@
     return result;
 }
 
+static void assignAnglePlatformMethods(PlatformMethods* platformMethods) {
+    platformMethods->addTraceEvent = addTraceEvent;
+    platformMethods->getTraceCategoryEnabledFlag = getTraceCategoryEnabledFlag;
+    platformMethods->monotonicallyIncreasingTime = monotonicallyIncreasingTime;
+    platformMethods->logError = logError;
+    platformMethods->logWarning = logWarning;
+    platformMethods->logInfo = logInfo;
+}
+
+// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace
+bool initializeAnglePlatform(EGLDisplay dpy) {
+    // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform
+    android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+    const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = ns,
+    };
+    void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    angleGetDisplayPlatform =
+            reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
+
+    if (!angleGetDisplayPlatform) {
+        ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!");
+        return false;
+    }
+
+    angleResetDisplayPlatform =
+            reinterpret_cast<ResetDisplayPlatformFunc>(
+                    eglGetProcAddress("ANGLEResetDisplayPlatform"));
+
+    PlatformMethods* platformMethods = nullptr;
+    if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames,
+                                                              g_NumPlatformMethods, nullptr,
+                                                              &platformMethods))) {
+        ALOGE("ANGLEGetDisplayPlatform call failed!");
+        return false;
+    }
+    if (platformMethods) {
+        assignAnglePlatformMethods(platformMethods);
+    } else {
+        ALOGE("In initializeAnglePlatform() platformMethods struct ptr is NULL. Not assigning "
+              "tracing function ptrs!");
+    }
+    return true;
+}
+
+void resetAnglePlatform(EGLDisplay dpy) {
+    if (angleResetDisplayPlatform) {
+        angleResetDisplayPlatform(dpy);
+    }
+}
+
 }; // namespace angle
 
 #endif // __ANDROID__
diff --git a/opengl/libs/EGL/egl_angle_platform.h b/opengl/libs/EGL/egl_angle_platform.h
index 7c6c8ed..6c24aa5 100644
--- a/opengl/libs/EGL/egl_angle_platform.h
+++ b/opengl/libs/EGL/egl_angle_platform.h
@@ -18,40 +18,15 @@
 
 #if defined(__ANDROID__)
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <EGL/Platform.h>
-#pragma GCC diagnostic pop
+#include "egldefs.h"
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
 #include "egl_trace.h"
 
 namespace angle {
 
-class AnglePlatformImpl {
-public:
-    static void assignAnglePlatformMethods(PlatformMethods* platformMethods);
-    static GetDisplayPlatformFunc angleGetDisplayPlatform;
-    static ResetDisplayPlatformFunc angleResetDisplayPlatform;
-
-private:
-    static time_t startTime;
-    static const unsigned char* getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
-                                                            const char* /*categoryName*/);
-    static double monotonicallyIncreasingTime(PlatformMethods* /*platform*/);
-    static void logError(PlatformMethods* /*platform*/, const char* errorMessage);
-    static void logWarning(PlatformMethods* /*platform*/, const char* warningMessage);
-    static void logInfo(PlatformMethods* /*platform*/, const char* infoMessage);
-    static TraceEventHandle addTraceEvent(PlatformMethods* /**platform*/, char phase,
-                                          const unsigned char* /*category_group_enabled*/,
-                                          const char* name, unsigned long long /*id*/,
-                                          double /*timestamp*/, int /*num_args*/,
-                                          const char** /*arg_names*/,
-                                          const unsigned char* /*arg_types*/,
-                                          const unsigned long long* /*arg_values*/,
-                                          unsigned char /*flags*/);
-};
+bool initializeAnglePlatform(EGLDisplay dpy);
+void resetAnglePlatform(EGLDisplay dpy);
 
 }; // namespace angle
 
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a065973..4433af0 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -164,43 +164,6 @@
     return true;
 }
 
-// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace
-bool initializeAnglePlatform(EGLDisplay dpy) {
-    // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform
-    android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
-    const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = ns,
-    };
-    void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-    angle::AnglePlatformImpl::angleGetDisplayPlatform =
-            reinterpret_cast<angle::GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
-
-    if (!angle::AnglePlatformImpl::angleGetDisplayPlatform) {
-        ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!");
-        return false;
-    }
-
-    angle::AnglePlatformImpl::angleResetDisplayPlatform =
-            reinterpret_cast<angle::ResetDisplayPlatformFunc>(
-                    eglGetProcAddress("ANGLEResetDisplayPlatform"));
-
-    angle::PlatformMethods* platformMethods = nullptr;
-    if (!((angle::AnglePlatformImpl::angleGetDisplayPlatform)(dpy, angle::g_PlatformMethodNames,
-                                                              angle::g_NumPlatformMethods, nullptr,
-                                                              &platformMethods))) {
-        ALOGE("ANGLEGetDisplayPlatform call failed!");
-        return false;
-    }
-    if (platformMethods) {
-        angle::AnglePlatformImpl::assignAnglePlatformMethods(platformMethods);
-    } else {
-        ALOGE("In initializeAnglePlatform() platformMethods struct ptr is NULL. Not assigning "
-              "tracing function ptrs!");
-    }
-    return true;
-}
-
 static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
                                           const EGLAttrib* attrib_list, EGLint* error) {
     EGLDisplay dpy = EGL_NO_DISPLAY;
@@ -228,7 +191,7 @@
         if (dpy == EGL_NO_DISPLAY) {
             ALOGE("eglGetPlatformDisplay failed!");
         } else {
-            if (!initializeAnglePlatform(dpy)) {
+            if (!angle::initializeAnglePlatform(dpy)) {
                 ALOGE("initializeAnglePlatform failed!");
             }
         }
@@ -505,8 +468,8 @@
         egl_connection_t* const cnx = &gEGLImpl;
         if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
             // If we're using ANGLE reset any custom DisplayPlatform
-            if (cnx->useAngle && angle::AnglePlatformImpl::angleResetDisplayPlatform) {
-                (angle::AnglePlatformImpl::angleResetDisplayPlatform)(disp.dpy);
+            if (cnx->useAngle) {
+                angle::resetAnglePlatform(disp.dpy);
             }
             if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
                 ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 7812cb2..4a8b613 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -18,24 +18,20 @@
     cpp_std: "c++17",
 
     srcs: [
-        "EventHub.cpp",
         "InputDispatcher.cpp",
-        "InputListener.cpp",
         "InputManager.cpp",
-        "InputReader.cpp",
     ],
 
     shared_libs: [
+        "libinputflinger_base",
+        "libinputreader",
         "libbase",
         "libbinder",
-        "libcrypto",
         "libcutils",
         "libinput",
         "liblog",
         "libutils",
         "libui",
-        "libhardware_legacy",
-        "libutils"
     ],
 
     cflags: [
@@ -47,7 +43,91 @@
         //-fvisibility=hidden
     ],
 
-    export_include_dirs: ["."],
+    export_include_dirs: [
+        ".",
+        "include",
+    ],
+
+}
+
+
+cc_library_headers {
+   name: "libinputflinger_headers",
+
+   export_include_dirs: ["include"],
+}
+
+cc_library_shared {
+    name: "libinputreader",
+
+    cpp_std: "c++17",
+
+    srcs: [
+        "EventHub.cpp",
+        "InputReader.cpp",
+        "InputReaderFactory.cpp",
+    ],
+
+    shared_libs: [
+        "libinputflinger_base",
+        "libbase",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libutils",
+        "libui",
+        "libhardware_legacy",
+        "libutils"
+    ],
+
+    header_libs: [
+        "libinputflinger_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libinputflinger_headers",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+}
+
+cc_library_shared {
+    name: "libinputflinger_base",
+
+    cpp_std: "c++17",
+
+    srcs: [
+        "InputListener.cpp",
+        "InputReaderBase.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libinput",
+        "liblog",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libinputflinger_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libinputflinger_headers",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
 }
 
 subdirs = [
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 40ca6a7..388423c 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 
 #include "InputManager.h"
+#include "InputReaderFactory.h"
 
 #include <log/log.h>
 #include <unordered_map>
@@ -26,19 +27,10 @@
 namespace android {
 
 InputManager::InputManager(
-        const sp<EventHubInterface>& eventHub,
         const sp<InputReaderPolicyInterface>& readerPolicy,
         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
     mDispatcher = new InputDispatcher(dispatcherPolicy);
-    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
-    initialize();
-}
-
-InputManager::InputManager(
-        const sp<InputReaderInterface>& reader,
-        const sp<InputDispatcherInterface>& dispatcher) :
-        mReader(reader),
-        mDispatcher(dispatcher) {
+    mReader = createInputReader(readerPolicy, mDispatcher);
     initialize();
 }
 
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index d0e4cb0..1173fa1 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -22,7 +22,7 @@
  */
 
 #include "EventHub.h"
-#include "InputReader.h"
+#include "InputReaderBase.h"
 #include "InputDispatcher.h"
 
 #include <input/Input.h>
@@ -80,15 +80,9 @@
 
 public:
     InputManager(
-            const sp<EventHubInterface>& eventHub,
             const sp<InputReaderPolicyInterface>& readerPolicy,
             const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
 
-    // (used for testing purposes)
-    InputManager(
-            const sp<InputReaderInterface>& reader,
-            const sp<InputDispatcherInterface>& dispatcher);
-
     virtual status_t start();
     virtual status_t stop();
 
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index e85e6ef..9dd14dc 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -254,47 +254,6 @@
 }
 
 
-// --- InputReaderConfiguration ---
-
-std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewport(
-        ViewportType viewportType, const std::string& uniqueDisplayId) const {
-    for (const DisplayViewport& currentViewport : mDisplays) {
-        if (currentViewport.type == viewportType) {
-            if (uniqueDisplayId.empty() ||
-                    (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) {
-                return std::make_optional(currentViewport);
-            }
-        }
-    }
-    return std::nullopt;
-}
-
-void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
-    mDisplays = viewports;
-}
-
-void InputReaderConfiguration::dump(std::string& dump) const {
-    for (const DisplayViewport& viewport : mDisplays) {
-        dumpViewport(dump, viewport);
-    }
-}
-
-void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport)
-        const {
-    dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str());
-}
-
-
-// -- TouchAffineTransformation --
-void TouchAffineTransformation::applyTo(float& x, float& y) const {
-    float newX, newY;
-    newX = x * x_scale + y * x_ymix + x_offset;
-    newY = x * y_xmix + y * y_scale + y_offset;
-
-    x = newX;
-    y = newY;
-}
-
 
 // --- InputReader ---
 
@@ -987,21 +946,6 @@
 }
 
 
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
-        Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
-    mReader->loopOnce();
-    return true;
-}
-
-
 // --- InputDevice ---
 
 InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 9b0007a..1786fe8 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -20,6 +20,7 @@
 #include "EventHub.h"
 #include "PointerControllerInterface.h"
 #include "InputListener.h"
+#include "InputReaderBase.h"
 
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
@@ -28,314 +29,20 @@
 #include <ui/DisplayInfo.h>
 #include <utils/KeyedVector.h>
 #include <utils/Condition.h>
-#include <utils/Thread.h>
 #include <utils/Mutex.h>
 #include <utils/Timers.h>
-#include <utils/RefBase.h>
 #include <utils/BitSet.h>
-#include <utils/SortedVector.h>
 
 #include <optional>
 #include <stddef.h>
 #include <unistd.h>
 #include <vector>
 
-// Maximum supported size of a vibration pattern.
-// Must be at least 2.
-#define MAX_VIBRATE_PATTERN_SIZE 100
-
-// Maximum allowable delay value in a vibration pattern before
-// which the delay will be truncated.
-#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
-
 namespace android {
 
 class InputDevice;
 class InputMapper;
 
-/*
- * Input reader configuration.
- *
- * Specifies various options that modify the behavior of the input reader.
- */
-struct InputReaderConfiguration {
-    // Describes changes that have occurred.
-    enum {
-        // The pointer speed changed.
-        CHANGE_POINTER_SPEED = 1 << 0,
-
-        // The pointer gesture control changed.
-        CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
-
-        // The display size or orientation changed.
-        CHANGE_DISPLAY_INFO = 1 << 2,
-
-        // The visible touches option changed.
-        CHANGE_SHOW_TOUCHES = 1 << 3,
-
-        // The keyboard layouts must be reloaded.
-        CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
-
-        // The device name alias supplied by the may have changed for some devices.
-        CHANGE_DEVICE_ALIAS = 1 << 5,
-
-        // The location calibration matrix changed.
-        CHANGE_TOUCH_AFFINE_TRANSFORMATION = 1 << 6,
-
-        // The presence of an external stylus has changed.
-        CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7,
-
-        // The pointer capture mode has changed.
-        CHANGE_POINTER_CAPTURE = 1 << 8,
-
-        // The set of disabled input devices (disabledDevices) has changed.
-        CHANGE_ENABLED_STATE = 1 << 9,
-
-        // All devices must be reopened.
-        CHANGE_MUST_REOPEN = 1 << 31,
-    };
-
-    // Gets the amount of time to disable virtual keys after the screen is touched
-    // in order to filter out accidental virtual key presses due to swiping gestures
-    // or taps near the edge of the display.  May be 0 to disable the feature.
-    nsecs_t virtualKeyQuietTime;
-
-    // The excluded device names for the platform.
-    // Devices with these names will be ignored.
-    std::vector<std::string> excludedDeviceNames;
-
-    // Velocity control parameters for mouse pointer movements.
-    VelocityControlParameters pointerVelocityControlParameters;
-
-    // Velocity control parameters for mouse wheel movements.
-    VelocityControlParameters wheelVelocityControlParameters;
-
-    // True if pointer gestures are enabled.
-    bool pointerGesturesEnabled;
-
-    // Quiet time between certain pointer gesture transitions.
-    // Time to allow for all fingers or buttons to settle into a stable state before
-    // starting a new gesture.
-    nsecs_t pointerGestureQuietInterval;
-
-    // The minimum speed that a pointer must travel for us to consider switching the active
-    // touch pointer to it during a drag.  This threshold is set to avoid switching due
-    // to noise from a finger resting on the touch pad (perhaps just pressing it down).
-    float pointerGestureDragMinSwitchSpeed; // in pixels per second
-
-    // Tap gesture delay time.
-    // The time between down and up must be less than this to be considered a tap.
-    nsecs_t pointerGestureTapInterval;
-
-    // Tap drag gesture delay time.
-    // The time between the previous tap's up and the next down must be less than
-    // this to be considered a drag.  Otherwise, the previous tap is finished and a
-    // new tap begins.
-    //
-    // Note that the previous tap will be held down for this entire duration so this
-    // interval must be shorter than the long press timeout.
-    nsecs_t pointerGestureTapDragInterval;
-
-    // The distance in pixels that the pointer is allowed to move from initial down
-    // to up and still be called a tap.
-    float pointerGestureTapSlop; // in pixels
-
-    // Time after the first touch points go down to settle on an initial centroid.
-    // This is intended to be enough time to handle cases where the user puts down two
-    // fingers at almost but not quite exactly the same time.
-    nsecs_t pointerGestureMultitouchSettleInterval;
-
-    // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
-    // at least two pointers have moved at least this far from their starting place.
-    float pointerGestureMultitouchMinDistance; // in pixels
-
-    // The transition from PRESS to SWIPE gesture mode can only occur when the
-    // cosine of the angle between the two vectors is greater than or equal to than this value
-    // which indicates that the vectors are oriented in the same direction.
-    // When the vectors are oriented in the exactly same direction, the cosine is 1.0.
-    // (In exactly opposite directions, the cosine is -1.0.)
-    float pointerGestureSwipeTransitionAngleCosine;
-
-    // The transition from PRESS to SWIPE gesture mode can only occur when the
-    // fingers are no more than this far apart relative to the diagonal size of
-    // the touch pad.  For example, a ratio of 0.5 means that the fingers must be
-    // no more than half the diagonal size of the touch pad apart.
-    float pointerGestureSwipeMaxWidthRatio;
-
-    // The gesture movement speed factor relative to the size of the display.
-    // Movement speed applies when the fingers are moving in the same direction.
-    // Without acceleration, a full swipe of the touch pad diagonal in movement mode
-    // will cover this portion of the display diagonal.
-    float pointerGestureMovementSpeedRatio;
-
-    // The gesture zoom speed factor relative to the size of the display.
-    // Zoom speed applies when the fingers are mostly moving relative to each other
-    // to execute a scale gesture or similar.
-    // Without acceleration, a full swipe of the touch pad diagonal in zoom mode
-    // will cover this portion of the display diagonal.
-    float pointerGestureZoomSpeedRatio;
-
-    // True to show the location of touches on the touch screen as spots.
-    bool showTouches;
-
-    // True if pointer capture is enabled.
-    bool pointerCapture;
-
-    // The set of currently disabled input devices.
-    SortedVector<int32_t> disabledDevices;
-
-    InputReaderConfiguration() :
-            virtualKeyQuietTime(0),
-            pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
-            wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
-            pointerGesturesEnabled(true),
-            pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
-            pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
-            pointerGestureTapInterval(150 * 1000000LL), // 150 ms
-            pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
-            pointerGestureTapSlop(10.0f), // 10 pixels
-            pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
-            pointerGestureMultitouchMinDistance(15), // 15 pixels
-            pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees
-            pointerGestureSwipeMaxWidthRatio(0.25f),
-            pointerGestureMovementSpeedRatio(0.8f),
-            pointerGestureZoomSpeedRatio(0.3f),
-            showTouches(false) { }
-
-    std::optional<DisplayViewport> getDisplayViewport(ViewportType viewportType,
-            const std::string& uniqueDisplayId) const;
-    void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
-
-
-    void dump(std::string& dump) const;
-    void dumpViewport(std::string& dump, const DisplayViewport& viewport) const;
-
-private:
-    std::vector<DisplayViewport> mDisplays;
-};
-
-
-struct TouchAffineTransformation {
-    float x_scale;
-    float x_ymix;
-    float x_offset;
-    float y_xmix;
-    float y_scale;
-    float y_offset;
-
-    TouchAffineTransformation() :
-        x_scale(1.0f), x_ymix(0.0f), x_offset(0.0f),
-        y_xmix(0.0f), y_scale(1.0f), y_offset(0.0f) {
-    }
-
-    TouchAffineTransformation(float xscale, float xymix, float xoffset,
-            float yxmix, float yscale, float yoffset) :
-        x_scale(xscale), x_ymix(xymix), x_offset(xoffset),
-        y_xmix(yxmix), y_scale(yscale), y_offset(yoffset) {
-    }
-
-    void applyTo(float& x, float& y) const;
-};
-
-
-/*
- * Input reader policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- *
- * These methods must NOT re-enter the input reader since they may be called while
- * holding the input reader lock.
- */
-class InputReaderPolicyInterface : public virtual RefBase {
-protected:
-    InputReaderPolicyInterface() { }
-    virtual ~InputReaderPolicyInterface() { }
-
-public:
-    /* Gets the input reader configuration. */
-    virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
-
-    /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
-    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
-
-    /* Notifies the input reader policy that some input devices have changed
-     * and provides information about all current input devices.
-     */
-    virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
-
-    /* Gets the keyboard layout for a particular input device. */
-    virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(
-            const InputDeviceIdentifier& identifier) = 0;
-
-    /* Gets a user-supplied alias for a particular input device, or an empty string if none. */
-    virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
-
-    /* Gets the affine calibration associated with the specified device. */
-    virtual TouchAffineTransformation getTouchAffineTransformation(
-            const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
-};
-
-
-/* Processes raw input events and sends cooked event data to an input listener. */
-class InputReaderInterface : public virtual RefBase {
-protected:
-    InputReaderInterface() { }
-    virtual ~InputReaderInterface() { }
-
-public:
-    /* Dumps the state of the input reader.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(std::string& dump) = 0;
-
-    /* Called by the heatbeat to ensures that the reader has not deadlocked. */
-    virtual void monitor() = 0;
-
-    /* Returns true if the input device is enabled. */
-    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
-
-    /* Runs a single iteration of the processing loop.
-     * Nominally reads and processes one incoming message from the EventHub.
-     *
-     * This method should be called on the input reader thread.
-     */
-    virtual void loopOnce() = 0;
-
-    /* Gets information about all input devices.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0;
-
-    /* Query current input state. */
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t scanCode) = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t keyCode) = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
-            int32_t sw) = 0;
-
-    /* Toggle Caps Lock */
-    virtual void toggleCapsLockState(int32_t deviceId) = 0;
-
-    /* Determine whether physical keys exist for the given framework-domain key codes. */
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
-            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
-
-    /* Requests that a reconfiguration of all input devices.
-     * The changes flag is a bitfield that indicates what has changed and whether
-     * the input devices must all be reopened. */
-    virtual void requestRefreshConfiguration(uint32_t changes) = 0;
-
-    /* Controls the vibrator of a particular input device. */
-    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
-            ssize_t repeat, int32_t token) = 0;
-    virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
-};
 
 struct StylusState {
     /* Time the stylus event was received. */
@@ -527,19 +234,6 @@
 };
 
 
-/* Reads raw events from the event hub and processes them, endlessly. */
-class InputReaderThread : public Thread {
-public:
-    explicit InputReaderThread(const sp<InputReaderInterface>& reader);
-    virtual ~InputReaderThread();
-
-private:
-    sp<InputReaderInterface> mReader;
-
-    virtual bool threadLoop();
-};
-
-
 /* Represents the state of a single input device. */
 class InputDevice {
 public:
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
new file mode 100644
index 0000000..17a116e
--- /dev/null
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "InputReaderBase"
+
+//#define LOG_NDEBUG 0
+
+#include "InputReaderBase.h"
+
+#include <android/log.h>
+#include <android-base/stringprintf.h>
+
+#define INDENT "  "
+#define INDENT2 "    "
+#define INDENT3 "      "
+#define INDENT4 "        "
+#define INDENT5 "          "
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// --- InputReaderThread ---
+
+InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
+        Thread(/*canCallJava*/ true), mReader(reader) {
+}
+
+InputReaderThread::~InputReaderThread() {
+}
+
+bool InputReaderThread::threadLoop() {
+    mReader->loopOnce();
+    return true;
+}
+
+// --- InputReaderConfiguration ---
+
+std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewport(
+        ViewportType viewportType, const std::string& uniqueDisplayId) const {
+    for (const DisplayViewport& currentViewport : mDisplays) {
+        if (currentViewport.type == viewportType) {
+            if (uniqueDisplayId.empty() ||
+                    (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) {
+                return std::make_optional(currentViewport);
+            }
+        }
+    }
+    return std::nullopt;
+}
+
+void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
+    mDisplays = viewports;
+}
+
+void InputReaderConfiguration::dump(std::string& dump) const {
+    for (const DisplayViewport& viewport : mDisplays) {
+        dumpViewport(dump, viewport);
+    }
+}
+
+void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport)
+        const {
+    dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str());
+}
+
+
+// -- TouchAffineTransformation --
+void TouchAffineTransformation::applyTo(float& x, float& y) const {
+    float newX, newY;
+    newX = x * x_scale + y * x_ymix + x_offset;
+    newY = x * y_xmix + y * y_scale + y_offset;
+
+    x = newX;
+    y = newY;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/InputReaderFactory.cpp b/services/inputflinger/InputReaderFactory.cpp
new file mode 100644
index 0000000..3534f6b
--- /dev/null
+++ b/services/inputflinger/InputReaderFactory.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 "InputReaderFactory.h"
+#include "InputReader.h"
+
+namespace android {
+
+sp<InputReaderInterface> createInputReader(
+        const sp<InputReaderPolicyInterface>& policy,
+        const sp<InputListenerInterface>& listener) {
+    return new InputReader(new EventHub(), policy, listener);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/include/EventHub.h
similarity index 100%
rename from services/inputflinger/EventHub.h
rename to services/inputflinger/include/EventHub.h
diff --git a/services/inputflinger/InputListener.h b/services/inputflinger/include/InputListener.h
similarity index 100%
rename from services/inputflinger/InputListener.h
rename to services/inputflinger/include/InputListener.h
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
new file mode 100644
index 0000000..fff8480
--- /dev/null
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _UI_INPUT_READER_BASE_H
+#define _UI_INPUT_READER_BASE_H
+
+#include "PointerControllerInterface.h"
+
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <input/DisplayViewport.h>
+#include <input/VelocityControl.h>
+#include <input/VelocityTracker.h>
+#include <utils/KeyedVector.h>
+#include <utils/Thread.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+
+#include <optional>
+#include <stddef.h>
+#include <unistd.h>
+#include <vector>
+
+// Maximum supported size of a vibration pattern.
+// Must be at least 2.
+#define MAX_VIBRATE_PATTERN_SIZE 100
+
+// Maximum allowable delay value in a vibration pattern before
+// which the delay will be truncated.
+#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
+
+namespace android {
+
+/* Processes raw input events and sends cooked event data to an input listener. */
+class InputReaderInterface : public virtual RefBase {
+protected:
+    InputReaderInterface() { }
+    virtual ~InputReaderInterface() { }
+
+public:
+    /* Dumps the state of the input reader.
+     *
+     * This method may be called on any thread (usually by the input manager). */
+    virtual void dump(std::string& dump) = 0;
+
+    /* Called by the heatbeat to ensures that the reader has not deadlocked. */
+    virtual void monitor() = 0;
+
+    /* Returns true if the input device is enabled. */
+    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
+
+    /* Runs a single iteration of the processing loop.
+     * Nominally reads and processes one incoming message from the EventHub.
+     *
+     * This method should be called on the input reader thread.
+     */
+    virtual void loopOnce() = 0;
+
+    /* Gets information about all input devices.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0;
+
+    /* Query current input state. */
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode) = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode) = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw) = 0;
+
+    /* Toggle Caps Lock */
+    virtual void toggleCapsLockState(int32_t deviceId) = 0;
+
+    /* Determine whether physical keys exist for the given framework-domain key codes. */
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+
+    /* Requests that a reconfiguration of all input devices.
+     * The changes flag is a bitfield that indicates what has changed and whether
+     * the input devices must all be reopened. */
+    virtual void requestRefreshConfiguration(uint32_t changes) = 0;
+
+    /* Controls the vibrator of a particular input device. */
+    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+            ssize_t repeat, int32_t token) = 0;
+    virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
+};
+
+/* Reads raw events from the event hub and processes them, endlessly. */
+class InputReaderThread : public Thread {
+public:
+    explicit InputReaderThread(const sp<InputReaderInterface>& reader);
+    virtual ~InputReaderThread();
+
+private:
+    sp<InputReaderInterface> mReader;
+
+    virtual bool threadLoop();
+};
+
+/*
+ * Input reader configuration.
+ *
+ * Specifies various options that modify the behavior of the input reader.
+ */
+struct InputReaderConfiguration {
+    // Describes changes that have occurred.
+    enum {
+        // The pointer speed changed.
+        CHANGE_POINTER_SPEED = 1 << 0,
+
+        // The pointer gesture control changed.
+        CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
+
+        // The display size or orientation changed.
+        CHANGE_DISPLAY_INFO = 1 << 2,
+
+        // The visible touches option changed.
+        CHANGE_SHOW_TOUCHES = 1 << 3,
+
+        // The keyboard layouts must be reloaded.
+        CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
+
+        // The device name alias supplied by the may have changed for some devices.
+        CHANGE_DEVICE_ALIAS = 1 << 5,
+
+        // The location calibration matrix changed.
+        CHANGE_TOUCH_AFFINE_TRANSFORMATION = 1 << 6,
+
+        // The presence of an external stylus has changed.
+        CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7,
+
+        // The pointer capture mode has changed.
+        CHANGE_POINTER_CAPTURE = 1 << 8,
+
+        // The set of disabled input devices (disabledDevices) has changed.
+        CHANGE_ENABLED_STATE = 1 << 9,
+
+        // All devices must be reopened.
+        CHANGE_MUST_REOPEN = 1 << 31,
+    };
+
+    // Gets the amount of time to disable virtual keys after the screen is touched
+    // in order to filter out accidental virtual key presses due to swiping gestures
+    // or taps near the edge of the display.  May be 0 to disable the feature.
+    nsecs_t virtualKeyQuietTime;
+
+    // The excluded device names for the platform.
+    // Devices with these names will be ignored.
+    std::vector<std::string> excludedDeviceNames;
+
+    // Velocity control parameters for mouse pointer movements.
+    VelocityControlParameters pointerVelocityControlParameters;
+
+    // Velocity control parameters for mouse wheel movements.
+    VelocityControlParameters wheelVelocityControlParameters;
+
+    // True if pointer gestures are enabled.
+    bool pointerGesturesEnabled;
+
+    // Quiet time between certain pointer gesture transitions.
+    // Time to allow for all fingers or buttons to settle into a stable state before
+    // starting a new gesture.
+    nsecs_t pointerGestureQuietInterval;
+
+    // The minimum speed that a pointer must travel for us to consider switching the active
+    // touch pointer to it during a drag.  This threshold is set to avoid switching due
+    // to noise from a finger resting on the touch pad (perhaps just pressing it down).
+    float pointerGestureDragMinSwitchSpeed; // in pixels per second
+
+    // Tap gesture delay time.
+    // The time between down and up must be less than this to be considered a tap.
+    nsecs_t pointerGestureTapInterval;
+
+    // Tap drag gesture delay time.
+    // The time between the previous tap's up and the next down must be less than
+    // this to be considered a drag.  Otherwise, the previous tap is finished and a
+    // new tap begins.
+    //
+    // Note that the previous tap will be held down for this entire duration so this
+    // interval must be shorter than the long press timeout.
+    nsecs_t pointerGestureTapDragInterval;
+
+    // The distance in pixels that the pointer is allowed to move from initial down
+    // to up and still be called a tap.
+    float pointerGestureTapSlop; // in pixels
+
+    // Time after the first touch points go down to settle on an initial centroid.
+    // This is intended to be enough time to handle cases where the user puts down two
+    // fingers at almost but not quite exactly the same time.
+    nsecs_t pointerGestureMultitouchSettleInterval;
+
+    // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
+    // at least two pointers have moved at least this far from their starting place.
+    float pointerGestureMultitouchMinDistance; // in pixels
+
+    // The transition from PRESS to SWIPE gesture mode can only occur when the
+    // cosine of the angle between the two vectors is greater than or equal to than this value
+    // which indicates that the vectors are oriented in the same direction.
+    // When the vectors are oriented in the exactly same direction, the cosine is 1.0.
+    // (In exactly opposite directions, the cosine is -1.0.)
+    float pointerGestureSwipeTransitionAngleCosine;
+
+    // The transition from PRESS to SWIPE gesture mode can only occur when the
+    // fingers are no more than this far apart relative to the diagonal size of
+    // the touch pad.  For example, a ratio of 0.5 means that the fingers must be
+    // no more than half the diagonal size of the touch pad apart.
+    float pointerGestureSwipeMaxWidthRatio;
+
+    // The gesture movement speed factor relative to the size of the display.
+    // Movement speed applies when the fingers are moving in the same direction.
+    // Without acceleration, a full swipe of the touch pad diagonal in movement mode
+    // will cover this portion of the display diagonal.
+    float pointerGestureMovementSpeedRatio;
+
+    // The gesture zoom speed factor relative to the size of the display.
+    // Zoom speed applies when the fingers are mostly moving relative to each other
+    // to execute a scale gesture or similar.
+    // Without acceleration, a full swipe of the touch pad diagonal in zoom mode
+    // will cover this portion of the display diagonal.
+    float pointerGestureZoomSpeedRatio;
+
+    // True to show the location of touches on the touch screen as spots.
+    bool showTouches;
+
+    // True if pointer capture is enabled.
+    bool pointerCapture;
+
+    // The set of currently disabled input devices.
+    SortedVector<int32_t> disabledDevices;
+
+    InputReaderConfiguration() :
+            virtualKeyQuietTime(0),
+            pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
+            wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
+            pointerGesturesEnabled(true),
+            pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
+            pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
+            pointerGestureTapInterval(150 * 1000000LL), // 150 ms
+            pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
+            pointerGestureTapSlop(10.0f), // 10 pixels
+            pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
+            pointerGestureMultitouchMinDistance(15), // 15 pixels
+            pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees
+            pointerGestureSwipeMaxWidthRatio(0.25f),
+            pointerGestureMovementSpeedRatio(0.8f),
+            pointerGestureZoomSpeedRatio(0.3f),
+            showTouches(false) { }
+
+    std::optional<DisplayViewport> getDisplayViewport(ViewportType viewportType,
+            const std::string& uniqueDisplayId) const;
+    void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
+
+
+    void dump(std::string& dump) const;
+    void dumpViewport(std::string& dump, const DisplayViewport& viewport) const;
+
+private:
+    std::vector<DisplayViewport> mDisplays;
+};
+
+struct TouchAffineTransformation {
+    float x_scale;
+    float x_ymix;
+    float x_offset;
+    float y_xmix;
+    float y_scale;
+    float y_offset;
+
+    TouchAffineTransformation() :
+        x_scale(1.0f), x_ymix(0.0f), x_offset(0.0f),
+        y_xmix(0.0f), y_scale(1.0f), y_offset(0.0f) {
+    }
+
+    TouchAffineTransformation(float xscale, float xymix, float xoffset,
+            float yxmix, float yscale, float yoffset) :
+        x_scale(xscale), x_ymix(xymix), x_offset(xoffset),
+        y_xmix(yxmix), y_scale(yscale), y_offset(yoffset) {
+    }
+
+    void applyTo(float& x, float& y) const;
+};
+
+/*
+ * Input reader policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI.  This interface is also mocked in the unit tests.
+ *
+ * These methods must NOT re-enter the input reader since they may be called while
+ * holding the input reader lock.
+ */
+class InputReaderPolicyInterface : public virtual RefBase {
+protected:
+    InputReaderPolicyInterface() { }
+    virtual ~InputReaderPolicyInterface() { }
+
+public:
+    /* Gets the input reader configuration. */
+    virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
+
+    /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
+    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
+
+    /* Notifies the input reader policy that some input devices have changed
+     * and provides information about all current input devices.
+     */
+    virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
+
+    /* Gets the keyboard layout for a particular input device. */
+    virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(
+            const InputDeviceIdentifier& identifier) = 0;
+
+    /* Gets a user-supplied alias for a particular input device, or an empty string if none. */
+    virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
+
+    /* Gets the affine calibration associated with the specified device. */
+    virtual TouchAffineTransformation getTouchAffineTransformation(
+            const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_COMMON_H
\ No newline at end of file
diff --git a/services/inputflinger/include/InputReaderFactory.h b/services/inputflinger/include/InputReaderFactory.h
new file mode 100644
index 0000000..9db6233
--- /dev/null
+++ b/services/inputflinger/include/InputReaderFactory.h
@@ -0,0 +1,29 @@
+/*
+ * 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 <utils/StrongPointer.h>
+
+namespace android {
+
+class InputReaderInterface;
+class InputReaderPolicyInterface;
+class InputListenerInterface;
+
+sp<InputReaderInterface> createInputReader(
+        const sp<InputReaderPolicyInterface>& policy,
+        const sp<InputListenerInterface>& listener);
+
+} // namespace android
diff --git a/services/inputflinger/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
similarity index 100%
rename from services/inputflinger/PointerControllerInterface.h
rename to services/inputflinger/include/PointerControllerInterface.h
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index ea42855..389a57c 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -24,6 +24,8 @@
         "libui",
         "libinput",
         "libinputflinger",
+        "libinputreader",
+        "libinputflinger_base",
         "libinputservice",
     ],
 }
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 6114f51..929424b 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1753,11 +1753,11 @@
         mFakePolicy->clearViewports();
     }
 
-    static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
+    static void process(InputMapper* mapper, nsecs_t when, int32_t type,
             int32_t code, int32_t value) {
         RawEvent event;
         event.when = when;
-        event.deviceId = deviceId;
+        event.deviceId = mapper->getDeviceId();
         event.type = type;
         event.code = code;
         event.value = value;
@@ -1835,10 +1835,10 @@
     SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
     addMapperAndConfigure(mapper);
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_HEADPHONE_INSERT, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SW, SW_LID, 1);
+    process(mapper, ARBITRARY_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
+    process(mapper, ARBITRARY_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
 
     NotifySwitchArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args));
@@ -1874,13 +1874,13 @@
         int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
     NotifyKeyArgs args;
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, originalScanCode, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
     ASSERT_EQ(originalScanCode, args.scanCode);
     ASSERT_EQ(rotatedKeyCode, args.keyCode);
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, originalScanCode, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
     ASSERT_EQ(originalScanCode, args.scanCode);
@@ -1907,8 +1907,7 @@
     addMapperAndConfigure(mapper);
 
     // Key down by scan code.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1);
     NotifyKeyArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -1923,8 +1922,7 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Key up by scan code.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_HOME, 0);
+    process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
@@ -1938,10 +1936,8 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Key down by usage code.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_MSC, MSC_SCAN, USAGE_A);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, 0, 1);
+    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_A);
+    process(mapper, ARBITRARY_TIME, EV_KEY, 0, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
@@ -1955,10 +1951,8 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Key up by usage code.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_MSC, MSC_SCAN, USAGE_A);
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, 0, 0);
+    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_A);
+    process(mapper, ARBITRARY_TIME + 1, EV_KEY, 0, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
@@ -1972,10 +1966,8 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Key down with unknown scan code or usage code.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_UNKNOWN, 1);
+    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UNKNOWN, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
@@ -1989,10 +1981,8 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Key up with unknown scan code or usage code.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_UNKNOWN, 0);
+    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
+    process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_UNKNOWN, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DEVICE_ID, args.deviceId);
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
@@ -2018,8 +2008,7 @@
     ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
 
     // Metakey down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
     NotifyKeyArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
@@ -2027,22 +2016,19 @@
     ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
 
     // Key down.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_A, 1);
+    process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_A, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
     ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
 
     // Key up.
-    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
-            EV_KEY, KEY_A, 0);
+    process(mapper, ARBITRARY_TIME + 2, EV_KEY, KEY_A, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
     ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
 
     // Metakey up.
-    process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, 0);
+    process(mapper, ARBITRARY_TIME + 3, EV_KEY, KEY_LEFTSHIFT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AMETA_NONE, args.metaState);
     ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
@@ -2129,7 +2115,7 @@
     NotifyKeyArgs args;
     clearViewports();
     prepareDisplay(DISPLAY_ORIENTATION_270);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
     ASSERT_EQ(KEY_UP, args.scanCode);
@@ -2137,7 +2123,7 @@
 
     clearViewports();
     prepareDisplay(DISPLAY_ORIENTATION_180);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
     ASSERT_EQ(KEY_UP, args.scanCode);
@@ -2155,16 +2141,16 @@
     NotifyKeyArgs args;
 
     // Display id should be ADISPLAY_ID_NONE without any display configuration.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
 
     prepareDisplay(DISPLAY_ORIENTATION_0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
 }
@@ -2185,9 +2171,9 @@
 
     setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
             UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(DISPLAY_ID, args.displayId);
 
@@ -2195,9 +2181,9 @@
     clearViewports();
     setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
             UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
     ASSERT_EQ(newDisplayId, args.displayId);
 }
@@ -2258,60 +2244,48 @@
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
 
     // Toggle caps lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0);
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
     ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
 
     // Toggle num lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0);
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
     ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
 
     // Toggle caps lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
     ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
 
     // Toggle scroll lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
     ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
 
     // Toggle num lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
     ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
 
     // Toggle scroll lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
@@ -2344,9 +2318,9 @@
         int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
     NotifyMotionArgs args;
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, originalX);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, originalY);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, originalX);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, originalY);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2432,8 +2406,8 @@
 
     // Button press.
     // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
     ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2473,8 +2447,8 @@
     ASSERT_EQ(ARBITRARY_TIME, args.downTime);
 
     // Button release.  Should have same down time.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME + 1, EV_KEY, BTN_MOUSE, 0);
+    process(mapper, ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
     ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2522,16 +2496,16 @@
     NotifyMotionArgs args;
 
     // Motion in X but not Y.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
             1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Motion in Y but not X.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, -2);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2546,8 +2520,8 @@
     NotifyMotionArgs args;
 
     // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2559,8 +2533,8 @@
             0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Button release.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2580,10 +2554,10 @@
     NotifyMotionArgs args;
 
     // Combined X, Y and Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 1);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, -2);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2597,9 +2571,9 @@
             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Move X, Y a bit while pressed.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 2);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 2);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2607,8 +2581,8 @@
             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Release Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2708,8 +2682,8 @@
     NotifyKeyArgs keyArgs;
 
     // press BTN_LEFT, release BTN_LEFT
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
     ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
@@ -2724,8 +2698,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_LEFT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2748,9 +2722,9 @@
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 1);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
     ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
@@ -2777,8 +2751,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
@@ -2793,16 +2767,16 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
     ASSERT_EQ(0, mFakePointerController->getButtonState());
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
 
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2819,8 +2793,8 @@
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // press BTN_BACK, release BTN_BACK
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_BACK, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
     ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
@@ -2839,8 +2813,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_BACK, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2860,8 +2834,8 @@
     ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
 
     // press BTN_SIDE, release BTN_SIDE
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_SIDE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
     ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
@@ -2880,8 +2854,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_SIDE, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2901,8 +2875,8 @@
     ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
 
     // press BTN_FORWARD, release BTN_FORWARD
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_FORWARD, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
     ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
@@ -2921,8 +2895,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_FORWARD, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2942,8 +2916,8 @@
     ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
 
     // press BTN_EXTRA, release BTN_EXTRA
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_EXTRA, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
     ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
@@ -2962,8 +2936,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_EXTRA, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
     ASSERT_EQ(0, motionArgs.buttonState);
@@ -2994,9 +2968,9 @@
 
     NotifyMotionArgs args;
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 10);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 20);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
@@ -3023,9 +2997,9 @@
     NotifyMotionArgs args;
 
     // Move.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 10);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 20);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
@@ -3034,8 +3008,8 @@
     ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 100.0f, 200.0f));
 
     // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
@@ -3048,8 +3022,8 @@
             0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Button release.
-    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
-    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME + 2, EV_KEY, BTN_MOUSE, 0);
+    process(mapper, ARBITRARY_TIME + 2, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
@@ -3062,9 +3036,9 @@
             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
 
     // Another move.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 30);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 40);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 30);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 40);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
@@ -3083,9 +3057,9 @@
     ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
     ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
 
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 10);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 20);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
     ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
@@ -3305,48 +3279,48 @@
 }
 
 void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 1);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, x);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, y);
 }
 
 void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, x);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, y);
 }
 
 void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0);
+    process(mapper, ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 0);
 }
 
 void SingleTouchInputMapperTest::processPressure(
         SingleTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, pressure);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_PRESSURE, pressure);
 }
 
 void SingleTouchInputMapperTest::processToolMajor(
         SingleTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
 }
 
 void SingleTouchInputMapperTest::processDistance(
         SingleTouchInputMapper* mapper, int32_t distance) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, distance);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_DISTANCE, distance);
 }
 
 void SingleTouchInputMapperTest::processTilt(
         SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_X, tiltX);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_Y, tiltY);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TILT_X, tiltX);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TILT_Y, tiltY);
 }
 
 void SingleTouchInputMapperTest::processKey(
         SingleTouchInputMapper* mapper, int32_t code, int32_t value) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value);
+    process(mapper, ARBITRARY_TIME, EV_KEY, code, value);
 }
 
 void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
 }
 
 
@@ -4661,75 +4635,75 @@
 
 void MultiTouchInputMapperTest::processPosition(
         MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, x);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
 }
 
 void MultiTouchInputMapperTest::processTouchMajor(
         MultiTouchInputMapper* mapper, int32_t touchMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
 }
 
 void MultiTouchInputMapperTest::processTouchMinor(
         MultiTouchInputMapper* mapper, int32_t touchMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
 }
 
 void MultiTouchInputMapperTest::processToolMajor(
         MultiTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
 }
 
 void MultiTouchInputMapperTest::processToolMinor(
         MultiTouchInputMapper* mapper, int32_t toolMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
 }
 
 void MultiTouchInputMapperTest::processOrientation(
         MultiTouchInputMapper* mapper, int32_t orientation) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, orientation);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
 }
 
 void MultiTouchInputMapperTest::processPressure(
         MultiTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, pressure);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
 }
 
 void MultiTouchInputMapperTest::processDistance(
         MultiTouchInputMapper* mapper, int32_t distance) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_DISTANCE, distance);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
 }
 
 void MultiTouchInputMapperTest::processId(
         MultiTouchInputMapper* mapper, int32_t id) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, id);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
 }
 
 void MultiTouchInputMapperTest::processSlot(
         MultiTouchInputMapper* mapper, int32_t slot) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_SLOT, slot);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, slot);
 }
 
 void MultiTouchInputMapperTest::processToolType(
         MultiTouchInputMapper* mapper, int32_t toolType) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
+    process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
 }
 
 void MultiTouchInputMapperTest::processKey(
         MultiTouchInputMapper* mapper, int32_t code, int32_t value) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value);
+    process(mapper, ARBITRARY_TIME, EV_KEY, code, value);
 }
 
 void MultiTouchInputMapperTest::processTimestamp(MultiTouchInputMapper* mapper, uint32_t value) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_MSC, MSC_TIMESTAMP, value);
+    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, value);
 }
 
 void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_MT_REPORT, 0);
 }
 
 void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
 }
 
 
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index f168db9..088c256 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -139,6 +139,7 @@
         "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
+        "Scheduler/LayerHistory.cpp",
         "Scheduler/MessageQueue.cpp",
         "Scheduler/Scheduler.cpp",
         "StartPropertySetThread.cpp",
@@ -184,6 +185,7 @@
         "libhidltransport",
         "liblayers_proto",
         "liblog",
+        "libsync",
         "libtimestats_proto",
         "libutils",
     ],
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5342bcf..1215bd9 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -35,6 +35,8 @@
 #include <gui/Surface.h>
 #include <hardware/gralloc.h>
 #include <renderengine/RenderEngine.h>
+#include <sync/sync.h>
+#include <system/window.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
@@ -221,8 +223,8 @@
         mDisplayToken(args.displayToken),
         mId(args.displayId),
         mNativeWindow(args.nativeWindow),
+        mGraphicBuffer(nullptr),
         mDisplaySurface(args.displaySurface),
-        mSurface{std::move(args.renderSurface)},
         mDisplayInstallOrientation(args.displayInstallOrientation),
         mPageFlipCount(0),
         mIsVirtual(args.isVirtual),
@@ -244,7 +246,6 @@
 
     ALOGE_IF(!mNativeWindow, "No native window was set for display");
     ALOGE_IF(!mDisplaySurface, "No display surface was set for display");
-    ALOGE_IF(!mSurface, "No render surface was set for display");
 
     std::vector<Hdr> types = args.hdrCapabilities.getSupportedHdrTypes();
     for (Hdr hdrType : types) {
@@ -284,6 +285,14 @@
     mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
 
     ANativeWindow* const window = mNativeWindow.get();
+
+    int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+    ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status);
+    status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+    ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status);
+    status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER);
+    ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status);
+
     mDisplayWidth = ANativeWindow_getWidth(window);
     mDisplayHeight = ANativeWindow_getHeight(window);
 
@@ -321,7 +330,6 @@
 
 void DisplayDevice::flip() const
 {
-    mFlinger->getRenderEngine().checkErrors();
     mPageFlipCount++;
 }
 
@@ -356,9 +364,71 @@
     return mDisplaySurface->prepareFrame(compositionType);
 }
 
-void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+sp<GraphicBuffer> DisplayDevice::dequeueBuffer() {
+    int fd;
+    ANativeWindowBuffer* buffer;
+
+    status_t res = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
+
+    if (res != NO_ERROR) {
+        ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
+              getDisplayName().c_str(), res);
+        // Return fast here as we can't do much more - any rendering we do
+        // now will just be wrong.
+        return mGraphicBuffer;
+    }
+
+    ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
+             mGraphicBuffer->getNativeBuffer()->handle);
+    mGraphicBuffer = GraphicBuffer::from(buffer);
+
+    // Block until the buffer is ready
+    // TODO(alecmouri): it's perhaps more appropriate to block renderengine so
+    // that the gl driver can block instead.
+    if (fd >= 0) {
+        sync_wait(fd, -1);
+        close(fd);
+    }
+
+    return mGraphicBuffer;
+}
+
+void DisplayDevice::queueBuffer(HWComposer& hwc) {
     if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) {
-        mSurface->swapBuffers();
+        // hasFlipClientTargetRequest could return true even if we haven't
+        // dequeued a buffer before. Try dequeueing one if we don't have a
+        // buffer ready.
+        if (mGraphicBuffer == nullptr) {
+            ALOGI("Attempting to queue a client composited buffer without one "
+                  "previously dequeued for display [%s]. Attempting to dequeue "
+                  "a scratch buffer now",
+                  mDisplayName.c_str());
+            // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
+            // after a successful call to queueBuffer, or if dequeueBuffer has
+            // never been called.
+            dequeueBuffer();
+        }
+
+        if (mGraphicBuffer == nullptr) {
+            ALOGE("No buffer is ready for display [%s]", mDisplayName.c_str());
+        } else {
+            int fd = mBufferReady.release();
+
+            status_t res = mNativeWindow->queueBuffer(mNativeWindow.get(),
+                                                      mGraphicBuffer->getNativeBuffer(), fd);
+            if (res != NO_ERROR) {
+                ALOGE("Error when queueing buffer for display [%s]: %d", mDisplayName.c_str(), res);
+                // We risk blocking on dequeueBuffer if the primary display failed
+                // to queue up its buffer, so crash here.
+                if (isPrimary()) {
+                    LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", res);
+                } else {
+                    mNativeWindow->cancelBuffer(mNativeWindow.get(),
+                                                mGraphicBuffer->getNativeBuffer(), fd);
+                }
+            }
+            mGraphicBuffer = nullptr;
+        }
     }
 
     status_t result = mDisplaySurface->advanceFrame();
@@ -367,16 +437,10 @@
     }
 }
 
-void DisplayDevice::onSwapBuffersCompleted() const {
+void DisplayDevice::onPresentDisplayCompleted() {
     mDisplaySurface->onFrameCommitted();
 }
 
-bool DisplayDevice::makeCurrent() const {
-    bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
-    setViewportAndProjection();
-    return success;
-}
-
 void DisplayDevice::setViewportAndProjection() const {
     size_t w = mDisplayWidth;
     size_t h = mDisplayHeight;
@@ -384,6 +448,13 @@
     mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0);
 }
 
+void DisplayDevice::finishBuffer() {
+    mBufferReady = mFlinger->getRenderEngine().flush();
+    if (mBufferReady.get() < 0) {
+        mFlinger->getRenderEngine().finish();
+    }
+}
+
 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
     return mDisplaySurface->getClientTargetAcquireFence();
 }
@@ -532,12 +603,8 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
-    mSurface->setNativeWindow(nullptr);
-
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
-    ANativeWindow* const window = mNativeWindow.get();
-    mSurface->setNativeWindow(window);
     mDisplayWidth = newWidth;
     mDisplayHeight = newHeight;
 }
@@ -653,12 +720,11 @@
     ANativeWindow* const window = mNativeWindow.get();
     result.appendFormat("+ %s\n", getDebugName().c_str());
     result.appendFormat("  layerStack=%u, (%4dx%4d), ANativeWindow=%p "
-                        "(%d:%d:%d:%d), orient=%2d (type=%08x), "
-                        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+                        "format=%d, orient=%2d (type=%08x), flips=%u, isSecure=%d, "
+                        "powerMode=%d, activeConfig=%d, numLayers=%zu\n",
                         mLayerStack, mDisplayWidth, mDisplayHeight, window,
-                        mSurface->queryRedSize(), mSurface->queryGreenSize(),
-                        mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
-                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        ANativeWindow_getFormat(window), mOrientation, tr.getType(),
+                        getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
                         mVisibleLayersSortedByZ.size());
     result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
                         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
@@ -669,9 +735,9 @@
     auto const surface = static_cast<Surface*>(window);
     ui::Dataspace dataspace = surface->getBuffersDataSpace();
     result.appendFormat("   wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
-                        mHasWideColorGamut, mHasHdr10,
-                        decodeColorMode(mActiveColorMode).c_str(),
-                        dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
+                        mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(),
+                        dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(),
+                        dataspace);
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bcd3330..eb2c5c3 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -24,25 +24,25 @@
 #include <string>
 #include <unordered_map>
 
+#include <android/native_window.h>
 #include <binder/IBinder.h>
 #include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <math/mat4.h>
-#include <renderengine/Surface.h>
+#include <renderengine/RenderEngine.h>
+#include <system/window.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
-#include <utils/RefBase.h>
 #include <utils/Mutex.h>
+#include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include "DisplayHardware/DisplayIdentification.h"
 #include "RenderArea.h"
 
-struct ANativeWindow;
-
 namespace android {
 
 class DisplaySurface;
@@ -146,10 +146,13 @@
                           ui::Dataspace* outDataspace, ui::ColorMode* outMode,
                           ui::RenderIntent* outIntent) const;
 
-    void swapBuffers(HWComposer& hwc) const;
+    // Queues the drawn buffer for consumption by HWC.
+    void queueBuffer(HWComposer& hwc);
+    // Allocates a buffer as scratch space for GPU composition
+    sp<GraphicBuffer> dequeueBuffer();
 
     // called after h/w composer has completed its set() call
-    void onSwapBuffersCompleted() const;
+    void onPresentDisplayCompleted();
 
     Rect getBounds() const {
         return Rect(mDisplayWidth, mDisplayHeight);
@@ -159,7 +162,11 @@
     void setDisplayName(const std::string& displayName);
     const std::string& getDisplayName() const { return mDisplayName; }
 
-    bool makeCurrent() const;
+    // Acquires a new buffer for GPU composition.
+    void readyNewBuffer();
+    // Marks the current buffer has finished, so that it can be presented and
+    // swapped out.
+    void finishBuffer();
     void setViewportAndProjection() const;
 
     const sp<Fence>& getClientTargetAcquireFence() const;
@@ -204,9 +211,13 @@
 
     // ANativeWindow this display is rendering into
     sp<ANativeWindow> mNativeWindow;
+    // Current buffer that this display can render to.
+    sp<GraphicBuffer> mGraphicBuffer;
     sp<DisplaySurface> mDisplaySurface;
+    // File descriptor indicating that mGraphicBuffer is ready for display, i.e.
+    // that drawing to the buffer is now complete.
+    base::unique_fd mBufferReady;
 
-    std::unique_ptr<renderengine::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
     const int       mDisplayInstallOrientation;
@@ -326,7 +337,6 @@
     bool isSecure{false};
     sp<ANativeWindow> nativeWindow;
     sp<DisplaySurface> displaySurface;
-    std::unique_ptr<renderengine::Surface> renderSurface;
     int displayInstallOrientation{DisplayState::eOrientationDefault};
     bool hasWideColorGamut{false};
     HdrCapabilities hdrCapabilities;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0f25b52..9bbc37f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -20,31 +20,12 @@
 #define LOG_TAG "HWComposer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
 #include <utils/Errors.h>
-#include <utils/misc.h>
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-#include <utils/Thread.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-
-#include <android/configuration.h>
-
-#include <cutils/properties.h>
 #include <log/log.h>
 
 #include "HWComposer.h"
@@ -85,11 +66,7 @@
 
 namespace android {
 
-#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
-
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer(std::unique_ptr<android::Hwc2::Composer> composer)
+HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
       : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
 
 HWComposer::~HWComposer() {
@@ -184,30 +161,31 @@
 
     RETURN_IF_INVALID_DISPLAY(*displayId, false);
 
-    const auto& displayData = mDisplayData[*displayId];
+    auto& displayData = mDisplayData[*displayId];
     if (displayData.isVirtual) {
         LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
         return false;
     }
 
     {
-        Mutex::Autolock _l(mLock);
+        std::lock_guard lock(displayData.lastHwVsyncLock);
 
         // There have been reports of HWCs that signal several vsync events
         // with the same timestamp when turning the display off and on. This
         // is a bug in the HWC implementation, but filter the extra events
         // out here so they don't cause havoc downstream.
-        if (timestamp == mLastHwVSync[*displayId]) {
+        if (timestamp == displayData.lastHwVsync) {
             ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
                   to_string(*displayId).c_str(), timestamp);
             return false;
         }
 
-        mLastHwVSync[*displayId] = timestamp;
+        displayData.lastHwVsync = timestamp;
     }
 
     const auto tag = "HW_VSYNC_" + to_string(*displayId);
-    ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1);
+    ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
+    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
 
     return true;
 }
@@ -270,13 +248,14 @@
 
 nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, 0);
+    const auto& displayData = mDisplayData.at(displayId);
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
     // the refresh period and whatever closest timestamp we have.
-    Mutex::Autolock _l(mLock);
+    std::lock_guard lock(displayData.lastHwVsyncLock);
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
     auto vsyncPeriod = getActiveConfig(displayId)->getVsyncPeriod();
-    return now - ((now - mLastHwVSync[displayId]) % vsyncPeriod);
+    return now - ((now - displayData.lastHwVsync) % vsyncPeriod);
 }
 
 bool HWComposer::isConnected(DisplayId displayId) const {
@@ -375,17 +354,19 @@
     // into the HWC with the lock held, and we want to make sure
     // that even if HWC blocks (which it shouldn't), it won't
     // affect other threads.
-    Mutex::Autolock _l(mVsyncLock);
-    if (enabled != displayData.vsyncEnabled) {
-        ATRACE_CALL();
-        auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
-        RETURN_IF_HWC_ERROR(error, displayId);
-
-        displayData.vsyncEnabled = enabled;
-
-        const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
-        ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
+    std::lock_guard lock(displayData.vsyncEnabledLock);
+    if (enabled == displayData.vsyncEnabled) {
+        return;
     }
+
+    ATRACE_CALL();
+    auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
+    RETURN_IF_HWC_ERROR(error, displayId);
+
+    displayData.vsyncEnabled = enabled;
+
+    const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
+    ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
 }
 
 status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
@@ -405,8 +386,6 @@
 
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
 
-    Mutex::Autolock _l(mDisplayLock);
-
     auto& displayData = mDisplayData[displayId];
     auto& hwcDisplay = displayData.hwcDisplay;
     if (!hwcDisplay->isConnected()) {
@@ -428,7 +407,7 @@
     // back to validate when there is any client layer.
     displayData.validateWasSkipped = false;
     if (!displayData.hasClientComposition) {
-        sp<android::Fence> outPresentFence;
+        sp<Fence> outPresentFence;
         uint32_t state = UINT32_MAX;
         error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
         if (error != HWC2::Error::HasChanges) {
@@ -689,7 +668,6 @@
     const auto hwcDisplayId = displayData.hwcDisplay->getId();
     mPhysicalDisplayIdMap.erase(hwcDisplayId);
     mDisplayData.erase(displayId);
-    mVSyncCounts.erase(displayId);
 
     // TODO(b/74619554): Select internal/external display from remaining displays.
     if (hwcDisplayId == mInternalHwcDisplayId) {
@@ -755,26 +733,6 @@
     return matrix;
 }
 
-// Converts a PixelFormat to a human-readable string.  Max 11 chars.
-// (Could use a table of prefab String8 objects.)
-/*
-static String8 getFormatStr(PixelFormat format) {
-    switch (format) {
-    case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
-    case PIXEL_FORMAT_RGBX_8888:    return String8("RGBx_8888");
-    case PIXEL_FORMAT_RGB_888:      return String8("RGB_888");
-    case PIXEL_FORMAT_RGB_565:      return String8("RGB_565");
-    case PIXEL_FORMAT_BGRA_8888:    return String8("BGRA_8888");
-    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-                                    return String8("ImplDef");
-    default:
-        String8 result;
-        result.appendFormat("? %08x", format);
-        return result;
-    }
-}
-*/
-
 bool HWComposer::isUsingVrComposer() const {
     return getComposer()->isUsingVrComposer();
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b78433d..2f57907 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -17,49 +17,26 @@
 #ifndef ANDROID_SF_HWCOMPOSER_H
 #define ANDROID_SF_HWCOMPOSER_H
 
-#include "HWC2.h"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <ui/Fence.h>
-#include <ui/GraphicTypes.h>
-#include <utils/BitSet.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <utils/StrongPointer.h>
-#include <utils/Thread.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
+#include <cstdint>
 #include <memory>
+#include <mutex>
 #include <optional>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
+#include <android-base/thread_annotations.h>
+#include <ui/Fence.h>
+#include <ui/GraphicTypes.h>
+#include <utils/StrongPointer.h>
+#include <utils/Timers.h>
+
 #include "DisplayIdentification.h"
-
-extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
-                           const struct timespec *request,
-                           struct timespec *remain);
-
-struct framebuffer_device_t;
-
-namespace HWC2 {
-    class Device;
-    class Display;
-}
+#include "HWC2.h"
 
 namespace android {
-// ---------------------------------------------------------------------------
 
-class DisplayDevice;
-class Fence;
-class FloatRect;
 class GraphicBuffer;
-class NativeHandle;
-class Region;
 class String8;
 class TestableSurfaceFlinger;
 struct CompositionInfo;
@@ -71,7 +48,7 @@
 class HWComposer
 {
 public:
-    explicit HWComposer(std::unique_ptr<android::Hwc2::Composer> composer);
+    explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
 
     ~HWComposer();
 
@@ -177,7 +154,7 @@
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
 
-    android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
+    Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
 
     // TODO(b/74619554): Remove special cases for internal/external display.
     std::optional<hwc2_display_t> getInternalHwcDisplayId() const { return mInternalHwcDisplayId; }
@@ -194,8 +171,6 @@
 
     static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
-    struct cb_context;
-
     struct DisplayData {
         bool isVirtual = false;
         bool hasClientComposition = false;
@@ -209,11 +184,16 @@
         mutable std::unordered_map<int32_t,
                 std::shared_ptr<const HWC2::Display::Config>> configMap;
 
-        // protected by mVsyncLock
-        HWC2::Vsync vsyncEnabled = HWC2::Vsync::Disable;
-
         bool validateWasSkipped;
         HWC2::Error presentError;
+
+        bool vsyncTraceToggle = false;
+
+        std::mutex vsyncEnabledLock;
+        HWC2::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = HWC2::Vsync::Disable;
+
+        mutable std::mutex lastHwVsyncLock;
+        nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
     };
 
     std::unordered_map<DisplayId, DisplayData> mDisplayData;
@@ -227,25 +207,11 @@
     std::optional<hwc2_display_t> mExternalHwcDisplayId;
     bool mHasMultiDisplaySupport = false;
 
-    // protect mDisplayData from races between prepare and dump
-    mutable Mutex mDisplayLock;
-
-    cb_context* mCBContext = nullptr;
-    std::unordered_map<DisplayId, size_t> mVSyncCounts;
-
     std::unordered_set<DisplayId> mFreeVirtualDisplayIds;
     uint32_t mNextVirtualDisplayId = 0;
     uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
-
-    // protected by mLock
-    mutable Mutex mLock;
-    mutable std::unordered_map<DisplayId, nsecs_t> mLastHwVSync;
-
-    // thread-safe
-    mutable Mutex mVsyncLock;
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
 
 #endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1e910ce..f3182be 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1021,6 +1021,10 @@
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
+    if (mLayerDetached) {
+        return 0;
+    }
+
     pushPendingState();
     State c = getCurrentState();
     if (!applyPendingStates(&c)) {
@@ -1553,6 +1557,9 @@
         return false;
     }
 
+    if (attachChildren()) {
+        setTransactionFlags(eTransactionNeeded);
+    }
     for (const sp<Layer>& child : mCurrentChildren) {
         newParent->addChild(child);
 
@@ -1597,6 +1604,13 @@
         client->updateParent(newParent);
     }
 
+    if (mLayerDetached) {
+        mLayerDetached = false;
+        setTransactionFlags(eTransactionNeeded);
+    }
+    if (attachChildren()) {
+        setTransactionFlags(eTransactionNeeded);
+    }
     return true;
 }
 
@@ -1605,7 +1619,7 @@
         sp<Client> parentClient = mClientRef.promote();
         sp<Client> client(child->mClientRef.promote());
         if (client != nullptr && parentClient != client) {
-            client->detachLayer(child.get());
+            child->mLayerDetached = true;
             child->detachChildren();
         }
     }
@@ -1613,6 +1627,23 @@
     return true;
 }
 
+bool Layer::attachChildren() {
+    bool changed = false;
+    for (const sp<Layer>& child : mCurrentChildren) {
+        sp<Client> parentClient = mClientRef.promote();
+        sp<Client> client(child->mClientRef.promote());
+        if (client != nullptr && parentClient != client) {
+            if (child->mLayerDetached) {
+                child->mLayerDetached = false;
+                changed = true;
+            }
+            changed |= child->attachChildren();
+        }
+    }
+
+    return changed;
+}
+
 bool Layer::setColorTransform(const mat4& matrix) {
     static const mat4 identityMatrix = mat4();
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 40ebe1e..ed51c61 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -263,6 +263,8 @@
     virtual void setChildrenDrawingParent(const sp<Layer>& layer);
     virtual bool reparent(const sp<IBinder>& newParentHandle);
     virtual bool detachChildren();
+    bool attachChildren();
+    bool isLayerDetached() const { return mLayerDetached; }
     virtual bool setColorTransform(const mat4& matrix);
     virtual const mat4& getColorTransform() const;
     virtual bool hasColorTransform() const;
@@ -355,7 +357,6 @@
     // to avoid grabbing the lock again to avoid deadlock
     virtual bool isCreatedFromMainThread() const { return false; }
 
-
     bool isRemovedFromCurrentState() const;
 
     void writeToProto(LayerProto* layerInfo,
@@ -776,6 +777,9 @@
 
     mutable LayerBE mBE;
 
+    // Can only be accessed with the SF state lock held.
+    bool mLayerDetached{false};
+
 private:
     /**
      * Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
new file mode 100644
index 0000000..e944eb9
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "LayerHistory.h"
+
+#include <cinttypes>
+#include <cstdint>
+#include <numeric>
+#include <string>
+#include <unordered_map>
+
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <utils/Trace.h>
+
+namespace android {
+
+LayerHistory::LayerHistory() {}
+
+LayerHistory::~LayerHistory() = default;
+
+void LayerHistory::insert(const std::string layerName, nsecs_t presentTime) {
+    mElements[mCounter].insert(std::make_pair(layerName, presentTime));
+}
+
+void LayerHistory::incrementCounter() {
+    mCounter++;
+    mCounter = mCounter % ARRAY_SIZE;
+    mElements[mCounter].clear();
+}
+
+const std::unordered_map<std::string, nsecs_t>& LayerHistory::get(size_t index) const {
+    return mElements.at(index);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
new file mode 100644
index 0000000..1a7f9cd
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <cinttypes>
+#include <cstdint>
+#include <numeric>
+#include <string>
+#include <unordered_map>
+
+#include <utils/Timers.h>
+
+namespace android {
+
+/*
+ * This class represents a circular buffer in which we keep layer history for
+ * the past ARRAY_SIZE frames. Each time, a signal for new frame comes, the counter
+ * gets incremented and includes all the layers that are requested to draw in that
+ * frame.
+ *
+ * Once the buffer reaches the end of the array, it starts overriding the elements
+ * at the beginning of the array.
+ */
+class LayerHistory {
+public:
+    LayerHistory();
+    ~LayerHistory();
+
+    // Method for inserting layers and their requested present time into the ring buffer.
+    // The elements are going to be inserted into an unordered_map at the position of
+    // mCounter.
+    void insert(const std::string layerName, nsecs_t presentTime);
+    // Method for incrementing the current slot in the ring buffer. It also clears the
+    // unordered_map, if it was created previously.
+    void incrementCounter();
+    // Returns unordered_map at the given at index.
+    const std::unordered_map<std::string, nsecs_t>& get(size_t index) const;
+
+private:
+    size_t mCounter = 0;
+    static constexpr size_t ARRAY_SIZE = 30;
+    std::array<std::unordered_map<std::string, nsecs_t>, ARRAY_SIZE> mElements;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 41c7a93..af73346 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,6 +45,7 @@
 #include <gui/BufferQueue.h>
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
+#include <gui/IProducerListener.h>
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
 #include <renderengine/RenderEngine.h>
@@ -676,10 +677,6 @@
     LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
                         "Internal display is disconnected.");
 
-    // make the default display GLContext current so that we can create textures
-    // when creating Layers (which may happens before we render something)
-    display->makeCurrent();
-
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
             // This callback is called from the vr flinger dispatch thread. We
@@ -1409,7 +1406,6 @@
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
-    getRenderEngine().resetCurrentSurface();
     mDisplays.clear();
 }
 
@@ -1717,7 +1713,7 @@
             auto& engine(getRenderEngine());
             engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
 
-            display->swapBuffers(getHwComposer());
+            display->queueBuffer(getHwComposer());
         }
     }
 
@@ -2203,8 +2199,7 @@
         if (displayId) {
             getHwComposer().presentAndGetReleaseFences(*displayId);
         }
-        display->onSwapBuffersCompleted();
-        display->makeCurrent();
+        display->onPresentDisplayCompleted();
         for (auto& layer : display->getVisibleLayersSortedByZ()) {
             sp<Fence> releaseFence = Fence::NO_FENCE;
 
@@ -2351,22 +2346,9 @@
     auto nativeWindow = nativeWindowSurface->getNativeWindow();
     creationArgs.nativeWindow = nativeWindow;
 
-    /*
-     * Create our display's surface
-     */
-    std::unique_ptr<renderengine::Surface> renderSurface = getRenderEngine().createSurface();
-    renderSurface->setCritical(isInternalDisplay);
-    renderSurface->setAsync(state.isVirtual());
-    renderSurface->setNativeWindow(nativeWindow.get());
-    creationArgs.renderSurface = std::move(renderSurface);
-
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
-    // in two places:
-    // * Here, in case the display is composed entirely by HWC.
-    // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
-    //   window's swap interval in eglMakeCurrent, so they'll override the
-    //   interval we set here.
+    // here, in case the display is composed entirely by HWC.
     if (state.isVirtual()) {
         nativeWindow->setSwapInterval(nativeWindow.get(), 0);
     }
@@ -2426,12 +2408,6 @@
                 const auto externalDisplayId = getExternalDisplayId();
 
                 // in drawing state but not in current state
-                // Call makeCurrent() on the primary display so we can
-                // be sure that nothing associated with this display
-                // is current.
-                if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) {
-                    defaultDisplay->makeCurrent();
-                }
                 if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
                     display->disconnect(getHwComposer());
                 }
@@ -2982,7 +2958,7 @@
     mGeometryInvalid = true;
 }
 
-void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display,
+void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& display,
                                           const Region& inDirtyRegion) {
     // We only need to actually compose the display if:
     // 1) It is being handled by hardware composer, which may need this to
@@ -2997,10 +2973,10 @@
     if (!doComposeSurfaces(display)) return;
 
     // swap buffers (presentation)
-    display->swapBuffers(getHwComposer());
+    display->queueBuffer(getHwComposer());
 }
 
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) {
     ALOGV("doComposeSurfaces");
 
     const Region bounds(display->bounds());
@@ -3013,9 +2989,31 @@
     bool applyColorMatrix = false;
     bool needsEnhancedColorMatrix = false;
 
+    // Framebuffer will live in this scope for GPU composition.
+    std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
+
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
+        sp<GraphicBuffer> buf = display->dequeueBuffer();
+
+        if (buf == nullptr) {
+            ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
+                  "client composition for this frame",
+                  display->getDisplayName().c_str());
+            return false;
+        }
+
+        // Bind the framebuffer in this scope.
+        fbo = std::make_unique<renderengine::BindNativeBufferAsFramebuffer>(getRenderEngine(),
+                                                                            buf->getNativeBuffer());
+
+        if (fbo->getStatus() != NO_ERROR) {
+            ALOGW("Binding buffer for display [%s] failed with status: %d",
+                  display->getDisplayName().c_str(), fbo->getStatus());
+            return false;
+        }
+
         Dataspace outputDataspace = Dataspace::UNKNOWN;
         if (display->hasWideColorGamut()) {
             outputDataspace = display->getCompositionDataSpace();
@@ -3044,18 +3042,7 @@
             colorMatrix *= mEnhancedSaturationMatrix;
         }
 
-        if (!display->makeCurrent()) {
-            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
-                  display->getDisplayName().c_str());
-            getRenderEngine().resetCurrentSurface();
-
-            // |mStateLock| not needed as we are on the main thread
-            const auto defaultDisplay = getDefaultDisplayDeviceLocked();
-            if (!defaultDisplay || !defaultDisplay->makeCurrent()) {
-                ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
-            }
-            return false;
-        }
+        display->setViewportAndProjection();
 
         // Never touch the framebuffer if we don't have any framebuffer layers
         if (hasDeviceComposition) {
@@ -3148,11 +3135,15 @@
         firstLayer = false;
     }
 
-    // Clear color transform matrix at the end of the frame.
-    getRenderEngine().setColorTransform(mat4());
-
-    // disable scissor at the end of the frame
-    getBE().mRenderEngine->disableScissor();
+    // Perform some cleanup steps if we used client composition.
+    if (hasClientComposition) {
+        getRenderEngine().setColorTransform(mat4());
+        getBE().mRenderEngine->disableScissor();
+        display->finishBuffer();
+        // Clear out error flags here so that we don't wait until next
+        // composition to log.
+        getRenderEngine().checkErrors();
+    }
     return true;
 }
 
@@ -3208,6 +3199,10 @@
 }
 
 status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
+    if (layer->isLayerDetached()) {
+        return NO_ERROR;
+    }
+
     const auto& p = layer->getParent();
     ssize_t index;
     if (p != nullptr) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8b389bc..f98dddf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -721,10 +721,10 @@
     void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
     void doTracing(const char* where);
     void logLayerStats();
-    void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
+    void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
 
     // This fails if using GL and the surface has been destroyed.
-    bool doComposeSurfaces(const sp<const DisplayDevice>& display);
+    bool doComposeSurfaces(const sp<DisplayDevice>& display);
 
     void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 67dcd06..1835929 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -26,22 +26,48 @@
 
 namespace android {
 
-void SurfaceTracing::enable() {
-    ATRACE_CALL();
+void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
+    // use the swap trick to make sure memory is released
+    std::queue<LayersTraceProto>().swap(mStorage);
+    mSizeInBytes = newSize;
+    mUsedInBytes = 0U;
+}
+
+void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
+    auto protoSize = proto.ByteSize();
+    while (mUsedInBytes + protoSize > mSizeInBytes) {
+        if (mStorage.empty()) {
+            return;
+        }
+        mUsedInBytes -= mStorage.front().ByteSize();
+        mStorage.pop();
+    }
+    mUsedInBytes += protoSize;
+    mStorage.emplace();
+    mStorage.back().Swap(&proto);
+}
+
+void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
+    fileProto->mutable_entry()->Reserve(mStorage.size());
+
+    while (!mStorage.empty()) {
+        auto entry = fileProto->add_entry();
+        entry->Swap(&mStorage.front());
+        mStorage.pop();
+    }
+}
+
+void SurfaceTracing::enable(size_t bufferSizeInByte) {
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
 
     if (mEnabled) {
         return;
     }
     mEnabled = true;
-
-    mTrace = std::make_unique<LayersTraceFileProto>();
-    mTrace->set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
-                             LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+    mBuffer.reset(bufferSizeInByte);
 }
 
 status_t SurfaceTracing::disable() {
-    ATRACE_CALL();
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
 
     if (!mEnabled) {
@@ -51,7 +77,7 @@
     status_t err(writeProtoFileLocked());
     ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied");
     ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields");
-    mTrace.reset();
+    mBuffer.reset(0);
     return err;
 }
 
@@ -65,32 +91,29 @@
     if (!mEnabled) {
         return;
     }
-    LayersTraceProto* entry = mTrace->add_entry();
-    entry->set_elapsed_realtime_nanos(elapsedRealtimeNano());
-    entry->set_where(where);
-    entry->mutable_layers()->Swap(&layers);
 
-    constexpr int maxBufferedEntryCount = 3600;
-    if (mTrace->entry_size() >= maxBufferedEntryCount) {
-        // TODO: flush buffered entries without disabling tracing
-        ALOGE("too many buffered frames; force disable tracing");
-        mEnabled = false;
-        writeProtoFileLocked();
-        mTrace.reset();
-    }
+    LayersTraceProto entry;
+    entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
+    entry.set_where(where);
+    entry.mutable_layers()->Swap(&layers);
+
+    mBuffer.emplace(std::move(entry));
 }
 
 status_t SurfaceTracing::writeProtoFileLocked() {
     ATRACE_CALL();
 
-    if (!mTrace->IsInitialized()) {
-        return NOT_ENOUGH_DATA;
-    }
+    LayersTraceFileProto fileProto;
     std::string output;
-    if (!mTrace->SerializeToString(&output)) {
+
+    fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
+                               LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+    mBuffer.flush(&fileProto);
+
+    if (!fileProto.SerializeToString(&output)) {
         return PERMISSION_DENIED;
     }
-    if (!android::base::WriteStringToFile(output, mOutputFileName, true)) {
+    if (!android::base::WriteStringToFile(output, kDefaultFileName, true)) {
         return PERMISSION_DENIED;
     }
 
@@ -101,7 +124,8 @@
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
 
     result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
-    result.appendFormat("  number of entries: %d\n", mTrace ? mTrace->entry_size() : 0);
+    result.appendFormat("  number of entries: %zu (%.2fMB / %.2fMB)\n", mBuffer.frameCount(),
+                        float(mBuffer.used()) / float(1_MB), float(mBuffer.size()) / float(1_MB));
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index fd8cb82..ec01be7 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -22,32 +22,54 @@
 
 #include <memory>
 #include <mutex>
+#include <queue>
 
 using namespace android::surfaceflinger;
 
 namespace android {
 
+constexpr auto operator""_MB(unsigned long long const num) {
+    return num * 1024 * 1024;
+}
+
 /*
  * SurfaceTracing records layer states during surface flinging.
  */
 class SurfaceTracing {
 public:
-    void enable();
+    void enable() { enable(kDefaultBufferCapInByte); }
+    void enable(size_t bufferSizeInByte);
     status_t disable();
-    bool isEnabled() const;
-
     void traceLayers(const char* where, LayersProto);
+
+    bool isEnabled() const;
     void dump(String8& result) const;
 
 private:
-    static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb";
+    static constexpr auto kDefaultBufferCapInByte = 100_MB;
+    static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
+
+    class LayersTraceBuffer { // ring buffer
+    public:
+        size_t size() const { return mSizeInBytes; }
+        size_t used() const { return mUsedInBytes; }
+        size_t frameCount() const { return mStorage.size(); }
+
+        void reset(size_t newSize);
+        void emplace(LayersTraceProto&& proto);
+        void flush(LayersTraceFileProto* fileProto);
+
+    private:
+        size_t mUsedInBytes = 0U;
+        size_t mSizeInBytes = 0U;
+        std::queue<LayersTraceProto> mStorage;
+    };
 
     status_t writeProtoFileLocked();
 
     bool mEnabled = false;
-    std::string mOutputFileName = DEFAULT_FILENAME;
     mutable std::mutex mTraceMutex;
-    std::unique_ptr<LayersTraceFileProto> mTrace;
+    LayersTraceBuffer mBuffer;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 599ff5c..75ce4be 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "timestatsproto/TimeStatsHelper.h"
+
 #include <android-base/stringprintf.h>
-#include <timestatsproto/TimeStatsHelper.h>
+#include <inttypes.h>
 
 #include <array>
 
@@ -46,6 +48,14 @@
     hist[*iter]++;
 }
 
+int64_t TimeStatsHelper::Histogram::totalTime() const {
+    int64_t ret = 0;
+    for (const auto& ele : hist) {
+        ret += ele.first * ele.second;
+    }
+    return ret;
+}
+
 float TimeStatsHelper::Histogram::averageTime() const {
     int64_t ret = 0;
     int64_t count = 0;
@@ -87,12 +97,13 @@
 
 std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> maxLayers) const {
     std::string result = "SurfaceFlinger TimeStats:\n";
-    StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart));
-    StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd));
+    StringAppendF(&result, "statsStart = %" PRId64 "\n", statsStart);
+    StringAppendF(&result, "statsEnd = %" PRId64 "\n", statsEnd);
     StringAppendF(&result, "totalFrames = %d\n", totalFrames);
     StringAppendF(&result, "missedFrames = %d\n", missedFrames);
     StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
-    StringAppendF(&result, "displayOnTime = %lld ms\n", static_cast<long long int>(displayOnTime));
+    StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTime);
+    StringAppendF(&result, "totalP2PTime = %" PRId64 " ms\n", presentToPresent.totalTime());
     StringAppendF(&result, "presentToPresent histogram is as below:\n");
     result.append(presentToPresent.toString());
     const auto dumpStats = generateDumpStats(maxLayers);
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index 7d0fe79..5f40a1a 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -34,6 +34,7 @@
         std::unordered_map<int32_t, int32_t> hist;
 
         void insert(int32_t delta);
+        int64_t totalTime() const;
         float averageTime() const;
         std::string toString() const;
     };
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 988454a..a600a0a 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -3356,6 +3356,61 @@
     }
 }
 
+TEST_F(ChildLayerTest, DetachChildrenThenAttach) {
+    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+    sp<SurfaceControl> childNewClient =
+            newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+    ASSERT_TRUE(childNewClient != nullptr);
+    ASSERT_TRUE(childNewClient->isValid());
+
+    fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+    Transaction()
+            .hide(mChild)
+            .show(childNewClient)
+            .setPosition(childNewClient, 10, 10)
+            .setPosition(mFGSurfaceControl, 64, 64)
+            .apply();
+
+    {
+        mCapture = screenshot();
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // But 10 pixels in we should see the child surface
+        mCapture->expectChildColor(74, 74);
+        // And 10 more pixels we should be back to the foreground surface
+        mCapture->expectFGColor(84, 84);
+    }
+
+    Transaction().detachChildren(mFGSurfaceControl).apply();
+    Transaction().hide(childNewClient).apply();
+
+    // Nothing should have changed.
+    {
+        mCapture = screenshot();
+        mCapture->expectFGColor(64, 64);
+        mCapture->expectChildColor(74, 74);
+        mCapture->expectFGColor(84, 84);
+    }
+
+    sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0);
+    fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32,
+                   32);
+    Transaction()
+            .setLayer(newParentSurface, INT32_MAX - 1)
+            .show(newParentSurface)
+            .setPosition(newParentSurface, 20, 20)
+            .reparent(childNewClient, newParentSurface->getHandle())
+            .apply();
+    {
+        mCapture = screenshot();
+        // Child is now hidden.
+        mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
+    }
+}
+
 TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
     asTransaction([&](Transaction& t) {
         t.show(mChild);
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 6fe52d3..58f1e9c 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -29,6 +29,7 @@
         "DisplayTransactionTest.cpp",
         "EventControlThreadTest.cpp",
         "EventThreadTest.cpp",
+        "LayerHistoryTest.cpp",
         "SchedulerTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplaySurface.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ab1b252..cfaf495 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -46,6 +46,7 @@
 using testing::AtLeast;
 using testing::ByMove;
 using testing::DoAll;
+using testing::Invoke;
 using testing::IsNull;
 using testing::Mock;
 using testing::NotNull;
@@ -93,6 +94,10 @@
         EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
         EXPECT_CALL(*mPrimaryDispSync, getPeriod())
                 .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+        EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
+        EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
 
         mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
         setupComposer(0);
@@ -139,9 +144,11 @@
     sp<DisplayDevice> mDisplay;
     sp<DisplayDevice> mExternalDisplay;
     sp<mock::DisplaySurface> mDisplaySurface = new mock::DisplaySurface();
-    renderengine::mock::Surface* mRenderSurface = new renderengine::mock::Surface();
     mock::NativeWindow* mNativeWindow = new mock::NativeWindow();
 
+    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
+    ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
+
     mock::EventThread* mEventThread = new mock::EventThread();
     mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
 
@@ -242,8 +249,6 @@
         test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
                                                    false /* isVirtual */, true /* isPrimary */)
                                  .setDisplaySurface(test->mDisplaySurface)
-                                 .setRenderSurface(std::unique_ptr<renderengine::Surface>(
-                                         test->mRenderSurface))
                                  .setNativeWindow(test->mNativeWindow)
                                  .setSecure(Derived::IS_SECURE)
                                  .setPowerMode(Derived::INIT_POWER_MODE)
@@ -266,13 +271,9 @@
         EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
         EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
 
-        EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
-                .WillOnce(Return(true));
-        EXPECT_CALL(*test->mRenderEngine,
-                    setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
-                                             Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
-                                             ui::Transform::ROT_0))
-                .Times(1);
+        EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
+            return base::unique_fd(0);
+        }));
 
         EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
         EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -323,8 +324,6 @@
 
     static void setupHwcCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC)).Times(1);
-
-        EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
     }
 
     static void setupRECompositionCallExpectations(CompositionTest* test) {
@@ -344,12 +343,18 @@
                     setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
                                              Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                                              ui::Transform::ROT_0))
-                .Times(1)
-                .RetiresOnSaturation();
-        EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
-                .WillOnce(Return(true))
-                .RetiresOnSaturation();
-        EXPECT_CALL(*test->mRenderSurface, swapBuffers()).Times(1);
+                .Times(1);
+        EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull())).WillOnce(Return(true));
+        EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull())).WillOnce(Return(true));
+        EXPECT_CALL(*test->mRenderEngine, createFramebuffer())
+                .WillOnce(Return(
+                        ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer))));
+        EXPECT_CALL(*test->mRenderEngine, bindFrameBuffer(test->mReFrameBuffer)).Times(1);
+        EXPECT_CALL(*test->mRenderEngine, unbindFrameBuffer(test->mReFrameBuffer)).Times(1);
+        EXPECT_CALL(*test->mNativeWindow, queueBuffer(_, _)).WillOnce(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, dequeueBuffer(_, _))
+                .WillOnce(DoAll(SetArgPointee<0>(test->mNativeWindowBuffer), SetArgPointee<1>(-1),
+                                Return(0)));
     }
 
     template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 32fce67..5aaf848 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -120,6 +120,7 @@
     mock::EventThread* mEventThread = new mock::EventThread();
     mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
     sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
+    sp<GraphicBuffer> mBuffer = new GraphicBuffer();
 
     // These mocks are created by the test, but are destroyed by SurfaceFlinger
     // by virtue of being stored into a std::unique_ptr. However we still need
@@ -134,7 +135,6 @@
     sp<mock::GraphicBufferConsumer> mConsumer;
     sp<mock::GraphicBufferProducer> mProducer;
     surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
-    renderengine::mock::Surface* mRenderSurface = nullptr;
 };
 
 DisplayTransactionTest::DisplayTransactionTest() {
@@ -340,26 +340,11 @@
     static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
         EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
                 .WillOnce(Return(test->mNativeWindow));
-        EXPECT_CALL(*test->mNativeWindow, perform(19)).WillRepeatedly(Return(NO_ERROR));
 
-        // For simplicity, we only expect to create a single render surface for
-        // each test.
-        ASSERT_TRUE(test->mRenderSurface == nullptr);
-        test->mRenderSurface = new renderengine::mock::Surface();
-        EXPECT_CALL(*test->mRenderEngine, createSurface())
-                .WillOnce(Return(ByMove(
-                        std::unique_ptr<renderengine::Surface>(test->mRenderSurface))));
-
-        // Creating a DisplayDevice requires getting default dimensions from the
-        // native window.
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
         EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
-
-        EXPECT_CALL(*test->mRenderSurface, setAsync(static_cast<bool>(ASYNC))).Times(1);
-        EXPECT_CALL(*test->mRenderSurface, setCritical(static_cast<bool>(CRITICAL))).Times(1);
-        EXPECT_CALL(*test->mRenderSurface, setNativeWindow(test->mNativeWindow.get())).Times(1);
     }
 
     static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
@@ -1070,9 +1055,6 @@
     // The call disable vsyncs
     EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);
 
-    // The call clears the current render engine surface
-    EXPECT_CALL(*mRenderEngine, resetCurrentSurface());
-
     // The call ends any display resyncs
     EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
 
@@ -1132,6 +1114,9 @@
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1080 /* arbitrary */), Return(0)));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
                 .WillRepeatedly(DoAll(SetArgPointee<1>(1920 /* arbitrary */), Return(0)));
+        EXPECT_CALL(*mNativeWindow, perform(9)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(13)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(30)).Times(1);
         auto displayDevice = mInjector.inject();
 
         displayDevice->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
@@ -1287,7 +1272,7 @@
     // Insert display data so that the HWC thinks it created the virtual display.
     const auto displayId = Case::Display::DISPLAY_ID::get();
     ASSERT_TRUE(displayId);
-    mFlinger.mutableHwcDisplayData()[*displayId] = {};
+    mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
 
     setupNewDisplayDeviceInternalTest<Case>();
 }
@@ -1725,7 +1710,6 @@
 
     EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
 
-    EXPECT_CALL(*mProducer, connect(_, _, _, _)).Times(1);
     EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
 
     Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -1801,7 +1785,7 @@
     // A virtual display is set up but is removed from the current state.
     const auto displayId = Case::Display::DISPLAY_ID::get();
     ASSERT_TRUE(displayId);
-    mFlinger.mutableHwcDisplayData()[*displayId] = {};
+    mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
     Case::Display::injectHwcDisplay(this);
     auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
     existing.inject();
@@ -1949,11 +1933,18 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    auto renderSurface = new renderengine::mock::Surface();
+    sp<GraphicBuffer> buf = new GraphicBuffer();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
+    // Setup injection expections
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
+    EXPECT_CALL(*nativeWindow, perform(9)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(30)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -1965,9 +1956,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
     EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
-    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -1988,11 +1977,18 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    auto renderSurface = new renderengine::mock::Surface();
+    sp<GraphicBuffer> buf = new GraphicBuffer();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
+    // Setup injection expections
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
+    EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
+            .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
+    EXPECT_CALL(*nativeWindow, perform(9)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(30)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -2004,9 +2000,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
     EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
-    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -2920,7 +2914,7 @@
     // Insert display data so that the HWC thinks it created the virtual display.
     const auto displayId = Case::Display::DISPLAY_ID::get();
     ASSERT_TRUE(displayId);
-    mFlinger.mutableHwcDisplayData()[*displayId] = {};
+    mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
 
     // A virtual display device is set up
     Case::Display::injectHwcDisplay(this);
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
new file mode 100644
index 0000000..b518f10
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -0,0 +1,144 @@
+#undef LOG_TAG
+#define LOG_TAG "LayerHistoryUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+
+#include <mutex>
+
+#include "Scheduler/LayerHistory.h"
+
+using testing::_;
+using testing::Return;
+
+namespace android {
+
+class LayerHistoryTest : public testing::Test {
+public:
+    LayerHistoryTest();
+    ~LayerHistoryTest() override;
+
+protected:
+    std::unique_ptr<LayerHistory> mLayerHistory;
+};
+
+LayerHistoryTest::LayerHistoryTest() {
+    mLayerHistory = std::make_unique<LayerHistory>();
+}
+LayerHistoryTest::~LayerHistoryTest() {}
+
+namespace {
+TEST_F(LayerHistoryTest, simpleInsertAndGet) {
+    mLayerHistory->insert("TestLayer", 0);
+
+    const std::unordered_map<std::string, nsecs_t>& testMap = mLayerHistory->get(0);
+    EXPECT_EQ(1, testMap.size());
+    auto element = testMap.find("TestLayer");
+    EXPECT_EQ("TestLayer", element->first);
+    EXPECT_EQ(0, element->second);
+
+    // Testing accessing object at an empty container will return an empty map.
+    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(1);
+    EXPECT_EQ(0, emptyMap.size());
+}
+
+TEST_F(LayerHistoryTest, multipleInserts) {
+    mLayerHistory->insert("TestLayer0", 0);
+    mLayerHistory->insert("TestLayer1", 1);
+    mLayerHistory->insert("TestLayer2", 2);
+    mLayerHistory->insert("TestLayer3", 3);
+
+    const std::unordered_map<std::string, nsecs_t>& testMap = mLayerHistory->get(0);
+    // Because the counter was not incremented, all elements were inserted into the first
+    // container.
+    EXPECT_EQ(4, testMap.size());
+    auto element = testMap.find("TestLayer0");
+    EXPECT_EQ("TestLayer0", element->first);
+    EXPECT_EQ(0, element->second);
+
+    element = testMap.find("TestLayer1");
+    EXPECT_EQ("TestLayer1", element->first);
+    EXPECT_EQ(1, element->second);
+
+    element = testMap.find("TestLayer2");
+    EXPECT_EQ("TestLayer2", element->first);
+    EXPECT_EQ(2, element->second);
+
+    element = testMap.find("TestLayer3");
+    EXPECT_EQ("TestLayer3", element->first);
+    EXPECT_EQ(3, element->second);
+
+    // Testing accessing object at an empty container will return an empty map.
+    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(1);
+    EXPECT_EQ(0, emptyMap.size());
+}
+
+TEST_F(LayerHistoryTest, incrementingCounter) {
+    mLayerHistory->insert("TestLayer0", 0);
+    mLayerHistory->incrementCounter();
+    mLayerHistory->insert("TestLayer1", 1);
+    mLayerHistory->insert("TestLayer2", 2);
+    mLayerHistory->incrementCounter();
+    mLayerHistory->insert("TestLayer3", 3);
+
+    // Because the counter was incremented, the elements were inserted into different
+    // containers.
+    const std::unordered_map<std::string, nsecs_t>& testMap1 = mLayerHistory->get(0);
+    EXPECT_EQ(1, testMap1.size());
+    auto element = testMap1.find("TestLayer0");
+    EXPECT_EQ("TestLayer0", element->first);
+    EXPECT_EQ(0, element->second);
+
+    const std::unordered_map<std::string, nsecs_t>& testMap2 = mLayerHistory->get(1);
+    EXPECT_EQ(2, testMap2.size());
+    element = testMap2.find("TestLayer1");
+    EXPECT_EQ("TestLayer1", element->first);
+    EXPECT_EQ(1, element->second);
+    element = testMap2.find("TestLayer2");
+    EXPECT_EQ("TestLayer2", element->first);
+    EXPECT_EQ(2, element->second);
+
+    const std::unordered_map<std::string, nsecs_t>& testMap3 = mLayerHistory->get(2);
+    EXPECT_EQ(1, testMap3.size());
+    element = testMap3.find("TestLayer3");
+    EXPECT_EQ("TestLayer3", element->first);
+    EXPECT_EQ(3, element->second);
+
+    // Testing accessing object at an empty container will return an empty map.
+    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(3);
+    EXPECT_EQ(0, emptyMap.size());
+}
+
+TEST_F(LayerHistoryTest, clearTheMap) {
+    mLayerHistory->insert("TestLayer0", 0);
+    mLayerHistory->incrementCounter();
+
+    const std::unordered_map<std::string, nsecs_t>& testMap1 = mLayerHistory->get(0);
+    EXPECT_EQ(1, testMap1.size());
+    auto element = testMap1.find("TestLayer0");
+    EXPECT_EQ("TestLayer0", element->first);
+    EXPECT_EQ(0, element->second);
+
+    // The array currently contains 30 elements.
+    for (int i = 1; i < 30; ++i) {
+        mLayerHistory->insert("TestLayer0", i);
+        mLayerHistory->incrementCounter();
+    }
+    // Expect the map to be cleared.
+    const std::unordered_map<std::string, nsecs_t>& testMap2 = mLayerHistory->get(0);
+    EXPECT_EQ(0, testMap2.size());
+
+    mLayerHistory->insert("TestLayer30", 30);
+    const std::unordered_map<std::string, nsecs_t>& testMap3 = mLayerHistory->get(0);
+    element = testMap3.find("TestLayer30");
+    EXPECT_EQ("TestLayer30", element->first);
+    EXPECT_EQ(30, element->second);
+    // The original element in this location does not exist anymore.
+    element = testMap3.find("TestLayer0");
+    EXPECT_EQ(testMap3.end(), element);
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a519f1f..85c835e 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -474,11 +474,6 @@
             return *this;
         }
 
-        auto& setRenderSurface(std::unique_ptr<renderengine::Surface> renderSurface) {
-            mCreationArgs.renderSurface = std::move(renderSurface);
-            return *this;
-        }
-
         auto& setSecure(bool secure) {
             mCreationArgs.isSecure = secure;
             return *this;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index af54df6..fbfbc3f 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -26,9 +26,6 @@
 RenderEngine::RenderEngine() = default;
 RenderEngine::~RenderEngine() = default;
 
-Surface::Surface() = default;
-Surface::~Surface() = default;
-
 Image::Image() = default;
 Image::~Image() = default;
 
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index afca63a..90c3c20 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -23,7 +23,6 @@
 #include <renderengine/LayerSettings.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
-#include <renderengine/Surface.h>
 #include <renderengine/Texture.h>
 #include <ui/GraphicBuffer.h>
 
@@ -37,15 +36,12 @@
     ~RenderEngine() override;
 
     MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
-    MOCK_METHOD0(createSurface, std::unique_ptr<renderengine::Surface>());
     MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(String8&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
-    MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&));
-    MOCK_METHOD0(resetCurrentSurface, void());
     MOCK_METHOD0(flush, base::unique_fd());
     MOCK_METHOD0(finish, bool());
     MOCK_METHOD1(waitFence, bool(base::unique_fd*));
@@ -82,23 +78,6 @@
                                 ANativeWindowBuffer* const, base::unique_fd*));
 };
 
-class Surface : public renderengine::Surface {
-public:
-    Surface();
-    ~Surface() override;
-
-    MOCK_METHOD1(setCritical, void(bool));
-    MOCK_METHOD1(setAsync, void(bool));
-    MOCK_METHOD1(setNativeWindow, void(ANativeWindow*));
-    MOCK_CONST_METHOD0(swapBuffers, void());
-    MOCK_CONST_METHOD0(queryRedSize, int32_t());
-    MOCK_CONST_METHOD0(queryGreenSize, int32_t());
-    MOCK_CONST_METHOD0(queryBlueSize, int32_t());
-    MOCK_CONST_METHOD0(queryAlphaSize, int32_t());
-    MOCK_CONST_METHOD0(getWidth, int32_t());
-    MOCK_CONST_METHOD0(getHeight, int32_t());
-};
-
 class Image : public renderengine::Image {
 public:
     Image();
diff --git a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
index 561fd58..4950a4b 100644
--- a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
+++ b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
@@ -36,6 +36,7 @@
     MOCK_METHOD1(queueBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
     MOCK_CONST_METHOD2(query, int(int, int*));
     MOCK_METHOD1(perform, int(int));
+    MOCK_METHOD2(perform, int(int, int));
     MOCK_METHOD1(cancelBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
     MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
     MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));