Merge "Add flag AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE to Input.h"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1855d26..6a9007c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -34,23 +34,21 @@
 # made today requires touching the same file, just copy the old
 # touch step and add it to the end of the list.
 #
-# *****************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
-# *****************************************************************
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
 
 # For example:
 #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
 #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
 #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
 #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
 $(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libdvr.so" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
 $(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libgui*" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/thermalserviced)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/thermalservice.rc)
-# ******************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
-# ******************************************************************
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "gpuservice*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/gpuservice_intermediates)
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
new file mode 100644
index 0000000..924a3a3
--- /dev/null
+++ b/cmds/bugreportz/Android.bp
@@ -0,0 +1,44 @@
+// bugreportz
+// ==========
+cc_binary {
+    name: "bugreportz",
+
+    srcs: [
+        "bugreportz.cpp",
+        "main.cpp",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+    ],
+}
+
+// bugreportz_test
+// ===============
+cc_test {
+    name: "bugreportz_test",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    srcs: [
+        "bugreportz.cpp",
+        "bugreportz_test.cpp",
+    ],
+
+    static_libs: ["libgmock"],
+
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
+}
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
deleted file mode 100644
index 10dda56..0000000
--- a/cmds/bugreportz/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# bugreportz
-# ==========
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-   bugreportz.cpp \
-   main.cpp \
-
-LOCAL_MODULE:= bugreportz
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-
-include $(BUILD_EXECUTABLE)
-
-# bugreportz_test
-# ===============
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bugreportz_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_SRC_FILES := \
-    bugreportz.cpp \
-    bugreportz_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libutils \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
new file mode 100644
index 0000000..d91184a
--- /dev/null
+++ b/cmds/cmd/Android.bp
@@ -0,0 +1,18 @@
+cc_binary {
+    name: "cmd",
+
+    srcs: ["cmd.cpp"],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+        "libselinux",
+        "libbinder",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DXP_UNIX",
+    ],
+}
diff --git a/cmds/cmd/Android.mk b/cmds/cmd/Android.mk
deleted file mode 100644
index 4868555..0000000
--- a/cmds/cmd/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	cmd.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libutils \
-	liblog \
-    libselinux \
-	libbinder
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_C_INCLUDES += \
-    $(JNI_H_INCLUDE)
-
-ifeq ($(TARGET_OS),linux)
-	LOCAL_CFLAGS += -DXP_UNIX
-	#LOCAL_SHARED_LIBRARIES += librt
-endif
-
-LOCAL_MODULE:= cmd
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 71658d8..0ee6c3a 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -24,10 +24,31 @@
 
 #include "DumpstateInternal.h"
 
+using android::base::StringPrintf;
+
 namespace android {
 namespace os {
 
 namespace {
+
+static binder::Status exception(uint32_t code, const std::string& msg) {
+    MYLOGE("%s (%d) ", msg.c_str(), code);
+    return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
+}
+
+static binder::Status error(uint32_t code, const std::string& msg) {
+    MYLOGE("%s (%d) ", msg.c_str(), code);
+    return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
+}
+
+static void* callAndNotify(void* data) {
+    Dumpstate& ds = *static_cast<Dumpstate*>(data);
+    // TODO(111441001): Return status on listener.
+    ds.Run();
+    MYLOGE("Finished Run()\n");
+    return nullptr;
+}
+
 class DumpstateToken : public BnDumpstateToken {};
 }
 
@@ -77,10 +98,30 @@
     return binder::Status::ok();
 }
 
-binder::Status DumpstateService::startBugreport(int, const sp<IDumpstateListener>&,
-                                                const DumpstateOptions&, int32_t* returned_id) {
-    // TODO: fork to handle the bugreport request and return the process id or a request id here.
+binder::Status DumpstateService::startBugreport(int, int bugreport_mode, int32_t* returned_id) {
+    // TODO(111441001): return a request id here.
     *returned_id = -1;
+    MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
+
+    if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                         StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
+    }
+
+    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+    ds_.SetOptions(std::move(options));
+
+    pthread_t thread;
+    status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
+    if (err != 0) {
+        return error(err, "Could not create a background thread.");
+    }
     return binder::Status::ok();
 }
 
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 131aff3..58095b3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,8 +41,7 @@
                                bool getSectionDetails,
                                sp<IDumpstateToken>* returned_token) override;
 
-    binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
-                                  const DumpstateOptions& options, int32_t* returned_id) override;
+    binder::Status startBugreport(int fd, int bugreport_mode, int32_t* returned_id) override;
 
   private:
     Dumpstate& ds_;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 68a4f21..9e59f58 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -39,10 +39,27 @@
     IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
                                 boolean getSectionDetails);
 
+    // These modes encapsulate a set of run time options for generating bugreports.
+    // A zipped bugreport; default mode.
+    const int BUGREPORT_MODE_FULL = 0;
+
+    // Interactive bugreport, i.e. triggered by the user.
+    const int BUGREPORT_MODE_INTERACTIVE = 1;
+
+    // Remote bugreport triggered by DevicePolicyManager, for e.g.
+    const int BUGREPORT_MODE_REMOTE = 2;
+
+    // Bugreport triggered on a wear device.
+    const int BUGREPORT_MODE_WEAR = 3;
+
+    // Bugreport limited to only telephony info.
+    const int BUGREPORT_MODE_TELEPHONY = 4;
+
+    // Bugreport limited to only wifi info.
+    const int BUGREPORT_MODE_WIFI = 5;
+
     /*
-     * Starts a bugreport in a child process.
-     *
-     * Returns an identifier of the bugreport process running in the background.
+     * Starts a bugreport in the background.
      */
-    int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
+    int startBugreport(int fd, int bugreportMode);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 1a45436..72d1de9 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1917,7 +1917,7 @@
             am_args.push_back("android.intent.extra.SCREENSHOT");
             am_args.push_back(ds.screenshot_path_);
         }
-        if (ds.options_->notification_title.empty()) {
+        if (!ds.options_->notification_title.empty()) {
             am_args.push_back("--es");
             am_args.push_back("android.intent.extra.TITLE");
             am_args.push_back(ds.options_->notification_title);
@@ -1940,37 +1940,95 @@
     }
 }
 
-// TODO: Move away from system properties when we have options passed via binder calls.
-/* Sets runtime options from the system properties and then clears those properties. */
-static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
-    options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
-    if (!options->extra_options.empty()) {
-        // Framework uses a system property to override some command-line args.
-        // Currently, it contains the type of the requested bugreport.
-        if (options->extra_options == "bugreportplus") {
+static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
+    switch (mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            return "BUGREPORT_FULL";
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
+            return "BUGREPORT_INTERACTIVE";
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
+            return "BUGREPORT_REMOTE";
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+            return "BUGREPORT_WEAR";
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
+            return "BUGREPORT_TELEPHONY";
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
+            return "BUGREPORT_WIFI";
+    }
+}
+
+static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
+    switch (mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            options->do_broadcast = true;
+            options->do_fb = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
             // Currently, the dumpstate binder is only used by Shell to update progress.
             options->do_start_service = true;
             options->do_progress_updates = true;
             options->do_fb = false;
-        } else if (options->extra_options == "bugreportremote") {
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
             options->do_vibrate = false;
             options->is_remote_mode = true;
             options->do_fb = false;
-        } else if (options->extra_options == "bugreportwear") {
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
             options->do_start_service = true;
             options->do_progress_updates = true;
             options->do_zip_file = true;
-        } else if (options->extra_options == "bugreporttelephony") {
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
             options->telephony_only = true;
-        } else if (options->extra_options == "bugreportwifi") {
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
             options->wifi_only = true;
             options->do_zip_file = true;
+            options->do_fb = true;
+            options->do_broadcast = true;
+            break;
+    }
+}
+
+static Dumpstate::BugreportMode getBugreportModeFromProperty() {
+    // If the system property is not set, it's assumed to be a full bugreport.
+    Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
+
+    std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
+    if (!extra_options.empty()) {
+        // Framework uses a system property to override some command-line args.
+        // Currently, it contains the type of the requested bugreport.
+        if (extra_options == "bugreportplus") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
+        } else if (extra_options == "bugreportremote") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
+        } else if (extra_options == "bugreportwear") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
+        } else if (extra_options == "bugreporttelephony") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
+        } else if (extra_options == "bugreportwifi") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
         } else {
-            MYLOGE("Unknown extra option: %s\n", options->extra_options.c_str());
+            MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
         }
         // Reset the property
         android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
     }
+    return mode;
+}
+
+// TODO: Move away from system properties when we have options passed via binder calls.
+/* Sets runtime options from the system properties and then clears those properties. */
+static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
+    Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
+    SetOptionsFromMode(mode, options);
 
     options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
     if (!options->notification_title.empty()) {
@@ -1988,6 +2046,40 @@
     }
 }
 
+static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
+    MYLOGI("do_zip_file: %d\n", options.do_zip_file);
+    MYLOGI("do_add_date: %d\n", options.do_add_date);
+    MYLOGI("do_vibrate: %d\n", options.do_vibrate);
+    MYLOGI("use_socket: %d\n", options.use_socket);
+    MYLOGI("use_control_socket: %d\n", options.use_control_socket);
+    MYLOGI("do_fb: %d\n", options.do_fb);
+    MYLOGI("do_broadcast: %d\n", options.do_broadcast);
+    MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
+    MYLOGI("show_header_only: %d\n", options.show_header_only);
+    MYLOGI("do_start_service: %d\n", options.do_start_service);
+    MYLOGI("telephony_only: %d\n", options.telephony_only);
+    MYLOGI("wifi_only: %d\n", options.wifi_only);
+    MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
+    MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
+    MYLOGI("extra_options: %s\n", options.extra_options.c_str());
+    MYLOGI("args: %s\n", options.args.c_str());
+    MYLOGI("notification_title: %s\n", options.notification_title.c_str());
+    MYLOGI("notification_description: %s\n", options.notification_description.c_str());
+}
+
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode) {
+    // In the new API world, date is always added; output is always a zip file.
+    // TODO(111441001): remove these options once they are obsolete.
+    do_add_date = true;
+    do_zip_file = true;
+
+    // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
+    use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+
+    extra_options = ModeToString(bugreport_mode);
+    SetOptionsFromMode(bugreport_mode, this);
+}
+
 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
     RunStatus status = RunStatus::OK;
     int c;
@@ -2052,11 +2144,16 @@
     return true;
 }
 
-Dumpstate::RunStatus Dumpstate::RunWithOptions(std::unique_ptr<DumpOptions> options) {
-    if (!options->ValidateOptions()) {
+void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
+    options_ = std::move(options);
+}
+
+Dumpstate::RunStatus Dumpstate::Run() {
+    if (!options_->ValidateOptions()) {
+        MYLOGE("Invalid options specified\n");
+        LogDumpOptions(*options_);
         return RunStatus::INVALID_INPUT;
     }
-    options_ = std::move(options);
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
 
@@ -2278,7 +2375,8 @@
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
     Dumpstate::RunStatus status = options->Initialize(argc, argv);
     if (status == Dumpstate::RunStatus::OK) {
-        status = ds.RunWithOptions(std::move(options));
+        ds.SetOptions(std::move(options));
+        status = ds.Run();
     }
 
     switch (status) {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c2f7f6a..5e7f71d 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -27,6 +27,7 @@
 
 #include <android-base/macros.h>
 #include <android-base/unique_fd.h>
+#include <android/os/IDumpstate.h>
 #include <android/os/IDumpstateListener.h>
 #include <utils/StrongPointer.h>
 #include <ziparchive/zip_writer.h>
@@ -42,6 +43,9 @@
 // TODO: and then remove explicitly android::os::dumpstate:: prefixes
 namespace android {
 namespace os {
+
+struct DumpstateOptions;
+
 namespace dumpstate {
 
 class DumpstateTest;
@@ -185,6 +189,16 @@
   public:
     enum RunStatus { OK, HELP, INVALID_INPUT, ERROR };
 
+    // The mode under which the bugreport should be run. Each mode encapsulates a few options.
+    enum BugreportMode {
+        BUGREPORT_FULL = android::os::IDumpstate::BUGREPORT_MODE_FULL,
+        BUGREPORT_INTERACTIVE = android::os::IDumpstate::BUGREPORT_MODE_INTERACTIVE,
+        BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE,
+        BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR,
+        BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY,
+        BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI
+    };
+
     static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
 
     static Dumpstate& GetInstance();
@@ -294,8 +308,11 @@
 
     struct DumpOptions;
 
-    /* Main entry point for running a complete bugreport. Takes ownership of options. */
-    RunStatus RunWithOptions(std::unique_ptr<DumpOptions> options);
+    /* Main entry point for running a complete bugreport. */
+    RunStatus Run();
+
+    /* Sets runtime options. */
+    void SetOptions(std::unique_ptr<DumpOptions> options);
 
     // TODO: add other options from DumpState.
     /*
@@ -317,6 +334,7 @@
         // Whether progress updates should be published.
         bool do_progress_updates = false;
         std::string use_outfile;
+        // TODO: rename to MODE.
         // Extra options passed as system property.
         std::string extra_options;
         // Command-line arguments as string
@@ -328,6 +346,9 @@
         /* Initializes options from commandline arguments and system properties. */
         RunStatus Initialize(int argc, char* argv[]);
 
+        /* Initializes options from the requested mode. */
+        void Initialize(BugreportMode bugreport_mode);
+
         /* Returns true if the options set so far are consistent. */
         bool ValidateOptions() const;
     };
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2cb9800..9ca894d 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -159,10 +159,11 @@
     };
     // clang-format on
 
-    Dumpstate::DumpOptions options;
     Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+
+    // These correspond to bugreport_mode = full, because that's the default.
     EXPECT_FALSE(options_.do_add_date);
     EXPECT_FALSE(options_.do_zip_file);
     EXPECT_EQ("", options_.use_outfile);
@@ -170,10 +171,10 @@
     EXPECT_FALSE(options_.use_control_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.do_fb);
+    EXPECT_TRUE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_broadcast);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial1) {
@@ -202,10 +203,10 @@
     // Other options retain default values
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_FALSE(options_.do_fb);
+    EXPECT_TRUE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_FALSE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_broadcast);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial2) {
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4ad5c4b..6cbb691 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -82,8 +82,12 @@
 
 CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
 
+// TODO(111441001): Default DumpOptions to sensible values.
 Dumpstate::Dumpstate(const std::string& version)
-    : pid_(getpid()), version_(version), now_(time(nullptr)) {
+    : pid_(getpid()),
+      options_(new Dumpstate::DumpOptions()),
+      version_(version),
+      now_(time(nullptr)) {
 }
 
 Dumpstate& Dumpstate::GetInstance() {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7a47724..f0c21f5 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -387,23 +387,28 @@
     return mStrictModePolicy;
 }
 
-uid_t IPCThreadState::setWorkSource(uid_t uid)
+int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid)
 {
-    uid_t returnValue = mWorkSource;
+    // Note: we currently only use half of the int64. We return an int64 for extensibility.
+    int64_t token = mWorkSource;
     mWorkSource = uid;
-    return returnValue;
+    return token;
 }
 
-uid_t IPCThreadState::getWorkSource() const
+uid_t IPCThreadState::getCallingWorkSourceUid() const
 {
     return mWorkSource;
 }
 
-uid_t IPCThreadState::clearWorkSource()
+int64_t IPCThreadState::clearCallingWorkSource()
 {
-    uid_t returnValue = mWorkSource;
-    mWorkSource = kUnsetWorkSource;
-    return returnValue;
+    return setCallingWorkSourceUid(kUnsetWorkSource);
+}
+
+void IPCThreadState::restoreCallingWorkSource(int64_t token)
+{
+    uid_t uid = (int)token;
+    setCallingWorkSourceUid(uid);
 }
 
 void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 532f7f1..643f428 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -601,7 +601,7 @@
 {
     writeInt32(IPCThreadState::self()->getStrictModePolicy() |
                STRICT_MODE_PENALTY_GATHER);
-    writeInt32(IPCThreadState::self()->getWorkSource());
+    writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
     // currently the interface identification token is just its name as a string
     return writeString16(interface);
 }
@@ -631,7 +631,7 @@
     }
     // WorkSource.
     int32_t workSource = readInt32();
-    threadState->setWorkSource(workSource);
+    threadState->setCallingWorkSourceUid(workSource);
     // Interface descriptor.
     const String16 str(readString16());
     if (str == interface) {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 5888e14..de126d5 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -47,12 +47,14 @@
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
 
-            // See Binder#setThreadWorkSource in Binder.java.
-            uid_t               setWorkSource(uid_t uid);
-            // See Binder#getThreadWorkSource in Binder.java.
-            uid_t               getWorkSource() const;
-            // See Binder#clearThreadWorkSource in Binder.java.
-            uid_t               clearWorkSource();
+            // See Binder#setCallingWorkSourceUid in Binder.java.
+            int64_t             setCallingWorkSourceUid(uid_t uid);
+            // See Binder#getCallingWorkSourceUid in Binder.java.
+            uid_t               getCallingWorkSourceUid() const;
+            // See Binder#clearCallingWorkSource in Binder.java.
+            int64_t             clearCallingWorkSource();
+            // See Binder#restoreCallingWorkSource in Binder.java.
+            void                restoreCallingWorkSource(int64_t token);
 
             void                setLastTransactionBinderFlags(int32_t flags);
             int32_t             getLastTransactionBinderFlags() const;
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index b021c23..3594349 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -347,7 +347,7 @@
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to write to.
- * \param fd the value to write to the parcel.
+ * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
  *
  * \return STATUS_OK on successful write.
  */
@@ -361,7 +361,8 @@
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel.
+ * \param fd the out parameter for what is read from the parcel (or -1 to represent a null
+ * ParcelFileDescriptor)
  *
  * \return STATUS_OK on successful write.
  */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index a478ee0..f99c3a9 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -26,6 +26,7 @@
 
 #pragma once
 
+#include <android/binder_auto_utils.h>
 #include <android/binder_parcel.h>
 
 #include <optional>
@@ -152,28 +153,103 @@
 }
 
 /**
+ * Convenience method to write a nullable strong binder.
+ */
+static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    return AParcel_writeStrongBinder(parcel, binder.get());
+}
+
+/**
+ * Convenience method to read a nullable strong binder.
+ */
+static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel,
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder);
+    if (status == STATUS_OK) {
+        binder->set(readBinder);
+    }
+    return status;
+}
+
+/**
  * Convenience method to write a strong binder but return an error if it is null.
  */
-static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel, AIBinder* binder) {
-    if (binder == nullptr) {
+static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    if (binder.get() == nullptr) {
         return STATUS_UNEXPECTED_NULL;
     }
-    return AParcel_writeStrongBinder(parcel, binder);
+    return AParcel_writeStrongBinder(parcel, binder.get());
 }
 
 /**
  * Convenience method to read a strong binder but return an error if it is null.
  */
 static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
-                                                               AIBinder** binder) {
-    binder_status_t ret = AParcel_readStrongBinder(parcel, binder);
-    if (ret == STATUS_OK && *binder == nullptr) {
-        return STATUS_UNEXPECTED_NULL;
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder);
+    if (ret == STATUS_OK) {
+        if (readBinder == nullptr) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+
+        binder->set(readBinder);
     }
     return ret;
 }
 
 /**
+ * Convenience method to write a ParcelFileDescriptor where -1 represents a null value.
+ */
+static inline binder_status_t AParcel_writeNullableParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
+}
+
+/**
+ * Convenience method to read a ParcelFileDescriptor where -1 represents a null value.
+ */
+static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        fd->set(readFd);
+    }
+    return status;
+}
+
+/**
+ * Convenience method to write a valid ParcelFileDescriptor.
+ */
+static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    if (fd.get() < 0) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
+}
+
+/**
+ * Convenience method to read a valid ParcelFileDescriptor.
+ */
+static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        if (readFd < 0) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+        fd->set(readFd);
+    }
+    return status;
+}
+
+/**
  * Allocates a std::string to length and returns the underlying buffer. For use with
  * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
  */
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index b1a2955..3c32100 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -229,23 +229,39 @@
 }
 
 binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
-    ParcelFileDescriptor parcelFd((unique_fd(fd)));
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
 
-    status_t status = parcel->get()->writeParcelable(parcelFd);
+    if (fd < 0) {
+        if (fd != -1) {
+            return STATUS_UNKNOWN_ERROR;
+        }
+        // parcelFd = nullptr
+    } else {  // fd >= 0
+        parcelFd = std::make_unique<ParcelFileDescriptor>(unique_fd(fd));
+    }
+
+    status_t status = parcel->get()->writeNullableParcelable(parcelFd);
 
     // ownership is retained by caller
-    (void)parcelFd.release().release();
+    if (parcelFd != nullptr) {
+        (void)parcelFd->release().release();
+    }
 
     return PruneStatusT(status);
 }
 
 binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
-    ParcelFileDescriptor parcelFd;
-    // status_t status = parcelFd.readFromParcel(parcel->get());
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
     status_t status = parcel->get()->readParcelable(&parcelFd);
     if (status != STATUS_OK) return PruneStatusT(status);
 
-    *fd = parcelFd.release().release();
+    if (parcelFd) {
+        *fd = parcelFd->release().release();
+    } else {
+        *fd = -1;
+    }
+
     return STATUS_OK;
 }
 
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 7bcfffd..22c1bad 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -953,7 +953,7 @@
 {
     status_t ret;
     Parcel data, reply;
-    uid_t previousWorkSource = IPCThreadState::self()->setWorkSource(100);
+    int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100);
     data.writeInterfaceToken(binderLibTestServiceName);
     ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
     EXPECT_EQ(100, reply.readInt32());
@@ -966,8 +966,8 @@
     status_t ret;
     Parcel data, reply;
 
-    IPCThreadState::self()->setWorkSource(100);
-    uid_t previousWorkSource = IPCThreadState::self()->clearWorkSource();
+    IPCThreadState::self()->setCallingWorkSourceUid(100);
+    int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource();
     data.writeInterfaceToken(binderLibTestServiceName);
     ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
 
@@ -976,6 +976,22 @@
     EXPECT_EQ(NO_ERROR, ret);
 }
 
+TEST_F(BinderLibTest, WorkSourceRestored)
+{
+    status_t ret;
+    Parcel data, reply;
+
+    IPCThreadState::self()->setCallingWorkSourceUid(100);
+    int64_t token = IPCThreadState::self()->clearCallingWorkSource();
+    IPCThreadState::self()->restoreCallingWorkSource(token);
+
+    data.writeInterfaceToken(binderLibTestServiceName);
+    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
+
+    EXPECT_EQ(100, reply.readInt32());
+    EXPECT_EQ(NO_ERROR, ret);
+}
+
 class BinderLibTestService : public BBinder
 {
     public:
@@ -1276,7 +1292,7 @@
             }
             case BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION: {
                 data.enforceInterface(binderLibTestServiceName);
-                reply->writeInt32(IPCThreadState::self()->getWorkSource());
+                reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
                 return NO_ERROR;
             }
             default:
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index 70a4322..e244a83 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -275,6 +275,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 +303,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 +316,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 +358,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) {
@@ -636,12 +637,6 @@
 
     // 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 {
@@ -974,12 +969,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..aebb319 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -47,7 +47,8 @@
     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;
@@ -120,11 +121,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;
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 8b43333..28a7501 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -25,6 +25,7 @@
         "BufferClient.cpp",
         "BufferHubService.cpp",
         "BufferNode.cpp",
+        "UniqueIdGenerator.cpp",
     ],
     header_libs: [
         "libbufferhub_headers",
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 3bfd9cb..fc5ad1d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -35,7 +35,7 @@
 
     std::shared_ptr<BufferNode> node =
             std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
-                                         desc.usage, userMetadataSize);
+                                         desc.usage, userMetadataSize, nodeIdGenerator.getId());
     if (node == nullptr || !node->IsValid()) {
         ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
         _hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::ALLOCATION_FAILED);
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index 53dd702..715d0a1 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -1,5 +1,6 @@
 #include <errno.h>
 
+#include <bufferhub/BufferHubService.h>
 #include <bufferhub/BufferNode.h>
 #include <private/dvr/buffer_hub_defs.h>
 #include <ui/GraphicBufferAllocator.h>
@@ -22,7 +23,8 @@
 
 // Allocates a new BufferNode.
 BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
-                       uint64_t usage, size_t user_metadata_size) {
+                       uint64_t usage, size_t user_metadata_size, uint32_t id)
+      : mId(id) {
     uint32_t out_stride = 0;
     // graphicBufferId is not used in GraphicBufferAllocator::allocate
     // TODO(b/112338294) After move to the service folder, stop using the
@@ -54,14 +56,23 @@
     InitializeMetadata();
 }
 
-// Free the handle
 BufferNode::~BufferNode() {
+    // Free the handle
     if (buffer_handle_ != nullptr) {
         status_t ret = GraphicBufferAllocator::get().free(buffer_handle_);
         if (ret != OK) {
             ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret);
         }
     }
+
+    // Free the id, if valid
+    if (id() != UniqueIdGenerator::kInvalidId) {
+        if (nodeIdGenerator.freeId(id())) {
+            ALOGI("%s: id #%u is freed.", __FUNCTION__, id());
+        } else {
+            ALOGE("%s: Cannot free nonexistent id #%u", __FUNCTION__, id());
+        }
+    }
 }
 
 uint64_t BufferNode::GetActiveClientsBitMask() const {
diff --git a/services/bufferhub/UniqueIdGenerator.cpp b/services/bufferhub/UniqueIdGenerator.cpp
new file mode 100644
index 0000000..362a026
--- /dev/null
+++ b/services/bufferhub/UniqueIdGenerator.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#include <bufferhub/UniqueIdGenerator.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+constexpr uint32_t UniqueIdGenerator::kInvalidId;
+
+uint32_t UniqueIdGenerator::getId() {
+    std::lock_guard<std::mutex> lock(mIdsInUseMutex);
+
+    do {
+        if (++mLastId >= std::numeric_limits<uint32_t>::max()) {
+            mLastId = kInvalidId + 1;
+        }
+    } while (mIdsInUse.find(mLastId) != mIdsInUse.end());
+
+    mIdsInUse.insert(mLastId);
+    return mLastId;
+}
+
+bool UniqueIdGenerator::freeId(uint32_t id) {
+    std::lock_guard<std::mutex> lock(mIdsInUseMutex);
+    auto iter = mIdsInUse.find(id);
+    if (iter != mIdsInUse.end()) {
+        mIdsInUse.erase(iter);
+        return true;
+    }
+
+    return false;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index dbbee8f..5441750 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -22,6 +22,7 @@
 
 #include <android/frameworks/bufferhub/1.0/IBufferHub.h>
 #include <bufferhub/BufferClient.h>
+#include <bufferhub/UniqueIdGenerator.h>
 #include <utils/Mutex.h>
 
 namespace android {
@@ -34,6 +35,8 @@
 using hardware::Return;
 using hardware::graphics::common::V1_2::HardwareBufferDescription;
 
+static UniqueIdGenerator nodeIdGenerator;
+
 class BufferHubService : public IBufferHub {
 public:
     Return<void> allocateBuffer(const HardwareBufferDescription& description,
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index ffeacac..c490e7c 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -2,6 +2,7 @@
 #define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
 
 #include <android/hardware_buffer.h>
+#include <bufferhub/UniqueIdGenerator.h>
 #include <ui/BufferHubMetadata.h>
 
 namespace android {
@@ -14,13 +15,16 @@
 public:
     // Allocates a new BufferNode.
     BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
-               uint64_t usage, size_t user_metadata_size);
+               uint64_t usage, size_t user_metadata_size,
+               uint32_t id = UniqueIdGenerator::kInvalidId);
 
     ~BufferNode();
 
     // Returns whether the object holds a valid metadata.
     bool IsValid() const { return metadata_.IsValid(); }
 
+    uint32_t id() const { return mId; }
+
     size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
 
     // Accessors of the buffer description and handle
@@ -59,6 +63,11 @@
     // Metadata in shared memory.
     BufferHubMetadata metadata_;
 
+    // A system-unique id generated by bufferhub from 1 to std::numeric_limits<uint32_t>::max().
+    // BufferNodes not created by bufferhub will have id = 0, meaning "not specified".
+    // TODO(b/118891412): remove default id = 0 and update comments after pdx is no longer in use
+    const uint32_t mId = 0;
+
     // The following variables are atomic variables in metadata_ that are visible
     // to Bn object and Bp objects. Please find more info in
     // BufferHubDefs::MetadataHeader.
diff --git a/services/bufferhub/include/bufferhub/UniqueIdGenerator.h b/services/bufferhub/include/bufferhub/UniqueIdGenerator.h
new file mode 100644
index 0000000..d2e702f
--- /dev/null
+++ b/services/bufferhub/include/bufferhub/UniqueIdGenerator.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
+#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
+
+#include <mutex>
+#include <set>
+
+#include <utils/Mutex.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+// A thread-safe incremental uint32_t id generator.
+class UniqueIdGenerator {
+public:
+    // 0 is considered invalid
+    static constexpr uint32_t kInvalidId = 0UL;
+
+    // Gets next available id. If next id is greater than std::numeric_limits<uint32_t>::max() (2 ^
+    // 32 - 1), it will try to get an id start from 1 again.
+    uint32_t getId();
+
+    // Free a specific id. Return true on freed, false on not found.
+    bool freeId(uint32_t id);
+
+private:
+    std::mutex mIdsInUseMutex;
+    // Start from kInvalidID to avoid generating it.
+    uint32_t mLastId = kInvalidId;
+    std::set<uint32_t> mIdsInUse GUARDED_BY(mIdsInUseMutex);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
index cef31f6..8a30ef5 100644
--- a/services/bufferhub/tests/Android.bp
+++ b/services/bufferhub/tests/Android.bp
@@ -21,4 +21,20 @@
     ],
     // TODO(b/117568153): Temporarily opt out using libcrt.
     no_libcrt: true,
+}
+
+cc_test {
+    name: "UniqueIdGenerator_test",
+    srcs: ["UniqueIdGenerator_test.cpp"],
+    cflags: [
+        "-DLOG_TAG=\"UniqueIdGenerator_test\"",
+        "-DTRACE=0",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+    ],
+    shared_libs: [
+        "libbufferhubservice",
+    ],
+    static_libs: [
+        "libgmock",
+    ],
 }
\ No newline at end of file
diff --git a/services/bufferhub/tests/UniqueIdGenerator_test.cpp b/services/bufferhub/tests/UniqueIdGenerator_test.cpp
new file mode 100644
index 0000000..c4d83e0
--- /dev/null
+++ b/services/bufferhub/tests/UniqueIdGenerator_test.cpp
@@ -0,0 +1,45 @@
+#include <bufferhub/UniqueIdGenerator.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+namespace {
+
+class UniqueIdGeneratorTest : public testing::Test {
+protected:
+    UniqueIdGenerator mIdGenerator;
+};
+
+TEST_F(UniqueIdGeneratorTest, TestGenerateAndFreeID) {
+    uint32_t id = mIdGenerator.getId();
+    EXPECT_NE(id, UniqueIdGenerator::kInvalidId);
+
+    EXPECT_TRUE(mIdGenerator.freeId(id));
+    EXPECT_FALSE(mIdGenerator.freeId(id));
+}
+
+TEST_F(UniqueIdGeneratorTest, TestGenerateUniqueIncrementalID) {
+    // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
+    // resulting IDs should still keep incresing.
+    const size_t kTestSize = 10U;
+    uint32_t ids[kTestSize];
+    for (int i = 0; i < kTestSize; ++i) {
+        ids[i] = mIdGenerator.getId();
+        EXPECT_NE(ids[i], UniqueIdGenerator::kInvalidId);
+        if (i >= 1) {
+            EXPECT_GT(ids[i], ids[i - 1]);
+        }
+    }
+}
+
+} // namespace
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
\ No newline at end of file
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index e4ca6bc..150896c 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -62,7 +62,7 @@
     status_t cmd_vkjson(int out, int err);
 }
 
-const char* const GpuService::SERVICE_NAME = "gpuservice";
+const char* const GpuService::SERVICE_NAME = "gpu";
 
 GpuService::GpuService() = default;
 
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
index d23cf46..65a5c27 100644
--- a/services/gpuservice/gpuservice.rc
+++ b/services/gpuservice/gpuservice.rc
@@ -1,4 +1,4 @@
-service gpuservice /system/bin/gpuservice
+service gpu /system/bin/gpuservice
     class core
     user gpu_service
     group graphics
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..9abb040 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -184,6 +184,7 @@
         "libhidltransport",
         "liblayers_proto",
         "liblog",
+        "libsync",
         "libtimestats_proto",
         "libutils",
     ],
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5342bcf..55ce434 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,6 +223,7 @@
         mDisplayToken(args.displayToken),
         mId(args.displayId),
         mNativeWindow(args.nativeWindow),
+        mGraphicBuffer(nullptr),
         mDisplaySurface(args.displaySurface),
         mSurface{std::move(args.renderSurface)},
         mDisplayInstallOrientation(args.displayInstallOrientation),
@@ -284,6 +287,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 +332,6 @@
 
 void DisplayDevice::flip() const
 {
-    mFlinger->getRenderEngine().checkErrors();
     mPageFlipCount++;
 }
 
@@ -356,9 +366,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,7 +439,7 @@
     }
 }
 
-void DisplayDevice::onSwapBuffersCompleted() const {
+void DisplayDevice::onPresentDisplayCompleted() {
     mDisplaySurface->onFrameCommitted();
 }
 
@@ -384,6 +456,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();
 }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bcd3330..560a958 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -28,13 +28,14 @@
 #include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <math/mat4.h>
+#include <renderengine/RenderEngine.h>
 #include <renderengine/Surface.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>
 
@@ -146,10 +147,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);
@@ -160,6 +164,11 @@
     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,7 +213,12 @@
 
     // 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;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 038bc58..1e910ce 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1344,7 +1344,10 @@
 
 void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
     uint32_t orientation = 0;
-    if (!mFlinger->mDebugDisableTransformHint) {
+    // Disable setting transform hint if the debug flag is set or if the
+    // getTransformToDisplayInverse flag is set and the client wants to submit buffers
+    // in one orientation.
+    if (!mFlinger->mDebugDisableTransformHint && !getTransformToDisplayInverse()) {
         // The transform hint is used to improve performance, but we can
         // only have a single transform hint, it cannot
         // apply to all displays.
@@ -1976,6 +1979,7 @@
     layerInfo->set_window_type(state.type);
     layerInfo->set_app_id(state.appId);
     layerInfo->set_curr_frame(mCurrentFrameNumber);
+    layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
 
     for (const auto& pendingState : mPendingStates) {
         auto barrierLayer = pendingState.barrierLayer_legacy.promote();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 35ba391..7150660 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();
 }
 
@@ -1719,7 +1715,7 @@
             auto& engine(getRenderEngine());
             engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
 
-            display->swapBuffers(getHwComposer());
+            display->queueBuffer(getHwComposer());
         }
     }
 
@@ -2194,8 +2190,7 @@
         if (displayId) {
             getHwComposer().presentAndGetReleaseFences(*displayId);
         }
-        display->onSwapBuffersCompleted();
-        display->makeCurrent();
+        display->onPresentDisplayCompleted();
         for (auto& layer : display->getVisibleLayersSortedByZ()) {
             sp<Fence> releaseFence = Fence::NO_FENCE;
 
@@ -2348,16 +2343,11 @@
     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);
     }
@@ -2417,12 +2407,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());
                 }
@@ -2973,7 +2957,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
@@ -2988,10 +2972,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());
@@ -3004,9 +2988,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();
@@ -3035,18 +3041,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) {
@@ -3139,11 +3134,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;
 }
 
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/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 2a09634..c141ee3 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -86,6 +86,7 @@
   repeated BarrierLayerProto barrier_layer = 38;
   // If active_buffer is not null, record its transform.
   optional TransformProto buffer_transform = 39;
+  optional int32 effective_scaling_mode = 40;
 }
 
 message PositionProto {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ab1b252..6d3e715 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;
@@ -142,6 +143,9 @@
     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();
 
@@ -266,13 +270,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 +323,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 +342,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..e8c8894 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
@@ -340,7 +341,6 @@
     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.
@@ -349,17 +349,15 @@
         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)));
 
+        // Creating a DisplayDevice requires getting default dimensions from the
+        // native window.
         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 +1068,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 +1127,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,
@@ -1725,7 +1723,6 @@
 
     EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
 
-    EXPECT_CALL(*mProducer, connect(_, _, _, _)).Times(1);
     EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
 
     Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -1950,10 +1947,19 @@
     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 +1971,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
@@ -1989,10 +1993,19 @@
     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 +2017,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
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));
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
new file mode 100644
index 0000000..20301f6
--- /dev/null
+++ b/services/vr/performanced/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2016 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.
+
+cc_defaults {
+    name: "performanced_defaults",
+    static_libs: [
+        "libperformance",
+        "libvr_manager",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libpdx_default_transport",
+    ],
+}
+
+cc_binary {
+    name: "performanced",
+    defaults: ["performanced_defaults"],
+    srcs: [
+        "cpu_set.cpp",
+        "main.cpp",
+        "performance_service.cpp",
+        "task.cpp",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"performanced\"",
+        "-DTRACE=0",
+        "-Wall",
+        "-Werror",
+    ],
+    init_rc: ["performanced.rc"],
+}
+
+cc_test {
+    name: "performance_service_tests",
+    defaults: ["performanced_defaults"],
+    srcs: ["performance_service_tests.cpp"],
+}
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
deleted file mode 100644
index a548ef0..0000000
--- a/services/vr/performanced/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH := $(call my-dir)
-
-sourceFiles := \
-	cpu_set.cpp \
-	main.cpp \
-	performance_service.cpp \
-	task.cpp
-
-staticLibraries := \
-	libperformance \
-	libvr_manager
-
-sharedLibraries := \
-	libbinder \
-	libbase \
-	libcutils \
-	liblog \
-	libutils \
-	libpdx_default_transport \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(sourceFiles)
-LOCAL_CFLAGS := -DLOG_TAG=\"performanced\"
-LOCAL_CFLAGS += -DTRACE=0
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_STATIC_LIBRARIES := $(staticLibraries)
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performanced
-LOCAL_INIT_RC := performanced.rc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := performance_service_tests.cpp
-LOCAL_STATIC_LIBRARIES := $(staticLibraries) libgtest_main
-LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
-LOCAL_MODULE := performance_service_tests
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_NATIVE_TEST)
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 8f76606..e4c50d5 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 1
-define VERSION_PATCH 91
+define VERSION_PATCH 93
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -615,6 +615,10 @@
 @extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
 @extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
 
+// 222
+@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
+@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
+
 // 224
 @extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 0
 @extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
@@ -623,6 +627,10 @@
 @extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 0
 @extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
 
+// 247
+@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
+@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
+
 /////////////
 //  Types  //
 /////////////
@@ -1848,10 +1856,16 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
 
     //@extension("VK_EXT_pci_bus_info") // 213
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT       = 1000212000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT   = 1000212000,
 
     //@extension("VK_FUCHSIA_imagepipe_surface") // 215
     VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA     = 1000214000,
+
+    //@extension("VK_EXT_scalar_block_layout")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT  = 1000221000,
+
+    //@extension("VK_EXT_separate_stencil_usage") // 247
+    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT       = 1000246000,
 }
 
 enum VkSubpassContents {
@@ -2382,6 +2396,7 @@
     VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR                = 7,
     VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR                   = 8,
     VK_DRIVER_ID_ARM_PROPRIETARY_KHR                        = 9,
+    VK_DRIVER_ID_GOOGLE_PASTEL_KHR                          = 10,
 }
 
 /////////////////
@@ -7656,6 +7671,20 @@
     platform.zx_handle_t                            imagePipeHandle
 }
 
+@extension("VK_EXT_scalar_block_layout") // 222
+class VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        scalarBlockLayout
+}
+
+@extension("VK_EXT_separate_stencil_usage") // 247
+class VkImageStencilUsageCreateInfoEXT {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkImageUsageFlags                               stencilUsage
+}
+
 
 ////////////////
 //  Commands  //
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index 4cd8ed5..35c0664 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 91
+#define VK_HEADER_VERSION 93
 
 
 #define VK_NULL_HANDLE 0
@@ -454,6 +454,8 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
     VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = 1000221000,
+    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = 1000246000,
     VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
     VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
@@ -6101,9 +6103,10 @@
     VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
     VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
     VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+    VK_DRIVER_ID_GOOGLE_PASTEL_KHR = 10,
     VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR,
-    VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_ARM_PROPRIETARY_KHR,
-    VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_ARM_PROPRIETARY_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
+    VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_GOOGLE_PASTEL_KHR,
+    VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_GOOGLE_PASTEL_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
     VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkDriverIdKHR;
 
@@ -7791,8 +7794,6 @@
 
 
 #define VK_EXT_image_drm_format_modifier 1
-#define VK_EXT_EXTENSION_159_SPEC_VERSION 0
-#define VK_EXT_EXTENSION_159_EXTENSION_NAME "VK_EXT_extension_159"
 #define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
 #define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
 
@@ -8806,6 +8807,18 @@
 
 
 
+#define VK_EXT_scalar_block_layout 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
+
+typedef struct VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           scalarBlockLayout;
+} VkPhysicalDeviceScalarBlockLayoutFeaturesEXT;
+
+
+
 #define VK_GOOGLE_hlsl_functionality1 1
 #define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 0
 #define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
@@ -8816,6 +8829,18 @@
 #define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
 
 
+#define VK_EXT_separate_stencil_usage 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
+
+typedef struct VkImageStencilUsageCreateInfoEXT {
+    VkStructureType      sType;
+    const void*          pNext;
+    VkImageUsageFlags    stencilUsage;
+} VkImageStencilUsageCreateInfoEXT;
+
+
+
 #ifdef __cplusplus
 }
 #endif