Merge "Export AIDL files as a filegroup for framework.jar" am: e6161630a1  -s ours am: dbe8513e74  -s ours
am: 40d33758aa  -s ours

Change-Id: I6e606ee28398fbedfebf4e6e1403d784cf127831
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9dbbb77..1b90579 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -130,6 +130,14 @@
         { REQ,      "events/irq/enable" },
         { OPT,      "events/ipi/enable" },
     } },
+    { "irqoff",     "IRQ-disabled code section tracing", 0, {
+        { REQ,      "events/preemptirq/irq_enable/enable" },
+        { REQ,      "events/preemptirq/irq_disable/enable" },
+    } },
+    { "preemptoff", "Preempt-disabled code section tracing", 0, {
+        { REQ,      "events/preemptirq/preempt_enable/enable" },
+        { REQ,      "events/preemptirq/preempt_disable/enable" },
+    } },
     { "i2c",        "I2C Events",   0, {
         { REQ,      "events/i2c/enable" },
         { REQ,      "events/i2c/i2c_read/enable" },
@@ -144,6 +152,8 @@
     { "freq",       "CPU Frequency",    0, {
         { REQ,      "events/power/cpu_frequency/enable" },
         { OPT,      "events/power/clock_set_rate/enable" },
+        { OPT,      "events/power/clock_disable/enable" },
+        { OPT,      "events/power/clock_enable/enable" },
         { OPT,      "events/power/cpu_frequency_limits/enable" },
     } },
     { "membus",     "Memory Bus Utilization", 0, {
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 014c995..6511b44 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -61,7 +61,8 @@
 public:
     bool mActive = true;
 
-    virtual int openOutputFile(const String16& path, const String16& seLinuxContext) {
+    virtual int openFile(const String16& path, const String16& seLinuxContext,
+            const String16& mode) {
         String8 path8(path);
         char cwd[256];
         getcwd(cwd, 256);
@@ -71,7 +72,32 @@
             aerr << "Open attempt after active for: " << fullPath << endl;
             return -EPERM;
         }
-        int fd = open(fullPath.string(), O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG);
+#if DEBUG
+        ALOGD("openFile: %s, full=%s", path8.string(), fullPath.string());
+#endif
+        int flags = 0;
+        bool checkRead = false;
+        bool checkWrite = false;
+        if (mode == String16("w")) {
+            flags = O_WRONLY|O_CREAT|O_TRUNC;
+            checkWrite = true;
+        } else if (mode == String16("w+")) {
+            flags = O_RDWR|O_CREAT|O_TRUNC;
+            checkRead = checkWrite = true;
+        } else if (mode == String16("r")) {
+            flags = O_RDONLY;
+            checkRead = true;
+        } else if (mode == String16("r+")) {
+            flags = O_RDWR;
+            checkRead = checkWrite = true;
+        } else {
+            aerr << "Invalid mode requested: " << mode.string() << endl;
+            return -EINVAL;
+        }
+        int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
+#if DEBUG
+        ALOGD("openFile: fd=%d", fd);
+#endif
         if (fd < 0) {
             return fd;
         }
@@ -80,14 +106,33 @@
             security_context_t tmp = NULL;
             int ret = getfilecon(fullPath.string(), &tmp);
             Unique_SecurityContext context(tmp);
-            int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
-                    "file", "write", NULL);
-            if (accessGranted != 0) {
-                close(fd);
-                aerr << "System server has no access to file context " << context.get()
-                        << " (from path " << fullPath.string() << ", context "
-                        << seLinuxContext8.string() << ")" << endl;
-                return -EPERM;
+            if (checkWrite) {
+                int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
+                        "file", "write", NULL);
+                if (accessGranted != 0) {
+#if DEBUG
+                    ALOGD("openFile: failed selinux write check!");
+#endif
+                    close(fd);
+                    aerr << "System server has no access to write file context " << context.get()
+                            << " (from path " << fullPath.string() << ", context "
+                            << seLinuxContext8.string() << ")" << endl;
+                    return -EPERM;
+                }
+            }
+            if (checkRead) {
+                int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
+                        "file", "read", NULL);
+                if (accessGranted != 0) {
+#if DEBUG
+                    ALOGD("openFile: failed selinux read check!");
+#endif
+                    close(fd);
+                    aerr << "System server has no access to read file context " << context.get()
+                            << " (from path " << fullPath.string() << ", context "
+                            << seLinuxContext8.string() << ")" << endl;
+                    return -EPERM;
+                }
             }
         }
         return fd;
@@ -131,6 +176,9 @@
     proc->setThreadPoolMaxThreadCount(0);
     proc->startThreadPool();
 
+#if DEBUG
+    ALOGD("cmd: starting");
+#endif
     sp<IServiceManager> sm = defaultServiceManager();
     fflush(stdout);
     if (sm == NULL) {
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index ede4254..85eb464 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -43,7 +43,7 @@
 
 static constexpr const char* kSuPath = "/system/xbin/su";
 
-static bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
+static bool waitpid_with_timeout(pid_t pid, int timeout_ms, int* status) {
     sigset_t child_mask, old_mask;
     sigemptyset(&child_mask);
     sigaddset(&child_mask, SIGCHLD);
@@ -54,10 +54,11 @@
     }
 
     timespec ts;
-    ts.tv_sec = timeout_seconds;
-    ts.tv_nsec = 0;
+    ts.tv_sec = MSEC_TO_SEC(timeout_ms);
+    ts.tv_nsec = (timeout_ms % 1000) * 1000000;
     int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
     int saved_errno = errno;
+
     // Set the signals back the way they were.
     if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
         printf("*** sigprocmask failed: %s\n", strerror(errno));
@@ -91,7 +92,7 @@
 CommandOptions CommandOptions::DEFAULT = CommandOptions::WithTimeout(10).Build();
 CommandOptions CommandOptions::AS_ROOT = CommandOptions::WithTimeout(10).AsRoot().Build();
 
-CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout) : values(timeout) {
+CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout_ms) : values(timeout_ms) {
 }
 
 CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Always() {
@@ -130,8 +131,8 @@
     return CommandOptions(values);
 }
 
-CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout)
-    : timeout_(timeout),
+CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout_ms)
+    : timeout_ms_(timeout_ms),
       always_(false),
       account_mode_(DONT_DROP_ROOT),
       output_mode_(NORMAL_OUTPUT),
@@ -142,7 +143,11 @@
 }
 
 int64_t CommandOptions::Timeout() const {
-    return values.timeout_;
+    return MSEC_TO_SEC(values.timeout_ms_);
+}
+
+int64_t CommandOptions::TimeoutInMs() const {
+    return values.timeout_ms_;
 }
 
 bool CommandOptions::Always() const {
@@ -161,8 +166,12 @@
     return values.logging_message_;
 }
 
-CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(int64_t timeout) {
-    return CommandOptions::CommandOptionsBuilder(timeout);
+CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(int64_t timeout_sec) {
+    return CommandOptions::CommandOptionsBuilder(SEC_TO_MSEC(timeout_sec));
+}
+
+CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeoutInMs(int64_t timeout_ms) {
+    return CommandOptions::CommandOptionsBuilder(timeout_ms);
 }
 
 std::string PropertiesHelper::build_type_ = "";
@@ -314,7 +323,7 @@
 
     /* handle parent case */
     int status;
-    bool ret = waitpid_with_timeout(pid, options.Timeout(), &status);
+    bool ret = waitpid_with_timeout(pid, options.TimeoutInMs(), &status);
     fsync(fd);
 
     uint64_t elapsed = Nanotime() - start;
@@ -333,9 +342,9 @@
                    static_cast<float>(elapsed) / NANOS_PER_SEC, pid);
         }
         kill(pid, SIGTERM);
-        if (!waitpid_with_timeout(pid, 5, nullptr)) {
+        if (!waitpid_with_timeout(pid, 5000, nullptr)) {
             kill(pid, SIGKILL);
-            if (!waitpid_with_timeout(pid, 5, nullptr)) {
+            if (!waitpid_with_timeout(pid, 5000, nullptr)) {
                 if (!silent)
                     dprintf(fd, "could not kill command '%s' (pid %d) even with SIGKILL.\n",
                             command, pid);
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 698ceff..8342099 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -19,6 +19,16 @@
 #include <cstdint>
 #include <string>
 
+/*
+ * Converts seconds to milliseconds.
+ */
+#define SEC_TO_MSEC(second) (second * 1000)
+
+/*
+ * Converts milliseconds to seconds.
+ */
+#define MSEC_TO_SEC(millisecond) (millisecond / 1000)
+
 namespace android {
 namespace os {
 namespace dumpstate {
@@ -66,9 +76,9 @@
   private:
     class CommandOptionsValues {
       private:
-        CommandOptionsValues(int64_t timeout);
+        CommandOptionsValues(int64_t timeout_ms);
 
-        int64_t timeout_;
+        int64_t timeout_ms_;
         bool always_;
         PrivilegeMode account_mode_;
         OutputMode output_mode_;
@@ -102,13 +112,15 @@
         CommandOptions Build();
 
       private:
-        CommandOptionsBuilder(int64_t timeout);
+        CommandOptionsBuilder(int64_t timeout_ms);
         CommandOptionsValues values;
         friend class CommandOptions;
     };
 
-    /** Gets the command timeout, in seconds. */
+    /** Gets the command timeout in seconds. */
     int64_t Timeout() const;
+    /** Gets the command timeout in milliseconds. */
+    int64_t TimeoutInMs() const;
     /* Checks whether the command should always be run, even on dry-run mode. */
     bool Always() const;
     /** Gets the PrivilegeMode of the command. */
@@ -118,8 +130,11 @@
     /** Gets the logging message header, it any. */
     std::string LoggingMessage() const;
 
-    /** Creates a builder with the requied timeout. */
-    static CommandOptionsBuilder WithTimeout(int64_t timeout);
+    /** Creates a builder with the requied timeout in seconds. */
+    static CommandOptionsBuilder WithTimeout(int64_t timeout_sec);
+
+    /** Creates a builder with the requied timeout in milliseconds. */
+    static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms);
 
     // Common options.
     static CommandOptions DEFAULT;
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index b995b80..dee89cf 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -56,8 +56,20 @@
 - `description.txt`: whose value is a multi-line, detailed description of the problem.
 
 ## Android O versions
-On _Android O (OhMightyAndroidWhatsYourNextReleaseName?)_, the following changes were made:
-- The ANR traces are added to the `FS` folder, typically under `FS/data/anr` (version `2.0-dev-1`).
+On _Android O (Oreo)_, the following changes were made:
+- The ANR traces are added to the `FS` folder, typically under `FS/data/anr` (version `2.0-dev-split-anr`).
+
+## Android P versions
+On _Android P (PleaseMightyAndroidWhatsYourNextReleaseName?)_, the following changes were made:
+- Dumpsys sections are dumped by priority (version `2.0-dev-priority-dumps`).
+  Supported priorities can be specified when registering framework services. Section headers are
+  changed to contain priority info.
+  `DUMPSYS` -> `DUMPSYS CRITICAL/HIGH/NORMAL`
+  `DUMP OF SERVICE <servicename>` -> `DUMP OF SERVICE CRITICAL/HIGH/NORMAL <servicename>`
+  Supported Priorities:
+    - CRITICAL - services that must dump first, and fast (under 100ms). Ex: cpuinfo.
+    - HIGH - services that also must dump first, but can take longer (under 250ms) to dump. Ex: meminfo.
+    - NORMAL - services that have no rush to dump and can take a long time (under 10s).
 
 ## Intermediate versions
 During development, the versions will be suffixed with _-devX_ or
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index e792942..4b67d8f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -81,6 +81,7 @@
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
 #define WLUTIL "/vendor/xbin/wlutil"
+#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -112,8 +113,8 @@
 }
 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
-                       long dumpsysTimeout = 0) {
-    return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
+                       long dumpsysTimeoutMs = 0) {
+    return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
 }
 static int DumpFile(const std::string& title, const std::string& path) {
     return ds.DumpFile(title, path);
@@ -829,33 +830,32 @@
 }
 
 static void DoLogcat() {
-    unsigned long timeout;
+    unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
     // calculate timeout
-    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout < 20000) {
-        timeout = 20000;
+    timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+    if (timeout_ms < 20000) {
+        timeout_ms = 20000;
     }
     RunCommand("SYSTEM LOG",
-               {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
-                        "-d", "*:v"},
-               CommandOptions::WithTimeout(timeout / 1000).Build());
-    timeout = logcat_timeout("events");
-    if (timeout < 20000) {
-        timeout = 20000;
+               {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
+               CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+    timeout_ms = logcat_timeout("events");
+    if (timeout_ms < 20000) {
+        timeout_ms = 20000;
     }
     RunCommand("EVENT LOG",
                {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
                         "-d", "*:v"},
-               CommandOptions::WithTimeout(timeout / 1000).Build());
-    timeout = logcat_timeout("radio");
-    if (timeout < 20000) {
-        timeout = 20000;
+               CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+    timeout_ms = logcat_timeout("radio");
+    if (timeout_ms < 20000) {
+        timeout_ms = 20000;
     }
     RunCommand("RADIO LOG",
                {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
                         "-d", "*:v"},
-               CommandOptions::WithTimeout(timeout / 1000).Build());
+               CommandOptions::WithTimeoutInMs(timeout_ms).Build());
 
     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
 
@@ -1055,6 +1055,40 @@
     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
 }
 
+// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
+static void RunDumpsysCritical() {
+    if (ds.CurrentVersionSupportsPriorityDumps()) {
+        RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
+                   CommandOptions::WithTimeout(5).DropRoot().Build());
+    } else {
+        RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
+                   CommandOptions::WithTimeout(90).DropRoot().Build());
+        RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
+                   CommandOptions::WithTimeout(10).DropRoot().Build());
+    }
+}
+
+// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
+static void RunDumpsysHigh() {
+    if (ds.CurrentVersionSupportsPriorityDumps()) {
+        RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
+                   CommandOptions::WithTimeout(20).DropRoot().Build());
+    } else {
+        RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
+    }
+}
+
+// Runs dumpsys on services that must dump but can take up to 10s to dump.
+static void RunDumpsysNormal() {
+    if (ds.CurrentVersionSupportsPriorityDumps()) {
+        RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
+                   CommandOptions::WithTimeout(90).DropRoot().Build());
+    } else {
+        RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
+                   CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
+    }
+}
+
 static void dumpstate() {
     DurationReporter duration_reporter("DUMPSTATE");
 
@@ -1080,7 +1114,7 @@
     DumpFile("KERNEL SYNC", "/d/sync");
 
     RunCommand("PROCESSES AND THREADS",
-               {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
+               {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
     RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
 
     if (ds.IsZipping()) {
@@ -1146,15 +1180,11 @@
     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
 
-    RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
-               CommandOptions::WithTimeout(10).Build());
+    RunDumpsysHigh();
 
     RunCommand("SYSTEM PROPERTIES", {"getprop"});
 
-    RunCommand("VOLD DUMP", {"vdc", "dump"});
-    RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
-
-    RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
+    RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
 
     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
 
@@ -1180,6 +1210,11 @@
     DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
     DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
 
+    /* Add window and surface trace files. */
+    if (!PropertiesHelper::IsUserBuild()) {
+        ds.AddDir(WMTRACE_DATA_DIR, false);
+    }
+
     ds.DumpstateBoard();
 
     /* Migrate the ril_dumpstate to a device specific dumpstate? */
@@ -1200,8 +1235,7 @@
     printf("== Android Framework Services\n");
     printf("========================================================\n");
 
-    RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
-               10);
+    RunDumpsysNormal();
 
     printf("========================================================\n");
     printf("== Checkins\n");
@@ -1273,8 +1307,10 @@
     printf("== Android Framework Services\n");
     printf("========================================================\n");
 
-    RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
-    RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
+    RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
+               SEC_TO_MSEC(10));
+    RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
+               SEC_TO_MSEC(10));
 
     printf("========================================================\n");
     printf("== Running Application Services\n");
@@ -1599,6 +1635,7 @@
             do_fb = 0;
         } else if (ds.extra_options_ == "bugreportwear") {
             ds.update_progress_ = true;
+            do_zip_file = 1;
         } else if (ds.extra_options_ == "bugreporttelephony") {
             telephony_only = true;
         } else {
@@ -1642,10 +1679,12 @@
         ds.version_ = VERSION_CURRENT;
     }
 
-    if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
-        MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
-               ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
-               VERSION_SPLIT_ANR.c_str());
+    if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR &&
+        ds.version_ != VERSION_PRIORITY_DUMPS) {
+        MYLOGE(
+            "invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s', '%s')\n",
+            ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
+            VERSION_SPLIT_ANR.c_str(), VERSION_PRIORITY_DUMPS.c_str());
         exit(1);
     }
 
@@ -1836,10 +1875,7 @@
 
         // Invoking the following dumpsys calls before dump_traces() to try and
         // keep the system stats as close to its initial state as possible.
-        RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
-                   CommandOptions::WithTimeout(90).DropRoot().Build());
-        RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
-                   CommandOptions::WithTimeout(10).DropRoot().Build());
+        RunDumpsysCritical();
 
         // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
         dump_raft();
@@ -1869,6 +1905,9 @@
         RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
                    CommandOptions::WithTimeout(10).Build());
 
+        // Run iotop as root to show top 100 IO threads
+        RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
+
         if (!DropRootUser()) {
             return -1;
         }
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7757c1e..8db23a9 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -149,9 +149,15 @@
 
 /*
  * Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version
- * will be bumped to 2.0-dev-1.
+ * will be bumped to 2.0.
  */
-static std::string VERSION_SPLIT_ANR = "2.0-dev-1";
+static std::string VERSION_SPLIT_ANR = "2.0-dev-split-anr";
+
+/*
+ * Temporary version that adds priority based dumps. Once tools support it, the current version
+ * will be bumped to 2.0.
+ */
+static std::string VERSION_PRIORITY_DUMPS = "2.0-dev-priority-dumps";
 
 /*
  * "Alias" for the current version.
@@ -190,19 +196,19 @@
 
     /*
      * Runs `dumpsys` with the given arguments, automatically setting its timeout
-     * (`-t` argument)
+     * (`-T` argument)
      * according to the command options.
      *
      * |title| description of the command printed on `stdout` (or empty to skip
      * description).
      * |dumpsys_args| `dumpsys` arguments (except `-t`).
      * |options| optional argument defining the command's behavior.
-     * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -t` (otherwise it uses the
+     * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -T` (otherwise it uses the
      * timeout from `options`)
      */
     void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
                     const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS,
-                    long dumpsys_timeout = 0);
+                    long dumpsys_timeout_ms = 0);
 
     /*
      * Prints the contents of a file.
@@ -266,6 +272,9 @@
     /* Gets the path of a bugreport file with the given suffix. */
     std::string GetPath(const std::string& suffix) const;
 
+    /* Returns true if the current version supports priority dump feature. */
+    bool CurrentVersionSupportsPriorityDumps() const;
+
     // TODO: initialize fields on constructor
 
     // dumpstate id - unique after each device reboot.
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 92b0c0d..a2e9453 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1001,7 +1001,7 @@
         err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
 }
 
-TEST_F(DumpstateUtilTest, RunCommandTimesout) {
+TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
     CreateFd("RunCommandTimesout.txt");
     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
                              CommandOptions::WithTimeout(1).Build()));
@@ -1011,6 +1011,17 @@
                                 " --sleep 2' timed out after 1"));
 }
 
+TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
+    CreateFd("RunCommandTimesout.txt");
+    EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
+                             CommandOptions::WithTimeoutInMs(1000).Build()));
+    EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
+                                " --sleep 2' timed out after 1"));
+    EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
+                                " --sleep 2' timed out after 1"));
+}
+
+
 TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
     CreateFd("RunCommandIsKilled.txt");
     CaptureStderr();
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index a96a69d..ac48041 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -215,10 +215,10 @@
     return progress_;
 }
 
-bool Progress::Inc(int32_t delta) {
+bool Progress::Inc(int32_t delta_sec) {
     bool changed = false;
-    if (delta >= 0) {
-        progress_ += delta;
+    if (delta_sec >= 0) {
+        progress_ += delta_sec;
         if (progress_ > max_) {
             int32_t old_max = max_;
             max_ = floor((float)progress_ * growth_factor_);
@@ -257,6 +257,10 @@
                                        name_.c_str(), suffix.c_str());
 }
 
+bool Dumpstate::CurrentVersionSupportsPriorityDumps() const {
+    return (version_ == VERSION_PRIORITY_DUMPS);
+}
+
 void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
     progress_ = std::move(progress);
 }
@@ -719,9 +723,9 @@
 }
 
 void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
-                           const CommandOptions& options, long dumpsysTimeout) {
-    long timeout = dumpsysTimeout > 0 ? dumpsysTimeout : options.Timeout();
-    std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-t", std::to_string(timeout)};
+                           const CommandOptions& options, long dumpsysTimeoutMs) {
+    long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
+    std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
     dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
     RunCommand(title, dumpsys, options);
 }
@@ -1161,14 +1165,14 @@
 }
 
 // TODO: make this function thread safe if sections are generated in parallel.
-void Dumpstate::UpdateProgress(int32_t delta) {
+void Dumpstate::UpdateProgress(int32_t delta_sec) {
     if (progress_ == nullptr) {
         MYLOGE("UpdateProgress: progress_ not set\n");
         return;
     }
 
     // Always update progess so stats can be tuned...
-    bool max_changed = progress_->Inc(delta);
+    bool max_changed = progress_->Inc(delta_sec);
 
     // ...but only notifiy listeners when necessary.
     if (!update_progress_) return;
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index 3476964..f68b862 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -17,6 +17,10 @@
         "libbinder",
     ],
 
+    static_libs: [
+        "libserviceutils",
+    ],
+
     clang: true,
 }
 
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 3227749..0862a40 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -25,6 +25,7 @@
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/TextOutput.h>
+#include <serviceutils/PriorityDumper.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
 
@@ -53,13 +54,19 @@
 
 static void usage() {
     fprintf(stderr,
-        "usage: dumpsys\n"
+            "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
+            "SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
-            "         -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
+            "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
+            "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+            "         --proto: filter services that support dumping data in proto format. Dumps"
+            "               will be in proto format.\n"
+            "         --priority LEVEL: filter services based on specified priority\n"
+            "               LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
             "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
             "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
 }
@@ -73,18 +80,38 @@
     return false;
 }
 
+static bool ConvertPriorityTypeToBitmask(const String16& type, int& bitmask) {
+    if (type == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+        bitmask = IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL;
+        return true;
+    }
+    if (type == PriorityDumper::PRIORITY_ARG_HIGH) {
+        bitmask = IServiceManager::DUMP_FLAG_PRIORITY_HIGH;
+        return true;
+    }
+    if (type == PriorityDumper::PRIORITY_ARG_NORMAL) {
+        bitmask = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL;
+        return true;
+    }
+    return false;
+}
+
 int Dumpsys::main(int argc, char* const argv[]) {
     Vector<String16> services;
     Vector<String16> args;
+    String16 priorityType;
     Vector<String16> skippedServices;
+    Vector<String16> protoServices;
     bool showListOnly = false;
     bool skipServices = false;
-    int timeoutArg = 10;
-    static struct option longOptions[] = {
-        {"skip", no_argument, 0,  0 },
-        {"help", no_argument, 0,  0 },
-        {     0,           0, 0,  0 }
-    };
+    bool filterByProto = false;
+    int timeoutArgMs = 10000;
+    int dumpPriorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
+    static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+                                          {"proto", no_argument, 0, 0},
+                                          {"skip", no_argument, 0, 0},
+                                          {"help", no_argument, 0, 0},
+                                          {0, 0, 0, 0}};
 
     // Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
     // happens on test cases).
@@ -93,7 +120,7 @@
         int c;
         int optionIndex = 0;
 
-        c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
+        c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);
 
         if (c == -1) {
             break;
@@ -103,18 +130,39 @@
         case 0:
             if (!strcmp(longOptions[optionIndex].name, "skip")) {
                 skipServices = true;
+            } else if (!strcmp(longOptions[optionIndex].name, "proto")) {
+                filterByProto = true;
             } else if (!strcmp(longOptions[optionIndex].name, "help")) {
                 usage();
                 return 0;
+            } else if (!strcmp(longOptions[optionIndex].name, "priority")) {
+                priorityType = String16(String8(optarg));
+                if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriorityFlags)) {
+                    fprintf(stderr, "\n");
+                    usage();
+                    return -1;
+                }
             }
             break;
 
         case 't':
             {
-                char *endptr;
-                timeoutArg = strtol(optarg, &endptr, 10);
-                if (*endptr != '\0' || timeoutArg <= 0) {
-                    fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
+                char* endptr;
+                timeoutArgMs = strtol(optarg, &endptr, 10);
+                timeoutArgMs = timeoutArgMs * 1000;
+                if (*endptr != '\0' || timeoutArgMs <= 0) {
+                    fprintf(stderr, "Error: invalid timeout(seconds) number: '%s'\n", optarg);
+                    return -1;
+                }
+            }
+            break;
+
+        case 'T':
+            {
+                char* endptr;
+                timeoutArgMs = strtol(optarg, &endptr, 10);
+                if (*endptr != '\0' || timeoutArgMs <= 0) {
+                    fprintf(stderr, "Error: invalid timeout(milliseconds) number: '%s'\n", optarg);
                     return -1;
                 }
             }
@@ -151,9 +199,23 @@
 
     if (services.empty() || showListOnly) {
         // gets all services
-        services = sm_->listServices();
+        services = sm_->listServices(dumpPriorityFlags);
         services.sort(sort_func);
-        args.add(String16("-a"));
+        if (filterByProto) {
+            protoServices = sm_->listServices(IServiceManager::DUMP_FLAG_PROTO);
+            protoServices.sort(sort_func);
+            Vector<String16> intersection;
+            std::set_intersection(services.begin(), services.end(), protoServices.begin(),
+                                  protoServices.end(), std::back_inserter(intersection));
+            services = std::move(intersection);
+            args.insertAt(String16(PriorityDumper::PROTO_ARG), 0);
+        }
+        if (dumpPriorityFlags != IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
+            args.insertAt(String16(PriorityDumper::PRIORITY_ARG), 0);
+            args.insertAt(priorityType, 1);
+        } else {
+            args.add(String16("-a"));
+        }
     }
 
     const size_t N = services.size();
@@ -197,7 +259,11 @@
             if (N > 1) {
                 aout << "------------------------------------------------------------"
                         "-------------------" << endl;
-                aout << "DUMP OF SERVICE " << service_name << ":" << endl;
+                if (dumpPriorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
+                    aout << "DUMP OF SERVICE " << service_name << ":" << endl;
+                } else {
+                    aout << "DUMP OF SERVICE " << priorityType << " " << service_name << ":" << endl;
+                }
             }
 
             // dump blocks until completion, so spawn a thread..
@@ -216,7 +282,7 @@
                 }
             });
 
-            auto timeout = std::chrono::seconds(timeoutArg);
+            auto timeout = std::chrono::milliseconds(timeoutArgMs);
             auto start = std::chrono::steady_clock::now();
             auto end = start + timeout;
 
@@ -268,8 +334,8 @@
 
             if (timed_out) {
                 aout << endl
-                     << "*** SERVICE '" << service_name << "' DUMP TIMEOUT (" << timeoutArg
-                     << "s) EXPIRED ***" << endl
+                     << "*** SERVICE '" << service_name << "' DUMP TIMEOUT (" << timeoutArgMs
+                     << "ms) EXPIRED ***" << endl
                      << endl;
             }
 
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index 39fcb80..e182b9d 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -15,6 +15,7 @@
     static_libs: [
         "libdumpsys",
         "libgmock",
+        "libserviceutils",
     ],
 
     clang: true,
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 16fefe6..bdb0a9a 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -22,6 +22,7 @@
 #include <gtest/gtest.h>
 
 #include <android-base/file.h>
+#include <serviceutils/PriorityDumper.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -50,8 +51,8 @@
   public:
     MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&));
     MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&));
-    MOCK_METHOD3(addService, status_t(const String16&, const sp<IBinder>&, bool));
-    MOCK_METHOD0(listServices, Vector<String16>());
+    MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
+    MOCK_METHOD1(listServices, Vector<String16>(int));
 
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
@@ -131,7 +132,16 @@
         for (auto& service : services) {
             services16.add(String16(service.c_str()));
         }
-        EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16));
+        EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL))
+            .WillRepeatedly(Return(services16));
+    }
+
+    void ExpectListServicesWithPriority(std::vector<std::string> services, int dumpFlags) {
+        Vector<String16> services16;
+        for (auto& service : services) {
+            services16.add(String16(service.c_str()));
+        }
+        EXPECT_CALL(sm_, listServices(dumpFlags)).WillRepeatedly(Return(services16));
     }
 
     sp<BinderMock> ExpectCheckService(const char* name, bool running = true) {
@@ -179,7 +189,10 @@
     }
 
     void AssertRunningServices(const std::vector<std::string>& services) {
-        std::string expected("Currently running services:\n");
+        std::string expected;
+        if (services.size() > 1) {
+            expected.append("Currently running services:\n");
+        }
         for (const std::string& service : services) {
             expected.append("  ").append(service).append("\n");
         }
@@ -198,6 +211,13 @@
         EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
     }
 
+    void AssertDumpedWithPriority(const std::string& service, const std::string& dump,
+                                  const char16_t* priorityType) {
+        std::string priority = String8(priorityType).c_str();
+        EXPECT_THAT(stdout_,
+                    HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump));
+    }
+
     void AssertNotDumped(const std::string& dump) {
         EXPECT_THAT(stdout_, Not(HasSubstr(dump)));
     }
@@ -236,6 +256,39 @@
     AssertNotDumped({"Valet"});
 }
 
+// Tests 'dumpsys -l --priority HIGH'
+TEST_F(DumpsysTest, ListAllServicesWithPriority) {
+    ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+    ExpectCheckService("Locksmith");
+    ExpectCheckService("Valet");
+
+    CallMain({"-l", "--priority", "HIGH"});
+
+    AssertRunningServices({"Locksmith", "Valet"});
+}
+
+// Tests 'dumpsys -l --priority HIGH' with and empty list
+TEST_F(DumpsysTest, ListEmptyServicesWithPriority) {
+    ExpectListServicesWithPriority({}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+
+    CallMain({"-l", "--priority", "HIGH"});
+
+    AssertRunningServices({});
+}
+
+// Tests 'dumpsys -l --proto'
+TEST_F(DumpsysTest, ListAllServicesWithProto) {
+    ExpectListServicesWithPriority({"Locksmith", "Valet", "Car"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+    ExpectListServicesWithPriority({"Valet", "Car"}, IServiceManager::DUMP_FLAG_PROTO);
+    ExpectCheckService("Car");
+    ExpectCheckService("Valet");
+
+    CallMain({"-l", "--proto"});
+
+    AssertRunningServices({"Car", "Valet"});
+}
+
 // Tests 'dumpsys service_name' on a service is running
 TEST_F(DumpsysTest, DumpRunningService) {
     ExpectDump("Valet", "Here's your car");
@@ -246,12 +299,25 @@
 }
 
 // Tests 'dumpsys -t 1 service_name' on a service that times out after 2s
-TEST_F(DumpsysTest, DumpRunningServiceTimeout) {
+TEST_F(DumpsysTest, DumpRunningServiceTimeoutInSec) {
     sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car");
 
     CallMain({"-t", "1", "Valet"});
 
-    AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1s) EXPIRED");
+    AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1000ms) EXPIRED");
+    AssertNotDumped("Here's your car");
+
+    // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp
+    Mock::AllowLeak(binder_mock.get());
+}
+
+// Tests 'dumpsys -T 500 service_name' on a service that times out after 2s
+TEST_F(DumpsysTest, DumpRunningServiceTimeoutInMs) {
+    sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car");
+
+    CallMain({"-T", "500", "Valet"});
+
+    AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (500ms) EXPIRED");
     AssertNotDumped("Here's your car");
 
     // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp
@@ -300,3 +366,98 @@
     AssertNotDumped("dump3");
     AssertNotDumped("dump5");
 }
+
+// Tests 'dumpsys --skip skipped3 skipped5 --priority CRITICAL', which should skip these services
+TEST_F(DumpsysTest, DumpWithSkipAndPriority) {
+    ExpectListServicesWithPriority({"running1", "stopped2", "skipped3", "running4", "skipped5"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+    ExpectDump("running1", "dump1");
+    ExpectCheckService("stopped2", false);
+    ExpectDump("skipped3", "dump3");
+    ExpectDump("running4", "dump4");
+    ExpectDump("skipped5", "dump5");
+
+    CallMain({"--priority", "CRITICAL", "--skip", "skipped3", "skipped5"});
+
+    AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"});
+    AssertDumpedWithPriority("running1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+    AssertDumpedWithPriority("running4", "dump4", PriorityDumper::PRIORITY_ARG_CRITICAL);
+    AssertStopped("stopped2");
+    AssertNotDumped("dump3");
+    AssertNotDumped("dump5");
+}
+
+// Tests 'dumpsys --priority CRITICAL'
+TEST_F(DumpsysTest, DumpWithPriorityCritical) {
+    ExpectListServicesWithPriority({"runningcritical1", "runningcritical2"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+    ExpectDump("runningcritical1", "dump1");
+    ExpectDump("runningcritical2", "dump2");
+
+    CallMain({"--priority", "CRITICAL"});
+
+    AssertRunningServices({"runningcritical1", "runningcritical2"});
+    AssertDumpedWithPriority("runningcritical1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+    AssertDumpedWithPriority("runningcritical2", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL);
+}
+
+// Tests 'dumpsys --priority HIGH'
+TEST_F(DumpsysTest, DumpWithPriorityHigh) {
+    ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+    ExpectDump("runninghigh1", "dump1");
+    ExpectDump("runninghigh2", "dump2");
+
+    CallMain({"--priority", "HIGH"});
+
+    AssertRunningServices({"runninghigh1", "runninghigh2"});
+    AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+    AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
+}
+
+// Tests 'dumpsys --priority NORMAL'
+TEST_F(DumpsysTest, DumpWithPriorityNormal) {
+    ExpectListServicesWithPriority({"runningnormal1", "runningnormal2"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
+    ExpectDump("runningnormal1", "dump1");
+    ExpectDump("runningnormal2", "dump2");
+
+    CallMain({"--priority", "NORMAL"});
+
+    AssertRunningServices({"runningnormal1", "runningnormal2"});
+    AssertDumpedWithPriority("runningnormal1", "dump1", PriorityDumper::PRIORITY_ARG_NORMAL);
+    AssertDumpedWithPriority("runningnormal2", "dump2", PriorityDumper::PRIORITY_ARG_NORMAL);
+}
+
+// Tests 'dumpsys --proto'
+TEST_F(DumpsysTest, DumpWithProto) {
+    ExpectListServicesWithPriority({"run8", "run1", "run2", "run5"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+    ExpectListServicesWithPriority({"run3", "run2", "run4", "run8"},
+                                   IServiceManager::DUMP_FLAG_PROTO);
+    ExpectDump("run2", "dump1");
+    ExpectDump("run8", "dump2");
+
+    CallMain({"--proto"});
+
+    AssertRunningServices({"run2", "run8"});
+    AssertDumped("run2", "dump1");
+    AssertDumped("run8", "dump2");
+}
+
+// Tests 'dumpsys --priority HIGH --proto'
+TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) {
+    ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
+                                   IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+    ExpectListServicesWithPriority({"runninghigh1", "runninghigh2", "runninghigh3"},
+                                   IServiceManager::DUMP_FLAG_PROTO);
+
+    ExpectDump("runninghigh1", "dump1");
+    ExpectDump("runninghigh2", "dump2");
+
+    CallMain({"--priority", "HIGH", "--proto"});
+
+    AssertRunningServices({"runninghigh1", "runninghigh2"});
+    AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+    AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
+}
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index dfc3e58..d5b3372 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -269,24 +269,10 @@
         return false;
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    err = sc->setLayer(0x7FFFFFFF);
-    if (err != NO_ERROR) {
-        fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err);
-        return false;
-    }
-    err = sc->setMatrix(scale, 0.0f, 0.0f, scale);
-    if (err != NO_ERROR) {
-        fprintf(stderr, "SurfaceComposer::setMatrix error: %#x\n", err);
-        return false;
-    }
-
-    err = sc->show();
-    if (err != NO_ERROR) {
-        fprintf(stderr, "SurfaceComposer::show error: %#x\n", err);
-        return false;
-    }
-    SurfaceComposerClient::closeGlobalTransaction();
+    SurfaceComposerClient::Transaction{}.setLayer(sc, 0x7FFFFFFF)
+            .setMatrix(sc, scale, 0.0f, 0.0f, scale)
+            .show(sc)
+            .apply();
 
     sp<ANativeWindow> anw = sc->getSurface();
     EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), NULL);
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 7d1537a..90c7da4 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -18,6 +18,7 @@
     shared_libs: [
         "libbase",
         "libbinder",
+        "libcrypto",
         "libcutils",
         "liblog",
         "liblogwrap",
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 1d21b3c..b3dc5ec 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -27,6 +27,7 @@
 LOCAL_HEADER_LIBRARIES := dex2oat_headers
 LOCAL_SHARED_LIBRARIES := \
     libbase \
+    libcrypto \
     libcutils \
     liblog \
     liblogwrap \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 04e39f9..48d5b36 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2365,6 +2365,22 @@
     return result ? ok() : error();
 }
 
+binder::Status InstalldNativeService::hashSecondaryDexFile(
+        const std::string& dexPath, const std::string& packageName, int32_t uid,
+        const std::unique_ptr<std::string>& volumeUuid, int32_t storageFlag,
+        std::vector<uint8_t>* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_UUID(volumeUuid);
+    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+
+    // mLock is not taken here since we will never modify the file system.
+    // If a file is modified just as we are reading it this may result in an
+    // anomalous hash, but that's ok.
+    bool result = android::installd::hash_secondary_dex_file(
+        dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return);
+    return result ? ok() : error();
+}
+
 binder::Status InstalldNativeService::invalidateMounts() {
     ENFORCE_UID(AID_SYSTEM);
     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f205efc..eb7231c 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -120,6 +120,9 @@
     binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
         const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
         const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
+    binder::Status hashSecondaryDexFile(const std::string& dexPath,
+        const std::string& packageName, int32_t uid, const std::unique_ptr<std::string>& volumeUuid,
+        int32_t storageFlag, std::vector<uint8_t>* _aidl_return);
 
     binder::Status invalidateMounts();
     binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 3374106..16ba2af 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -85,6 +85,9 @@
         int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
         int storage_flag);
 
+    byte[] hashSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
+        int uid, @nullable @utf8InCpp String volumeUuid, int storageFlag);
+
     void invalidateMounts();
     boolean isQuotaSupported(@nullable @utf8InCpp String uuid);
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 8917684..beffe00 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -15,6 +15,7 @@
  */
 #define LOG_TAG "installed"
 
+#include <array>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,6 +28,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
@@ -36,6 +38,7 @@
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <log/log.h>               // TODO: Move everything to base/logging.
+#include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
 #include <selinux/android.h>
 #include <system/thread_defs.h>
@@ -46,8 +49,10 @@
 #include "otapreopt_utils.h"
 #include "utils.h"
 
-using android::base::StringPrintf;
 using android::base::EndsWith;
+using android::base::ReadFully;
+using android::base::StringPrintf;
+using android::base::WriteFully;
 using android::base::unique_fd;
 
 namespace android {
@@ -2055,6 +2060,90 @@
     }
 }
 
+// Compute and return the hash (SHA-256) of the secondary dex file at dex_path.
+// Returns true if all parameters are valid and the hash successfully computed and stored in
+// out_secondary_dex_hash.
+// Also returns true with an empty hash if the file does not currently exist or is not accessible to
+// the app.
+// For any other errors (e.g. if any of the parameters are invalid) returns false.
+bool hash_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid,
+        const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
+        std::vector<uint8_t>* out_secondary_dex_hash) {
+    out_secondary_dex_hash->clear();
+
+    const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+
+    if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
+        LOG(ERROR) << "hash_secondary_dex_file called with invalid storage_flag: "
+                << storage_flag;
+        return false;
+    }
+
+    // Pipe to get the hash result back from our child process.
+    unique_fd pipe_read, pipe_write;
+    if (!Pipe(&pipe_read, &pipe_write)) {
+        PLOG(ERROR) << "Failed to create pipe";
+        return false;
+    }
+
+    // Fork so that actual access to the files is done in the app's own UID, to ensure we only
+    // access data the app itself can access.
+    pid_t pid = fork();
+    if (pid == 0) {
+        // child -- drop privileges before continuing
+        drop_capabilities(uid);
+        pipe_read.reset();
+
+        if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
+            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            _exit(1);
+        }
+
+        unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
+        if (fd == -1) {
+            if (errno == EACCES || errno == ENOENT) {
+                // Not treated as an error.
+                _exit(0);
+            }
+            PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
+            _exit(1);
+        }
+
+        SHA256_CTX ctx;
+        SHA256_Init(&ctx);
+
+        std::vector<uint8_t> buffer(65536);
+        while (true) {
+            ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
+            if (bytes_read == 0) {
+                break;
+            } else if (bytes_read == -1) {
+                PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
+                _exit(1);
+            }
+
+            SHA256_Update(&ctx, buffer.data(), bytes_read);
+        }
+
+        std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
+        SHA256_Final(hash.data(), &ctx);
+        if (!WriteFully(pipe_write, hash.data(), hash.size())) {
+            _exit(1);
+        }
+
+        _exit(0);
+    }
+
+    // parent
+    pipe_write.reset();
+
+    out_secondary_dex_hash->resize(SHA256_DIGEST_LENGTH);
+    if (!ReadFully(pipe_read, out_secondary_dex_hash->data(), out_secondary_dex_hash->size())) {
+        out_secondary_dex_hash->clear();
+    }
+    return wait_child(pid) == 0;
+}
+
 // Helper for move_ab, so that we can have common failure-case cleanup.
 static bool unlink_and_rename(const char* from, const char* to) {
     // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 8ece893..8a9ffd2 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -74,6 +74,10 @@
         const std::unique_ptr<std::string>& volumeUuid, int storage_flag,
         /*out*/bool* out_secondary_dex_exists);
 
+bool hash_secondary_dex_file(const std::string& dex_path,
+        const std::string& pkgname, int uid, const std::unique_ptr<std::string>& volume_uuid,
+        int storage_flag, std::vector<uint8_t>* out_secondary_dex_hash);
+
 int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
         const char* volume_uuid, const char* class_loader_context, const char* se_info,
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index e0d23da..0c2d341 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -889,6 +889,7 @@
                 CHECK(EndsWith(path, "/"));
                 path = path + "oat";
                 if (access(path.c_str(), F_OK) == 0) {
+                    LOG(INFO) << "Skipping A/B OTA preopt of already preopted package " << apk_path;
                     return true;
                 }
             }
@@ -900,7 +901,7 @@
         // this tool will wipe the OTA artifact cache and try again (for robustness after
         // a failed OTA with remaining cache artifacts).
         if (access(apk_path, F_OK) != 0) {
-            LOG(WARNING) << "Skipping preopt of non-existing package " << apk_path;
+            LOG(WARNING) << "Skipping A/B OTA preopt of non-existing package " << apk_path;
             return true;
         }
 
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 1a22992..47346fb 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -24,6 +24,7 @@
     shared_libs: [
         "libbase",
         "libbinder",
+        "libcrypto",
         "libcutils",
         "libselinux",
         "libutils",
@@ -44,6 +45,7 @@
     shared_libs: [
         "libbase",
         "libbinder",
+        "libcrypto",
         "libcutils",
         "libselinux",
         "libutils",
@@ -64,6 +66,7 @@
     shared_libs: [
         "libbase",
         "libbinder",
+        "libcrypto",
         "libcutils",
         "libselinux",
         "libutils",
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index ca812bd..a5af5d7 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <sstream>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/statvfs.h>
@@ -56,16 +57,19 @@
     return create_cache_path_default(path, src, instruction_set);
 }
 
+static std::string get_full_path(const char* path) {
+    return StringPrintf("/data/local/tmp/user/0/%s", path);
+}
+
 static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
-    const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
-    ::mkdir(fullPath, mode);
-    ::chown(fullPath, owner, group);
-    ::chmod(fullPath, mode);
+    const std::string fullPath = get_full_path(path);
+    ::mkdir(fullPath.c_str(), mode);
+    ::chown(fullPath.c_str(), owner, group);
+    ::chmod(fullPath.c_str(), mode);
 }
 
 static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
-    int fd = ::open(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(),
-            O_RDWR | O_CREAT, mode);
+    int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
     ::fchown(fd, owner, group);
     ::fchmod(fd, mode);
     ::close(fd);
@@ -73,13 +77,13 @@
 
 static int stat_gid(const char* path) {
     struct stat buf;
-    ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+    ::stat(get_full_path(path).c_str(), &buf);
     return buf.st_gid;
 }
 
 static int stat_mode(const char* path) {
     struct stat buf;
-    ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+    ::stat(get_full_path(path).c_str(), &buf);
     return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
 }
 
@@ -149,6 +153,69 @@
     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
 }
 
+TEST_F(ServiceTest, HashSecondaryDex) {
+    LOG(INFO) << "HashSecondaryDex";
+
+    mkdir("com.example", 10000, 10000, 0700);
+    mkdir("com.example/foo", 10000, 10000, 0700);
+    touch("com.example/foo/file", 10000, 20000, 0700);
+
+    std::vector<uint8_t> result;
+    std::string dexPath = get_full_path("com.example/foo/file");
+    EXPECT_TRUE(service->hashSecondaryDexFile(
+        dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+    EXPECT_EQ(result.size(), 32U);
+
+    std::ostringstream output;
+    output << std::hex << std::setfill('0');
+    for (auto b : result) {
+        output << std::setw(2) << +b;
+    }
+
+    // This is the SHA256 of an empty string (sha256sum /dev/null)
+    EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
+    LOG(INFO) << "HashSecondaryDex_NoSuch";
+
+    std::vector<uint8_t> result;
+    std::string dexPath = get_full_path("com.example/foo/file");
+    EXPECT_TRUE(service->hashSecondaryDexFile(
+        dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+    EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
+    LOG(INFO) << "HashSecondaryDex_Unreadable";
+
+    mkdir("com.example", 10000, 10000, 0700);
+    mkdir("com.example/foo", 10000, 10000, 0700);
+    touch("com.example/foo/file", 10000, 20000, 0300);
+
+    std::vector<uint8_t> result;
+    std::string dexPath = get_full_path("com.example/foo/file");
+    EXPECT_TRUE(service->hashSecondaryDexFile(
+        dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+    EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
+    LOG(INFO) << "HashSecondaryDex_WrongApp";
+
+    mkdir("com.example", 10000, 10000, 0700);
+    mkdir("com.example/foo", 10000, 10000, 0700);
+    touch("com.example/foo/file", 10000, 20000, 0700);
+
+    std::vector<uint8_t> result;
+    std::string dexPath = get_full_path("com.example/foo/file");
+    EXPECT_FALSE(service->hashSecondaryDexFile(
+        dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+}
+
 TEST_F(ServiceTest, CalculateOat) {
     char buf[PKG_PATH_MAX];
 
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 31cd0cb..6b340a8 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -138,6 +138,7 @@
     uint32_t handle;
     struct binder_death death;
     int allow_isolated;
+    uint32_t dumpsys_priority;
     size_t len;
     uint16_t name[0];
 };
@@ -198,11 +199,8 @@
     return si->handle;
 }
 
-int do_add_service(struct binder_state *bs,
-                   const uint16_t *s, size_t len,
-                   uint32_t handle, uid_t uid, int allow_isolated,
-                   pid_t spid)
-{
+int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
+                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
     struct svcinfo *si;
 
     //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -239,6 +237,7 @@
         si->death.func = (void*) svcinfo_death;
         si->death.ptr = si;
         si->allow_isolated = allow_isolated;
+        si->dumpsys_priority = dumpsys_priority;
         si->next = svclist;
         svclist = si;
     }
@@ -259,6 +258,7 @@
     uint32_t handle;
     uint32_t strict_policy;
     int allow_isolated;
+    uint32_t dumpsys_priority;
 
     //ALOGI("target=%p code=%d pid=%d uid=%d\n",
     //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
@@ -317,13 +317,15 @@
         }
         handle = bio_get_ref(msg);
         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
-        if (do_add_service(bs, s, len, handle, txn->sender_euid,
-            allow_isolated, txn->sender_pid))
+        dumpsys_priority = bio_get_uint32(msg);
+        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
+                           txn->sender_pid))
             return -1;
         break;
 
     case SVC_MGR_LIST_SERVICES: {
         uint32_t n = bio_get_uint32(msg);
+        uint32_t req_dumpsys_priority = bio_get_uint32(msg);
 
         if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
@@ -331,8 +333,15 @@
             return -1;
         }
         si = svclist;
-        while ((n-- > 0) && si)
+        // walk through the list of services n times skipping services that
+        // do not support the requested priority
+        while (si) {
+            if (si->dumpsys_priority & req_dumpsys_priority) {
+                if (n == 0) break;
+                n--;
+            }
             si = si->next;
+        }
         if (si) {
             bio_put_string16(reply, si->name);
             return 0;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 2b5389b..4140f40 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -24,9 +24,9 @@
 
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
 #include <gui/Surface.h>
 #include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
 
 #include <ui/DisplayInfo.h>
 #include <utils/Log.h>
@@ -338,27 +338,29 @@
 status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
     ALOGV("Started Transaction");
 
-    SurfaceComposerClient::openGlobalTransaction();
+    SurfaceComposerClient::Transaction liveTransaction;
 
     status_t status = NO_ERROR;
 
-    status = doSurfaceTransaction(t.surface_change());
-    doDisplayTransaction(t.display_change());
+    status = doSurfaceTransaction(liveTransaction, t.surface_change());
+    doDisplayTransaction(liveTransaction, t.display_change());
 
     if (t.animation()) {
-        SurfaceComposerClient::setAnimationTransaction();
+        liveTransaction.setAnimationTransaction();
     }
 
     event->readyToExecute();
 
-    SurfaceComposerClient::closeGlobalTransaction(t.synchronous());
+    liveTransaction.apply(t.synchronous());
 
     ALOGV("Ended Transaction");
 
     return status;
 }
 
-status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) {
+status_t Replayer::doSurfaceTransaction(
+        SurfaceComposerClient::Transaction& transaction,
+        const SurfaceChanges& surfaceChanges) {
     status_t status = NO_ERROR;
 
     for (const SurfaceChange& change : surfaceChanges) {
@@ -369,62 +371,66 @@
 
         switch (change.SurfaceChange_case()) {
             case SurfaceChange::SurfaceChangeCase::kPosition:
-                status = setPosition(change.id(), change.position());
+                setPosition(transaction, change.id(), change.position());
                 break;
             case SurfaceChange::SurfaceChangeCase::kSize:
-                status = setSize(change.id(), change.size());
+                setSize(transaction, change.id(), change.size());
                 break;
             case SurfaceChange::SurfaceChangeCase::kAlpha:
-                status = setAlpha(change.id(), change.alpha());
+                setAlpha(transaction, change.id(), change.alpha());
                 break;
             case SurfaceChange::SurfaceChangeCase::kLayer:
-                status = setLayer(change.id(), change.layer());
+                setLayer(transaction, change.id(), change.layer());
                 break;
             case SurfaceChange::SurfaceChangeCase::kCrop:
-                status = setCrop(change.id(), change.crop());
+                setCrop(transaction, change.id(), change.crop());
                 break;
             case SurfaceChange::SurfaceChangeCase::kMatrix:
-                status = setMatrix(change.id(), change.matrix());
+                setMatrix(transaction, change.id(), change.matrix());
                 break;
             case SurfaceChange::SurfaceChangeCase::kFinalCrop:
-                status = setFinalCrop(change.id(), change.final_crop());
+                setFinalCrop(transaction, change.id(), change.final_crop());
                 break;
             case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
-                status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
+                setOverrideScalingMode(transaction, change.id(),
+                        change.override_scaling_mode());
                 break;
             case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
-                status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
+                setTransparentRegionHint(transaction, change.id(),
+                        change.transparent_region_hint());
                 break;
             case SurfaceChange::SurfaceChangeCase::kLayerStack:
-                status = setLayerStack(change.id(), change.layer_stack());
+                setLayerStack(transaction, change.id(), change.layer_stack());
                 break;
             case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
-                status = setHiddenFlag(change.id(), change.hidden_flag());
+                setHiddenFlag(transaction, change.id(), change.hidden_flag());
                 break;
             case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
-                status = setOpaqueFlag(change.id(), change.opaque_flag());
+                setOpaqueFlag(transaction, change.id(), change.opaque_flag());
                 break;
             case SurfaceChange::SurfaceChangeCase::kSecureFlag:
-                status = setSecureFlag(change.id(), change.secure_flag());
+                setSecureFlag(transaction, change.id(), change.secure_flag());
                 break;
             case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
                 waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
-                status = setDeferredTransaction(change.id(), change.deferred_transaction());
+                setDeferredTransaction(transaction, change.id(),
+                        change.deferred_transaction());
                 break;
             default:
-                status = NO_ERROR;
+                status = 1;
                 break;
         }
 
         if (status != NO_ERROR) {
-            ALOGE("SET TRANSACTION FAILED");
+            ALOGE("Unknown Transaction Code");
             return status;
         }
     }
     return status;
 }
 
-void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) {
+void Replayer::doDisplayTransaction(SurfaceComposerClient::Transaction& t,
+        const DisplayChanges& displayChanges) {
     for (const DisplayChange& change : displayChanges) {
         ALOGV("Doing display transaction");
         std::unique_lock<std::mutex> lock(mDisplayLock);
@@ -434,16 +440,16 @@
 
         switch (change.DisplayChange_case()) {
             case DisplayChange::DisplayChangeCase::kSurface:
-                setDisplaySurface(change.id(), change.surface());
+                setDisplaySurface(t, change.id(), change.surface());
                 break;
             case DisplayChange::DisplayChangeCase::kLayerStack:
-                setDisplayLayerStack(change.id(), change.layer_stack());
+                setDisplayLayerStack(t, change.id(), change.layer_stack());
                 break;
             case DisplayChange::DisplayChangeCase::kSize:
-                setDisplaySize(change.id(), change.size());
+                setDisplaySize(t, change.id(), change.size());
                 break;
             case DisplayChange::DisplayChangeCase::kProjection:
-                setDisplayProjection(change.id(), change.projection());
+                setDisplayProjection(t, change.id(), change.projection());
                 break;
             default:
                 break;
@@ -451,57 +457,66 @@
     }
 }
 
-status_t Replayer::setPosition(layer_id id, const PositionChange& pc) {
+void Replayer::setPosition(SurfaceComposerClient::Transaction& t,
+        layer_id id, const PositionChange& pc) {
     ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
-    return mLayers[id]->setPosition(pc.x(), pc.y());
+    t.setPosition(mLayers[id], pc.x(), pc.y());
 }
 
-status_t Replayer::setSize(layer_id id, const SizeChange& sc) {
+void Replayer::setSize(SurfaceComposerClient::Transaction& t,
+        layer_id id, const SizeChange& sc) {
     ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
-    return mLayers[id]->setSize(sc.w(), sc.h());
+    t.setSize(mLayers[id], sc.w(), sc.h());
 }
 
-status_t Replayer::setLayer(layer_id id, const LayerChange& lc) {
+void Replayer::setLayer(SurfaceComposerClient::Transaction& t,
+        layer_id id, const LayerChange& lc) {
     ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
-    return mLayers[id]->setLayer(lc.layer());
+    t.setLayer(mLayers[id], lc.layer());
 }
 
-status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) {
+void Replayer::setAlpha(SurfaceComposerClient::Transaction& t,
+        layer_id id, const AlphaChange& ac) {
     ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
-    return mLayers[id]->setAlpha(ac.alpha());
+    t.setAlpha(mLayers[id], ac.alpha());
 }
 
-status_t Replayer::setCrop(layer_id id, const CropChange& cc) {
+void Replayer::setCrop(SurfaceComposerClient::Transaction& t,
+        layer_id id, const CropChange& cc) {
     ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
             cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
             cc.rectangle().bottom());
 
     Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
             cc.rectangle().bottom());
-    return mLayers[id]->setCrop(r);
+    t.setCrop(mLayers[id], r);
 }
 
-status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) {
+void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t,
+        layer_id id, const FinalCropChange& fcc) {
     ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
             fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
             fcc.rectangle().bottom());
     Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
             fcc.rectangle().bottom());
-    return mLayers[id]->setFinalCrop(r);
+    t.setFinalCrop(mLayers[id], r);
 }
 
-status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) {
+void Replayer::setMatrix(SurfaceComposerClient::Transaction& t,
+        layer_id id, const MatrixChange& mc) {
     ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
             mc.dtdx(), mc.dsdy(), mc.dtdy());
-    return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
+    t.setMatrix(mLayers[id], mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
 }
 
-status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) {
+void Replayer::setOverrideScalingMode(SurfaceComposerClient::Transaction& t,
+        layer_id id, const OverrideScalingModeChange& osmc) {
     ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
-    return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
+    t.setOverrideScalingMode(mLayers[id], osmc.override_scaling_mode());
 }
 
-status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) {
+void Replayer::setTransparentRegionHint(SurfaceComposerClient::Transaction& t,
+        layer_id id, const TransparentRegionHintChange& trhc) {
     ALOGV("Setting Transparent Region Hint");
     Region re = Region();
 
@@ -510,71 +525,80 @@
         re.merge(rect);
     }
 
-    return mLayers[id]->setTransparentRegionHint(re);
+    t.setTransparentRegionHint(mLayers[id], re);
 }
 
-status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) {
+void Replayer::setLayerStack(SurfaceComposerClient::Transaction& t,
+        layer_id id, const LayerStackChange& lsc) {
     ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
-    return mLayers[id]->setLayerStack(lsc.layer_stack());
+    t.setLayerStack(mLayers[id], lsc.layer_stack());
 }
 
-status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) {
+void Replayer::setHiddenFlag(SurfaceComposerClient::Transaction& t,
+        layer_id id, const HiddenFlagChange& hfc) {
     ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
     layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
 
-    return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
+    t.setFlags(mLayers[id], flag, layer_state_t::eLayerHidden);
 }
 
-status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) {
+void Replayer::setOpaqueFlag(SurfaceComposerClient::Transaction& t,
+        layer_id id, const OpaqueFlagChange& ofc) {
     ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
     layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
 
-    return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
+    t.setFlags(mLayers[id], flag, layer_state_t::eLayerOpaque);
 }
 
-status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) {
+void Replayer::setSecureFlag(SurfaceComposerClient::Transaction& t,
+        layer_id id, const SecureFlagChange& sfc) {
     ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
     layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
 
-    return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
+    t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure);
 }
 
-status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) {
+void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t,
+        layer_id id, const DeferredTransactionChange& dtc) {
     ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
           "frame_number=%llu",
             id, dtc.layer_id(), dtc.frame_number());
     if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
         ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id());
-        return BAD_VALUE;
+        return;
     }
 
     auto handle = mLayers[dtc.layer_id()]->getHandle();
 
-    return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
+    t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number());
 }
 
-void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) {
+void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t,
+        display_id id, const DispSurfaceChange& /*dsc*/) {
     sp<IGraphicBufferProducer> outProducer;
     sp<IGraphicBufferConsumer> outConsumer;
     BufferQueue::createBufferQueue(&outProducer, &outConsumer);
 
-    SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer);
+    t.setDisplaySurface(mDisplays[id], outProducer);
 }
 
-void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) {
-    SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
+void Replayer::setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
+        display_id id, const LayerStackChange& lsc) {
+    t.setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
 }
 
-void Replayer::setDisplaySize(display_id id, const SizeChange& sc) {
-    SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h());
+void Replayer::setDisplaySize(SurfaceComposerClient::Transaction& t,
+        display_id id, const SizeChange& sc) {
+    t.setDisplaySize(mDisplays[id], sc.w(), sc.h());
 }
 
-void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) {
+void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t,
+        display_id id, const ProjectionChange& pc) {
     Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
             pc.viewport().bottom());
     Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
 
-    SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
+    t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
 }
 
 status_t Replayer::createSurfaceControl(
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index f36c9fd..295403e 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -77,28 +77,48 @@
     void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
     void updatePowerMode(const PowerModeUpdate& update, const std::shared_ptr<Event>& event);
 
-    status_t doSurfaceTransaction(const SurfaceChanges& surfaceChange);
-    void doDisplayTransaction(const DisplayChanges& displayChange);
+    status_t doSurfaceTransaction(SurfaceComposerClient::Transaction& transaction,
+            const SurfaceChanges& surfaceChange);
+    void doDisplayTransaction(SurfaceComposerClient::Transaction& transaction,
+            const DisplayChanges& displayChange);
 
-    status_t setPosition(layer_id id, const PositionChange& pc);
-    status_t setSize(layer_id id, const SizeChange& sc);
-    status_t setAlpha(layer_id id, const AlphaChange& ac);
-    status_t setLayer(layer_id id, const LayerChange& lc);
-    status_t setCrop(layer_id id, const CropChange& cc);
-    status_t setFinalCrop(layer_id id, const FinalCropChange& fcc);
-    status_t setMatrix(layer_id id, const MatrixChange& mc);
-    status_t setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc);
-    status_t setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trgc);
-    status_t setLayerStack(layer_id id, const LayerStackChange& lsc);
-    status_t setHiddenFlag(layer_id id, const HiddenFlagChange& hfc);
-    status_t setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc);
-    status_t setSecureFlag(layer_id id, const SecureFlagChange& sfc);
-    status_t setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc);
+    void setPosition(SurfaceComposerClient::Transaction& t,
+            layer_id id, const PositionChange& pc);
+    void setSize(SurfaceComposerClient::Transaction& t,
+            layer_id id, const SizeChange& sc);
+    void setAlpha(SurfaceComposerClient::Transaction& t,
+            layer_id id, const AlphaChange& ac);
+    void setLayer(SurfaceComposerClient::Transaction& t,
+            layer_id id, const LayerChange& lc);
+    void setCrop(SurfaceComposerClient::Transaction& t,
+            layer_id id, const CropChange& cc);
+    void setFinalCrop(SurfaceComposerClient::Transaction& t,
+            layer_id id, const FinalCropChange& fcc);
+    void setMatrix(SurfaceComposerClient::Transaction& t,
+            layer_id id, const MatrixChange& mc);
+    void setOverrideScalingMode(SurfaceComposerClient::Transaction& t,
+            layer_id id, const OverrideScalingModeChange& osmc);
+    void setTransparentRegionHint(SurfaceComposerClient::Transaction& t,
+            layer_id id, const TransparentRegionHintChange& trgc);
+    void setLayerStack(SurfaceComposerClient::Transaction& t,
+            layer_id id, const LayerStackChange& lsc);
+    void setHiddenFlag(SurfaceComposerClient::Transaction& t,
+            layer_id id, const HiddenFlagChange& hfc);
+    void setOpaqueFlag(SurfaceComposerClient::Transaction& t,
+            layer_id id, const OpaqueFlagChange& ofc);
+    void setSecureFlag(SurfaceComposerClient::Transaction& t,
+            layer_id id, const SecureFlagChange& sfc);
+    void setDeferredTransaction(SurfaceComposerClient::Transaction& t,
+            layer_id id, const DeferredTransactionChange& dtc);
 
-    void setDisplaySurface(display_id id, const DispSurfaceChange& dsc);
-    void setDisplayLayerStack(display_id id, const LayerStackChange& lsc);
-    void setDisplaySize(display_id id, const SizeChange& sc);
-    void setDisplayProjection(display_id id, const ProjectionChange& pc);
+    void setDisplaySurface(SurfaceComposerClient::Transaction& t,
+            display_id id, const DispSurfaceChange& dsc);
+    void setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
+            display_id id, const LayerStackChange& lsc);
+    void setDisplaySize(SurfaceComposerClient::Transaction& t,
+            display_id id, const SizeChange& sc);
+    void setDisplayProjection(SurfaceComposerClient::Transaction& t,
+            display_id id, const ProjectionChange& pc);
 
     void doDeleteSurfaceControls();
     void waitUntilTimestamp(int64_t timestamp);
diff --git a/data/etc/android.hardware.wifi.rtt.xml b/data/etc/android.hardware.wifi.rtt.xml
new file mode 100644
index 0000000..60529ea
--- /dev/null
+++ b/data/etc/android.hardware.wifi.rtt.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device supports WiFi RTT (IEEE 802.11mc). -->
+<permissions>
+    <feature name="android.hardware.wifi.rtt" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index ec7be53..b6abc1b 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -55,7 +55,7 @@
     <feature name="android.software.device_admin" />
 
     <!-- Feature to specify if the device support managed users. -->
-    <feature name="android.software.managed_users" />
+    <feature name="android.software.managed_users" notLowRam="true"/>
 
     <!-- Feature to specify if the device supports a VR mode.
          feature name="android.software.vr.mode" -->
diff --git a/docs/Doxyfile b/docs/Doxyfile
index bb0ca32..0ec4551 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -677,7 +677,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../include/android ../../av/include/ndk ../../av/include/camera/ndk
+INPUT                  = ../include/android ../../av/media/ndk/include ../../av/camera/ndk/include
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/include/android/sensor.h b/include/android/sensor.h
index a88733c..2db0ee7 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -197,7 +197,7 @@
  * A sensor event.
  */
 
-/* NOTE: Must match hardware/sensors.h */
+/* NOTE: changes to these structs have to be backward compatible */
 typedef struct ASensorVector {
     union {
         float v[3];
@@ -259,7 +259,7 @@
     };
 } AAdditionalInfoEvent;
 
-/* NOTE: Must match hardware/sensors.h */
+/* NOTE: changes to this struct has to be backward compatible */
 typedef struct ASensorEvent {
     int32_t version; /* sizeof(struct ASensorEvent) */
     int32_t sensor;
diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h
deleted file mode 100644
index de5c1c7..0000000
--- a/include/audiomanager/IPlayer.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IPLAYER_H
-#define ANDROID_IPLAYER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <media/VolumeShaper.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IPlayer : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(Player);
-
-    virtual void start() = 0;
-
-    virtual void pause() = 0;
-
-    virtual void stop() = 0;
-
-    virtual void setVolume(float vol) = 0;
-
-    virtual void setPan(float pan) = 0;
-
-    virtual void setStartDelayMs(int delayMs) = 0;
-
-    virtual void applyVolumeShaper(
-            const sp<VolumeShaper::Configuration>& configuration,
-            const sp<VolumeShaper::Operation>& operation) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnPlayer : public BnInterface<IPlayer>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IPLAYER_H
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 9449474..c4b5dca 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -455,7 +455,6 @@
             int32_t* displayId);
 
     void updateTouchState(InputMessage& msg);
-    bool rewriteMessage(const TouchState& state, InputMessage& msg);
     void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
             const InputMessage *next);
 
@@ -464,6 +463,7 @@
 
     status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
 
+    static bool rewriteMessage(const TouchState& state, InputMessage& msg);
     static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
     static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
     static void addSample(MotionEvent* event, const InputMessage* msg);
diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h
index 795f575..ffa1614 100644
--- a/include/input/VelocityTracker.h
+++ b/include/input/VelocityTracker.h
@@ -264,6 +264,40 @@
     Movement mMovements[HISTORY_SIZE];
 };
 
+class ImpulseVelocityTrackerStrategy : public VelocityTrackerStrategy {
+public:
+    ImpulseVelocityTrackerStrategy();
+    virtual ~ImpulseVelocityTrackerStrategy();
+
+    virtual void clear();
+    virtual void clearPointers(BitSet32 idBits);
+    virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
+            const VelocityTracker::Position* positions);
+    virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
+
+private:
+    // Sample horizon.
+    // We don't use too much history by default since we want to react to quick
+    // changes in direction.
+    static constexpr nsecs_t HORIZON = 100 * 1000000; // 100 ms
+
+    // Number of samples to keep.
+    static constexpr size_t HISTORY_SIZE = 20;
+
+    struct Movement {
+        nsecs_t eventTime;
+        BitSet32 idBits;
+        VelocityTracker::Position positions[MAX_POINTERS];
+
+        inline const VelocityTracker::Position& getPosition(uint32_t id) const {
+            return positions[idBits.getIndexOfBit(id)];
+        }
+    };
+
+    size_t mIndex;
+    Movement mMovements[HISTORY_SIZE];
+};
+
 } // namespace android
 
 #endif // _LIBINPUT_VELOCITY_TRACKER_H
diff --git a/include/layerproto b/include/layerproto
new file mode 120000
index 0000000..ef21a4e
--- /dev/null
+++ b/include/layerproto
@@ -0,0 +1 @@
+../services/surfaceflinger/layerproto/include/layerproto/
\ No newline at end of file
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index c0e0296..289433b 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
+#include <cutils/compiler.h>
 #include <utils/Log.h>
 
 #include <stdio.h>
@@ -32,6 +33,23 @@
 
 // ---------------------------------------------------------------------------
 
+Mutex BpBinder::sTrackingLock;
+std::unordered_map<int32_t,uint32_t> BpBinder::sTrackingMap;
+int BpBinder::sNumTrackedUids = 0;
+std::atomic_bool BpBinder::sCountByUidEnabled(false);
+binder_proxy_limit_callback BpBinder::sLimitCallback;
+bool BpBinder::sBinderProxyThrottleCreate = false;
+
+// Arbitrarily high value that probably distinguishes a bad behaving app
+uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
+// Another arbitrary value a binder count needs to drop below before another callback will be called
+uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
+
+enum {
+    CALLBACK_TRIGGERED_MASK = 0x80000000,   // A flag denoting that the callback has been called
+    COUNTING_VALUE_MASK = 0x7FFFFFFF,       // A mask of the remaining bits for the count value
+};
+
 BpBinder::ObjectManager::ObjectManager()
 {
 }
@@ -87,11 +105,47 @@
 
 // ---------------------------------------------------------------------------
 
-BpBinder::BpBinder(int32_t handle)
+
+BpBinder* BpBinder::create(int32_t handle) {
+    int32_t trackedUid = -1;
+    if (sCountByUidEnabled) {
+        BpBinder* out;
+        trackedUid = IPCThreadState::self()->getCallingUid();
+        AutoMutex _l(sTrackingLock);
+        if ((sTrackingMap[trackedUid] & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
+            ALOGE("Too many binder proxy objects sent to uid %d from uid %d (over %d proxies held)",
+                   getuid(), trackedUid, sBinderProxyCountHighWatermark);
+
+            if (sBinderProxyThrottleCreate) {
+                ALOGE("Returning Null Binder Proxy Object to uid %d", trackedUid);
+                out = nullptr;
+            } else {
+                // increment and construct here in case callback has an async kill causing a race
+                sTrackingMap[trackedUid]++;
+                out = new BpBinder(handle, trackedUid);
+            }
+
+            if (sLimitCallback && !(sTrackingMap[trackedUid] & CALLBACK_TRIGGERED_MASK)) {
+                sTrackingMap[trackedUid] |= CALLBACK_TRIGGERED_MASK;
+                sLimitCallback(trackedUid);
+            }
+        } else {
+            sTrackingMap[trackedUid]++;
+            out = new BpBinder(handle, trackedUid);
+        }
+
+        return out;
+    } else {
+        return new BpBinder(handle, trackedUid);
+    }
+}
+
+BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
     : mHandle(handle)
     , mAlive(1)
     , mObitsSent(0)
     , mObituaries(NULL)
+    , mTrackedUid(trackedUid)
 {
     ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
 
@@ -315,6 +369,24 @@
 
     IPCThreadState* ipc = IPCThreadState::self();
 
+    if (mTrackedUid >= 0) {
+        AutoMutex _l(sTrackingLock);
+        if (CC_UNLIKELY(sTrackingMap[mTrackedUid] == 0)) {
+            ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
+        } else {
+            if (CC_UNLIKELY(
+                (sTrackingMap[mTrackedUid] & CALLBACK_TRIGGERED_MASK) &&
+                ((sTrackingMap[mTrackedUid] & COUNTING_VALUE_MASK) <= sBinderProxyCountLowWatermark)
+                )) {
+                // Clear the Callback Triggered bit when crossing below the low watermark
+                sTrackingMap[mTrackedUid] &= ~CALLBACK_TRIGGERED_MASK;
+            }
+            if (--sTrackingMap[mTrackedUid] == 0) {
+                sTrackingMap.erase(mTrackedUid);
+            }
+        }
+    }
+
     mLock.lock();
     Vector<Obituary>* obits = mObituaries;
     if(obits != NULL) {
@@ -360,6 +432,42 @@
     return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
 }
 
+uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
+{
+    AutoMutex _l(sTrackingLock);
+    auto it = sTrackingMap.find(uid);
+    if (it != sTrackingMap.end()) {
+        return it->second & COUNTING_VALUE_MASK;
+    }
+    return 0;
+}
+
+void BpBinder::getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts)
+{
+    AutoMutex _l(sTrackingLock);
+    uids.setCapacity(sTrackingMap.size());
+    counts.setCapacity(sTrackingMap.size());
+    for (const auto& it : sTrackingMap) {
+        uids.push_back(it.first);
+        counts.push_back(it.second & COUNTING_VALUE_MASK);
+    }
+}
+
+void BpBinder::enableCountByUid() { sCountByUidEnabled.store(true); }
+void BpBinder::disableCountByUid() { sCountByUidEnabled.store(false); }
+void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }
+
+void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
+    AutoMutex _l(sTrackingLock);
+    sLimitCallback = cb;
+}
+
+void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
+    AutoMutex _l(sTrackingLock);
+    sBinderProxyCountHighWatermark = high;
+    sBinderProxyCountLowWatermark = low;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index c7a0f43..70f5108 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -161,19 +161,18 @@
     }
 
     virtual status_t addService(const String16& name, const sp<IBinder>& service,
-            bool allowIsolated)
-    {
+                                bool allowIsolated, int dumpsysPriority) {
         Parcel data, reply;
         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
         data.writeString16(name);
         data.writeStrongBinder(service);
         data.writeInt32(allowIsolated ? 1 : 0);
+        data.writeInt32(dumpsysPriority);
         status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
         return err == NO_ERROR ? reply.readExceptionCode() : err;
     }
 
-    virtual Vector<String16> listServices()
-    {
+    virtual Vector<String16> listServices(int dumpsysPriority) {
         Vector<String16> res;
         int n = 0;
 
@@ -181,6 +180,7 @@
             Parcel data, reply;
             data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
             data.writeInt32(n++);
+            data.writeInt32(dumpsysPriority);
             status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
             if (err != NO_ERROR)
                 break;
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index c793df3..23b83a6 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -39,11 +39,13 @@
     {
     }
 
-    virtual int openOutputFile(const String16& path, const String16& seLinuxContext) {
+    virtual int openFile(const String16& path, const String16& seLinuxContext,
+            const String16& mode) {
         Parcel data, reply;
         data.writeInterfaceToken(IShellCallback::getInterfaceDescriptor());
         data.writeString16(path);
         data.writeString16(seLinuxContext);
+        data.writeString16(mode);
         remote()->transact(OP_OPEN_OUTPUT_FILE, data, &reply, 0);
         reply.readExceptionCode();
         int fd = reply.readParcelFileDescriptor();
@@ -64,7 +66,8 @@
             CHECK_INTERFACE(IShellCallback, data, reply);
             String16 path(data.readString16());
             String16 seLinuxContext(data.readString16());
-            int fd = openOutputFile(path, seLinuxContext);
+            String16 mode(data.readString16());
+            int fd = openFile(path, seLinuxContext, mode);
             if (reply != NULL) {
                 reply->writeNoException();
                 if (fd >= 0) {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 11dd525..44039f8 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -276,7 +276,7 @@
                    return NULL;
             }
 
-            b = new BpBinder(handle); 
+            b = BpBinder::create(handle);
             e->binder = b;
             if (b) e->refs = b->getWeakRefs();
             result = b;
@@ -310,7 +310,7 @@
         // arriving from the driver.
         IBinder* b = e->binder;
         if (b == NULL || !e->refs->attemptIncWeak(this)) {
-            b = new BpBinder(handle);
+            b = BpBinder::create(handle);
             result = b;
             e->binder = b;
             if (b) e->refs = b->getWeakRefs();
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 006f7f9..a9d5055 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,6 +102,15 @@
     }
     mMessage = String8(message);
 
+    // Skip over the remote stack trace data
+    int32_t remote_stack_trace_header_size;
+    status = parcel.readInt32(&remote_stack_trace_header_size);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+    parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
+
     if (mException == EX_SERVICE_SPECIFIC) {
         status = parcel.readInt32(&mErrorCode);
     } else if (mException == EX_PARCELABLE) {
@@ -137,6 +146,7 @@
         return status;
     }
     status = parcel->writeString16(String16(mMessage));
+    status = parcel->writeInt32(0); // Empty remote stack trace header
     if (mException == EX_SERVICE_SPECIFIC) {
         status = parcel->writeInt32(mErrorCode);
     } else if (mException == EX_PARCELABLE) {
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index ef703bd..4ce82a1 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -34,15 +34,17 @@
 class BinderService
 {
 public:
-    static status_t publish(bool allowIsolated = false) {
+    static status_t publish(bool allowIsolated = false,
+                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
         sp<IServiceManager> sm(defaultServiceManager());
-        return sm->addService(
-                String16(SERVICE::getServiceName()),
-                new SERVICE(), allowIsolated);
+        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
+                              dumpFlags);
     }
 
-    static void publishAndJoinThreadPool(bool allowIsolated = false) {
-        publish(allowIsolated);
+    static void publishAndJoinThreadPool(
+            bool allowIsolated = false,
+            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
+        publish(allowIsolated, dumpFlags);
         joinThreadPool();
     }
 
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7ef93aa..8bd297b 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -19,15 +19,20 @@
 
 #include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
 #include <utils/threads.h>
 
+#include <unordered_map>
+
 // ---------------------------------------------------------------------------
 namespace android {
 
+using binder_proxy_limit_callback = void(*)(int);
+
 class BpBinder : public IBinder
 {
 public:
-                        BpBinder(int32_t handle);
+    static BpBinder*    create(int32_t handle);
 
     inline  int32_t     handle() const { return mHandle; }
 
@@ -61,6 +66,14 @@
             status_t    setConstantData(const void* data, size_t size);
             void        sendObituary();
 
+    static uint32_t     getBinderProxyCount(uint32_t uid);
+    static void         getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
+    static void         enableCountByUid();
+    static void         disableCountByUid();
+    static void         setCountByUidEnabled(bool enable);
+    static void         setLimitCallback(binder_proxy_limit_callback cb);
+    static void         setBinderProxyCountWatermarks(int high, int low);
+
     class ObjectManager
     {
     public:
@@ -91,6 +104,7 @@
     };
 
 protected:
+                        BpBinder(int32_t handle,int32_t trackedUid);
     virtual             ~BpBinder();
     virtual void        onFirstRef();
     virtual void        onLastStrongRef(const void* id);
@@ -115,6 +129,16 @@
             ObjectManager       mObjects;
             Parcel*             mConstantData;
     mutable String16            mDescriptorCache;
+            int32_t             mTrackedUid;
+
+    static Mutex                                sTrackingLock;
+    static std::unordered_map<int32_t,uint32_t> sTrackingMap;
+    static int                                  sNumTrackedUids;
+    static std::atomic_bool                     sCountByUidEnabled;
+    static binder_proxy_limit_callback          sLimitCallback;
+    static uint32_t                             sBinderProxyCountHighWatermark;
+    static uint32_t                             sBinderProxyCountLowWatermark;
+    static bool                                 sBinderProxyThrottleCreate;
 };
 
 }; // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 3b23f81..19e841a 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -31,6 +31,15 @@
 {
 public:
     DECLARE_META_INTERFACE(ServiceManager)
+    /*
+     * Must match values in IServiceManager.java
+     */
+    static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
+    static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
+    static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
+    static const int DUMP_FLAG_PRIORITY_ALL =
+            DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL;
+    static const int DUMP_FLAG_PROTO = 1 << 3;
 
     /**
      * Retrieve an existing service, blocking for a few seconds
@@ -46,14 +55,14 @@
     /**
      * Register a service.
      */
-    virtual status_t            addService( const String16& name,
-                                            const sp<IBinder>& service,
-                                            bool allowIsolated = false) = 0;
+    virtual status_t addService(const String16& name, const sp<IBinder>& service,
+                                bool allowIsolated = false,
+                                int dumpsysFlags = DUMP_FLAG_PRIORITY_NORMAL) = 0;
 
     /**
      * Return list of all existing services.
      */
-    virtual Vector<String16>    listServices() = 0;
+    virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
 
     enum {
         GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index fda9ee6..b47e995 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -29,7 +29,8 @@
 public:
     DECLARE_META_INTERFACE(ShellCallback);
 
-    virtual int openOutputFile(const String16& path, const String16& seLinuxContext) = 0;
+    virtual int openFile(const String16& path, const String16& seLinuxContext,
+            const String16& mode) = 0;
 
     enum {
         OP_OPEN_OUTPUT_FILE = IBinder::FIRST_CALL_TRANSACTION
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index 455f2c4..bf41e0b 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -215,7 +215,7 @@
         int target = cs_pair ? num % server_count : rand() % workers.size();
         int sz = payload_size;
 
-        while (sz > sizeof(uint32_t)) {
+        while (sz >= sizeof(uint32_t)) {
             data.writeInt32(0);
             sz -= sizeof(uint32_t);
         }
@@ -381,6 +381,7 @@
             // No need to run training round in this case.
             if (atoi(argv[i+1]) > 0) {
                 max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
+                time_per_bucket = max_time_bucket / num_buckets;
                 i++;
             } else {
                 cout << "Max latency -m must be positive." << endl;
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 39b5829..f46e9f6 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -22,6 +22,7 @@
 
 #include <log/log.h>
 #include <nativeloader/dlext_namespaces.h>
+#include <nativeloader/native_loader.h>
 
 // TODO(b/37049319) Get this from a header once one exists
 extern "C" {
@@ -45,6 +46,32 @@
     mDriverPath = path;
 }
 
+void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths) {
+    if (mLayerPaths.empty()) {
+        mLayerPaths = layerPaths;
+        mAppNamespace = appNamespace;
+    } else {
+        ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
+                layerPaths.c_str(), appNamespace);
+    }
+}
+
+android_namespace_t* GraphicsEnv::getAppNamespace() {
+    return mAppNamespace;
+}
+
+const std::string GraphicsEnv::getLayerPaths(){
+    return mLayerPaths;
+}
+
+const std::string GraphicsEnv::getDebugLayers() {
+    return mDebugLayers;
+}
+
+void GraphicsEnv::setDebugLayers(const std::string layers) {
+    mDebugLayers = layers;
+}
+
 android_namespace_t* GraphicsEnv::getDriverNamespace() {
     static std::once_flag once;
     std::call_once(once, [this]() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 7817076..213580c 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -35,10 +35,20 @@
     void setDriverPath(const std::string path);
     android_namespace_t* getDriverNamespace();
 
+    void setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths);
+    android_namespace_t* getAppNamespace();
+    const std::string getLayerPaths();
+
+    void setDebugLayers(const std::string layers);
+    const std::string getDebugLayers();
+
 private:
     GraphicsEnv() = default;
     std::string mDriverPath;
+    std::string mDebugLayers;
+    std::string mLayerPaths;
     android_namespace_t* mDriverNamespace = nullptr;
+    android_namespace_t* mAppNamespace = nullptr;
 };
 
 } // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8e7f814..5de84ec 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -29,8 +29,7 @@
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerDebugInfo.h>
-
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
 
 #include <system/graphics.h>
 
@@ -101,17 +100,13 @@
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t captureScreen(const sp<IBinder>& display,
-            const sp<IGraphicBufferProducer>& producer,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform,
-            ISurfaceComposer::Rotation rotation)
-    {
+    virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                                   int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+                                   ISurfaceComposer::Rotation rotation) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
-        data.writeStrongBinder(IInterface::asBinder(producer));
         data.write(sourceCrop);
         data.writeUint32(reqWidth);
         data.writeUint32(reqHeight);
@@ -119,8 +114,45 @@
         data.writeInt32(maxLayerZ);
         data.writeInt32(static_cast<int32_t>(useIdentityTransform));
         data.writeInt32(static_cast<int32_t>(rotation));
-        remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
-        return reply.readInt32();
+        status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
+
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        err = reply.readInt32();
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        *outBuffer = new GraphicBuffer();
+        reply.read(**outBuffer);
+        return err;
+    }
+
+    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+                                   sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+                                   float frameScale) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeStrongBinder(layerHandleBinder);
+        data.write(sourceCrop);
+        data.writeFloat(frameScale);
+        status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        err = reply.readInt32();
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        *outBuffer = new GraphicBuffer();
+        reply.read(**outBuffer);
+
+        return err;
     }
 
     virtual bool authenticateSurfaceTexture(
@@ -571,8 +603,7 @@
         case CAPTURE_SCREEN: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
-            sp<IGraphicBufferProducer> producer =
-                    interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+            sp<GraphicBuffer> outBuffer;
             Rect sourceCrop(Rect::EMPTY_RECT);
             data.read(sourceCrop);
             uint32_t reqWidth = data.readUint32();
@@ -582,11 +613,28 @@
             bool useIdentityTransform = static_cast<bool>(data.readInt32());
             int32_t rotation = data.readInt32();
 
-            status_t res = captureScreen(display, producer,
-                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform,
-                    static_cast<ISurfaceComposer::Rotation>(rotation));
+            status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
+                                         minLayerZ, maxLayerZ, useIdentityTransform,
+                                         static_cast<ISurfaceComposer::Rotation>(rotation));
             reply->writeInt32(res);
+            if (res == NO_ERROR) {
+                reply->write(*outBuffer);
+            }
+            return NO_ERROR;
+        }
+        case CAPTURE_LAYERS: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> layerHandleBinder = data.readStrongBinder();
+            sp<GraphicBuffer> outBuffer;
+            Rect sourceCrop(Rect::EMPTY_RECT);
+            data.read(sourceCrop);
+            float frameScale = data.readFloat();
+
+            status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale);
+            reply->writeInt32(res);
+            if (res == NO_ERROR) {
+                reply->write(*outBuffer);
+            }
             return NO_ERROR;
         }
         case AUTHENTICATE_SURFACE: {
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index 57ddde0..d3dc16d 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -43,7 +43,10 @@
     RETURN_ON_ERROR(parcel->writeInt32(mHeight));
     RETURN_ON_ERROR(parcel->write(mCrop));
     RETURN_ON_ERROR(parcel->write(mFinalCrop));
-    RETURN_ON_ERROR(parcel->writeFloat(mAlpha));
+    RETURN_ON_ERROR(parcel->writeFloat(mColor.r));
+    RETURN_ON_ERROR(parcel->writeFloat(mColor.g));
+    RETURN_ON_ERROR(parcel->writeFloat(mColor.b));
+    RETURN_ON_ERROR(parcel->writeFloat(mColor.a));
     RETURN_ON_ERROR(parcel->writeUint32(mFlags));
     RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat));
     RETURN_ON_ERROR(parcel->writeUint32(static_cast<uint32_t>(mDataSpace)));
@@ -79,7 +82,14 @@
     RETURN_ON_ERROR(parcel->readInt32(&mHeight));
     RETURN_ON_ERROR(parcel->read(mCrop));
     RETURN_ON_ERROR(parcel->read(mFinalCrop));
-    RETURN_ON_ERROR(parcel->readFloat(&mAlpha));
+    mColor.r = parcel->readFloat();
+    RETURN_ON_ERROR(parcel->errorCheck());
+    mColor.g = parcel->readFloat();
+    RETURN_ON_ERROR(parcel->errorCheck());
+    mColor.b = parcel->readFloat();
+    RETURN_ON_ERROR(parcel->errorCheck());
+    mColor.a = parcel->readFloat();
+    RETURN_ON_ERROR(parcel->errorCheck());
     RETURN_ON_ERROR(parcel->readUint32(&mFlags));
     RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat));
     // \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways?
@@ -116,8 +126,10 @@
     result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
     result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
     result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
-    result.appendFormat("alpha=%.3f, flags=0x%08x, ",
-            static_cast<double>(info.mAlpha), info.mFlags);
+    result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+            static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g),
+            static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a),
+            info.mFlags);
     result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]",
             static_cast<double>(info.mMatrix[0][0]), static_cast<double>(info.mMatrix[0][1]),
             static_cast<double>(info.mMatrix[1][0]), static_cast<double>(info.mMatrix[1][1]));
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 9b06e63..b5295f2 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -18,7 +18,7 @@
 #include <binder/Parcel.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/IGraphicBufferProducer.h>
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
 
 namespace android {
 
@@ -45,6 +45,10 @@
     output.writeInt32(overrideScalingMode);
     output.writeStrongBinder(IInterface::asBinder(barrierGbp));
     output.writeStrongBinder(relativeLayerHandle);
+    output.writeStrongBinder(parentHandleForChild);
+    output.writeFloat(color.r);
+    output.writeFloat(color.g);
+    output.writeFloat(color.b);
     output.write(transparentRegion);
     return NO_ERROR;
 }
@@ -77,6 +81,10 @@
     barrierGbp =
         interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
     relativeLayerHandle = input.readStrongBinder();
+    parentHandleForChild = input.readStrongBinder();
+    color.r = input.readFloat();
+    color.g = input.readFloat();
+    color.b = input.readFloat();
     input.read(transparentRegion);
     return NO_ERROR;
 }
@@ -128,5 +136,101 @@
     return NO_ERROR;
 }
 
+void DisplayState::merge(const DisplayState& other) {
+    if (other.what & eSurfaceChanged) {
+        what |= eSurfaceChanged;
+        surface = other.surface;
+    }
+    if (other.what & eLayerStackChanged) {
+        what |= eLayerStackChanged;
+        layerStack = other.layerStack;
+    }
+    if (other.what & eDisplayProjectionChanged) {
+        what |= eDisplayProjectionChanged;
+        orientation = other.orientation;
+        viewport = other.viewport;
+        frame = other.frame;
+    }
+    if (other.what & eDisplaySizeChanged) {
+        what |= eDisplaySizeChanged;
+        width = other.width;
+        height = other.height;
+    }
+}
+
+void layer_state_t::merge(const layer_state_t& other) {
+    if (other.what & ePositionChanged) {
+        what |= ePositionChanged;
+        x = other.x;
+        y = other.y;
+    }
+    if (other.what & eLayerChanged) {
+        what |= eLayerChanged;
+        z = other.z;
+    }
+    if (other.what & eSizeChanged) {
+        what |= eSizeChanged;
+        w = other.w;
+        h = other.h;
+    }
+    if (other.what & eAlphaChanged) {
+        what |= eAlphaChanged;
+        alpha = other.alpha;
+    }
+    if (other.what & eMatrixChanged) {
+        what |= eMatrixChanged;
+        matrix = other.matrix;
+    }
+    if (other.what & eTransparentRegionChanged) {
+        what |= eTransparentRegionChanged;
+        transparentRegion = other.transparentRegion;
+    }
+    if (other.what & eFlagsChanged) {
+        what |= eFlagsChanged;
+        flags = other.flags;
+        mask = other.mask;
+    }
+    if (other.what & eLayerStackChanged) {
+        what |= eLayerStackChanged;
+        layerStack = other.layerStack;
+    }
+    if (other.what & eCropChanged) {
+        what |= eCropChanged;
+        crop = other.crop;
+    }
+    if (other.what & eDeferTransaction) {
+        what |= eDeferTransaction;
+        barrierHandle = other.barrierHandle;
+        barrierGbp = other.barrierGbp;
+        frameNumber = other.frameNumber;
+    }
+    if (other.what & eFinalCropChanged) {
+        what |= eFinalCropChanged;
+        finalCrop = other.finalCrop;
+    }
+    if (other.what & eOverrideScalingModeChanged) {
+        what |= eOverrideScalingModeChanged;
+        overrideScalingMode = other.overrideScalingMode;
+    }
+    if (other.what & eGeometryAppliesWithResize) {
+        what |= eGeometryAppliesWithResize;
+    }
+    if (other.what & eReparentChildren) {
+        what |= eReparentChildren;
+        reparentHandle = other.reparentHandle;
+    }
+    if (other.what & eDetachChildren) {
+        what |= eDetachChildren;
+    }
+    if (other.what & eRelativeLayerChanged) {
+        what |= eRelativeLayerChanged;
+        z = other.z;
+        relativeLayerHandle = other.relativeLayerHandle;
+    }
+    if (other.what & eReparent) {
+        what |= eReparent;
+        parentHandleForChild = other.parentHandleForChild;
+    }
+}
 
 }; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index d9d945d..80216bc 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1512,6 +1512,12 @@
     return NO_ERROR;
 }
 
+android_dataspace_t Surface::getBuffersDataSpace() {
+    ALOGV("Surface::getBuffersDataSpace");
+    Mutex::Autolock lock(mMutex);
+    return mDataSpace;
+}
+
 void Surface::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].buffer = 0;
@@ -1754,4 +1760,25 @@
     return OK;
 }
 
+status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
+    if (buffer == nullptr) {
+        return BAD_VALUE;
+    }
+    int err = static_cast<ANativeWindow*>(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
+                                                            NATIVE_WINDOW_API_CPU);
+    if (err != OK) {
+        return err;
+    }
+    err = surface->attachBuffer(buffer->getNativeBuffer());
+    if (err != OK) {
+        return err;
+    }
+    err = static_cast<ANativeWindow*>(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1);
+    if (err != OK) {
+        return err;
+    }
+    err = surface->disconnect(NATIVE_WINDOW_API_CPU);
+    return err;
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7ae2672..0dbe786 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -21,7 +21,6 @@
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
-#include <utils/Singleton.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
@@ -37,11 +36,11 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
 #include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -97,204 +96,95 @@
 
 // ---------------------------------------------------------------------------
 
-static inline
-int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
-    if (lhs.client < rhs.client)  return -1;
-    if (lhs.client > rhs.client)  return 1;
-    if (lhs.state.surface < rhs.state.surface)  return -1;
-    if (lhs.state.surface > rhs.state.surface)  return 1;
-    return 0;
+SurfaceComposerClient::Transaction::Transaction(const Transaction& other) :
+    mForceSynchronous(other.mForceSynchronous),
+    mTransactionNestCount(other.mTransactionNestCount),
+    mAnimation(other.mAnimation) {
+    mDisplayStates = other.mDisplayStates;
+    mComposerStates = other.mComposerStates;
 }
 
-static inline
-int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
-    return compare_type(lhs.token, rhs.token);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
+    for (auto const& state : other.mComposerStates) {
+        ssize_t index = mComposerStates.indexOf(state);
+        if (index < 0) {
+            mComposerStates.add(state);
+        } else {
+            mComposerStates.editItemAt(static_cast<size_t>(index)).state.merge(state.state);
+        }
+    }
+    other.mComposerStates.clear();
+
+    for (auto const& state : other.mDisplayStates) {
+        ssize_t index = mDisplayStates.indexOf(state);
+        if (index < 0) {
+            mDisplayStates.add(state);
+        } else {
+            mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
+        }
+    }
+    other.mDisplayStates.clear();
+
+    return *this;
 }
 
-class Composer : public Singleton<Composer>
-{
-    friend class Singleton<Composer>;
-
-    mutable Mutex               mLock;
-    SortedVector<ComposerState> mComposerStates;
-    SortedVector<DisplayState > mDisplayStates;
-    uint32_t                    mForceSynchronous;
-    uint32_t                    mTransactionNestCount;
-    bool                        mAnimation;
-
-    Composer() : Singleton<Composer>(),
-        mForceSynchronous(0), mTransactionNestCount(0),
-        mAnimation(false)
-    { }
-
-    void openGlobalTransactionImpl();
-    void closeGlobalTransactionImpl(bool synchronous);
-    void setAnimationTransactionImpl();
-    status_t enableVSyncInjectionsImpl(bool enable);
-    status_t injectVSyncImpl(nsecs_t when);
-
-    layer_state_t* getLayerStateLocked(
-            const sp<SurfaceComposerClient>& client, const sp<IBinder>& id);
-
-    DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
-
-public:
-    sp<IBinder> createDisplay(const String8& displayName, bool secure);
-    void destroyDisplay(const sp<IBinder>& display);
-    sp<IBinder> getBuiltInDisplay(int32_t id);
-
-    status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            float x, float y);
-    status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            uint32_t w, uint32_t h);
-    status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            int32_t z);
-    status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            const sp<IBinder>& relativeTo, int32_t z);
-    status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            uint32_t flags, uint32_t mask);
-    status_t setTransparentRegionHint(
-            const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            const Region& transparentRegion);
-    status_t setAlpha(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            float alpha);
-    status_t setMatrix(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            float dsdx, float dtdx, float dtdy, float dsdy);
-    status_t setOrientation(int orientation);
-    status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
-            const Rect& crop);
-    status_t setFinalCrop(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id, const Rect& crop);
-    status_t setLayerStack(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id, uint32_t layerStack);
-    status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id, const sp<IBinder>& handle,
-            uint64_t frameNumber);
-    status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id, const sp<Surface>& barrierSurface,
-            uint64_t frameNumber);
-    status_t reparentChildren(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id,
-            const sp<IBinder>& newParentHandle);
-    status_t detachChildren(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id);
-    status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id, int32_t overrideScalingMode);
-    status_t setGeometryAppliesWithResize(const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& id);
-
-    status_t setDisplaySurface(const sp<IBinder>& token,
-            sp<IGraphicBufferProducer> bufferProducer);
-    void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
-    void setDisplayProjection(const sp<IBinder>& token,
-            uint32_t orientation,
-            const Rect& layerStackRect,
-            const Rect& displayRect);
-    void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
-    static void setAnimationTransaction() {
-        Composer::getInstance().setAnimationTransactionImpl();
+status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
+    if (mStatus != NO_ERROR) {
+        return mStatus;
     }
 
-    static void openGlobalTransaction() {
-        Composer::getInstance().openGlobalTransactionImpl();
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+    Vector<ComposerState> composerStates;
+    Vector<DisplayState> displayStates;
+    uint32_t flags = 0;
+
+    mForceSynchronous |= synchronous;
+
+    composerStates = mComposerStates;
+    mComposerStates.clear();
+
+    displayStates = mDisplayStates;
+    mDisplayStates.clear();
+
+    if (mForceSynchronous) {
+        flags |= ISurfaceComposer::eSynchronous;
+    }
+    if (mAnimation) {
+        flags |= ISurfaceComposer::eAnimation;
     }
 
-    static void closeGlobalTransaction(bool synchronous) {
-        Composer::getInstance().closeGlobalTransactionImpl(synchronous);
-    }
+    mForceSynchronous = false;
+    mAnimation = false;
 
-    static status_t enableVSyncInjections(bool enable) {
-        return Composer::getInstance().enableVSyncInjectionsImpl(enable);
-    }
-
-    static status_t injectVSync(nsecs_t when) {
-        return Composer::getInstance().injectVSyncImpl(when);
-    }
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(Composer);
+    sf->setTransactionState(composerStates, displayStates, flags);
+    mStatus = NO_ERROR;
+    return NO_ERROR;
+}
 
 // ---------------------------------------------------------------------------
 
-sp<IBinder> Composer::createDisplay(const String8& displayName, bool secure) {
+sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) {
     return ComposerService::getComposerService()->createDisplay(displayName,
             secure);
 }
 
-void Composer::destroyDisplay(const sp<IBinder>& display) {
+void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
     return ComposerService::getComposerService()->destroyDisplay(display);
 }
 
-sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
+sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
     return ComposerService::getComposerService()->getBuiltInDisplay(id);
 }
 
-void Composer::openGlobalTransactionImpl() {
-    { // scope for the lock
-        Mutex::Autolock _l(mLock);
-        mTransactionNestCount += 1;
-    }
-}
-
-void Composer::closeGlobalTransactionImpl(bool synchronous) {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-
-    Vector<ComposerState> transaction;
-    Vector<DisplayState> displayTransaction;
-    uint32_t flags = 0;
-
-    { // scope for the lock
-        Mutex::Autolock _l(mLock);
-        mForceSynchronous |= synchronous;
-        if (!mTransactionNestCount) {
-            ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
-                    "call to openGlobalTransaction().");
-        } else if (--mTransactionNestCount) {
-            return;
-        }
-
-        transaction = mComposerStates;
-        mComposerStates.clear();
-
-        displayTransaction = mDisplayStates;
-        mDisplayStates.clear();
-
-        if (mForceSynchronous) {
-            flags |= ISurfaceComposer::eSynchronous;
-        }
-        if (mAnimation) {
-            flags |= ISurfaceComposer::eAnimation;
-        }
-
-        mForceSynchronous = false;
-        mAnimation = false;
-    }
-
-   sm->setTransactionState(transaction, displayTransaction, flags);
-}
-
-status_t Composer::enableVSyncInjectionsImpl(bool enable) {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-    return sm->enableVSyncInjections(enable);
-}
-
-status_t Composer::injectVSyncImpl(nsecs_t when) {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-    return sm->injectVSync(when);
-}
-
-void Composer::setAnimationTransactionImpl() {
-    Mutex::Autolock _l(mLock);
+void SurfaceComposerClient::Transaction::setAnimationTransaction() {
     mAnimation = true;
 }
 
-layer_state_t* Composer::getLayerStateLocked(
-        const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) {
-
+layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp<SurfaceControl>& sc) {
     ComposerState s;
-    s.client = client->mClient;
-    s.state.surface = id;
+    s.client = sc->getClient()->mClient;
+    s.state.surface = sc->getHandle();
 
     ssize_t index = mComposerStates.indexOf(s);
     if (index < 0) {
@@ -306,24 +196,36 @@
     return &(out[index].state);
 }
 
-status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, float x, float y) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition(
+        const sp<SurfaceControl>& sc, float x, float y) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::ePositionChanged;
     s->x = x;
     s->y = y;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, uint32_t w, uint32_t h) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show(
+        const sp<SurfaceControl>& sc) {
+    return setFlags(sc, 0, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide(
+        const sp<SurfaceControl>& sc) {
+    return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize(
+        const sp<SurfaceControl>& sc, uint32_t w, uint32_t h) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eSizeChanged;
     s->w = w;
     s->h = h;
@@ -331,41 +233,41 @@
     // Resizing a surface makes the transaction synchronous.
     mForceSynchronous = true;
 
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, int32_t z) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
+        const sp<SurfaceControl>& sc, int32_t z) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eLayerChanged;
     s->z = z;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp<SurfaceControl>& sc, const sp<IBinder>& relativeTo,
         int32_t z) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
     }
     s->what |= layer_state_t::eRelativeLayerChanged;
     s->relativeLayerHandle = relativeTo;
     s->z = z;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, uint32_t flags,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags(
+        const sp<SurfaceControl>& sc, uint32_t flags,
         uint32_t mask) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     if ((mask & layer_state_t::eLayerOpaque) ||
             (mask & layer_state_t::eLayerHidden) ||
             (mask & layer_state_t::eLayerSecure)) {
@@ -374,50 +276,54 @@
     s->flags &= ~mask;
     s->flags |= (flags & mask);
     s->mask |= mask;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setTransparentRegionHint(
-        const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransparentRegionHint(
+        const sp<SurfaceControl>& sc,
         const Region& transparentRegion) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eTransparentRegionChanged;
     s->transparentRegion = transparentRegion;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, float alpha) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha(
+        const sp<SurfaceControl>& sc, float alpha) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eAlphaChanged;
     s->alpha = alpha;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, uint32_t layerStack) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack(
+        const sp<SurfaceControl>& sc, uint32_t layerStack) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eLayerStackChanged;
     s->layerStack = layerStack;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, float dsdx, float dtdx,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix(
+        const sp<SurfaceControl>& sc, float dsdx, float dtdx,
         float dtdy, float dsdy) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eMatrixChanged;
     layer_state_t::matrix22_t matrix;
     matrix.dsdx = dsdx;
@@ -425,93 +331,115 @@
     matrix.dsdy = dsdy;
     matrix.dtdy = dtdy;
     s->matrix = matrix;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, const Rect& crop) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
-    if (!s)
-        return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop(
+        const sp<SurfaceControl>& sc, const Rect& crop) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
     s->what |= layer_state_t::eCropChanged;
     s->crop = crop;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setFinalCrop(const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, const Rect& crop) {
-    Mutex::Autolock _l(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop) {
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eFinalCropChanged;
     s->finalCrop = crop;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::deferTransactionUntil(
-        const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+        const sp<SurfaceControl>& sc,
         const sp<IBinder>& handle, uint64_t frameNumber) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eDeferTransaction;
     s->barrierHandle = handle;
     s->frameNumber = frameNumber;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::deferTransactionUntil(
-        const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+        const sp<SurfaceControl>& sc,
         const sp<Surface>& barrierSurface, uint64_t frameNumber) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eDeferTransaction;
     s->barrierGbp = barrierSurface->getIGraphicBufferProducer();
     s->frameNumber = frameNumber;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::reparentChildren(
-        const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren(
+        const sp<SurfaceControl>& sc,
         const sp<IBinder>& newParentHandle) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eReparentChildren;
     s->reparentHandle = newParentHandle;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::detachChildren(
-        const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent(
+        const sp<SurfaceControl>& sc,
+        const sp<IBinder>& newParentHandle) {
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+    s->what |= layer_state_t::eReparent;
+    s->parentHandleForChild = newParentHandle;
+    return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor(
+        const sp<SurfaceControl>& sc,
+        const half3& color) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+    s->what |= layer_state_t::eColorChanged;
+    s->color = color;
+    return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
+        const sp<SurfaceControl>& sc) {
+    layer_state_t* s = getLayerStateLocked(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
     }
     s->what |= layer_state_t::eDetachChildren;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setOverrideScalingMode(
-        const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id, int32_t overrideScalingMode) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode(
+        const sp<SurfaceControl>& sc, int32_t overrideScalingMode) {
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
 
     switch (overrideScalingMode) {
@@ -524,29 +452,29 @@
         default:
             ALOGE("unknown scaling mode: %d",
                     overrideScalingMode);
-            return BAD_VALUE;
+            mStatus = BAD_VALUE;
+            return *this;
     }
 
     s->what |= layer_state_t::eOverrideScalingModeChanged;
     s->overrideScalingMode = overrideScalingMode;
-    return NO_ERROR;
+    return *this;
 }
 
-status_t Composer::setGeometryAppliesWithResize(
-        const sp<SurfaceComposerClient>& client,
-        const sp<IBinder>& id) {
-    Mutex::Autolock lock(mLock);
-    layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize(
+        const sp<SurfaceControl>& sc) {
+    layer_state_t* s = getLayerStateLocked(sc);
     if (!s) {
-        return BAD_INDEX;
+        mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eGeometryAppliesWithResize;
-    return NO_ERROR;
+    return *this;
 }
 
 // ---------------------------------------------------------------------------
 
-DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
+DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp<IBinder>& token) {
     DisplayState s;
     s.token = token;
     ssize_t index = mDisplayStates.indexOf(s);
@@ -558,8 +486,8 @@
     return mDisplayStates.editItemAt(static_cast<size_t>(index));
 }
 
-status_t Composer::setDisplaySurface(const sp<IBinder>& token,
-        sp<IGraphicBufferProducer> bufferProducer) {
+status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token,
+        const sp<IGraphicBufferProducer>& bufferProducer) {
     if (bufferProducer.get() != nullptr) {
         // Make sure that composition can never be stalled by a virtual display
         // consumer that isn't processing buffers fast enough.
@@ -571,26 +499,23 @@
             return err;
         }
     }
-    Mutex::Autolock _l(mLock);
     DisplayState& s(getDisplayStateLocked(token));
     s.surface = bufferProducer;
     s.what |= DisplayState::eSurfaceChanged;
     return NO_ERROR;
 }
 
-void Composer::setDisplayLayerStack(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp<IBinder>& token,
         uint32_t layerStack) {
-    Mutex::Autolock _l(mLock);
     DisplayState& s(getDisplayStateLocked(token));
     s.layerStack = layerStack;
     s.what |= DisplayState::eLayerStackChanged;
 }
 
-void Composer::setDisplayProjection(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,
         uint32_t orientation,
         const Rect& layerStackRect,
         const Rect& displayRect) {
-    Mutex::Autolock _l(mLock);
     DisplayState& s(getDisplayStateLocked(token));
     s.orientation = orientation;
     s.viewport = layerStackRect;
@@ -599,8 +524,7 @@
     mForceSynchronous = true; // TODO: do we actually still need this?
 }
 
-void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
-    Mutex::Autolock _l(mLock);
+void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
     DisplayState& s(getDisplayStateLocked(token));
     s.width = width;
     s.height = height;
@@ -610,22 +534,22 @@
 // ---------------------------------------------------------------------------
 
 SurfaceComposerClient::SurfaceComposerClient()
-    : mStatus(NO_INIT), mComposer(Composer::getInstance())
+    : mStatus(NO_INIT)
 {
 }
 
 SurfaceComposerClient::SurfaceComposerClient(const sp<IGraphicBufferProducer>& root)
-    : mStatus(NO_INIT), mComposer(Composer::getInstance()), mParent(root)
+    : mStatus(NO_INIT), mParent(root)
 {
 }
 
 void SurfaceComposerClient::onFirstRef() {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-    if (sm != 0) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    if (sf != 0) {
         auto rootProducer = mParent.promote();
         sp<ISurfaceComposerClient> conn;
-        conn = (rootProducer != nullptr) ? sm->createScopedConnection(rootProducer) :
-                sm->createConnection();
+        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
+                sf->createConnection();
         if (conn != 0) {
             mClient = conn;
             mStatus = NO_ERROR;
@@ -648,8 +572,8 @@
 status_t SurfaceComposerClient::linkToComposerDeath(
         const sp<IBinder::DeathRecipient>& recipient,
         void* cookie, uint32_t flags) {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-    return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags);
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    return IInterface::asBinder(sf)->linkToDeath(recipient, cookie, flags);
 }
 
 void SurfaceComposerClient::dispose() {
@@ -692,19 +616,6 @@
     return sur;
 }
 
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName,
-        bool secure) {
-    return Composer::getInstance().createDisplay(displayName, secure);
-}
-
-void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
-    Composer::getInstance().destroyDisplay(display);
-}
-
-sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
-    return Composer::getInstance().getBuiltInDisplay(id);
-}
-
 status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
     if (mStatus != NO_ERROR)
         return mStatus;
@@ -727,152 +638,18 @@
     return mClient->getLayerFrameStats(token, outStats);
 }
 
-inline Composer& SurfaceComposerClient::getComposer() {
-    return mComposer;
-}
-
 // ----------------------------------------------------------------------------
 
-void SurfaceComposerClient::openGlobalTransaction() {
-    Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
-    Composer::closeGlobalTransaction(synchronous);
-}
-
-void SurfaceComposerClient::setAnimationTransaction() {
-    Composer::setAnimationTransaction();
-}
-
 status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
-    return Composer::enableVSyncInjections(enable);
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    return sf->enableVSyncInjections(enable);
 }
 
 status_t SurfaceComposerClient::injectVSync(nsecs_t when) {
-    return Composer::injectVSync(when);
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    return sf->injectVSync(when);
 }
 
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setCrop(const sp<IBinder>& id, const Rect& crop) {
-    return getComposer().setCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setFinalCrop(const sp<IBinder>& id,
-        const Rect& crop) {
-    return getComposer().setFinalCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) {
-    return getComposer().setPosition(this, id, x, y);
-}
-
-status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint32_t h) {
-    return getComposer().setSize(this, id, w, h);
-}
-
-status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
-    return getComposer().setLayer(this, id, z);
-}
-
-status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
-        const sp<IBinder>& relativeTo, int32_t z) {
-    return getComposer().setRelativeLayer(this, id, relativeTo, z);
-}
-
-status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
-    return getComposer().setFlags(this, id,
-            layer_state_t::eLayerHidden,
-            layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(const sp<IBinder>& id) {
-    return getComposer().setFlags(this, id,
-            0,
-            layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::setFlags(const sp<IBinder>& id, uint32_t flags,
-        uint32_t mask) {
-    return getComposer().setFlags(this, id, flags, mask);
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(const sp<IBinder>& id,
-        const Region& transparentRegion) {
-    return getComposer().setTransparentRegionHint(this, id, transparentRegion);
-}
-
-status_t SurfaceComposerClient::setAlpha(const sp<IBinder>& id, float alpha) {
-    return getComposer().setAlpha(this, id, alpha);
-}
-
-status_t SurfaceComposerClient::setLayerStack(const sp<IBinder>& id, uint32_t layerStack) {
-    return getComposer().setLayerStack(this, id, layerStack);
-}
-
-status_t SurfaceComposerClient::setMatrix(const sp<IBinder>& id, float dsdx, float dtdx,
-        float dtdy, float dsdy) {
-    return getComposer().setMatrix(this, id, dsdx, dtdx, dtdy, dsdy);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
-        const sp<IBinder>& handle, uint64_t frameNumber) {
-    return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
-        const sp<Surface>& barrierSurface, uint64_t frameNumber) {
-    return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber);
-}
-
-status_t SurfaceComposerClient::reparentChildren(const sp<IBinder>& id,
-        const sp<IBinder>& newParentHandle) {
-    return getComposer().reparentChildren(this, id, newParentHandle);
-}
-
-status_t SurfaceComposerClient::detachChildren(const sp<IBinder>& id) {
-    return getComposer().detachChildren(this, id);
-}
-
-status_t SurfaceComposerClient::setOverrideScalingMode(
-        const sp<IBinder>& id, int32_t overrideScalingMode) {
-    return getComposer().setOverrideScalingMode(
-            this, id, overrideScalingMode);
-}
-
-status_t SurfaceComposerClient::setGeometryAppliesWithResize(
-        const sp<IBinder>& id) {
-    return getComposer().setGeometryAppliesWithResize(this, id);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
-        sp<IGraphicBufferProducer> bufferProducer) {
-    return Composer::getInstance().setDisplaySurface(token, bufferProducer);
-}
-
-void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,
-        uint32_t layerStack) {
-    Composer::getInstance().setDisplayLayerStack(token, layerStack);
-}
-
-void SurfaceComposerClient::setDisplayProjection(const sp<IBinder>& token,
-        uint32_t orientation,
-        const Rect& layerStackRect,
-        const Rect& displayRect) {
-    Composer::getInstance().setDisplayProjection(token, orientation,
-            layerStackRect, displayRect);
-}
-
-void SurfaceComposerClient::setDisplaySize(const sp<IBinder>& token,
-        uint32_t width, uint32_t height) {
-    Composer::getInstance().setDisplaySize(token, width, height);
-}
-
-// ----------------------------------------------------------------------------
-
 status_t SurfaceComposerClient::getDisplayConfigs(
         const sp<IBinder>& display, Vector<DisplayInfo>* configs)
 {
@@ -940,149 +717,27 @@
 
 // ----------------------------------------------------------------------------
 
-status_t ScreenshotClient::capture(
-        const sp<IBinder>& display,
-        const sp<IGraphicBufferProducer>& producer,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) {
+status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+                                   uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+                                   bool useIdentityTransform, uint32_t rotation,
+                                   sp<GraphicBuffer>* outBuffer) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    return s->captureScreen(display, producer, sourceCrop,
-            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
-}
-
-status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
-        uint32_t rotation,
-        sp<GraphicBuffer>* outBuffer) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    if (s == NULL) return NO_INIT;
-
-    sp<IGraphicBufferConsumer> gbpConsumer;
-    sp<IGraphicBufferProducer> producer;
-    BufferQueue::createBufferQueue(&producer, &gbpConsumer);
-    sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer,
-           GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER,
-           1, true));
-
-    status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
-            minLayerZ, maxLayerZ, useIdentityTransform,
-            static_cast<ISurfaceComposer::Rotation>(rotation));
+    status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
+                                    maxLayerZ, useIdentityTransform,
+                                    static_cast<ISurfaceComposer::Rotation>(rotation));
     if (ret != NO_ERROR) {
         return ret;
     }
-    BufferItem b;
-    consumer->acquireBuffer(&b, 0, true);
-    *outBuffer = b.mGraphicBuffer;
     return ret;
 }
 
-ScreenshotClient::ScreenshotClient()
-    : mHaveBuffer(false) {
-    memset(&mBuffer, 0, sizeof(mBuffer));
-}
-
-ScreenshotClient::~ScreenshotClient() {
-    ScreenshotClient::release();
-}
-
-sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
-    if (mCpuConsumer == NULL) {
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&mProducer, &consumer);
-        mCpuConsumer = new CpuConsumer(consumer, 1);
-        mCpuConsumer->setName(String8("ScreenshotClient"));
-    }
-    return mCpuConsumer;
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform, uint32_t rotation) {
+status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+                                         float frameScale, sp<GraphicBuffer>* outBuffer) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    sp<CpuConsumer> cpuConsumer = getCpuConsumer();
-
-    if (mHaveBuffer) {
-        mCpuConsumer->unlockBuffer(mBuffer);
-        memset(&mBuffer, 0, sizeof(mBuffer));
-        mHaveBuffer = false;
-    }
-
-    status_t err = s->captureScreen(display, mProducer, sourceCrop,
-            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
-            static_cast<ISurfaceComposer::Rotation>(rotation));
-
-    if (err == NO_ERROR) {
-        err = mCpuConsumer->lockNextBuffer(&mBuffer);
-        if (err == NO_ERROR) {
-            mHaveBuffer = true;
-        }
-    }
-    return err;
+    status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale);
+    return ret;
 }
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform) {
-
-    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
-            minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
-        bool useIdentityTransform) {
-    return ScreenshotClient::update(display, sourceCrop, 0, 0,
-            INT32_MIN, INT32_MAX,
-            useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
-        uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
-    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
-            INT32_MIN, INT32_MAX,
-            useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-void ScreenshotClient::release() {
-    if (mHaveBuffer) {
-        mCpuConsumer->unlockBuffer(mBuffer);
-        memset(&mBuffer, 0, sizeof(mBuffer));
-        mHaveBuffer = false;
-    }
-    mCpuConsumer.clear();
-}
-
-void const* ScreenshotClient::getPixels() const {
-    return mBuffer.data;
-}
-
-uint32_t ScreenshotClient::getWidth() const {
-    return mBuffer.width;
-}
-
-uint32_t ScreenshotClient::getHeight() const {
-    return mBuffer.height;
-}
-
-PixelFormat ScreenshotClient::getFormat() const {
-    return mBuffer.format;
-}
-
-uint32_t ScreenshotClient::getStride() const {
-    return mBuffer.stride;
-}
-
-size_t ScreenshotClient::getSize() const {
-    return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
-}
-
-android_dataspace ScreenshotClient::getDataSpace() const {
-    return mBuffer.dataSpace;
-}
-
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 58bd273..f6a2b8f 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -97,112 +97,6 @@
     return lhs->mHandle == rhs->mHandle;
 }
 
-status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setLayerStack(mHandle, layerStack);
-}
-
-status_t SurfaceControl::setLayer(int32_t layer) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setLayer(mHandle, layer);
-}
-
-status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setRelativeLayer(mHandle, relativeTo, layer);
-}
-
-status_t SurfaceControl::setPosition(float x, float y) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setPosition(mHandle, x, y);
-}
-status_t SurfaceControl::setGeometryAppliesWithResize() {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setGeometryAppliesWithResize(mHandle);
-}
-status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setSize(mHandle, w, h);
-}
-status_t SurfaceControl::hide() {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->hide(mHandle);
-}
-status_t SurfaceControl::show() {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->show(mHandle);
-}
-status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setFlags(mHandle, flags, mask);
-}
-status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setTransparentRegionHint(mHandle, transparent);
-}
-status_t SurfaceControl::setAlpha(float alpha) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setAlpha(mHandle, alpha);
-}
-status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setMatrix(mHandle, dsdx, dtdx, dtdy, dsdy);
-}
-status_t SurfaceControl::setCrop(const Rect& crop) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setCrop(mHandle, crop);
-}
-status_t SurfaceControl::setFinalCrop(const Rect& crop) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setFinalCrop(mHandle, crop);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<IBinder>& handle,
-        uint64_t frameNumber) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<Surface>& handle,
-        uint64_t frameNumber) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::reparentChildren(const sp<IBinder>& newParentHandle) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->reparentChildren(mHandle, newParentHandle);
-}
-
-status_t SurfaceControl::detachChildren() {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->detachChildren(mHandle);
-}
-
-status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
-    status_t err = validate();
-    if (err < 0) return err;
-    return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
-}
-
 status_t SurfaceControl::clearLayerFrameStats() const {
     status_t err = validate();
     if (err < 0) return err;
@@ -267,5 +161,10 @@
     return mHandle;
 }
 
+sp<SurfaceComposerClient> SurfaceControl::getClient() const
+{
+    return mClient;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index e9fc8fd..4a86021 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -187,7 +187,7 @@
     // ConsumerBase::releaseBufferLocked.
     virtual status_t releaseBufferLocked(int slot,
             const sp<GraphicBuffer> graphicBuffer,
-            EGLDisplay display, EGLSyncKHR eglFence);
+            EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
 
     // returns true iff the slot still has the graphicBuffer in it.
     bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index b226742..e26e332 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -29,6 +29,7 @@
 
 #include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
+#include <ui/GraphicBuffer.h>
 
 #include <vector>
 
@@ -167,12 +168,14 @@
     /* Capture the specified screen. requires READ_FRAME_BUFFER permission
      * This function will fail if there is a secure window on screen.
      */
-    virtual status_t captureScreen(const sp<IBinder>& display,
-            const sp<IGraphicBufferProducer>& producer,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform,
-            Rotation rotation = eRotateNone) = 0;
+    virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                                   int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+                                   Rotation rotation = eRotateNone) = 0;
+
+    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+                                   sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+                                   float frameScale = 1.0) = 0;
 
     /* Clears the frame statistics for animations.
      *
@@ -226,6 +229,7 @@
         SET_ACTIVE_CONFIG,
         CONNECT_DISPLAY,
         CAPTURE_SCREEN,
+        CAPTURE_LAYERS,
         CLEAR_ANIMATION_FRAME_STATS,
         GET_ANIMATION_FRAME_STATS,
         SET_POWER_MODE,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 2c613ea..d5bbef2 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -41,7 +41,7 @@
         eCursorWindow = 0x00002000,
 
         eFXSurfaceNormal = 0x00000000,
-        eFXSurfaceDim = 0x00020000,
+        eFXSurfaceColor = 0x00020000,
         eFXSurfaceMask = 0x000F0000,
     };
 
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 8453e04..92bd8c5 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -22,6 +22,7 @@
 #include <ui/Region.h>
 
 #include <string>
+#include <math/vec4.h>
 
 namespace android {
 
@@ -52,7 +53,7 @@
     int32_t mHeight = -1;
     Rect mCrop = Rect::INVALID_RECT;
     Rect mFinalCrop = Rect::INVALID_RECT;
-    float mAlpha = 0.f;
+    half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf);
     uint32_t mFlags = 0;
     PixelFormat mPixelFormat = PIXEL_FORMAT_NONE;
     android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
similarity index 85%
rename from libs/gui/include/private/gui/LayerState.h
rename to libs/gui/include/gui/LayerState.h
index 307c764..f3fb82f 100644
--- a/libs/gui/include/private/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -25,6 +25,7 @@
 #include <ui/Region.h>
 #include <ui/Rect.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <math/vec3.h>
 
 namespace android {
 
@@ -59,7 +60,9 @@
         eGeometryAppliesWithResize  = 0x00001000,
         eReparentChildren           = 0x00002000,
         eDetachChildren             = 0x00004000,
-        eRelativeLayerChanged       = 0x00008000
+        eRelativeLayerChanged       = 0x00008000,
+        eReparent                   = 0x00010000,
+        eColorChanged               = 0x00020000
     };
 
     layer_state_t()
@@ -74,6 +77,7 @@
         matrix.dsdy = matrix.dtdx = 0.0f;
     }
 
+    void merge(const layer_state_t& other);
     status_t    write(Parcel& output) const;
     status_t    read(const Parcel& input);
 
@@ -107,6 +111,10 @@
 
             sp<IBinder>     relativeLayerHandle;
 
+            sp<IBinder>     parentHandleForChild;
+
+            half3           color;
+
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
@@ -137,6 +145,7 @@
     };
 
     DisplayState();
+    void merge(const DisplayState& other);
 
     uint32_t what;
     sp<IBinder> token;
@@ -150,6 +159,20 @@
     status_t read(const Parcel& input);
 };
 
+static inline
+int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
+    if (lhs.client < rhs.client) return -1;
+    if (lhs.client > rhs.client) return 1;
+    if (lhs.state.surface < rhs.state.surface)  return -1;
+    if (lhs.state.surface > rhs.state.surface)  return 1;
+    return 0;
+}
+
+static inline
+int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
+    return compare_type(lhs.token, rhs.token);
+}
+
 }; // namespace android
 
 #endif // ANDROID_SF_LAYER_STATE_H
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 55dd6bf..354f23a 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -281,6 +281,10 @@
     // detachNextBuffer, or attachBuffer call.
     status_t getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out);
 
+    android_dataspace_t getBuffersDataSpace();
+
+    static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
+
 protected:
     enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 145c059..3f13946 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -32,13 +32,14 @@
 
 #include <gui/CpuConsumer.h>
 #include <gui/SurfaceControl.h>
+#include <math/vec3.h>
+#include <gui/LayerState.h>
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
 struct DisplayInfo;
-class Composer;
 class HdrCapabilities;
 class ISurfaceComposerClient;
 class IGraphicBufferProducer;
@@ -121,157 +122,173 @@
     //! Possible values for id are eDisplayIdMain and eDisplayIdHdmi.
     static sp<IBinder> getBuiltInDisplay(int32_t id);
 
-    // ------------------------------------------------------------------------
-    // Composer parameters
-    // All composer parameters must be changed within a transaction
-    // several surfaces can be updated in one transaction, all changes are
-    // committed at once when the transaction is closed.
-    // closeGlobalTransaction() requires an IPC with the server.
-
-    //! Open a composer transaction on all active SurfaceComposerClients.
-    static void openGlobalTransaction();
-
-    //! Close a composer transaction on all active SurfaceComposerClients.
-    static void closeGlobalTransaction(bool synchronous = false);
-
     static status_t enableVSyncInjections(bool enable);
 
     static status_t injectVSync(nsecs_t when);
 
-    //! Flag the currently open transaction as an animation transaction.
-    static void setAnimationTransaction();
+    class Transaction {
+        SortedVector<ComposerState> mComposerStates;
+        SortedVector<DisplayState > mDisplayStates;
+        uint32_t                    mForceSynchronous = 0;
+        uint32_t                    mTransactionNestCount = 0;
+        bool                        mAnimation = false;
 
-    status_t    hide(const sp<IBinder>& id);
-    status_t    show(const sp<IBinder>& id);
-    status_t    setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
-    status_t    setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
-    status_t    setLayer(const sp<IBinder>& id, int32_t layer);
-    status_t    setRelativeLayer(const sp<IBinder>& id,
-            const sp<IBinder>& relativeTo, int32_t layer);
-    status_t    setAlpha(const sp<IBinder>& id, float alpha=1.0f);
-    status_t    setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
-    status_t    setPosition(const sp<IBinder>& id, float x, float y);
-    status_t    setSize(const sp<IBinder>& id, uint32_t w, uint32_t h);
-    status_t    setCrop(const sp<IBinder>& id, const Rect& crop);
-    status_t    setFinalCrop(const sp<IBinder>& id, const Rect& crop);
-    status_t    setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
-    status_t    deferTransactionUntil(const sp<IBinder>& id,
-            const sp<IBinder>& handle, uint64_t frameNumber);
-    status_t    deferTransactionUntil(const sp<IBinder>& id,
-            const sp<Surface>& handle, uint64_t frameNumber);
-    status_t    reparentChildren(const sp<IBinder>& id,
-            const sp<IBinder>& newParentHandle);
-    status_t    detachChildren(const sp<IBinder>& id);
-    status_t    setOverrideScalingMode(const sp<IBinder>& id,
-            int32_t overrideScalingMode);
-    status_t    setGeometryAppliesWithResize(const sp<IBinder>& id);
+        int mStatus = NO_ERROR;
+
+        layer_state_t* getLayerStateLocked(const sp<SurfaceControl>& sc);
+        DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
+
+    public:
+        Transaction() = default;
+        virtual ~Transaction() = default;
+        Transaction(Transaction const& other);
+
+        status_t apply(bool synchronous = false);
+        // Merge another transaction in to this one, clearing other
+        // as if it had been applied.
+        Transaction& merge(Transaction&& other);
+        Transaction& show(const sp<SurfaceControl>& sc);
+        Transaction& hide(const sp<SurfaceControl>& sc);
+        Transaction& setPosition(const sp<SurfaceControl>& sc,
+                float x, float y);
+        Transaction& setSize(const sp<SurfaceControl>& sc,
+                uint32_t w, uint32_t h);
+        Transaction& setLayer(const sp<SurfaceControl>& sc,
+                int32_t z);
+
+        // Sets a Z order relative to the Surface specified by "relativeTo" but
+        // without becoming a full child of the relative. Z-ordering works exactly
+        // as if it were a child however.
+        //
+        // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+        //
+        // This overrides any previous call and is overriden by any future calls
+        // to setLayer.
+        //
+        // If the relative is removed, the Surface will have no layer and be
+        // invisible, until the next time set(Relative)Layer is called.
+        Transaction& setRelativeLayer(const sp<SurfaceControl>& sc,
+                const sp<IBinder>& relativeTo, int32_t z);
+        Transaction& setFlags(const sp<SurfaceControl>& sc,
+                uint32_t flags, uint32_t mask);
+        Transaction& setTransparentRegionHint(const sp<SurfaceControl>& sc,
+                const Region& transparentRegion);
+        Transaction& setAlpha(const sp<SurfaceControl>& sc,
+                float alpha);
+        Transaction& setMatrix(const sp<SurfaceControl>& sc,
+                float dsdx, float dtdx, float dtdy, float dsdy);
+        Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+        Transaction& setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+        Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
+        // Defers applying any changes made in this transaction until the Layer
+        // identified by handle reaches the given frameNumber. If the Layer identified
+        // by handle is removed, then we will apply this transaction regardless of
+        // what frame number has been reached.
+        Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+                const sp<IBinder>& handle,
+                uint64_t frameNumber);
+        // A variant of deferTransactionUntil which identifies the Layer we wait for by
+        // Surface instead of Handle. Useful for clients which may not have the
+        // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
+        Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+                const sp<Surface>& barrierSurface,
+                uint64_t frameNumber);
+        // Reparents all children of this layer to the new parent handle.
+        Transaction& reparentChildren(const sp<SurfaceControl>& sc,
+                const sp<IBinder>& newParentHandle);
+
+        /// Reparents the current layer to the new parent handle. The new parent must not be null.
+        // This can be used instead of reparentChildren if the caller wants to
+        // only re-parent a specific child.
+        Transaction& reparent(const sp<SurfaceControl>& sc,
+                const sp<IBinder>& newParentHandle);
+
+        Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color);
+
+        // Detaches all child surfaces (and their children recursively)
+        // from their SurfaceControl.
+        // The child SurfaceControls will not throw exceptions or return errors,
+        // but transactions will have no effect.
+        // The child surfaces will continue to follow their parent surfaces,
+        // and remain eligible for rendering, but their relative state will be
+        // frozen. We use this in the WindowManager, in app shutdown/relaunch
+        // scenarios, where the app would otherwise clean up its child Surfaces.
+        // Sometimes the WindowManager needs to extend their lifetime slightly
+        // in order to perform an exit animation or prevent flicker.
+        Transaction& detachChildren(const sp<SurfaceControl>& sc);
+        // Set an override scaling mode as documented in <system/window.h>
+        // the override scaling mode will take precedence over any client
+        // specified scaling mode. -1 will clear the override scaling mode.
+        Transaction& setOverrideScalingMode(const sp<SurfaceControl>& sc,
+                int32_t overrideScalingMode);
+
+        // If the size changes in this transaction, all geometry updates specified
+        // in this transaction will not complete until a buffer of the new size
+        // arrives. As some elements normally apply immediately, this enables
+        // freezing the total geometry of a surface until a resize is completed.
+        Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
+
+        status_t setDisplaySurface(const sp<IBinder>& token,
+                const sp<IGraphicBufferProducer>& bufferProducer);
+
+        void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+
+        /* setDisplayProjection() defines the projection of layer stacks
+         * to a given display.
+         *
+         * - orientation defines the display's orientation.
+         * - layerStackRect defines which area of the window manager coordinate
+         * space will be used.
+         * - displayRect defines where on the display will layerStackRect be
+         * mapped to. displayRect is specified post-orientation, that is
+         * it uses the orientation seen by the end-user.
+         */
+        void setDisplayProjection(const sp<IBinder>& token,
+                uint32_t orientation,
+                const Rect& layerStackRect,
+                const Rect& displayRect);
+        void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
+        void setAnimationTransaction();
+    };
 
     status_t    destroySurface(const sp<IBinder>& id);
 
     status_t clearLayerFrameStats(const sp<IBinder>& token) const;
     status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
-
     static status_t clearAnimationFrameStats();
     static status_t getAnimationFrameStats(FrameStats* outStats);
 
     static status_t getHdrCapabilities(const sp<IBinder>& display,
             HdrCapabilities* outCapabilities);
 
-    static status_t setDisplaySurface(const sp<IBinder>& token,
-            sp<IGraphicBufferProducer> bufferProducer);
-    static void setDisplayLayerStack(const sp<IBinder>& token,
-            uint32_t layerStack);
-    static void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
-    /* setDisplayProjection() defines the projection of layer stacks
-     * to a given display.
-     *
-     * - orientation defines the display's orientation.
-     * - layerStackRect defines which area of the window manager coordinate
-     * space will be used.
-     * - displayRect defines where on the display will layerStackRect be
-     * mapped to. displayRect is specified post-orientation, that is
-     * it uses the orientation seen by the end-user.
-     */
     static void setDisplayProjection(const sp<IBinder>& token,
             uint32_t orientation,
             const Rect& layerStackRect,
             const Rect& displayRect);
 
+    inline sp<ISurfaceComposerClient> getClient() { return mClient; }
+
 private:
     virtual void onFirstRef();
-    Composer& getComposer();
 
     mutable     Mutex                       mLock;
                 status_t                    mStatus;
                 sp<ISurfaceComposerClient>  mClient;
-                Composer&                   mComposer;
                 wp<IGraphicBufferProducer>  mParent;
 };
 
 // ---------------------------------------------------------------------------
 
-class ScreenshotClient
-{
+class ScreenshotClient {
 public:
     // if cropping isn't required, callers may pass in a default Rect, e.g.:
     //   capture(display, producer, Rect(), reqWidth, ...);
-    static status_t capture(
-            const sp<IBinder>& display,
-            const sp<IGraphicBufferProducer>& producer,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform);
-    static status_t captureToBuffer(
-            const sp<IBinder>& display,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform,
-            uint32_t rotation,
-            sp<GraphicBuffer>* outbuffer);
-private:
-    mutable sp<CpuConsumer> mCpuConsumer;
-    mutable sp<IGraphicBufferProducer> mProducer;
-    CpuConsumer::LockedBuffer mBuffer;
-    bool mHaveBuffer;
-
-public:
-    ScreenshotClient();
-    ~ScreenshotClient();
-
-    // frees the previous screenshot and captures a new one
-    // if cropping isn't required, callers may pass in a default Rect, e.g.:
-    //   update(display, Rect(), useIdentityTransform);
-    status_t update(const sp<IBinder>& display,
-            Rect sourceCrop, bool useIdentityTransform);
-    status_t update(const sp<IBinder>& display,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            bool useIdentityTransform);
-    status_t update(const sp<IBinder>& display,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform);
-    status_t update(const sp<IBinder>& display,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform, uint32_t rotation);
-
-    sp<CpuConsumer> getCpuConsumer() const;
-
-    // release memory occupied by the screenshot
-    void release();
-
-    // pixels are valid until this object is freed or
-    // release() or update() is called
-    void const* getPixels() const;
-
-    uint32_t getWidth() const;
-    uint32_t getHeight() const;
-    PixelFormat getFormat() const;
-    uint32_t getStride() const;
-    // size of allocated memory in bytes
-    size_t getSize() const;
-    android_dataspace getDataSpace() const;
+    static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+                            uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+                            bool useIdentityTransform, uint32_t rotation,
+                            sp<GraphicBuffer>* outBuffer);
+    static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float fameScale,
+                                  sp<GraphicBuffer>* outBuffer);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index c15209d..384815d 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -29,6 +29,7 @@
 #include <ui/Region.h>
 
 #include <gui/ISurfaceComposerClient.h>
+#include <math/vec3.h>
 
 namespace android {
 
@@ -60,87 +61,6 @@
     // disconnect any api that's connected
     void        disconnect();
 
-    status_t    setLayerStack(uint32_t layerStack);
-    status_t    setLayer(int32_t layer);
-
-    // Sets a Z order relative to the Surface specified by "relativeTo" but
-    // without becoming a full child of the relative. Z-ordering works exactly
-    // as if it were a child however.
-    //
-    // As a nod to sanity, only non-child surfaces may have a relative Z-order.
-    //
-    // This overrides any previous and is overriden by any future calls
-    // to setLayer.
-    //
-    // If the relative dissapears, the Surface will have no layer and be
-    // invisible, until the next time set(Relative)Layer is called.
-    //
-    // TODO: This is probably a hack. Currently it exists only to work around
-    // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
-    // which allows inserting a window between a SurfaceView and it's main application
-    // window. However, since we are using child windows for the SurfaceView, but not using
-    // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
-    // This is only used by the "TvInputService" and following the port of ViewRootImpl
-    // to child surfaces, we can then port this and remove this method.
-    status_t    setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
-    status_t    setPosition(float x, float y);
-    status_t    setSize(uint32_t w, uint32_t h);
-    status_t    hide();
-    status_t    show();
-    status_t    setFlags(uint32_t flags, uint32_t mask);
-    status_t    setTransparentRegionHint(const Region& transparent);
-    status_t    setAlpha(float alpha=1.0f);
-
-    // Experimentarily it appears that the matrix transforms the
-    // on-screen rectangle and it's contents before the position is
-    // applied.
-    //
-    // TODO: Test with other combinations to find approximate transformation rules.
-    //
-    // For example:
-    // Layer sized (W,H) set to position (x,y) with matrix M=[-1, 0, 0, 1] (Horizontal flip) gives
-    // [((0, 0), (W, H)) x M] + (x,y) = ((-W, 0), (0, H)) + (x,y) = ((-W + x, y), (x, H+y))
-    status_t    setMatrix(float dsdx, float dtdx, float dtdy, float dsdy);
-    status_t    setCrop(const Rect& crop);
-    status_t    setFinalCrop(const Rect& crop);
-
-    // If the size changes in this transaction, all geometry updates specified
-    // in this transaction will not complete until a buffer of the new size
-    // arrives. As some elements normally apply immediately, this enables
-    // freezing the total geometry of a surface until a resize is completed.
-    status_t    setGeometryAppliesWithResize();
-
-    // Defers applying any changes made in this transaction until the Layer
-    // identified by handle reaches the given frameNumber. If the Layer identified
-    // by handle is removed, then we will apply this transaction regardless of
-    // what frame number has been reached.
-    status_t deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
-
-    // A variant of deferTransactionUntil which identifies the Layer we wait for by
-    // Surface instead of Handle. Useful for clients which may not have the
-    // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
-    status_t deferTransactionUntil(const sp<Surface>& barrier, uint64_t frameNumber);
-
-    // Reparents all children of this layer to the new parent handle.
-    status_t reparentChildren(const sp<IBinder>& newParentHandle);
-
-    // Detaches all child surfaces (and their children recursively)
-    // from their SurfaceControl.
-    // The child SurfaceControl's will not throw exceptions or return errors,
-    // but transactions will have no effect.
-    // The child surfaces will continue to follow their parent surfaces,
-    // and remain eligible for rendering, but their relative state will be
-    // frozen. We use this in the WindowManager, in app shutdown/relaunch
-    // scenarios, where the app would otherwise clean up its child Surfaces.
-    // Sometimes the WindowManager needs to extend their lifetime slightly
-    // in order to perform an exit animation or prevent flicker.
-    status_t detachChildren();
-
-    // Set an override scaling mode as documented in <system/window.h>
-    // the override scaling mode will take precedence over any client
-    // specified scaling mode. -1 will clear the override scaling mode.
-    status_t setOverrideScalingMode(int32_t overrideScalingMode);
-
     static status_t writeSurfaceToParcel(
             const sp<SurfaceControl>& control, Parcel* parcel);
 
@@ -151,6 +71,8 @@
     status_t clearLayerFrameStats() const;
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
+    sp<SurfaceComposerClient> getClient() const;
+
 private:
     // can't be copied
     SurfaceControl& operator = (SurfaceControl& rhs);
diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp
index 1739d9c..a91552f 100644
--- a/libs/gui/tests/GLTest.cpp
+++ b/libs/gui/tests/GLTest.cpp
@@ -22,6 +22,8 @@
 
 namespace android {
 
+using Transaction = SurfaceComposerClient::Transaction;
+
 static int abs(int value) {
     return value > 0 ? value : -value;
 }
@@ -68,10 +70,10 @@
         ASSERT_TRUE(mSurfaceControl != NULL);
         ASSERT_TRUE(mSurfaceControl->isValid());
 
-        SurfaceComposerClient::openGlobalTransaction();
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-        SurfaceComposerClient::closeGlobalTransaction();
+        Transaction t;
+        ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7FFFFFFF)
+                .show(mSurfaceControl)
+                .apply());
 
         sp<ANativeWindow> window = mSurfaceControl->getSurface();
         mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ca43c68..470a338 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -42,6 +42,8 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 
+using Transaction = SurfaceComposerClient::Transaction;
+
 static bool hasWideColorDisplay =
         getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
 
@@ -69,10 +71,10 @@
         ASSERT_TRUE(mSurfaceControl != NULL);
         ASSERT_TRUE(mSurfaceControl->isValid());
 
-        SurfaceComposerClient::openGlobalTransaction();
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff));
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-        SurfaceComposerClient::closeGlobalTransaction();
+        Transaction t;
+        ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7fffffff)
+                .show(mSurfaceControl)
+                .apply());
 
         mSurface = mSurfaceControl->getSurface();
         ASSERT_TRUE(mSurface != NULL);
@@ -114,14 +116,11 @@
     sp<ANativeWindow> anw(mSurface);
 
     // Verify the screenshot works with no protected buffers.
-    sp<IGraphicBufferProducer> producer;
-    sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer);
-    sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sp<IBinder> display(sf->getBuiltInDisplay(
             ISurfaceComposer::eDisplayIdMain));
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+    sp<GraphicBuffer> outBuffer;
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 
     ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -152,7 +151,7 @@
                 &buf));
         ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
     }
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 }
 
@@ -522,11 +521,16 @@
     status_t setActiveColorMode(const sp<IBinder>& /*display*/,
             android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
     status_t captureScreen(const sp<IBinder>& /*display*/,
-            const sp<IGraphicBufferProducer>& /*producer*/,
+            sp<GraphicBuffer>* /*outBuffer*/,
             Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
             int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
             bool /*useIdentityTransform*/,
             Rotation /*rotation*/) override { return NO_ERROR; }
+    virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
+                                   sp<GraphicBuffer>* /*outBuffer*/,
+                                   const Rect& /*sourceCrop*/, float /*frameScale*/) override {
+        return NO_ERROR;
+    }
     status_t clearAnimationFrameStats() override { return NO_ERROR; }
     status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
         return NO_ERROR;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 9abd04c..b8901bd 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -254,7 +254,7 @@
 #if DEBUG_TRANSPORT_ACTIONS
     ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
             "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
-            "downTime=%lld, eventTime=%lld",
+            "downTime=%" PRId64 ", eventTime=%" PRId64,
             mChannel->getName().string(), seq,
             deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
             downTime, eventTime);
@@ -305,7 +305,7 @@
     ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
             "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
             "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
-            "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
+            "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
             "pointerCount=%" PRIu32,
             mChannel->getName().string(), seq,
             deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
@@ -401,7 +401,7 @@
         bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
         int32_t* displayId) {
 #if DEBUG_TRANSPORT_ACTIONS
-    ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
+    ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
             mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
 #endif
 
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 62acea3..e54f147 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -75,7 +75,9 @@
     str += " ]";
     return str;
 }
+#endif
 
+#if DEBUG_STRATEGY
 static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
     std::string str;
     str = "[";
@@ -141,6 +143,11 @@
 }
 
 VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
+    if (!strcmp("impulse", strategy)) {
+        // Physical model of pushing an object.  Quality: VERY GOOD.
+        // Works with duplicate coordinates, unclean finger liftoff.
+        return new ImpulseVelocityTrackerStrategy();
+    }
     if (!strcmp("lsq1", strategy)) {
         // 1st order least squares.  Quality: POOR.
         // Frequently underfits the touch data especially when the finger accelerates
@@ -352,9 +359,6 @@
 
 // --- LeastSquaresVelocityTrackerStrategy ---
 
-const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON;
-const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE;
-
 LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(
         uint32_t degree, Weighting weighting) :
         mDegree(degree), mWeighting(weighting) {
@@ -863,10 +867,6 @@
 
 // --- LegacyVelocityTrackerStrategy ---
 
-const nsecs_t LegacyVelocityTrackerStrategy::HORIZON;
-const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE;
-const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION;
-
 LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() {
     clear();
 }
@@ -979,4 +979,194 @@
     return true;
 }
 
+// --- ImpulseVelocityTrackerStrategy ---
+
+ImpulseVelocityTrackerStrategy::ImpulseVelocityTrackerStrategy() {
+    clear();
+}
+
+ImpulseVelocityTrackerStrategy::~ImpulseVelocityTrackerStrategy() {
+}
+
+void ImpulseVelocityTrackerStrategy::clear() {
+    mIndex = 0;
+    mMovements[0].idBits.clear();
+}
+
+void ImpulseVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
+    BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
+    mMovements[mIndex].idBits = remainingIdBits;
+}
+
+void ImpulseVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
+        const VelocityTracker::Position* positions) {
+    if (++mIndex == HISTORY_SIZE) {
+        mIndex = 0;
+    }
+
+    Movement& movement = mMovements[mIndex];
+    movement.eventTime = eventTime;
+    movement.idBits = idBits;
+    uint32_t count = idBits.count();
+    for (uint32_t i = 0; i < count; i++) {
+        movement.positions[i] = positions[i];
+    }
+}
+
+/**
+ * Calculate the total impulse provided to the screen and the resulting velocity.
+ *
+ * The touchscreen is modeled as a physical object.
+ * Initial condition is discussed below, but for now suppose that v(t=0) = 0
+ *
+ * The kinetic energy of the object at the release is E=0.5*m*v^2
+ * Then vfinal = sqrt(2E/m). The goal is to calculate E.
+ *
+ * The kinetic energy at the release is equal to the total work done on the object by the finger.
+ * The total work W is the sum of all dW along the path.
+ *
+ * dW = F*dx, where dx is the piece of path traveled.
+ * Force is change of momentum over time, F = dp/dt = m dv/dt.
+ * Then substituting:
+ * dW = m (dv/dt) * dx = m * v * dv
+ *
+ * Summing along the path, we get:
+ * W = sum(dW) = sum(m * v * dv) = m * sum(v * dv)
+ * Since the mass stays constant, the equation for final velocity is:
+ * vfinal = sqrt(2*sum(v * dv))
+ *
+ * Here,
+ * dv : change of velocity = (v[i+1]-v[i])
+ * dx : change of distance = (x[i+1]-x[i])
+ * dt : change of time = (t[i+1]-t[i])
+ * v : instantaneous velocity = dx/dt
+ *
+ * The final formula is:
+ * vfinal = sqrt(2) * sqrt(sum((v[i]-v[i-1])*|v[i]|)) for all i
+ * The absolute value is needed to properly account for the sign. If the velocity over a
+ * particular segment descreases, then this indicates braking, which means that negative
+ * work was done. So for two positive, but decreasing, velocities, this contribution would be
+ * negative and will cause a smaller final velocity.
+ *
+ * Initial condition
+ * There are two ways to deal with initial condition:
+ * 1) Assume that v(0) = 0, which would mean that the screen is initially at rest.
+ * This is not entirely accurate. We are only taking the past X ms of touch data, where X is
+ * currently equal to 100. However, a touch event that created a fling probably lasted for longer
+ * than that, which would mean that the user has already been interacting with the touchscreen
+ * and it has probably already been moving.
+ * 2) Assume that the touchscreen has already been moving at a certain velocity, calculate this
+ * initial velocity and the equivalent energy, and start with this initial energy.
+ * Consider an example where we have the following data, consisting of 3 points:
+ *                 time: t0, t1, t2
+ *                 x   : x0, x1, x2
+ *                 v   : 0 , v1, v2
+ * Here is what will happen in each of these scenarios:
+ * 1) By directly applying the formula above with the v(0) = 0 boundary condition, we will get
+ * vfinal = sqrt(2*(|v1|*(v1-v0) + |v2|*(v2-v1))). This can be simplified since v0=0
+ * vfinal = sqrt(2*(|v1|*v1 + |v2|*(v2-v1))) = sqrt(2*(v1^2 + |v2|*(v2 - v1)))
+ * since velocity is a real number
+ * 2) If we treat the screen as already moving, then it must already have an energy (per mass)
+ * equal to 1/2*v1^2. Then the initial energy should be 1/2*v1*2, and only the second segment
+ * will contribute to the total kinetic energy (since we can effectively consider that v0=v1).
+ * This will give the following expression for the final velocity:
+ * vfinal = sqrt(2*(1/2*v1^2 + |v2|*(v2-v1)))
+ * This analysis can be generalized to an arbitrary number of samples.
+ *
+ *
+ * Comparing the two equations above, we see that the only mathematical difference
+ * is the factor of 1/2 in front of the first velocity term.
+ * This boundary condition would allow for the "proper" calculation of the case when all of the
+ * samples are equally spaced in time and distance, which should suggest a constant velocity.
+ *
+ * Note that approach 2) is sensitive to the proper ordering of the data in time, since
+ * the boundary condition must be applied to the oldest sample to be accurate.
+ */
+static float kineticEnergyToVelocity(float work) {
+    static constexpr float sqrt2 = 1.41421356237;
+    return (work < 0 ? -1.0 : 1.0) * sqrtf(fabsf(work)) * sqrt2;
+}
+
+static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) {
+    // The input should be in reversed time order (most recent sample at index i=0)
+    // t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function
+    static constexpr float NANOS_PER_SECOND = 1E-9;
+
+    if (count < 2) {
+        return 0; // if 0 or 1 points, velocity is zero
+    }
+    if (t[1] > t[0]) { // Algorithm will still work, but not perfectly
+        ALOGE("Samples provided to calculateImpulseVelocity in the wrong order");
+    }
+    if (count == 2) { // if 2 points, basic linear calculation
+        if (t[1] == t[0]) {
+            ALOGE("Events have identical time stamps t=%" PRId64 ", setting velocity = 0", t[0]);
+            return 0;
+        }
+        return (x[1] - x[0]) / (NANOS_PER_SECOND * (t[1] - t[0]));
+    }
+    // Guaranteed to have at least 3 points here
+    float work = 0;
+    for (size_t i = count - 1; i > 0 ; i--) { // start with the oldest sample and go forward in time
+        if (t[i] == t[i-1]) {
+            ALOGE("Events have identical time stamps t=%" PRId64 ", skipping sample", t[i]);
+            continue;
+        }
+        float vprev = kineticEnergyToVelocity(work); // v[i-1]
+        float vcurr = (x[i] - x[i-1]) / (NANOS_PER_SECOND * (t[i] - t[i-1])); // v[i]
+        work += (vcurr - vprev) * fabsf(vcurr);
+        if (i == count - 1) {
+            work *= 0.5; // initial condition, case 2) above
+        }
+    }
+    return kineticEnergyToVelocity(work);
+}
+
+bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
+        VelocityTracker::Estimator* outEstimator) const {
+    outEstimator->clear();
+
+    // Iterate over movement samples in reverse time order and collect samples.
+    float x[HISTORY_SIZE];
+    float y[HISTORY_SIZE];
+    nsecs_t time[HISTORY_SIZE];
+    size_t m = 0; // number of points that will be used for fitting
+    size_t index = mIndex;
+    const Movement& newestMovement = mMovements[mIndex];
+    do {
+        const Movement& movement = mMovements[index];
+        if (!movement.idBits.hasBit(id)) {
+            break;
+        }
+
+        nsecs_t age = newestMovement.eventTime - movement.eventTime;
+        if (age > HORIZON) {
+            break;
+        }
+
+        const VelocityTracker::Position& position = movement.getPosition(id);
+        x[m] = position.x;
+        y[m] = position.y;
+        time[m] = movement.eventTime;
+        index = (index == 0 ? HISTORY_SIZE : index) - 1;
+    } while (++m < HISTORY_SIZE);
+
+    if (m == 0) {
+        return false; // no data
+    }
+    outEstimator->xCoeff[0] = 0;
+    outEstimator->yCoeff[0] = 0;
+    outEstimator->xCoeff[1] = calculateImpulseVelocity(time, x, m);
+    outEstimator->yCoeff[1] = calculateImpulseVelocity(time, y, m);
+    outEstimator->xCoeff[2] = 0;
+    outEstimator->yCoeff[2] = 0;
+    outEstimator->time = newestMovement.eventTime;
+    outEstimator->degree = 2; // similar results to 2nd degree fit
+    outEstimator->confidence = 1;
+#if DEBUG_STRATEGY
+    ALOGD("velocity: (%f, %f)", outEstimator->xCoeff[1], outEstimator->yCoeff[1]);
+#endif
+    return true;
+}
+
 } // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 0028655..aca9521 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -6,11 +6,12 @@
         "InputChannel_test.cpp",
         "InputEvent_test.cpp",
         "InputPublisherAndConsumer_test.cpp",
+        "VelocityTracker_test.cpp",
     ],
     cflags: [
         "-Wall",
+        "-Wextra",
         "-Werror",
-        "-Wno-error=sign-compare", // to fix later
         "-Wno-unused-variable",
     ],
     shared_libs: [
@@ -19,6 +20,7 @@
         "libutils",
         "libbinder",
         "libui",
+        "libbase",
     ]
 }
 
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 3fb1c6d..fd3b7c8 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -184,7 +184,7 @@
 
     ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
     ASSERT_EQ(2, event.getDeviceId());
-    ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource());
+    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_GAMEPAD), event.getSource());
     ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction());
     ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags());
     ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode());
@@ -196,7 +196,7 @@
 
     // Set source.
     event.setSource(AINPUT_SOURCE_JOYSTICK);
-    ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
 }
 
 
@@ -300,7 +300,7 @@
     // Check properties.
     ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
     ASSERT_EQ(2, event->getDeviceId());
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
+    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource());
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
     ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
     ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
@@ -432,7 +432,7 @@
 
     // Set source.
     event.setSource(AINPUT_SOURCE_JOYSTICK);
-    ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
 
     // Set action.
     event.setAction(AMOTION_EVENT_ACTION_CANCEL);
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index a136738..f86f876 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,8 +89,9 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
+    int32_t displayId;
     status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
-            0);
+            &displayId);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -133,7 +134,7 @@
     const uint32_t seq = 15;
     const int32_t deviceId = 1;
     const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
-    const int32_t displayId = 0;
+    int32_t displayId = 0;
     const int32_t action = AMOTION_EVENT_ACTION_MOVE;
     const int32_t actionButton = 0;
     const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -176,7 +177,7 @@
     uint32_t consumeSeq;
     InputEvent* event;
     status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
-            0);
+            &displayId);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -253,11 +254,15 @@
     ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
 }
 
-TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
     status_t status;
-    const size_t pointerCount = 0;
+    const size_t pointerCount = 1;
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
     status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
@@ -265,7 +270,20 @@
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
 
-TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
+    status_t status;
+    const size_t pointerCount = 0;
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            pointerCount, pointerProperties, pointerCoords);
+    ASSERT_EQ(BAD_VALUE, status)
+            << "publisher publishMotionEvent should return BAD_VALUE";
+}
+
+TEST_F(InputPublisherAndConsumerTest,
+        PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
     status_t status;
     const size_t pointerCount = MAX_POINTERS + 1;
     PointerProperties pointerProperties[pointerCount];
@@ -275,7 +293,7 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
new file mode 100644
index 0000000..43b6012
--- /dev/null
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -0,0 +1,664 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VelocityTracker_test"
+
+#include <math.h>
+
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <input/VelocityTracker.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+
+constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually defined tests
+
+// velocity must be in the range (1-tol)*EV <= velocity <= (1+tol)*EV
+// here EV = expected value, tol = VELOCITY_TOLERANCE
+constexpr float VELOCITY_TOLERANCE = 0.2;
+
+// --- VelocityTrackerTest ---
+class VelocityTrackerTest : public testing::Test { };
+
+static void checkVelocity(float Vactual, float Vtarget) {
+    // Compare directions
+    if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
+        FAIL() << StringPrintf("Velocity %f does not have the same direction"
+                " as the target velocity %f", Vactual, Vtarget);
+    }
+
+    // Compare magnitudes
+    const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
+    const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
+    if (fabsf(Vactual) < Vlower) {
+        FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
+                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+    }
+    if (fabsf(Vactual) > Vupper) {
+        FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
+                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+    }
+    SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",
+            Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+}
+
+void failWithMessage(std::string message) {
+    FAIL() << message; // cannot do this directly from a non-void function
+}
+
+struct Position {
+      nsecs_t time;
+      float x;
+      float y;
+};
+
+
+MotionEvent* createSimpleMotionEvent(const Position* positions, size_t numSamples) {
+    /**
+     * Only populate the basic fields of a MotionEvent, such as time and a single axis
+     * Designed for use with manually-defined tests.
+     * Create a new MotionEvent on the heap, caller responsible for destroying the object.
+     */
+    if (numSamples < 1) {
+        failWithMessage(StringPrintf("Need at least 1 sample to create a MotionEvent."
+                " Received numSamples=%zu", numSamples));
+    }
+
+    MotionEvent* event = new MotionEvent();
+    PointerCoords coords;
+    PointerProperties properties[1];
+
+    properties[0].id = DEFAULT_POINTER_ID;
+    properties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+    // First sample added separately with initialize
+    coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
+    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
+    event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords);
+
+    for (size_t i = 1; i < numSamples; i++) {
+        coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[i].x);
+        coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[i].y);
+        event->addSample(positions[i].time, &coords);
+    }
+    return event;
+}
+
+static void computeAndCheckVelocity(const Position* positions, size_t numSamples,
+            int32_t axis, float targetVelocity) {
+    VelocityTracker vt(nullptr);
+    float Vx, Vy;
+
+    MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
+    vt.addMovement(event);
+
+    vt.getVelocity(DEFAULT_POINTER_ID, &Vx, &Vy);
+
+    switch (axis) {
+    case AMOTION_EVENT_AXIS_X:
+        checkVelocity(Vx, targetVelocity);
+        break;
+    case AMOTION_EVENT_AXIS_Y:
+        checkVelocity(Vy, targetVelocity);
+        break;
+    default:
+        FAIL() << "Axis must be either AMOTION_EVENT_AXIS_X or AMOTION_EVENT_AXIS_Y";
+    }
+    delete event;
+}
+
+/*
+ * ================== VelocityTracker tests generated manually =====================================
+ */
+ // @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
+TEST_F(VelocityTrackerTest, DISABLED_ThreePointsPositiveVelocityTest) {
+    // Same coordinate is reported 2 times in a row
+    // It is difficult to determine the correct answer here, but at least the direction
+    // of the reported velocity should be positive.
+    Position values[] = {
+        { 0, 273, NAN },
+        { 12585000, 293, NAN },
+        { 14730000, 293, NAN },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1600);
+}
+
+TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) {
+    // Same coordinate is reported 3 times in a row
+    Position values[] = {
+        { 0, 293, NAN },
+        { 6132000, 293, NAN },
+        { 11283000, 293, NAN },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 0);
+}
+
+TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) {
+    // Fixed velocity at 5 points per 10 milliseconds
+    Position values[] = {
+        { 0, 0, NAN },
+        { 10000000, 5, NAN },
+        { 20000000, 10, NAN },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 500);
+}
+
+
+/**
+ * ================== VelocityTracker tests generated by recording real events =====================
+ *
+ * To add a test, record the input coordinates and event times to all calls
+ * to void VelocityTracker::addMovement(const MotionEvent* event).
+ * Also record all calls to VelocityTracker::clear().
+ * Finally, record the output of VelocityTracker::getVelocity(...)
+ * This will give you the necessary data to create a new test.
+ */
+
+// --------------- Recorded by hand on swordfish ---------------------------------------------------
+// @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
+TEST_F(VelocityTrackerTest, DISABLED_SwordfishFlingDown) {
+    // Recording of a fling on Swordfish that could cause a fling in the wrong direction
+    Position values[] = {
+        { 0, 271, 96 },
+        { 16071042, 269.786346, 106.922775 },
+        { 35648403, 267.983063, 156.660034 },
+        { 52313925, 262.638397, 220.339081 },
+        { 68976522, 266.138824, 331.581116 },
+        { 85639375, 274.79245, 428.113159 },
+        { 96948871, 274.79245, 428.113159 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 623.577637);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 8523.348633);
+}
+
+// --------------- Recorded by hand on sailfish, generated by a script -----------------------------
+// For some of these tests, the X-direction velocity checking has been removed, because the lsq2
+// and the impulse VelocityTrackerStrategies did not agree within 20%.
+// Since the flings were recorded in the Y-direction, the intentional user action should only
+// be relevant for the Y axis.
+// There have been also cases where lsq2 and impulse disagreed more than 20% in the Y-direction.
+// Those recordings have been discarded because we didn't feel one strategy's interpretation was
+// more correct than another's but didn't want to increase the tolerance for the entire test suite.
+//
+// There are 18 tests total below: 9 in the positive Y direction and 9 in the opposite.
+// The recordings were loosely binned into 3 categories - slow, faster, and fast, which roughly
+// characterizes the velocity of the finger motion.
+// These can be treated approximately as:
+// slow - less than 1 page gets scrolled
+// faster - more than 1 page gets scrolled, but less than 3
+// fast - entire list is scrolled (fling is done as hard as possible)
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) {
+    // Sailfish - fling up - slow - 1
+    Position values[] = {
+        { 235089067457000, 528.00, 983.00 },
+        { 235089084684000, 527.00, 981.00 },
+        { 235089093349000, 527.00, 977.00 },
+        { 235089095677625, 527.00, 975.93 },
+        { 235089101859000, 527.00, 970.00 },
+        { 235089110378000, 528.00, 960.00 },
+        { 235089112497111, 528.25, 957.51 },
+        { 235089118760000, 531.00, 946.00 },
+        { 235089126686000, 535.00, 931.00 },
+        { 235089129316820, 536.33, 926.02 },
+        { 235089135199000, 540.00, 914.00 },
+        { 235089144297000, 546.00, 896.00 },
+        { 235089146136443, 547.21, 892.36 },
+        { 235089152923000, 553.00, 877.00 },
+        { 235089160784000, 559.00, 851.00 },
+        { 235089162955851, 560.66, 843.82 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 872.794617); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 951.698181); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3604.819336); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3044.966064); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow2) {
+    // Sailfish - fling up - slow - 2
+    Position values[] = {
+        { 235110560704000, 522.00, 1107.00 },
+        { 235110575764000, 522.00, 1107.00 },
+        { 235110584385000, 522.00, 1107.00 },
+        { 235110588421179, 521.52, 1106.52 },
+        { 235110592830000, 521.00, 1106.00 },
+        { 235110601385000, 520.00, 1104.00 },
+        { 235110605088160, 519.14, 1102.27 },
+        { 235110609952000, 518.00, 1100.00 },
+        { 235110618353000, 517.00, 1093.00 },
+        { 235110621755146, 516.60, 1090.17 },
+        { 235110627010000, 517.00, 1081.00 },
+        { 235110634785000, 518.00, 1063.00 },
+        { 235110638422450, 518.87, 1052.58 },
+        { 235110643161000, 520.00, 1039.00 },
+        { 235110651767000, 524.00, 1011.00 },
+        { 235110655089581, 525.54, 1000.19 },
+        { 235110660368000, 530.00, 980.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4096.583008); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3455.094238); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow3) {
+    // Sailfish - fling up - slow - 3
+    Position values[] = {
+        { 792536237000, 580.00, 1317.00 },
+        { 792541538987, 580.63, 1311.94 },
+        { 792544613000, 581.00, 1309.00 },
+        { 792552301000, 583.00, 1295.00 },
+        { 792558362309, 585.13, 1282.92 },
+        { 792560828000, 586.00, 1278.00 },
+        { 792569446000, 589.00, 1256.00 },
+        { 792575185095, 591.54, 1241.41 },
+        { 792578491000, 593.00, 1233.00 },
+        { 792587044000, 597.00, 1211.00 },
+        { 792592008172, 600.28, 1195.92 },
+        { 792594616000, 602.00, 1188.00 },
+        { 792603129000, 607.00, 1167.00 },
+        { 792608831290, 609.48, 1155.83 },
+        { 792612321000, 611.00, 1149.00 },
+        { 792620768000, 615.00, 1131.00 },
+        { 792625653873, 617.32, 1121.73 },
+        { 792629200000, 619.00, 1115.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 574.33429); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 617.40564); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -2361.982666); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -2500.055664); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster1) {
+    // Sailfish - fling up - faster - 1
+    Position values[] = {
+        { 235160420675000, 610.00, 1042.00 },
+        { 235160428220000, 609.00, 1026.00 },
+        { 235160436544000, 609.00, 1024.00 },
+        { 235160441852394, 609.64, 1020.82 },
+        { 235160444878000, 610.00, 1019.00 },
+        { 235160452673000, 613.00, 1006.00 },
+        { 235160458519743, 617.18, 992.06 },
+        { 235160461061000, 619.00, 986.00 },
+        { 235160469798000, 627.00, 960.00 },
+        { 235160475186713, 632.22, 943.02 },
+        { 235160478051000, 635.00, 934.00 },
+        { 235160486489000, 644.00, 906.00 },
+        { 235160491853697, 649.56, 890.56 },
+        { 235160495177000, 653.00, 881.00 },
+        { 235160504148000, 662.00, 858.00 },
+        { 235160509231495, 666.81, 845.37 },
+        { 235160512603000, 670.00, 837.00 },
+        { 235160520366000, 679.00, 814.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1274.141724); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1438.53186); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3877.35498); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3695.859619); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster2) {
+    // Sailfish - fling up - faster - 2
+    Position values[] = {
+        { 847153808000, 576.00, 1264.00 },
+        { 847171174000, 576.00, 1262.00 },
+        { 847179640000, 576.00, 1257.00 },
+        { 847185187540, 577.41, 1249.22 },
+        { 847187487000, 578.00, 1246.00 },
+        { 847195710000, 581.00, 1227.00 },
+        { 847202027059, 583.93, 1209.40 },
+        { 847204324000, 585.00, 1203.00 },
+        { 847212672000, 590.00, 1176.00 },
+        { 847218861395, 594.36, 1157.11 },
+        { 847221190000, 596.00, 1150.00 },
+        { 847230484000, 602.00, 1124.00 },
+        { 847235701400, 607.56, 1103.83 },
+        { 847237986000, 610.00, 1095.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4280.07959); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4241.004395); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster3) {
+    // Sailfish - fling up - faster - 3
+    Position values[] = {
+        { 235200532789000, 507.00, 1084.00 },
+        { 235200549221000, 507.00, 1083.00 },
+        { 235200557841000, 507.00, 1081.00 },
+        { 235200558051189, 507.00, 1080.95 },
+        { 235200566314000, 507.00, 1078.00 },
+        { 235200574876586, 508.97, 1070.12 },
+        { 235200575006000, 509.00, 1070.00 },
+        { 235200582900000, 514.00, 1054.00 },
+        { 235200591276000, 525.00, 1023.00 },
+        { 235200591701829, 525.56, 1021.42 },
+        { 235200600064000, 542.00, 976.00 },
+        { 235200608519000, 563.00, 911.00 },
+        { 235200608527086, 563.02, 910.94 },
+        { 235200616933000, 590.00, 844.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -8715.686523); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -7639.026367); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast1) {
+    // Sailfish - fling up - fast - 1
+    Position values[] = {
+        { 920922149000, 561.00, 1412.00 },
+        { 920930185000, 559.00, 1377.00 },
+        { 920930262463, 558.98, 1376.66 },
+        { 920938547000, 559.00, 1371.00 },
+        { 920947096857, 562.91, 1342.68 },
+        { 920947302000, 563.00, 1342.00 },
+        { 920955502000, 577.00, 1272.00 },
+        { 920963931021, 596.87, 1190.54 },
+        { 920963987000, 597.00, 1190.00 },
+        { 920972530000, 631.00, 1093.00 },
+        { 920980765511, 671.31, 994.68 },
+        { 920980906000, 672.00, 993.00 },
+        { 920989261000, 715.00, 903.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 5670.329102); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 5991.866699); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -13021.101562); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -15093.995117); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast2) {
+    // Sailfish - fling up - fast - 2
+    Position values[] = {
+        { 235247153233000, 518.00, 1168.00 },
+        { 235247170452000, 517.00, 1167.00 },
+        { 235247178908000, 515.00, 1159.00 },
+        { 235247179556213, 514.85, 1158.39 },
+        { 235247186821000, 515.00, 1125.00 },
+        { 235247195265000, 521.00, 1051.00 },
+        { 235247196389476, 521.80, 1041.15 },
+        { 235247203649000, 538.00, 932.00 },
+        { 235247212253000, 571.00, 794.00 },
+        { 235247213222491, 574.72, 778.45 },
+        { 235247220736000, 620.00, 641.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -20286.958984); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -20494.587891); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast3) {
+    // Sailfish - fling up - fast - 3
+    Position values[] = {
+        { 235302568736000, 529.00, 1167.00 },
+        { 235302576644000, 523.00, 1140.00 },
+        { 235302579395063, 520.91, 1130.61 },
+        { 235302585140000, 522.00, 1130.00 },
+        { 235302593615000, 527.00, 1065.00 },
+        { 235302596207444, 528.53, 1045.12 },
+        { 235302602102000, 559.00, 872.00 },
+        { 235302610545000, 652.00, 605.00 },
+        { 235302613019881, 679.26, 526.73 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -39295.941406); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -36461.421875); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow1) {
+    // Sailfish - fling down - slow - 1
+    Position values[] = {
+        { 235655749552755, 582.00, 432.49 },
+        { 235655750638000, 582.00, 433.00 },
+        { 235655758865000, 582.00, 440.00 },
+        { 235655766221523, 581.16, 448.43 },
+        { 235655767594000, 581.00, 450.00 },
+        { 235655776044000, 580.00, 462.00 },
+        { 235655782890696, 579.18, 474.35 },
+        { 235655784360000, 579.00, 477.00 },
+        { 235655792795000, 578.00, 496.00 },
+        { 235655799559531, 576.27, 515.04 },
+        { 235655800612000, 576.00, 518.00 },
+        { 235655809535000, 574.00, 542.00 },
+        { 235655816988015, 572.17, 564.86 },
+        { 235655817685000, 572.00, 567.00 },
+        { 235655825981000, 569.00, 595.00 },
+        { 235655833808653, 566.26, 620.60 },
+        { 235655834541000, 566.00, 623.00 },
+        { 235655842893000, 563.00, 649.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -419.749695); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -398.303894); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3309.016357); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3969.099854); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow2) {
+    // Sailfish - fling down - slow - 2
+    Position values[] = {
+        { 235671152083370, 485.24, 558.28 },
+        { 235671154126000, 485.00, 559.00 },
+        { 235671162497000, 484.00, 566.00 },
+        { 235671168750511, 483.27, 573.29 },
+        { 235671171071000, 483.00, 576.00 },
+        { 235671179390000, 482.00, 588.00 },
+        { 235671185417210, 481.31, 598.98 },
+        { 235671188173000, 481.00, 604.00 },
+        { 235671196371000, 480.00, 624.00 },
+        { 235671202084196, 479.27, 639.98 },
+        { 235671204235000, 479.00, 646.00 },
+        { 235671212554000, 478.00, 673.00 },
+        { 235671219471011, 476.39, 697.12 },
+        { 235671221159000, 476.00, 703.00 },
+        { 235671229592000, 474.00, 734.00 },
+        { 235671236281462, 472.43, 758.38 },
+        { 235671238098000, 472.00, 765.00 },
+        { 235671246532000, 470.00, 799.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -262.80426); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -243.665344); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4215.682129); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4587.986816); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow3) {
+    // Sailfish - fling down - slow - 3
+    Position values[] = {
+        { 170983201000, 557.00, 533.00 },
+        { 171000668000, 556.00, 534.00 },
+        { 171007359750, 554.73, 535.27 },
+        { 171011197000, 554.00, 536.00 },
+        { 171017660000, 552.00, 540.00 },
+        { 171024201831, 549.97, 544.73 },
+        { 171027333000, 549.00, 547.00 },
+        { 171034603000, 545.00, 557.00 },
+        { 171041043371, 541.98, 567.55 },
+        { 171043147000, 541.00, 571.00 },
+        { 171051052000, 536.00, 586.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -723.413513); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -651.038452); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 2091.502441); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 1934.517456); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster1) {
+    // Sailfish - fling down - faster - 1
+    Position values[] = {
+        { 235695280333000, 558.00, 451.00 },
+        { 235695283971237, 558.43, 454.45 },
+        { 235695289038000, 559.00, 462.00 },
+        { 235695297388000, 561.00, 478.00 },
+        { 235695300638465, 561.83, 486.25 },
+        { 235695305265000, 563.00, 498.00 },
+        { 235695313591000, 564.00, 521.00 },
+        { 235695317305492, 564.43, 532.68 },
+        { 235695322181000, 565.00, 548.00 },
+        { 235695330709000, 565.00, 577.00 },
+        { 235695333972227, 565.00, 588.10 },
+        { 235695339250000, 565.00, 609.00 },
+        { 235695347839000, 565.00, 642.00 },
+        { 235695351313257, 565.00, 656.18 },
+        { 235695356412000, 565.00, 677.00 },
+        { 235695364899000, 563.00, 710.00 },
+        { 235695368118682, 562.24, 722.52 },
+        { 235695373403000, 564.00, 744.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4254.639648); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4698.415039); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster2) {
+    // Sailfish - fling down - faster - 2
+    Position values[] = {
+        { 235709624766000, 535.00, 579.00 },
+        { 235709642256000, 534.00, 580.00 },
+        { 235709643350278, 533.94, 580.06 },
+        { 235709650760000, 532.00, 584.00 },
+        { 235709658615000, 530.00, 593.00 },
+        { 235709660170495, 529.60, 594.78 },
+        { 235709667095000, 527.00, 606.00 },
+        { 235709675616000, 524.00, 628.00 },
+        { 235709676983261, 523.52, 631.53 },
+        { 235709684289000, 521.00, 652.00 },
+        { 235709692763000, 518.00, 682.00 },
+        { 235709693804993, 517.63, 685.69 },
+        { 235709701438000, 515.00, 709.00 },
+        { 235709709830000, 512.00, 739.00 },
+        { 235709710626776, 511.72, 741.85 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -430.440247); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -447.600311); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3953.859375); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4316.155273); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster3) {
+    // Sailfish - fling down - faster - 3
+    Position values[] = {
+        { 235727628927000, 540.00, 440.00 },
+        { 235727636810000, 537.00, 454.00 },
+        { 235727646176000, 536.00, 454.00 },
+        { 235727653586628, 535.12, 456.65 },
+        { 235727654557000, 535.00, 457.00 },
+        { 235727663024000, 534.00, 465.00 },
+        { 235727670410103, 533.04, 479.45 },
+        { 235727670691000, 533.00, 480.00 },
+        { 235727679255000, 531.00, 501.00 },
+        { 235727687233704, 529.09, 526.73 },
+        { 235727687628000, 529.00, 528.00 },
+        { 235727696113000, 526.00, 558.00 },
+        { 235727704057546, 523.18, 588.98 },
+        { 235727704576000, 523.00, 591.00 },
+        { 235727713099000, 520.00, 626.00 },
+        { 235727720880776, 516.33, 655.36 },
+        { 235727721580000, 516.00, 658.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4484.617676); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4927.92627); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast1) {
+    // Sailfish - fling down - fast - 1
+    Position values[] = {
+        { 235762352849000, 467.00, 286.00 },
+        { 235762360250000, 443.00, 344.00 },
+        { 235762362787412, 434.77, 363.89 },
+        { 235762368807000, 438.00, 359.00 },
+        { 235762377220000, 425.00, 423.00 },
+        { 235762379608561, 421.31, 441.17 },
+        { 235762385698000, 412.00, 528.00 },
+        { 235762394133000, 406.00, 648.00 },
+        { 235762396429369, 404.37, 680.67 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 19084.931641); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 16064.685547); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast2) {
+    // Sailfish - fling down - fast - 2
+    Position values[] = {
+        { 235772487188000, 576.00, 204.00 },
+        { 235772495159000, 553.00, 236.00 },
+        { 235772503568000, 551.00, 240.00 },
+        { 235772508192247, 545.55, 254.17 },
+        { 235772512051000, 541.00, 266.00 },
+        { 235772520794000, 520.00, 337.00 },
+        { 235772525015263, 508.92, 394.43 },
+        { 235772529174000, 498.00, 451.00 },
+        { 235772537635000, 484.00, 589.00 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 18660.048828); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 16918.439453); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast3) {
+    // Sailfish - fling down - fast - 3
+    Position values[] = {
+        { 507650295000, 628.00, 233.00 },
+        { 507658234000, 605.00, 269.00 },
+        { 507666784000, 601.00, 274.00 },
+        { 507669660483, 599.65, 275.68 },
+        { 507675427000, 582.00, 308.00 },
+        { 507683740000, 541.00, 404.00 },
+        { 507686506238, 527.36, 435.95 },
+        { 507692220000, 487.00, 581.00 },
+        { 507700707000, 454.00, 792.00 },
+        { 507703352649, 443.71, 857.77 },
+    };
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -6772.508301); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -6388.48877); // lsq2
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 29765.908203); // impulse
+    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
+}
+
+
+} // namespace android
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index f20668d..efbbf7d 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -63,7 +63,8 @@
         Vector<Sensor> v;
         uint32_t n = reply.readUint32();
         v.setCapacity(n);
-        while (n--) {
+        while (n) {
+            n--;
             reply.read(s);
             v.add(s);
         }
@@ -80,7 +81,8 @@
         Vector<Sensor> v;
         uint32_t n = reply.readUint32();
         v.setCapacity(n);
-        while (n--) {
+        while (n) {
+            n--;
             reply.read(s);
             v.add(s);
         }
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
new file mode 100644
index 0000000..6a38a1f
--- /dev/null
+++ b/libs/sensor/OWNERS
@@ -0,0 +1,2 @@
+ashutoshj@google.com
+pengxu@google.com
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 07aba32..102964f 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -47,7 +47,7 @@
     ],
 
     sanitize: {
-        //misc_undefined: ["integer"],
+        integer_overflow: true,
     },
 
     srcs: [
@@ -74,6 +74,7 @@
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
         "libbase",
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 0eb08e5..1f746a2 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -39,9 +39,15 @@
 Mapper::Mapper()
 {
     mMapper = IMapper::getService();
-    if (mMapper == nullptr || mMapper->isRemote()) {
+    if (mMapper == nullptr) {
+        LOG_ALWAYS_FATAL("gralloc-mapper is missing");
+    }
+    if (mMapper->isRemote()) {
         LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
     }
+
+    // IMapper 2.1 is optional
+    mMapperV2_1 = hardware::graphics::mapper::V2_1::IMapper::castFrom(mMapper);
 }
 
 Error Mapper::createDescriptor(
@@ -91,6 +97,50 @@
             buffer, error);
 }
 
+Error Mapper::validateBufferSize(buffer_handle_t bufferHandle,
+        const IMapper::BufferDescriptorInfo& descriptorInfo,
+        uint32_t stride) const
+{
+    if (mMapperV2_1 == nullptr) {
+        return Error::NONE;
+    }
+
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride);
+
+    return (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+}
+
+void Mapper::getTransportSize(buffer_handle_t bufferHandle,
+        uint32_t* outNumFds, uint32_t* outNumInts) const
+{
+    *outNumFds = uint32_t(bufferHandle->numFds);
+    *outNumInts = uint32_t(bufferHandle->numInts);
+
+    if (mMapperV2_1 == nullptr) {
+        return;
+    }
+
+    Error error;
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapperV2_1->getTransportSize(buffer,
+            [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outNumFds = tmpNumFds;
+                *outNumInts = tmpNumInts;
+            });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+    ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d",
+            buffer, error);
+}
+
 Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
         const IMapper::Rect& accessRegion,
         int acquireFence, void** outData) const
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index c880500..4ed2aa4 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -170,6 +170,8 @@
             inUsage, &handle, &outStride, mId,
             std::move(requestorName));
     if (err == NO_ERROR) {
+        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
+
         width = static_cast<int>(inWidth);
         height = static_cast<int>(inHeight);
         format = inFormat;
@@ -199,7 +201,8 @@
 
     if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
         buffer_handle_t importedHandle;
-        status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
+        status_t err = mBufferMapper.importBuffer(handle, width, height,
+                layerCount, format, usage, stride, &importedHandle);
         if (err != NO_ERROR) {
             initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
 
@@ -212,6 +215,7 @@
         }
 
         handle = importedHandle;
+        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
     }
 
     ANativeWindowBuffer::handle = handle;
@@ -323,11 +327,11 @@
 }
 
 size_t GraphicBuffer::getFlattenedSize() const {
-    return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int);
+    return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
-    return static_cast<size_t>(handle ? handle->numFds : 0);
+    return static_cast<size_t>(handle ? mTransportNumFds : 0);
 }
 
 status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
@@ -353,18 +357,18 @@
     buf[12] = int(usage >> 32); // high 32-bits
 
     if (handle) {
-        buf[10] = handle->numFds;
-        buf[11] = handle->numInts;
-        memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
+        buf[10] = int32_t(mTransportNumFds);
+        buf[11] = int32_t(mTransportNumInts);
+        memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
         memcpy(buf + 13, handle->data + handle->numFds,
-                static_cast<size_t>(handle->numInts) * sizeof(int));
+                static_cast<size_t>(mTransportNumInts) * sizeof(int));
     }
 
     buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
     size -= sizeNeeded;
     if (handle) {
-        fds += handle->numFds;
-        count -= static_cast<size_t>(handle->numFds);
+        fds += mTransportNumFds;
+        count -= static_cast<size_t>(mTransportNumFds);
     }
 
     return NO_ERROR;
@@ -457,7 +461,8 @@
 
     if (handle != 0) {
         buffer_handle_t importedHandle;
-        status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
+        status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
+                uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
         if (err != NO_ERROR) {
             width = height = stride = format = usage_deprecated = 0;
             layerCount = 0;
@@ -470,6 +475,7 @@
         native_handle_close(handle);
         native_handle_delete(const_cast<native_handle_t*>(handle));
         handle = importedHandle;
+        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
     }
 
     buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index d854489..2cac287 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -52,17 +52,42 @@
 }
 
 status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+        uint32_t width, uint32_t height, uint32_t layerCount,
+        PixelFormat format, uint64_t usage, uint32_t stride,
         buffer_handle_t* outHandle)
 {
     ATRACE_CALL();
 
+    buffer_handle_t bufferHandle;
     Gralloc2::Error error = mMapper->importBuffer(
-            hardware::hidl_handle(rawHandle), outHandle);
+            hardware::hidl_handle(rawHandle), &bufferHandle);
+    if (error != Gralloc2::Error::NONE) {
+        ALOGW("importBuffer(%p) failed: %d", rawHandle, error);
+        return static_cast<status_t>(error);
+    }
 
-    ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
-            rawHandle, error);
+    Gralloc2::IMapper::BufferDescriptorInfo info = {};
+    info.width = width;
+    info.height = height;
+    info.layerCount = layerCount;
+    info.format = static_cast<Gralloc2::PixelFormat>(format);
+    info.usage = usage;
+    error = mMapper->validateBufferSize(bufferHandle, info, stride);
+    if (error != Gralloc2::Error::NONE) {
+        ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error);
+        freeBuffer(bufferHandle);
+        return static_cast<status_t>(error);
+    }
 
-    return static_cast<status_t>(error);
+    *outHandle = bufferHandle;
+
+    return NO_ERROR;
+}
+
+void GraphicBufferMapper::getTransportSize(buffer_handle_t handle,
+            uint32_t* outTransportNumFds, uint32_t* outTransportNumInts)
+{
+    mMapper->getTransportSize(handle, outTransportNumFds, outTransportNumInts);
 }
 
 status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 8aee160..69c35f7 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -21,6 +21,7 @@
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -55,6 +56,13 @@
 
     void freeBuffer(buffer_handle_t bufferHandle) const;
 
+    Error validateBufferSize(buffer_handle_t bufferHandle,
+            const IMapper::BufferDescriptorInfo& descriptorInfo,
+            uint32_t stride) const;
+
+    void getTransportSize(buffer_handle_t bufferHandle,
+            uint32_t* outNumFds, uint32_t* outNumInts) const;
+
     // The ownership of acquireFence is always transferred to the callee, even
     // on errors.
     Error lock(buffer_handle_t bufferHandle, uint64_t usage,
@@ -73,6 +81,7 @@
 
 private:
     sp<IMapper> mMapper;
+    sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1;
 };
 
 // A wrapper to IAllocator
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 95c2d22..e794462 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -230,6 +230,10 @@
     GraphicBufferMapper& mBufferMapper;
     ssize_t mInitCheck;
 
+    // numbers of fds/ints in native_handle_t to flatten
+    uint32_t mTransportNumFds;
+    uint32_t mTransportNumInts;
+
     uint64_t mId;
 
     // Stores the generation number of this buffer. If this number does not
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 06961b1..7cf003d 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -22,6 +22,7 @@
 
 #include <memory>
 
+#include <ui/PixelFormat.h>
 #include <utils/Singleton.h>
 
 
@@ -49,10 +50,15 @@
     // The imported outHandle must be freed with freeBuffer when no longer
     // needed. rawHandle is owned by the caller.
     status_t importBuffer(buffer_handle_t rawHandle,
+            uint32_t width, uint32_t height, uint32_t layerCount,
+            PixelFormat format, uint64_t usage, uint32_t stride,
             buffer_handle_t* outHandle);
 
     status_t freeBuffer(buffer_handle_t handle);
 
+    void getTransportSize(buffer_handle_t handle,
+            uint32_t* outTransportNumFds, uint32_t* outTransportNumInts);
+
     status_t lock(buffer_handle_t handle,
             uint32_t usage, const Rect& bounds, void** vaddr);
 
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index a2287e1..9481c37 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,6 +29,7 @@
 
 sharedLibraries = [
     "libbase",
+    "libbinder",
     "libcutils",
     "libhardware",
     "liblog",
@@ -63,10 +64,10 @@
 
 cc_test {
     tags: ["optional"],
-    srcs: ["bufferhub_tests.cpp"],
+    srcs: ["buffer_hub-test.cpp"],
     static_libs: ["libbufferhub"] + staticLibraries,
     shared_libs: sharedLibraries,
     header_libs: headerLibraries,
-    name: "bufferhub_tests",
+    name: "buffer_hub-test",
 }
 
diff --git a/libs/vr/libbufferhub/bufferhub_tests.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
similarity index 60%
rename from libs/vr/libbufferhub/bufferhub_tests.cpp
rename to libs/vr/libbufferhub/buffer_hub-test.cpp
index c4b9a8c..a5cf9ae 100644
--- a/libs/vr/libbufferhub/bufferhub_tests.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -20,6 +20,10 @@
 using android::dvr::BufferConsumer;
 using android::dvr::BufferHubDefs::kConsumerStateMask;
 using android::dvr::BufferHubDefs::kProducerStateBit;
+using android::dvr::BufferHubDefs::IsBufferGained;
+using android::dvr::BufferHubDefs::IsBufferPosted;
+using android::dvr::BufferHubDefs::IsBufferAcquired;
+using android::dvr::BufferHubDefs::IsBufferReleased;
 using android::dvr::BufferProducer;
 using android::pdx::LocalHandle;
 
@@ -28,6 +32,8 @@
 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 const int kUsage = 0;
 const uint64_t kContext = 42;
+const size_t kMaxConsumerCount = 63;
+const int kPollTimeoutMs = 100;
 
 using LibBufferHubTest = ::testing::Test;
 
@@ -46,51 +52,51 @@
   // Producer state mask is unique, i.e. 1.
   EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
   // Consumer state mask cannot have producer bit on.
-  EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
+  EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
   // Consumer state mask must be a single, i.e. power of 2.
-  EXPECT_NE(c->buffer_state_bit(), 0);
-  EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
+  EXPECT_NE(c->buffer_state_bit(), 0U);
+  EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
   // Consumer state mask cannot have producer bit on.
-  EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
+  EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
   // Consumer state mask must be a single, i.e. power of 2.
-  EXPECT_NE(c2->buffer_state_bit(), 0);
-  EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
+  EXPECT_NE(c2->buffer_state_bit(), 0U);
+  EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
   // Each consumer should have unique bit.
-  EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
+  EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
 
   // Initial state: producer not available, consumers not available.
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
-  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
 
   EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
 
   // New state: producer not available, consumers available.
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
-  EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
-  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
 
   uint64_t context;
   LocalHandle fence;
   EXPECT_EQ(0, c->Acquire(&fence, &context));
   EXPECT_EQ(kContext, context);
-  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
-  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
 
   EXPECT_EQ(0, c2->Acquire(&fence, &context));
   EXPECT_EQ(kContext, context);
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
-  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
 
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, c2->Discard());
 
-  EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
+  EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, p->Gain(&fence));
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
-  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
 }
 
 TEST_F(LibBufferHubTest, TestEpoll) {
@@ -132,7 +138,8 @@
 
   // Post the producer and check for consumer signal.
   EXPECT_EQ(0, p->Post({}, kContext));
-  ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
   ASSERT_TRUE(events[0].events & EPOLLIN);
   ASSERT_EQ(c->event_fd(), events[0].data.fd);
 
@@ -140,10 +147,14 @@
   event = events[0];
 
   // Check for events again. Edge-triggered mode should prevent any.
-  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
-  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
-  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
-  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
 
   // Translate the events.
   auto event_status = c->GetEventMask(event.events);
@@ -151,7 +162,8 @@
   ASSERT_TRUE(event_status.get() & EPOLLIN);
 
   // Check for events again. Edge-triggered mode should prevent any.
-  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+                          kPollTimeoutMs));
 }
 
 TEST_F(LibBufferHubTest, TestStateMask) {
@@ -159,14 +171,14 @@
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p.get() != nullptr);
 
-  // It's ok to create up to 63 consumer buffers.
+  // It's ok to create up to kMaxConsumerCount consumer buffers.
   uint64_t buffer_state_bits = p->buffer_state_bit();
-  std::array<std::unique_ptr<BufferConsumer>, 63> cs;
-  for (size_t i = 0; i < 63; i++) {
+  std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
     cs[i] = BufferConsumer::Import(p->CreateConsumer());
     ASSERT_TRUE(cs[i].get() != nullptr);
     // Expect all buffers have unique state mask.
-    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
     buffer_state_bits |= cs[i]->buffer_state_bit();
   }
   EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
@@ -176,13 +188,13 @@
   EXPECT_EQ(state.error(), E2BIG);
 
   // Release any consumer should allow us to re-create.
-  for (size_t i = 0; i < 63; i++) {
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
     buffer_state_bits &= ~cs[i]->buffer_state_bit();
     cs[i] = nullptr;
     cs[i] = BufferConsumer::Import(p->CreateConsumer());
     ASSERT_TRUE(cs[i].get() != nullptr);
     // The released state mask will be reused.
-    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
     buffer_state_bits |= cs[i]->buffer_state_bit();
     EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
   }
@@ -224,7 +236,7 @@
 
   // Release in acquired state should succeed.
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   // Release, acquire, and post in released state should fail.
   EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
@@ -240,6 +252,217 @@
   EXPECT_EQ(-EALREADY, p->Gain(&fence));
 }
 
+TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // The producer buffer starts in gained state.
+
+  // Acquire, release, and gain in gained state should fail.
+  EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+
+  // Post in gained state should succeed.
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_EQ(p->buffer_state(), c->buffer_state());
+  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+  // Post, release, and gain in posted state should fail.
+  EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+
+  // Acquire in posted state should succeed.
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(p->buffer_state(), c->buffer_state());
+  EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
+
+  // Acquire, post, and gain in acquired state should fail.
+  EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+
+  // Release in acquired state should succeed.
+  EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(p->buffer_state(), c->buffer_state());
+  EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+
+  // Release, acquire, and post in released state should fail.
+  EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+
+  // Gain in released state should succeed.
+  EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(p->buffer_state(), c->buffer_state());
+  EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+  // Acquire, release, and gain in gained state should fail.
+  EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+  EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+  EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_FALSE(invalid_fence.IsValid());
+}
+
+TEST_F(LibBufferHubTest, TestZeroConsumer) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // Newly created.
+  EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+  // The buffer should stay in posted stay until a consumer picks it up.
+  EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+
+  // A new consumer should still be able to acquire the buffer immediately.
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+  EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestMaxConsumers) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+
+  std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
+    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    ASSERT_TRUE(cs[i].get() != nullptr);
+    EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
+  }
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // Post the producer should trigger all consumers to be available.
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
+    EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
+                               cs[i]->buffer_state_bit()));
+    EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
+    EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
+    EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
+  }
+
+  // All consumers have to release before the buffer is considered to be
+  // released.
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
+    EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
+    EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
+  }
+
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+
+  // Buffer state cross all clients must be consistent.
+  for (size_t i = 0; i < kMaxConsumerCount; i++) {
+    EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
+  }
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+  EXPECT_TRUE(IsBufferGained(c->buffer_state()));
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // Post the gained buffer should signal already created consumer.
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // Post the gained buffer before any consumer gets created.
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+  // Newly created consumer should be automatically sigalled.
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+  EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
+  EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+
+  std::unique_ptr<BufferConsumer> c1 =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c1.get() != nullptr);
+
+  DvrNativeBufferMetadata metadata;
+  LocalHandle invalid_fence;
+
+  // Post, acquire, and release the buffer..
+  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+  EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
+  EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
+
+  // Create another consumer immediately after the release, should not make the
+  // buffer un-released. This is guaranteed by IPC execution order in bufferhubd.
+  std::unique_ptr<BufferConsumer> c2 =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c2.get() != nullptr);
+
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+  EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
+  EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+}
+
 TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
   struct Metadata {
     int64_t field1;
@@ -254,7 +477,7 @@
 
   Metadata m = {1, 3};
   EXPECT_EQ(0, p->Post(LocalHandle(), m));
-  EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
 
   LocalHandle fence;
   Metadata m2 = {};
@@ -287,7 +510,7 @@
   // buffer allocation.
   OverSizedMetadata evil_meta = {};
   EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
-  EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
 
   // It is ok to post metadata smaller than originally requested during
   // buffer allocation.
@@ -422,7 +645,7 @@
   EXPECT_EQ(0, p->Post<void>(LocalHandle()));
   EXPECT_EQ(0, c->Acquire(&fence));
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   // Test that removing persistence and closing the producer orphans the
   // consumer.
@@ -463,7 +686,7 @@
 
   // Should acquire a valid fence.
   LocalHandle f2;
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
   EXPECT_TRUE(f2.IsValid());
   // The original fence and acquired fence should have different fd number.
@@ -473,14 +696,14 @@
   // Signal the original fence will trigger the new fence.
   eventfd_write(f1.Get(), 1);
   // Now the original FD has been signaled.
-  EXPECT_LT(0, PollFd(f2.Get(), 10));
+  EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
 
   // Release the consumer with an invalid fence.
   EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
 
   // Should gain an invalid fence.
   LocalHandle f3;
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, p->GainAsync(&meta, &f3));
   EXPECT_FALSE(f3.IsValid());
 
@@ -489,10 +712,10 @@
 
   // Should acquire a valid fence and it's already signalled.
   LocalHandle f4;
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
   EXPECT_TRUE(f4.IsValid());
-  EXPECT_LT(0, PollFd(f4.Get(), 10));
+  EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
 
   // Release with an unsignalled fence and signal it immediately after release
   // without producer gainning.
@@ -502,10 +725,10 @@
 
   // Should gain a valid fence, which is already signaled.
   LocalHandle f6;
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
   EXPECT_EQ(0, p->GainAsync(&meta, &f6));
   EXPECT_TRUE(f6.IsValid());
-  EXPECT_LT(0, PollFd(f6.Get(), 10));
+  EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
 }
 
 TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
@@ -521,12 +744,12 @@
   EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
 
   LocalHandle fence;
-  EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
   EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
   // Destroy the consumer now will make it orphaned and the buffer is still
   // acquired.
   c1 = nullptr;
-  EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   std::unique_ptr<BufferConsumer> c2 =
       BufferConsumer::Import(p->CreateConsumer());
@@ -535,13 +758,13 @@
   EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
 
   // The new consumer is available for acquire.
-  EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
   EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
   // Releasing the consumer makes the buffer gainable.
   EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
 
   // The buffer is now available for the producer to gain.
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
   // But if another consumer is created in released state.
   std::unique_ptr<BufferConsumer> c3 =
@@ -550,7 +773,7 @@
   const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
   EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
   // The consumer buffer is not acquirable.
-  EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
+  EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
   EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
 
   // Producer should be able to gain no matter what.
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 1186f93..a356959 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -94,6 +94,9 @@
 
   int id() const { return id_; }
 
+  // Returns the buffer buffer state.
+  uint64_t buffer_state() { return buffer_state_->load(); };
+
   // A state mask which is unique to a buffer hub client among all its siblings
   // sharing the same concrete graphic buffer.
   uint64_t buffer_state_bit() const { return buffer_state_bit_; }
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index b279875..8241809 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -14,6 +14,7 @@
 
 sourceFiles = [
     "buffer_hub_queue_client.cpp",
+    "buffer_hub_queue_parcelable.cpp",
     "buffer_hub_queue_producer.cpp",
 ]
 
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 8bea0cd..a5cefd9 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -137,6 +137,28 @@
   return status;
 }
 
+pdx::Status<ConsumerQueueParcelable>
+BufferHubQueue::CreateConsumerQueueParcelable(bool silent) {
+  auto status = CreateConsumerQueueHandle(silent);
+  if (!status)
+    return status.error_status();
+
+  // A temporary consumer queue client to pull its channel parcelable.
+  auto consumer_queue =
+      std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
+  ConsumerQueueParcelable queue_parcelable(
+      consumer_queue->GetChannel()->TakeChannelParcelable());
+
+  if (!queue_parcelable.IsValid()) {
+    ALOGE(
+        "BufferHubQueue::CreateConsumerQueueParcelable: Failed to create "
+        "consumer queue parcelable.");
+    return ErrorStatus(EINVAL);
+  }
+
+  return {std::move(queue_parcelable)};
+}
+
 bool BufferHubQueue::WaitForBuffers(int timeout) {
   ATRACE_NAME("BufferHubQueue::WaitForBuffers");
   std::array<epoll_event, kMaxEvents> events;
@@ -555,6 +577,25 @@
   return {std::move(buffer)};
 }
 
+pdx::Status<ProducerQueueParcelable> ProducerQueue::TakeAsParcelable() {
+  if (capacity() != 0) {
+    ALOGE(
+        "ProducerQueue::TakeAsParcelable: producer queue can only be taken out"
+        " as a parcelable when empty. Current queue capacity: %zu",
+        capacity());
+    return ErrorStatus(EINVAL);
+  }
+
+  std::unique_ptr<pdx::ClientChannel> channel = TakeChannel();
+  ProducerQueueParcelable queue_parcelable(channel->TakeChannelParcelable());
+
+  // Here the queue parcelable is returned and holds the underlying system
+  // resources backing the queue; while the original client channel of this
+  // producer queue is destroyed in place so that this client can no longer
+  // provide producer operations.
+  return {std::move(queue_parcelable)};
+}
+
 ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
     : BufferHubQueue(std::move(handle)) {
   auto status = ImportQueue();
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp
new file mode 100644
index 0000000..2cd7c45
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp
@@ -0,0 +1,82 @@
+#include "include/private/dvr/buffer_hub_queue_parcelable.h"
+
+#include <binder/Parcel.h>
+#include <pdx/default_transport/channel_parcelable.h>
+
+namespace android {
+namespace dvr {
+
+template <BufferHubQueueParcelableMagic Magic>
+bool BufferHubQueueParcelable<Magic>::IsValid() const {
+  return !!channel_parcelable_ && channel_parcelable_->IsValid();
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+pdx::LocalChannelHandle BufferHubQueueParcelable<Magic>::TakeChannelHandle() {
+  if (!IsValid()) {
+    ALOGE(
+        "BufferHubQueueParcelable::TakeChannelHandle: Invalid channel parcel.");
+    return {};  // Returns an empty channel handle.
+  }
+
+  // Take channel handle out of the parcelable and reset the parcelable.
+  pdx::LocalChannelHandle handle = channel_parcelable_->TakeChannelHandle();
+  // Now channel_parcelable_ should already be invalid, but reset it to release
+  // the invalid parcelable object from unique_ptr.
+  channel_parcelable_ = nullptr;
+  return handle;
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+status_t BufferHubQueueParcelable<Magic>::writeToParcel(Parcel* parcel) const {
+  if (!IsValid()) {
+    ALOGE("BufferHubQueueParcelable::writeToParcel: Invalid channel.");
+    return -EINVAL;
+  }
+
+  status_t res = parcel->writeUint32(Magic);
+  if (res != NO_ERROR) {
+    ALOGE("BufferHubQueueParcelable::writeToParcel: Cannot write magic.");
+    return res;
+  }
+
+  return channel_parcelable_->writeToParcel(parcel);
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+status_t BufferHubQueueParcelable<Magic>::readFromParcel(const Parcel* parcel) {
+  if (IsValid()) {
+    ALOGE(
+        "BufferHubQueueParcelable::readFromParcel: This parcelable object has "
+        "been initialized already.");
+    return -EINVAL;
+  }
+
+  uint32_t out_magic = 0;
+  status_t res = NO_ERROR;
+
+  res = parcel->readUint32(&out_magic);
+  if (res != NO_ERROR)
+    return res;
+
+  if (out_magic != Magic) {
+    ALOGE(
+        "BufferHubQueueParcelable::readFromParcel: Unexpected magic: 0x%x, "
+        "epxected: 0x%x",
+        out_magic, Magic);
+    return -EINVAL;
+  }
+
+  // (Re)Alocate channel parcelable object.
+  channel_parcelable_ =
+      std::make_unique<pdx::default_transport::ChannelParcelable>();
+  return channel_parcelable_->readFromParcel(parcel);
+}
+
+template class BufferHubQueueParcelable<
+    BufferHubQueueParcelableMagic::Producer>;
+template class BufferHubQueueParcelable<
+    BufferHubQueueParcelableMagic::Consumer>;
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 221bc4f..ace01a6 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -9,16 +9,6 @@
 namespace dvr {
 
 /* static */
-sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
-  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
-  auto config = ProducerQueueConfigBuilder()
-                    .SetMetadata<DvrNativeBufferMetadata>()
-                    .Build();
-  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
-  return producer;
-}
-
-/* static */
 sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
     const std::shared_ptr<ProducerQueue>& queue) {
   if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
@@ -33,6 +23,19 @@
   return producer;
 }
 
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
+    ProducerQueueParcelable parcelable) {
+  if (!parcelable.IsValid()) {
+    ALOGE("BufferHubQueueProducer::Create: Invalid producer parcelable.");
+    return nullptr;
+  }
+
+  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+  producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
+  return producer;
+}
+
 status_t BufferHubQueueProducer::requestBuffer(int slot,
                                                sp<GraphicBuffer>* buf) {
   ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
@@ -475,6 +478,13 @@
     return BAD_VALUE;
   }
 
+  if (!queue_->is_connected()) {
+    ALOGE(
+        "BufferHubQueueProducer::connect: This BufferHubQueueProducer is not "
+        "connected to bufferhud. Has it been taken out as a parcelable?");
+    return BAD_VALUE;
+  }
+
   switch (api) {
     case NATIVE_WINDOW_API_EGL:
     case NATIVE_WINDOW_API_CPU:
@@ -617,6 +627,39 @@
   return NO_ERROR;
 }
 
+status_t BufferHubQueueProducer::TakeAsParcelable(
+    ProducerQueueParcelable* out_parcelable) {
+  if (!out_parcelable || out_parcelable->IsValid())
+    return BAD_VALUE;
+
+  if (connected_api_ != kNoConnectedApi) {
+    ALOGE(
+        "BufferHubQueueProducer::TakeAsParcelable: BufferHubQueueProducer has "
+        "connected client. Must disconnect first.");
+    return BAD_VALUE;
+  }
+
+  if (!queue_->is_connected()) {
+    ALOGE(
+        "BufferHubQueueProducer::TakeAsParcelable: This BufferHubQueueProducer "
+        "is not connected to bufferhud. Has it been taken out as a "
+        "parcelable?");
+    return BAD_VALUE;
+  }
+
+  auto status = queue_->TakeAsParcelable();
+  if (!status) {
+    ALOGE(
+        "BufferHubQueueProducer::TakeAsParcelable: Failed to take out "
+        "ProducuerQueueParcelable from the producer queue, error: %s.",
+        status.GetErrorMessage().c_str());
+    return BAD_VALUE;
+  }
+
+  *out_parcelable = status.take();
+  return NO_ERROR;
+}
+
 status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
                                                 uint32_t layer_count,
                                                 PixelFormat format,
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 6962d6c..5b320a4 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -6,6 +6,7 @@
 #include <pdx/client.h>
 #include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
 #include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/epoll_file_descriptor.h>
 #include <private/dvr/ring_buffer.h>
@@ -54,6 +55,11 @@
   pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
       bool silent = false);
 
+  // Creates a new consumer in parcelable form for immediate transport over
+  // Binder.
+  pdx::Status<ConsumerQueueParcelable> CreateConsumerQueueParcelable(
+      bool silent = false);
+
   // Returns the number of buffers avaiable for dequeue.
   size_t count() const { return available_buffers_.size(); }
 
@@ -68,7 +74,8 @@
     return available_buffers_.size() >= kMaxQueueCapacity;
   }
 
-  explicit operator bool() const { return epoll_fd_.IsValid(); }
+  // Returns whether the buffer queue is connected to bufferhubd.
+  bool is_connected() const { return !!GetChannel(); }
 
   int GetBufferId(size_t slot) const {
     return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
@@ -337,6 +344,11 @@
     return BufferHubQueue::Enqueue({buffer, slot, index});
   }
 
+  // Takes out the current producer queue as a binder parcelable object. Note
+  // that the queue must be empty to be exportable. After successful export, the
+  // producer queue client should no longer be used.
+  pdx::Status<ProducerQueueParcelable> TakeAsParcelable();
+
  private:
   friend BASE;
 
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
new file mode 100644
index 0000000..89baf92
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -0,0 +1,60 @@
+#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
+#define ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
+
+#include <pdx/channel_parcelable.h>
+
+namespace android {
+namespace dvr {
+
+enum BufferHubQueueParcelableMagic : uint32_t {
+  Producer = 0x62687170,  // 'bhqp'
+  Consumer = 0x62687163,  // 'bhqc'
+};
+
+template <BufferHubQueueParcelableMagic Magic>
+class BufferHubQueueParcelable : public Parcelable {
+ public:
+  BufferHubQueueParcelable() = default;
+
+  BufferHubQueueParcelable(BufferHubQueueParcelable&& other) = default;
+  BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) =
+      default;
+
+  // Constructs an parcelable contains the channel parcelable.
+  BufferHubQueueParcelable(
+      std::unique_ptr<pdx::ChannelParcelable> channel_parcelable)
+      : channel_parcelable_(std::move(channel_parcelable)) {}
+
+  BufferHubQueueParcelable(const BufferHubQueueParcelable&) = delete;
+  void operator=(const BufferHubQueueParcelable&) = delete;
+
+  bool IsValid() const;
+
+  // Returns a channel handle constructed from this parcelable object and takes
+  // the ownership of all resources from the parcelable object.
+  pdx::LocalChannelHandle TakeChannelHandle();
+
+  // Serializes the queue parcelable into the given parcel. Note that no system
+  // resources are getting duplicated, nor did the parcel takes ownership of the
+  // queue parcelable. Thus, the parcelable object must remain valid for the
+  // lifetime of the parcel.
+  status_t writeToParcel(Parcel* parcel) const override;
+
+  // Deserialize the queue parcelable from the given parcel. Note that system
+  // resources are duplicated from the parcel into the queue parcelable. Returns
+  // error if the targeting parcelable object is already valid.
+  status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+  std::unique_ptr<pdx::ChannelParcelable> channel_parcelable_;
+};
+
+using ProducerQueueParcelable =
+    BufferHubQueueParcelable<BufferHubQueueParcelableMagic::Producer>;
+using ConsumerQueueParcelable =
+    BufferHubQueueParcelable<BufferHubQueueParcelableMagic::Consumer>;
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 7ed55fb..9c85048 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -3,6 +3,7 @@
 
 #include <gui/IGraphicBufferProducer.h>
 #include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
 
 namespace android {
 namespace dvr {
@@ -17,14 +18,16 @@
   // that.
   static constexpr int kDefaultUndequeuedBuffers = 1;
 
-  // Create a BufferHubQueueProducer instance by creating a new producer queue.
-  static sp<BufferHubQueueProducer> Create();
-
-  // Create a BufferHubQueueProducer instance by importing an existing prodcuer
+  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
   // queue.
   static sp<BufferHubQueueProducer> Create(
       const std::shared_ptr<ProducerQueue>& producer);
 
+  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
+  // parcelable. Note that this call takes the ownership of the parcelable
+  // object and is guaranteed to succeed if parcelable object is valid.
+  static sp<BufferHubQueueProducer> Create(ProducerQueueParcelable parcelable);
+
   // See |IGraphicBufferProducer::requestBuffer|
   status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
 
@@ -115,6 +118,14 @@
   // See |IGraphicBufferProducer::getConsumerUsage|
   status_t getConsumerUsage(uint64_t* out_usage) const override;
 
+  // Takes out the current producer as a binder parcelable object. Note that the
+  // producer must be disconnected to be exportable. After successful export,
+  // the producer queue can no longer be connected again. Returns NO_ERROR when
+  // takeout is successful and out_parcelable will hold the new parcelable
+  // object. Also note that out_parcelable cannot be NULL and must points to an
+  // invalid parcelable.
+  status_t TakeAsParcelable(ProducerQueueParcelable* out_parcelable);
+
  private:
   using LocalHandle = pdx::LocalHandle;
 
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index d8a9b90..abeb719 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -12,6 +12,7 @@
     "libhardware",
     "libui",
     "libutils",
+    "libnativewindow",
 ]
 
 static_libraries = [
@@ -20,6 +21,7 @@
     "libchrome",
     "libdvrcommon",
     "libpdx_default_transport",
+    "libperformance",
 ]
 
 cc_test {
@@ -56,3 +58,17 @@
     name: "buffer_hub_queue_producer-test",
     tags: ["optional"],
 }
+
+cc_benchmark {
+    srcs: ["buffer_transport_benchmark.cpp"],
+    static_libs: static_libraries,
+    shared_libs: shared_libraries,
+    header_libs: header_libraries,
+    cflags: [
+        "-DLOG_TAG=\"buffer_transport_benchmark\"",
+        "-DTRACE=0",
+        "-O2",
+    ],
+    name: "buffer_transport_benchmark",
+    tags: ["optional"],
+}
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 8a72531..3efa723 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -1,4 +1,5 @@
 #include <base/logging.h>
+#include <binder/Parcel.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/buffer_hub_queue_client.h>
 
@@ -14,6 +15,7 @@
 namespace android {
 namespace dvr {
 
+using pdx::LocalChannelHandle;
 using pdx::LocalHandle;
 
 namespace {
@@ -23,6 +25,8 @@
 constexpr uint32_t kBufferLayerCount = 1;
 constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
 constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+constexpr int kTimeoutMs = 100;
+constexpr int kNoTimeout = 0;
 
 class BufferHubQueueTest : public ::testing::Test {
  public:
@@ -82,41 +86,49 @@
 };
 
 TEST_F(BufferHubQueueTest, TestDequeue) {
-  const size_t nb_dequeue_times = 16;
+  const int64_t nb_dequeue_times = 16;
 
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
-                           UsagePolicy{}));
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate only one buffer.
   AllocateBuffer();
 
   // But dequeue multiple times.
-  for (size_t i = 0; i < nb_dequeue_times; i++) {
+  for (int64_t i = 0; i < nb_dequeue_times; i++) {
     size_t slot;
     LocalHandle fence;
-    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
-    ASSERT_TRUE(p1_status.ok());
+    DvrNativeBufferMetadata mi, mo;
+
+    // Producer gains a buffer.
+    auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+    EXPECT_TRUE(p1_status.ok());
     auto p1 = p1_status.take();
-    ASSERT_NE(nullptr, p1);
-    size_t mi = i;
-    ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
-    size_t mo;
-    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
-    ASSERT_TRUE(c1_status.ok());
+    ASSERT_NE(p1, nullptr);
+
+    // Producer posts the buffer.
+    mi.index = i;
+    EXPECT_EQ(p1->PostAsync(&mi, LocalHandle()), 0);
+
+    // Consumer acquires a buffer.
+    auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+    EXPECT_TRUE(c1_status.ok());
     auto c1 = c1_status.take();
-    ASSERT_NE(nullptr, c1);
-    ASSERT_EQ(mi, mo);
-    c1->Release(LocalHandle());
+    ASSERT_NE(c1, nullptr);
+    EXPECT_EQ(mi.index, i);
+    EXPECT_EQ(mo.index, i);
+
+    // Consumer releases the buffer.
+    EXPECT_EQ(c1->ReleaseAsync(&mi, LocalHandle()), 0);
   }
 }
 
 TEST_F(BufferHubQueueTest, TestProducerConsumer) {
   const size_t kBufferCount = 16;
   size_t slot;
-  uint64_t seq;
+  DvrNativeBufferMetadata mi, mo;
+  LocalHandle fence;
 
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
-                           UsagePolicy{}));
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   for (size_t i = 0; i < kBufferCount; i++) {
     AllocateBuffer();
@@ -131,8 +143,7 @@
     ASSERT_EQ(consumer_queue_->capacity(), i);
     // Dequeue returns timeout since no buffer is ready to consumer, but
     // this implicitly triggers buffer import and bump up |capacity|.
-    LocalHandle fence;
-    auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+    auto status = consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
     ASSERT_FALSE(status.ok());
     ASSERT_EQ(ETIMEDOUT, status.error());
     ASSERT_EQ(consumer_queue_->capacity(), i + 1);
@@ -142,37 +153,37 @@
   LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
 
   for (size_t i = 0; i < kBufferCount; i++) {
-    LocalHandle fence;
-
     // First time there is no buffer available to dequeue.
-    auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+    auto consumer_status =
+        consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
     ASSERT_FALSE(consumer_status.ok());
-    ASSERT_EQ(ETIMEDOUT, consumer_status.error());
+    ASSERT_EQ(consumer_status.error(), ETIMEDOUT);
 
     // Make sure Producer buffer is POSTED so that it's ready to Accquire
     // in the consumer's Dequeue() function.
-    auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    auto producer_status =
+        producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(producer_status.ok());
     auto producer = producer_status.take();
     ASSERT_NE(nullptr, producer);
 
-    uint64_t seq_in = static_cast<uint64_t>(i);
-    ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
+    mi.index = static_cast<int64_t>(i);
+    ASSERT_EQ(producer->PostAsync(&mi, post_fence), 0);
 
     // Second time the just the POSTED buffer should be dequeued.
-    uint64_t seq_out = 0;
-    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
+    consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(consumer_status.ok());
     EXPECT_TRUE(fence.IsValid());
 
     auto consumer = consumer_status.take();
     ASSERT_NE(nullptr, consumer);
-    ASSERT_EQ(seq_in, seq_out);
+    ASSERT_EQ(mi.index, mo.index);
   }
 }
 
 TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
   ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+  DvrNativeBufferMetadata mo;
 
   // Allocate buffers.
   const size_t kBufferCount = 4u;
@@ -201,7 +212,7 @@
   for (size_t i = 0; i < kBufferCount; i++) {
     Entry* entry = &buffers[i];
     auto producer_status = producer_queue_->Dequeue(
-        /*timeout_ms=*/100, &entry->slot, &entry->fence);
+        kTimeoutMs, &entry->slot, &mo, &entry->fence);
     ASSERT_TRUE(producer_status.ok());
     entry->buffer = producer_status.take();
     ASSERT_NE(nullptr, entry->buffer);
@@ -221,7 +232,7 @@
   buffers[0].buffer = nullptr;
 
   // Now the consumer queue should know it's gone.
-  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
+  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs));
   ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());
 
   // Allocate a new buffer. This should take the first empty slot.
@@ -290,126 +301,154 @@
   ASSERT_NE(nullptr, silent_queue);
 
   // Check that silent queue doesn't import buffers on creation.
-  EXPECT_EQ(0, silent_queue->capacity());
+  EXPECT_EQ(silent_queue->capacity(), 0U);
 
   // Dequeue and post a buffer.
   size_t slot;
   LocalHandle fence;
+  DvrNativeBufferMetadata mi, mo;
   auto producer_status =
-      producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
-  ASSERT_TRUE(producer_status.ok());
+      producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+  EXPECT_TRUE(producer_status.ok());
   auto producer_buffer = producer_status.take();
-  ASSERT_NE(nullptr, producer_buffer);
-  ASSERT_EQ(0, producer_buffer->Post<void>({}));
+  ASSERT_NE(producer_buffer, nullptr);
+  EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);
   // After post, check the number of remaining available buffers.
-  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
 
   // Currently we expect no buffer to be available prior to calling
   // WaitForBuffers/HandleQueueEvents.
   // TODO(eieio): Note this behavior may change in the future.
-  EXPECT_EQ(0u, silent_queue->count());
+  EXPECT_EQ(silent_queue->count(), 0U);
   EXPECT_FALSE(silent_queue->HandleQueueEvents());
-  EXPECT_EQ(0u, silent_queue->count());
+  EXPECT_EQ(silent_queue->count(), 0U);
 
   // Build a new consumer queue to test multi-consumer queue features.
   consumer_queue_ = silent_queue->CreateConsumerQueue();
-  ASSERT_NE(nullptr, consumer_queue_);
+  ASSERT_NE(consumer_queue_, nullptr);
 
   // Check that buffers are correctly imported on construction.
-  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
-  EXPECT_EQ(1u, consumer_queue_->count());
+  EXPECT_EQ(consumer_queue_->capacity(), kBufferCount);
+  EXPECT_EQ(consumer_queue_->count(), 1U);
 
   // Reclaim released/ignored buffers.
-  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
 
   usleep(10000);
-  WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
-  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+  WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
+  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
 
   // Post another buffer.
-  producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
-  ASSERT_TRUE(producer_status.ok());
+  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+  EXPECT_TRUE(producer_status.ok());
   producer_buffer = producer_status.take();
-  ASSERT_NE(nullptr, producer_buffer);
-  ASSERT_EQ(0, producer_buffer->Post<void>({}));
+  ASSERT_NE(producer_buffer, nullptr);
+  EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);
 
   // Verify that the consumer queue receives it.
   size_t consumer_queue_count = consumer_queue_->count();
-  WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
-  EXPECT_LT(consumer_queue_count, consumer_queue_->count());
+  WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs);
+  EXPECT_GT(consumer_queue_->count(), consumer_queue_count);
 
   // Save the current consumer queue buffer count to compare after the dequeue.
   consumer_queue_count = consumer_queue_->count();
 
   // Dequeue and acquire/release (discard) buffers on the consumer end.
   auto consumer_status =
-      consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
-  ASSERT_TRUE(consumer_status.ok());
+      consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+  EXPECT_TRUE(consumer_status.ok());
   auto consumer_buffer = consumer_status.take();
-  ASSERT_NE(nullptr, consumer_buffer);
+  ASSERT_NE(consumer_buffer, nullptr);
   consumer_buffer->Discard();
 
   // Buffer should be returned to the producer queue without being handled by
   // the silent consumer queue.
-  EXPECT_GT(consumer_queue_count, consumer_queue_->count());
-  EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
-  EXPECT_TRUE(producer_queue_->HandleQueueEvents());
-  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+  EXPECT_LT(consumer_queue_->count(), consumer_queue_count);
+  EXPECT_EQ(producer_queue_->count(), kBufferCount - 2);
+
+  WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
+  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
 }
 
-struct TestMetadata {
+struct TestUserMetadata {
   char a;
   int32_t b;
   int64_t c;
 };
 
-TEST_F(BufferHubQueueTest, TestMetadata) {
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
-                           UsagePolicy{}));
+constexpr uint64_t kUserMetadataSize =
+    static_cast<uint64_t>(sizeof(TestUserMetadata));
+
+TEST_F(BufferHubQueueTest, TestUserMetadata) {
+  ASSERT_TRUE(CreateQueues(
+      config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));
 
   AllocateBuffer();
 
-  std::vector<TestMetadata> ms = {
+  std::vector<TestUserMetadata> user_metadata_list = {
       {'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}};
 
-  for (auto mi : ms) {
+  for (auto user_metadata : user_metadata_list) {
     size_t slot;
     LocalHandle fence;
-    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
-    ASSERT_TRUE(p1_status.ok());
+    DvrNativeBufferMetadata mi, mo;
+
+    auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+    EXPECT_TRUE(p1_status.ok());
     auto p1 = p1_status.take();
-    ASSERT_NE(nullptr, p1);
-    ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
-    TestMetadata mo;
-    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
-    ASSERT_TRUE(c1_status.ok());
+    ASSERT_NE(p1, nullptr);
+
+    // TODO(b/69469185): Test against metadata from consumer once we implement
+    // release metadata properly.
+    // EXPECT_EQ(mo.user_metadata_ptr, 0U);
+    // EXPECT_EQ(mo.user_metadata_size, 0U);
+
+    mi.user_metadata_size = kUserMetadataSize;
+    mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+    EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
+    auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+    EXPECT_TRUE(c1_status.ok());
     auto c1 = c1_status.take();
-    ASSERT_EQ(mi.a, mo.a);
-    ASSERT_EQ(mi.b, mo.b);
-    ASSERT_EQ(mi.c, mo.c);
-    c1->Release(LocalHandle(-1));
+    ASSERT_NE(c1, nullptr);
+
+    EXPECT_EQ(mo.user_metadata_size, kUserMetadataSize);
+    auto out_user_metadata =
+        reinterpret_cast<TestUserMetadata*>(mo.user_metadata_ptr);
+    EXPECT_EQ(user_metadata.a, out_user_metadata->a);
+    EXPECT_EQ(user_metadata.b, out_user_metadata->b);
+    EXPECT_EQ(user_metadata.c, out_user_metadata->c);
+
+    // When release, empty metadata is also legit.
+    mi.user_metadata_size = 0U;
+    mi.user_metadata_ptr = 0U;
+    c1->ReleaseAsync(&mi, {});
   }
 }
 
-TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
-                           UsagePolicy{}));
+TEST_F(BufferHubQueueTest, TestUserMetadataMismatch) {
+  ASSERT_TRUE(CreateQueues(
+      config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));
 
   AllocateBuffer();
 
-  int64_t mi = 3;
+  TestUserMetadata user_metadata;
   size_t slot;
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
-  ASSERT_TRUE(p1_status.ok());
+  DvrNativeBufferMetadata mi, mo;
+  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+  EXPECT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
-  ASSERT_NE(nullptr, p1);
-  ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
+  ASSERT_NE(p1, nullptr);
 
-  int32_t mo;
-  // Acquire a buffer with mismatched metadata is not OK.
-  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
-  ASSERT_FALSE(c1_status.ok());
+  // Post with mismatched user metadata size will fail. But the producer buffer
+  // itself should stay untouched.
+  mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+  mi.user_metadata_size = kUserMetadataSize + 1;
+  EXPECT_EQ(p1->PostAsync(&mi, {}), -E2BIG);
+  // Post with the exact same user metdata size can success.
+  mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+  mi.user_metadata_size = kUserMetadataSize;
+  EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
@@ -419,32 +458,32 @@
 
   size_t slot;
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+  DvrNativeBufferMetadata mo;
+  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
 
-  int64_t mo;
   producer_queue_->Enqueue(p1, slot, 0ULL);
-  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+  auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_FALSE(c1_status.ok());
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
-                           UsagePolicy{}));
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
-  size_t s1;
+  size_t ps1;
   AllocateBuffer();
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
+  DvrNativeBufferMetadata mi, mo;
+  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &ps1, &mo, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
-  ASSERT_NE(nullptr, p1);
+  ASSERT_NE(p1, nullptr);
 
   // producer queue is exhausted
-  size_t s2;
-  auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
+  size_t ps2;
+  auto p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
   ASSERT_FALSE(p2_status.ok());
   ASSERT_EQ(ETIMEDOUT, p2_status.error());
 
@@ -454,41 +493,43 @@
   ASSERT_EQ(producer_queue_->capacity(), 2U);
 
   // now we can dequeue again
-  p2_status = producer_queue_->Dequeue(100, &s2, &fence);
+  p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
   ASSERT_TRUE(p2_status.ok());
   auto p2 = p2_status.take();
-  ASSERT_NE(nullptr, p2);
+  ASSERT_NE(p2, nullptr);
   ASSERT_EQ(producer_queue_->count(), 0U);
   // p1 and p2 should have different slot number
-  ASSERT_NE(s1, s2);
+  ASSERT_NE(ps1, ps2);
 
   // Consumer queue does not import buffers until |Dequeue| or |ImportBuffers|
   // are called. So far consumer_queue_ should be empty.
   ASSERT_EQ(consumer_queue_->count(), 0U);
 
   int64_t seq = 1;
-  ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
+  mi.index = seq;
+  ASSERT_EQ(p1->PostAsync(&mi, {}), 0);
+
   size_t cs1, cs2;
-  auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
+  auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &cs1, &mo, &fence);
   ASSERT_TRUE(c1_status.ok());
   auto c1 = c1_status.take();
-  ASSERT_NE(nullptr, c1);
+  ASSERT_NE(c1, nullptr);
   ASSERT_EQ(consumer_queue_->count(), 0U);
   ASSERT_EQ(consumer_queue_->capacity(), 2U);
-  ASSERT_EQ(cs1, s1);
+  ASSERT_EQ(cs1, ps1);
 
-  ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
-  auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
+  ASSERT_EQ(p2->PostAsync(&mi, {}), 0);
+  auto c2_status = consumer_queue_->Dequeue(kTimeoutMs, &cs2, &mo, &fence);
   ASSERT_TRUE(c2_status.ok());
   auto c2 = c2_status.take();
-  ASSERT_NE(nullptr, c2);
-  ASSERT_EQ(cs2, s2);
+  ASSERT_NE(c2, nullptr);
+  ASSERT_EQ(cs2, ps2);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
-                           UsagePolicy{set_mask, 0, 0, 0}));
+  ASSERT_TRUE(
+      CreateQueues(config_builder_.Build(), UsagePolicy{set_mask, 0, 0, 0}));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   auto status = producer_queue_->AllocateBuffer(
@@ -498,7 +539,8 @@
 
   LocalHandle fence;
   size_t slot;
-  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+  DvrNativeBufferMetadata mo;
+  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_EQ(p1->usage() & set_mask, set_mask);
@@ -506,8 +548,8 @@
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
   const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
-                           UsagePolicy{0, clear_mask, 0, 0}));
+  ASSERT_TRUE(
+      CreateQueues(config_builder_.Build(), UsagePolicy{0, clear_mask, 0, 0}));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   auto status = producer_queue_->AllocateBuffer(
@@ -517,10 +559,11 @@
 
   LocalHandle fence;
   size_t slot;
-  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+  DvrNativeBufferMetadata mo;
+  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
-  ASSERT_EQ(0u, p1->usage() & clear_mask);
+  ASSERT_EQ(p1->usage() & clear_mask, 0U);
 }
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
@@ -598,16 +641,15 @@
   EXPECT_EQ(producer_queue_->capacity(), num_buffers);
 
   size_t slot;
-  uint64_t seq;
   LocalHandle fence;
   pdx::Status<void> status;
   pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
   pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
   std::shared_ptr<BufferConsumer> consumer_buffer;
   std::shared_ptr<BufferProducer> producer_buffer;
+  DvrNativeBufferMetadata mi, mo;
 
-  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
-                           UsagePolicy{}));
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Free all buffers when buffers are avaible for dequeue.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
@@ -616,7 +658,7 @@
 
   // Free all buffers when one buffer is dequeued.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
-  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_TRUE(producer_status.ok());
   status = producer_queue_->FreeAllBuffers();
   EXPECT_TRUE(status.ok());
@@ -624,7 +666,7 @@
   // Free all buffers when all buffers are dequeued.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
   for (size_t i = 0; i < kBufferCount; i++) {
-    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(producer_status.ok());
   }
   status = producer_queue_->FreeAllBuffers();
@@ -632,22 +674,22 @@
 
   // Free all buffers when one buffer is posted.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
-  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
   ASSERT_TRUE(producer_status.ok());
   producer_buffer = producer_status.take();
   ASSERT_NE(nullptr, producer_buffer);
-  ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+  ASSERT_EQ(0, producer_buffer->PostAsync(&mi, fence));
   status = producer_queue_->FreeAllBuffers();
   EXPECT_TRUE(status.ok());
 
   // Free all buffers when all buffers are posted.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
   for (size_t i = 0; i < kBufferCount; i++) {
-    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(producer_status.ok());
     producer_buffer = producer_status.take();
-    ASSERT_NE(nullptr, producer_buffer);
-    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+    ASSERT_NE(producer_buffer, nullptr);
+    ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
   }
   status = producer_queue_->FreeAllBuffers();
   EXPECT_TRUE(status.ok());
@@ -655,12 +697,12 @@
   // Free all buffers when all buffers are acquired.
   CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
   for (size_t i = 0; i < kBufferCount; i++) {
-    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(producer_status.ok());
     producer_buffer = producer_status.take();
-    ASSERT_NE(nullptr, producer_buffer);
-    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
-    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+    ASSERT_NE(producer_buffer, nullptr);
+    ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
+    consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
     ASSERT_TRUE(consumer_status.ok());
   }
 
@@ -680,6 +722,156 @@
 #undef CHECK_NO_BUFFER_THEN_ALLOCATE
 }
 
+TEST_F(BufferHubQueueTest, TestProducerToParcelableNotEmpty) {
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+                           UsagePolicy{}));
+
+  // Allocate only one buffer.
+  AllocateBuffer();
+
+  // Export should fail as the queue is not empty.
+  auto status = producer_queue_->TakeAsParcelable();
+  EXPECT_FALSE(status.ok());
+}
+
+TEST_F(BufferHubQueueTest, TestProducerExportToParcelable) {
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+
+  auto s1 = producer_queue_->TakeAsParcelable();
+  EXPECT_TRUE(s1.ok());
+
+  ProducerQueueParcelable output_parcelable = s1.take();
+  EXPECT_TRUE(output_parcelable.IsValid());
+
+  Parcel parcel;
+  status_t res;
+  res = output_parcelable.writeToParcel(&parcel);
+  EXPECT_EQ(res, NO_ERROR);
+
+  // After written into parcelable, the output_parcelable is still valid has
+  // keeps the producer channel alive.
+  EXPECT_TRUE(output_parcelable.IsValid());
+
+  // Creating producer buffer should fail.
+  auto s2 = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferLayerCount, kBufferFormat,
+                                            kBufferUsage);
+  ASSERT_FALSE(s2.ok());
+
+  // Reset the data position so that we can read back from the same parcel
+  // without doing actually Binder IPC.
+  parcel.setDataPosition(0);
+  producer_queue_ = nullptr;
+
+  // Recreate the producer queue from the parcel.
+  ProducerQueueParcelable input_parcelable;
+  EXPECT_FALSE(input_parcelable.IsValid());
+
+  res = input_parcelable.readFromParcel(&parcel);
+  EXPECT_EQ(res, NO_ERROR);
+  EXPECT_TRUE(input_parcelable.IsValid());
+
+  EXPECT_EQ(producer_queue_, nullptr);
+  producer_queue_ = ProducerQueue::Import(input_parcelable.TakeChannelHandle());
+  EXPECT_FALSE(input_parcelable.IsValid());
+  ASSERT_NE(producer_queue_, nullptr);
+
+  // Newly created queue from the parcel can allocate buffer, post buffer to
+  // consumer.
+  EXPECT_NO_FATAL_FAILURE(AllocateBuffer());
+  EXPECT_EQ(producer_queue_->count(), 1U);
+  EXPECT_EQ(producer_queue_->capacity(), 1U);
+
+  size_t slot;
+  DvrNativeBufferMetadata producer_meta;
+  DvrNativeBufferMetadata consumer_meta;
+  LocalHandle fence;
+  auto s3 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
+  EXPECT_TRUE(s3.ok());
+
+  std::shared_ptr<BufferProducer> p1 = s3.take();
+  ASSERT_NE(p1, nullptr);
+
+  producer_meta.timestamp = 42;
+  EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);
+
+  // Make sure the buffer can be dequeued from consumer side.
+  auto s4 = consumer_queue_->Dequeue(kTimeoutMs, &slot, &consumer_meta, &fence);
+  EXPECT_TRUE(s4.ok());
+  EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+  auto consumer = s4.take();
+  ASSERT_NE(consumer, nullptr);
+  EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
+}
+
+TEST_F(BufferHubQueueTest, TestCreateConsumerParcelable) {
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+
+  auto s1 = producer_queue_->CreateConsumerQueueParcelable();
+  EXPECT_TRUE(s1.ok());
+  ConsumerQueueParcelable output_parcelable = s1.take();
+  EXPECT_TRUE(output_parcelable.IsValid());
+
+  // Write to a Parcel new object.
+  Parcel parcel;
+  status_t res;
+  res = output_parcelable.writeToParcel(&parcel);
+
+  // Reset the data position so that we can read back from the same parcel
+  // without doing actually Binder IPC.
+  parcel.setDataPosition(0);
+
+  // No consumer queue created yet.
+  EXPECT_EQ(consumer_queue_, nullptr);
+
+  // If the parcel contains a consumer queue, read into a
+  // ProducerQueueParcelable should fail.
+  ProducerQueueParcelable wrongly_typed_parcelable;
+  EXPECT_FALSE(wrongly_typed_parcelable.IsValid());
+  res = wrongly_typed_parcelable.readFromParcel(&parcel);
+  EXPECT_EQ(res, -EINVAL);
+  parcel.setDataPosition(0);
+
+  // Create the consumer queue from the parcel.
+  ConsumerQueueParcelable input_parcelable;
+  EXPECT_FALSE(input_parcelable.IsValid());
+
+  res = input_parcelable.readFromParcel(&parcel);
+  EXPECT_EQ(res, NO_ERROR);
+  EXPECT_TRUE(input_parcelable.IsValid());
+
+  consumer_queue_ = ConsumerQueue::Import(input_parcelable.TakeChannelHandle());
+  EXPECT_FALSE(input_parcelable.IsValid());
+  ASSERT_NE(consumer_queue_, nullptr);
+
+  EXPECT_NO_FATAL_FAILURE(AllocateBuffer());
+  EXPECT_EQ(producer_queue_->count(), 1U);
+  EXPECT_EQ(producer_queue_->capacity(), 1U);
+
+  size_t slot;
+  DvrNativeBufferMetadata producer_meta;
+  DvrNativeBufferMetadata consumer_meta;
+  LocalHandle fence;
+  auto s2 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
+  EXPECT_TRUE(s2.ok());
+
+  std::shared_ptr<BufferProducer> p1 = s2.take();
+  ASSERT_NE(p1, nullptr);
+
+  producer_meta.timestamp = 42;
+  EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);
+
+  // Make sure the buffer can be dequeued from consumer side.
+  auto s3 = consumer_queue_->Dequeue(kTimeoutMs, &slot, &consumer_meta, &fence);
+  EXPECT_TRUE(s3.ok());
+  EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+  auto consumer = s3.take();
+  ASSERT_NE(consumer, nullptr);
+  EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 28cd63a..96f5404 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -3,12 +3,15 @@
 #include <base/logging.h>
 #include <gui/IProducerListener.h>
 #include <gui/Surface.h>
+#include <pdx/default_transport/channel_parcelable.h>
 
 #include <gtest/gtest.h>
 
 namespace android {
 namespace dvr {
 
+using pdx::LocalHandle;
+
 namespace {
 
 // Default dimensions before setDefaultBufferSize is called by the consumer.
@@ -92,7 +95,13 @@
     ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
              testInfo->name());
 
-    mProducer = BufferHubQueueProducer::Create();
+    auto config = ProducerQueueConfigBuilder()
+                      .SetMetadata<DvrNativeBufferMetadata>()
+                      .Build();
+    auto queue = ProducerQueue::Create(config, UsagePolicy{});
+    ASSERT_TRUE(queue != nullptr);
+
+    mProducer = BufferHubQueueProducer::Create(std::move(queue));
     ASSERT_TRUE(mProducer != nullptr);
     mSurface = new Surface(mProducer, true);
     ASSERT_TRUE(mSurface != nullptr);
@@ -546,6 +555,55 @@
   EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
 }
 
+TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
+  // Connected producer cannot be taken out as a parcelable.
+  EXPECT_NO_FATAL_FAILURE(ConnectProducer());
+  ProducerQueueParcelable producer_parcelable;
+  EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
+
+  // Create a valid dummy producer parcelable.
+  auto dummy_channel_parcelable =
+      std::make_unique<pdx::default_transport::ChannelParcelable>(
+          LocalHandle(0), LocalHandle(0), LocalHandle(0));
+  EXPECT_TRUE(dummy_channel_parcelable->IsValid());
+  ProducerQueueParcelable dummy_producer_parcelable(
+      std::move(dummy_channel_parcelable));
+  EXPECT_TRUE(dummy_producer_parcelable.IsValid());
+
+  // Disconnect producer can be taken out, but only to an invalid parcelable.
+  ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
+  EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
+  EXPECT_FALSE(producer_parcelable.IsValid());
+  EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
+  EXPECT_TRUE(producer_parcelable.IsValid());
+
+  // Should still be able to query buffer dimension after disconnect.
+  int32_t value = -1;
+  EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
+  EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
+
+  EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
+  EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
+
+  EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
+  EXPECT_EQ(value, kDefaultFormat);
+
+  // But connect to API will fail.
+  IGraphicBufferProducer::QueueBufferOutput output;
+  EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
+                               &output),
+            BAD_VALUE);
+
+  // Create a new producer from the parcelable and connect to kTestApi should
+  // succeed.
+  sp<BufferHubQueueProducer> new_producer =
+      BufferHubQueueProducer::Create(std::move(producer_parcelable));
+  ASSERT_TRUE(new_producer != nullptr);
+  EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
+                                  kTestControlledByApp, &output),
+            NO_ERROR);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
new file mode 100644
index 0000000..658b496
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
@@ -0,0 +1,539 @@
+#include <android/native_window.h>
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <dvr/dvr_api.h>
+#include <dvr/performance_client_api.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+#include <private/dvr/buffer_hub_queue_producer.h>
+#include <utils/Trace.h>
+
+#include <chrono>
+#include <functional>
+#include <iostream>
+#include <thread>
+#include <vector>
+
+#include <poll.h>
+#include <sys/wait.h>
+
+// Use ALWAYS at the tag level. Control is performed manually during command
+// line processing.
+#ifdef ATRACE_TAG
+#undef ATRACE_TAG
+#endif
+#define ATRACE_TAG ATRACE_TAG_ALWAYS
+
+using namespace android;
+using namespace android::dvr;
+using ::benchmark::State;
+
+static const String16 kBinderService = String16("bufferTransport");
+static const uint32_t kBufferWidth = 100;
+static const uint32_t kBufferHeight = 1;
+static const uint32_t kBufferLayerCount = 1;
+static const uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+static const uint64_t kBufferUsage =
+    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+static const int kMaxAcquiredImages = 1;
+static const int kQueueDepth = 2;  // We are double buffering for this test.
+static const size_t kMaxQueueCounts = 128;
+
+enum BufferTransportServiceCode {
+  CREATE_BUFFER_QUEUE = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+// A binder services that minics a compositor that consumes buffers. It provides
+// one Binder interface to create a new Surface for buffer producer to write
+// into; while itself will carry out no-op buffer consuming by acquiring then
+// releasing the buffer immediately.
+class BufferTransportService : public BBinder {
+ public:
+  BufferTransportService() = default;
+  ~BufferTransportService() = default;
+
+  virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                              uint32_t flags = 0) {
+    (void)flags;
+    (void)data;
+    switch (code) {
+      case CREATE_BUFFER_QUEUE: {
+        auto new_queue = std::make_shared<BufferQueueHolder>(this);
+        reply->writeStrongBinder(
+            IGraphicBufferProducer::asBinder(new_queue->producer_));
+        buffer_queues_.push_back(new_queue);
+        return NO_ERROR;
+      }
+      default:
+        return UNKNOWN_TRANSACTION;
+    };
+  }
+
+ private:
+  struct FrameListener : public ConsumerBase::FrameAvailableListener {
+   public:
+    FrameListener(BufferTransportService* service,
+                  sp<BufferItemConsumer> buffer_item_consumer)
+        : service_(service),
+          buffer_item_consumer_(buffer_item_consumer) {}
+
+    void onFrameAvailable(const BufferItem& /*item*/) override {
+      BufferItem buffer;
+      status_t ret = 0;
+      {
+        ATRACE_NAME("AcquireBuffer");
+        ret = buffer_item_consumer_->acquireBuffer(&buffer, /*presentWhen=*/0,
+                                                   /*waitForFence=*/false);
+      }
+
+      if (ret != NO_ERROR) {
+        LOG(ERROR) << "Failed to acquire next buffer.";
+        return;
+      }
+
+      {
+        ATRACE_NAME("ReleaseBuffer");
+        ret = buffer_item_consumer_->releaseBuffer(buffer);
+      }
+
+      if (ret != NO_ERROR) {
+        LOG(ERROR) << "Failed to release buffer.";
+        return;
+      }
+    }
+
+   private:
+    BufferTransportService* service_ = nullptr;
+    sp<BufferItemConsumer> buffer_item_consumer_;
+  };
+
+  struct BufferQueueHolder {
+    explicit BufferQueueHolder(BufferTransportService* service) {
+      BufferQueue::createBufferQueue(&producer_, &consumer_);
+
+      sp<BufferItemConsumer> buffer_item_consumer =
+          new BufferItemConsumer(consumer_, kBufferUsage, kMaxAcquiredImages,
+                                 /*controlledByApp=*/true);
+      buffer_item_consumer->setName(String8("BinderBufferTransport"));
+      frame_listener_ = new FrameListener(service, buffer_item_consumer);
+      buffer_item_consumer->setFrameAvailableListener(frame_listener_);
+    }
+
+    sp<IGraphicBufferProducer> producer_;
+    sp<IGraphicBufferConsumer> consumer_;
+    sp<FrameListener> frame_listener_;
+  };
+
+  std::vector<std::shared_ptr<BufferQueueHolder>> buffer_queues_;
+};
+
+// A virtual interfaces that abstracts the common BufferQueue operations, so
+// that the test suite can use the same test case to drive different types of
+// transport backends.
+class BufferTransport {
+ public:
+  virtual ~BufferTransport() {}
+
+  virtual int Start() = 0;
+  virtual sp<Surface> CreateSurface() = 0;
+};
+
+// Binder-based buffer transport backend.
+//
+// On Start() a new process will be swapned to run a Binder server that
+// actually consumes the buffer.
+// On CreateSurface() a new Binder BufferQueue will be created, which the
+// service holds the concrete binder node of the IGraphicBufferProducer while
+// sending the binder proxy to the client. In another word, the producer side
+// operations are carried out process while the consumer side operations are
+// carried out within the BufferTransportService's own process.
+class BinderBufferTransport : public BufferTransport {
+ public:
+  BinderBufferTransport() {}
+
+  int Start() override {
+    sp<IServiceManager> sm = defaultServiceManager();
+    service_ = sm->getService(kBinderService);
+    if (service_ == nullptr) {
+      LOG(ERROR) << "Failed to get the benchmark service.";
+      return -EIO;
+    }
+
+    LOG(INFO) << "Binder server is ready for client.";
+    return 0;
+  }
+
+  sp<Surface> CreateSurface() override {
+    Parcel data;
+    Parcel reply;
+    int error = service_->transact(CREATE_BUFFER_QUEUE, data, &reply);
+    if (error != NO_ERROR) {
+      LOG(ERROR) << "Failed to get buffer queue over binder.";
+      return nullptr;
+    }
+
+    sp<IBinder> binder;
+    error = reply.readNullableStrongBinder(&binder);
+    if (error != NO_ERROR) {
+      LOG(ERROR) << "Failed to get IGraphicBufferProducer over binder.";
+      return nullptr;
+    }
+
+    auto producer = interface_cast<IGraphicBufferProducer>(binder);
+    if (producer == nullptr) {
+      LOG(ERROR) << "Failed to get IGraphicBufferProducer over binder.";
+      return nullptr;
+    }
+
+    sp<Surface> surface = new Surface(producer, /*controlledByApp=*/true);
+
+    // Set buffer dimension.
+    ANativeWindow* window = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow_setBuffersGeometry(window, kBufferWidth, kBufferHeight,
+                                     kBufferFormat);
+
+    return surface;
+  }
+
+ private:
+  sp<IBinder> service_;
+};
+
+// BufferHub/PDX-based buffer transport.
+//
+// On Start() a new thread will be swapned to run an epoll polling thread which
+// minics the behavior of a compositor. Similar to Binder-based backend, the
+// buffer available handler is also a no-op: Buffer gets acquired and released
+// immediately.
+// On CreateSurface() a pair of dvr::ProducerQueue and dvr::ConsumerQueue will
+// be created. The epoll thread holds on the consumer queue and dequeues buffer
+// from it; while the producer queue will be wrapped in a Surface and returned
+// to test suite.
+class BufferHubTransport : public BufferTransport {
+ public:
+  virtual ~BufferHubTransport() {
+    stopped_.store(true);
+    if (reader_thread_.joinable()) {
+      reader_thread_.join();
+    }
+  }
+
+  int Start() override {
+    int ret = epoll_fd_.Create();
+    if (ret < 0) {
+      LOG(ERROR) << "Failed to create epoll fd: %s", strerror(-ret);
+      return -1;
+    }
+
+    // Create the reader thread.
+    reader_thread_ = std::thread([this]() {
+      int ret = dvrSetSchedulerClass(0, "graphics");
+      if (ret < 0) {
+        LOG(ERROR) << "Failed to set thread priority";
+        return;
+      }
+
+
+      ret = dvrSetCpuPartition(0, "/system/performance");
+      if (ret < 0) {
+        LOG(ERROR) << "Failed to set thread cpu partition";
+        return;
+      }
+
+      stopped_.store(false);
+      LOG(INFO) << "Reader Thread Running...";
+
+      while (!stopped_.load()) {
+        std::array<epoll_event, kMaxQueueCounts> events;
+
+        // Don't sleep forever so that we will have a chance to wake up.
+        const int ret = epoll_fd_.Wait(events.data(), events.size(),
+                                       /*timeout=*/100);
+        if (ret < 0) {
+          LOG(ERROR) << "Error polling consumer queues.";
+          continue;
+        }
+        if (ret == 0) {
+          continue;
+        }
+
+        const int num_events = ret;
+        for (int i = 0; i < num_events; i++) {
+          uint32_t surface_index = events[i].data.u32;
+          buffer_queues_[surface_index]->consumer_queue_->HandleQueueEvents();
+        }
+      }
+
+      LOG(INFO) << "Reader Thread Exiting...";
+    });
+
+    return 0;
+  }
+
+  sp<Surface> CreateSurface() override {
+    auto new_queue = std::make_shared<BufferQueueHolder>();
+    if (new_queue->producer_ == nullptr) {
+      LOG(ERROR) << "Failed to create buffer producer.";
+      return nullptr;
+    }
+
+    sp<Surface> surface =
+        new Surface(new_queue->producer_, /*controlledByApp=*/true);
+
+    // Set buffer dimension.
+    ANativeWindow* window = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow_setBuffersGeometry(window, kBufferWidth, kBufferHeight,
+                                     kBufferFormat);
+
+    // Use the next position as buffer_queue index.
+    uint32_t index = buffer_queues_.size();
+    epoll_event event = {.events = EPOLLIN | EPOLLET, .data = {.u32 = index}};
+    const int ret = epoll_fd_.Control(
+        EPOLL_CTL_ADD, new_queue->consumer_queue_->queue_fd(), &event);
+    if (ret < 0) {
+      LOG(ERROR) << "Failed to track consumer queue: " << strerror(-ret)
+                 << ", consumer queue fd: "
+                 << new_queue->consumer_queue_->queue_fd();
+      return nullptr;
+    }
+
+    new_queue->queue_index_ = index;
+    buffer_queues_.push_back(new_queue);
+    return surface;
+  }
+
+ private:
+  struct BufferQueueHolder {
+    BufferQueueHolder() {
+      ProducerQueueConfigBuilder config_builder;
+      producer_queue_ =
+          ProducerQueue::Create(config_builder.SetDefaultWidth(kBufferWidth)
+                                    .SetDefaultHeight(kBufferHeight)
+                                    .SetDefaultFormat(kBufferFormat)
+                                    .SetMetadata<DvrNativeBufferMetadata>()
+                                    .Build(),
+                                UsagePolicy{});
+      consumer_queue_ = producer_queue_->CreateConsumerQueue();
+      consumer_queue_->SetBufferAvailableCallback([this]() {
+        size_t index = 0;
+        pdx::LocalHandle fence;
+        DvrNativeBufferMetadata meta;
+        pdx::Status<std::shared_ptr<BufferConsumer>> status;
+
+        {
+          ATRACE_NAME("AcquireBuffer");
+          status = consumer_queue_->Dequeue(0, &index, &meta, &fence);
+        }
+        if (!status.ok()) {
+          LOG(ERROR) << "Failed to dequeue consumer buffer, error: "
+                     << status.GetErrorMessage().c_str();
+          return;
+        }
+
+        auto buffer = status.take();
+
+        if (buffer) {
+          ATRACE_NAME("ReleaseBuffer");
+          buffer->ReleaseAsync();
+        }
+      });
+
+      producer_ = BufferHubQueueProducer::Create(producer_queue_);
+    }
+
+    int count_ = 0;
+    int queue_index_;
+    std::shared_ptr<ProducerQueue> producer_queue_;
+    std::shared_ptr<ConsumerQueue> consumer_queue_;
+    sp<IGraphicBufferProducer> producer_;
+  };
+
+  std::atomic<bool> stopped_;
+  std::thread reader_thread_;
+
+  EpollFileDescriptor epoll_fd_;
+  std::vector<std::shared_ptr<BufferQueueHolder>> buffer_queues_;
+};
+
+enum TransportType {
+  kBinderBufferTransport,
+  kBufferHubTransport,
+};
+
+// Main test suite, which supports two transport backend: 1) BinderBufferQueue,
+// 2) BufferHubQueue. The test case drives the producer end of both transport
+// backend by queuing buffers into the buffer queue by using ANativeWindow API.
+class BufferTransportBenchmark : public ::benchmark::Fixture {
+ public:
+  void SetUp(State& state) override {
+    if (state.thread_index == 0) {
+      const int transport = state.range(0);
+      switch (transport) {
+        case kBinderBufferTransport:
+          transport_.reset(new BinderBufferTransport);
+          break;
+        case kBufferHubTransport:
+          transport_.reset(new BufferHubTransport);
+          break;
+        default:
+          CHECK(false) << "Unknown test case.";
+          break;
+      }
+
+      CHECK(transport_);
+      const int ret = transport_->Start();
+      CHECK_EQ(ret, 0);
+
+      LOG(INFO) << "Transport backend running, transport=" << transport << ".";
+
+      // Create surfaces for each thread.
+      surfaces_.resize(state.threads);
+      for (int i = 0; i < state.threads; i++) {
+        // Common setup every thread needs.
+        surfaces_[i] = transport_->CreateSurface();
+        CHECK(surfaces_[i]);
+
+        LOG(INFO) << "Surface initialized on thread " << i << ".";
+      }
+    }
+  }
+
+  void TearDown(State& state) override {
+    if (state.thread_index == 0) {
+      surfaces_.clear();
+      transport_.reset();
+      LOG(INFO) << "Tear down benchmark.";
+    }
+  }
+
+ protected:
+  std::unique_ptr<BufferTransport> transport_;
+  std::vector<sp<Surface>> surfaces_;
+};
+
+BENCHMARK_DEFINE_F(BufferTransportBenchmark, Producers)(State& state) {
+  ANativeWindow* window = nullptr;
+  ANativeWindow_Buffer buffer;
+  int32_t error = 0;
+  double total_gain_buffer_us = 0;
+  double total_post_buffer_us = 0;
+  int iterations = 0;
+
+  while (state.KeepRunning()) {
+    if (window == nullptr) {
+      CHECK(surfaces_[state.thread_index]);
+      window = static_cast<ANativeWindow*>(surfaces_[state.thread_index].get());
+
+      // Lock buffers a couple time from the queue, so that we have the buffer
+      // allocated.
+      for (int i = 0; i < kQueueDepth; i++) {
+        error = ANativeWindow_lock(window, &buffer,
+                                   /*inOutDirtyBounds=*/nullptr);
+        CHECK_EQ(error, 0);
+        error = ANativeWindow_unlockAndPost(window);
+        CHECK_EQ(error, 0);
+      }
+    }
+
+    {
+      ATRACE_NAME("GainBuffer");
+      auto t1 = std::chrono::high_resolution_clock::now();
+      error = ANativeWindow_lock(window, &buffer,
+                                 /*inOutDirtyBounds=*/nullptr);
+      auto t2 = std::chrono::high_resolution_clock::now();
+      std::chrono::duration<double, std::micro> delta_us = t2 - t1;
+      total_gain_buffer_us += delta_us.count();
+    }
+    CHECK_EQ(error, 0);
+
+    {
+      ATRACE_NAME("PostBuffer");
+      auto t1 = std::chrono::high_resolution_clock::now();
+      error = ANativeWindow_unlockAndPost(window);
+      auto t2 = std::chrono::high_resolution_clock::now();
+      std::chrono::duration<double, std::micro> delta_us = t2 - t1;
+      total_post_buffer_us += delta_us.count();
+    }
+    CHECK_EQ(error, 0);
+
+    iterations++;
+  }
+
+  state.counters["gain_buffer_us"] = ::benchmark::Counter(
+      total_gain_buffer_us / iterations, ::benchmark::Counter::kAvgThreads);
+  state.counters["post_buffer_us"] = ::benchmark::Counter(
+      total_post_buffer_us / iterations, ::benchmark::Counter::kAvgThreads);
+  state.counters["producer_us"] = ::benchmark::Counter(
+      (total_gain_buffer_us + total_post_buffer_us) / iterations,
+      ::benchmark::Counter::kAvgThreads);
+}
+
+BENCHMARK_REGISTER_F(BufferTransportBenchmark, Producers)
+    ->Unit(::benchmark::kMicrosecond)
+    ->Ranges({{kBinderBufferTransport, kBufferHubTransport}})
+    ->ThreadRange(1, 32);
+
+static void runBinderServer() {
+  ProcessState::self()->setThreadPoolMaxThreadCount(0);
+  ProcessState::self()->startThreadPool();
+
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<BufferTransportService> service = new BufferTransportService;
+  sm->addService(kBinderService, service, false);
+
+  LOG(INFO) << "Binder server running...";
+
+  while (true) {
+    int stat, retval;
+    retval = wait(&stat);
+    if (retval == -1 && errno == ECHILD) {
+      break;
+    }
+  }
+
+  LOG(INFO) << "Service Exiting...";
+}
+
+// To run binder-based benchmark, use:
+// adb shell buffer_transport_benchmark \
+//   --benchmark_filter="BufferTransportBenchmark/ContinuousLoad/0/"
+//
+// To run bufferhub-based benchmark, use:
+// adb shell buffer_transport_benchmark \
+//   --benchmark_filter="BufferTransportBenchmark/ContinuousLoad/1/"
+int main(int argc, char** argv) {
+  bool tracing_enabled = false;
+
+  // Parse arguments in addition to "--benchmark_filter" paramters.
+  for (int i = 1; i < argc; i++) {
+    if (std::string(argv[i]) == "--help") {
+      std::cout << "Usage: binderThroughputTest [OPTIONS]" << std::endl;
+      std::cout << "\t--trace: Enable systrace logging."
+                << std::endl;
+      return 0;
+    }
+    if (std::string(argv[i]) == "--trace") {
+      tracing_enabled = true;
+      continue;
+    }
+  }
+
+  // Setup ATRACE/systrace based on command line.
+  atrace_setup();
+  atrace_set_tracing_enabled(tracing_enabled);
+
+  pid_t pid = fork();
+  if (pid == 0) {
+    // parent, i.e. the client side.
+    ProcessState::self()->startThreadPool();
+
+    ::benchmark::Initialize(&argc, argv);
+    ::benchmark::RunSpecifiedBenchmarks();
+  } else {
+    LOG(INFO) << "Benchmark process pid: " << pid;
+    runBinderServer();
+  }
+}
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 8213ca2..69dbc84 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -26,6 +26,7 @@
 
 sharedLibraries = [
     "libbase",
+    "libbinder",
     "libcutils",
     "liblog",
     "libutils",
diff --git a/libs/vr/libpdx/private/pdx/channel_parcelable.h b/libs/vr/libpdx/private/pdx/channel_parcelable.h
new file mode 100644
index 0000000..59ef9d3
--- /dev/null
+++ b/libs/vr/libpdx/private/pdx/channel_parcelable.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_PDX_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_CHANNEL_PARCELABLE_H_
+
+#include <binder/Parcelable.h>
+#include <pdx/channel_handle.h>
+
+namespace android {
+namespace pdx {
+
+/**
+ * A parcelable object holds all necessary objects to recreate a ClientChannel.
+ * In addition to the android::Parcelable interface, this interface exposees
+ * more PDX-related interface.
+ */
+class ChannelParcelable : public Parcelable {
+ public:
+  virtual ~ChannelParcelable() = default;
+
+  // Returns whether the parcelable object holds a valid client channel.
+  virtual bool IsValid() const = 0;
+
+  // Returns a channel handle constructed from this parcelable object and takes
+  // the ownership of all resources from the parcelable object. In another word,
+  // the parcelable object will become invalid after TakeChannelHandle returns.
+  virtual LocalChannelHandle TakeChannelHandle() = 0;
+};
+
+}  // namespace pdx
+}  // namespace android
+
+#endif  // ANDROID_PDX_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx/private/pdx/client_channel.h b/libs/vr/libpdx/private/pdx/client_channel.h
index 10a49bb..8f5fdfe 100644
--- a/libs/vr/libpdx/private/pdx/client_channel.h
+++ b/libs/vr/libpdx/private/pdx/client_channel.h
@@ -4,6 +4,7 @@
 #include <vector>
 
 #include <pdx/channel_handle.h>
+#include <pdx/channel_parcelable.h>
 #include <pdx/file_handle.h>
 #include <pdx/status.h>
 
@@ -61,6 +62,11 @@
                              LocalHandle* handle) const = 0;
   virtual bool GetChannelHandle(void* transaction_state, ChannelReference ref,
                                 LocalChannelHandle* handle) const = 0;
+
+  // Returns the internal state of the channel as a parcelable object. The
+  // ClientChannel is invalidated however, the channel is kept alive by the
+  // parcelable object and may be transferred to another process.
+  virtual std::unique_ptr<ChannelParcelable> TakeChannelParcelable() = 0;
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel.h b/libs/vr/libpdx/private/pdx/mock_client_channel.h
index 49e0682..ecc20b3 100644
--- a/libs/vr/libpdx/private/pdx/mock_client_channel.h
+++ b/libs/vr/libpdx/private/pdx/mock_client_channel.h
@@ -49,6 +49,7 @@
   MOCK_CONST_METHOD3(GetChannelHandle,
                      bool(void* transaction_state, ChannelReference ref,
                           LocalChannelHandle* handle));
+  MOCK_METHOD0(TakeChannelParcelable, std::unique_ptr<ChannelParcelable>());
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index f891c59..cda3c95 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -42,6 +42,7 @@
         "pdx_tool.cpp",
     ],
     shared_libs: [
+        "libbinder",
         "libcutils",
         "liblog",
     ],
@@ -59,6 +60,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libchrome",
         "libcutils",
         "liblog",
diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h
new file mode 100644
index 0000000..a8623b2
--- /dev/null
+++ b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h
@@ -0,0 +1,17 @@
+#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
+
+#include <servicefs/channel_parcelable.h>
+
+namespace android {
+namespace pdx {
+namespace default_transport {
+
+using ChannelParcelable = ::android::pdx::servicefs::ChannelParcelable;
+
+}  // namespace default_transport
+}  // namespace pdx
+}  // namespace android
+
+
+#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h
new file mode 100644
index 0000000..bcd74e6
--- /dev/null
+++ b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h
@@ -0,0 +1,17 @@
+#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
+
+#include <uds/channel_parcelable.h>
+
+namespace android {
+namespace pdx {
+namespace default_transport {
+
+using ChannelParcelable = ::android::pdx::uds::ChannelParcelable;
+
+}  // namespace default_transport
+}  // namespace pdx
+}  // namespace android
+
+
+#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index d0b7cab..d640950 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -13,6 +13,7 @@
     srcs: [
         "channel_event_set.cpp",
         "channel_manager.cpp",
+        "channel_parcelable.cpp",
         "client_channel_factory.cpp",
         "client_channel.cpp",
         "ipc_helper.cpp",
@@ -23,6 +24,9 @@
         "libbase",
         "libpdx",
     ],
+    shared_libs: [
+        "libbinder",
+    ],
     whole_static_libs: [
         "libselinux",
     ],
@@ -52,5 +56,6 @@
         "libcutils",
         "liblog",
         "libutils",
+        "libbinder",
     ],
 }
diff --git a/libs/vr/libpdx_uds/channel_parcelable.cpp b/libs/vr/libpdx_uds/channel_parcelable.cpp
new file mode 100644
index 0000000..e7bce27
--- /dev/null
+++ b/libs/vr/libpdx_uds/channel_parcelable.cpp
@@ -0,0 +1,125 @@
+#include "uds/channel_parcelable.h"
+
+#include <binder/Parcel.h>
+#include <uds/channel_manager.h>
+
+namespace android {
+namespace pdx {
+namespace uds {
+
+namespace {
+
+static constexpr uint32_t kUdsMagicParcelHeader = 0x7564736d;  // 'udsm'.
+
+}  // namespace
+
+ChannelParcelable::ChannelParcelable(LocalHandle data_fd,
+                                     LocalHandle pollin_event_fd,
+                                     LocalHandle pollhup_event_fd)
+    : data_fd_{std::move(data_fd)},
+      pollin_event_fd_{std::move(pollin_event_fd)},
+      pollhup_event_fd_{std::move(pollhup_event_fd)} {}
+
+bool ChannelParcelable::IsValid() const {
+  return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_;
+}
+
+LocalChannelHandle ChannelParcelable::TakeChannelHandle() {
+  if (!IsValid()) {
+    ALOGE("ChannelParcelable::TakeChannelHandle: Invalid channel parcel.");
+    return {};  // Returns an empty channel handle.
+  }
+
+  return ChannelManager::Get().CreateHandle(std::move(data_fd_),
+                                            std::move(pollin_event_fd_),
+                                            std::move(pollhup_event_fd_));
+}
+
+status_t ChannelParcelable::writeToParcel(Parcel* parcel) const {
+  status_t res = NO_ERROR;
+
+  if (!IsValid()) {
+    ALOGE("ChannelParcelable::writeToParcel: Invalid channel parcel.");
+    return BAD_VALUE;
+  }
+
+  res = parcel->writeUint32(kUdsMagicParcelHeader);
+  if (res != NO_ERROR) {
+    ALOGE("ChannelParcelable::writeToParcel: Cannot write magic: res=%d.", res);
+    return res;
+  }
+
+  res = parcel->writeFileDescriptor(data_fd_.Get());
+  if (res != NO_ERROR) {
+    ALOGE("ChannelParcelable::writeToParcel: Cannot write data fd: res=%d.",
+          res);
+    return res;
+  }
+
+  res = parcel->writeFileDescriptor(pollin_event_fd_.Get());
+  if (res != NO_ERROR) {
+    ALOGE(
+        "ChannelParcelable::writeToParcel: Cannot write pollin event fd: "
+        "res=%d.",
+        res);
+    return res;
+  }
+
+  res = parcel->writeFileDescriptor(pollhup_event_fd_.Get());
+  if (res != NO_ERROR) {
+    ALOGE(
+        "ChannelParcelable::writeToParcel: Cannot write pollhup event fd: "
+        "res=%d.",
+        res);
+    return res;
+  }
+
+  return res;
+}
+
+status_t ChannelParcelable::readFromParcel(const Parcel* parcel) {
+  uint32_t magic = 0;
+  status_t res = NO_ERROR;
+
+  if (IsValid()) {
+    ALOGE(
+        "ChannelParcelable::readFromParcel: This channel parcel is already "
+        "initailzied.");
+    return ALREADY_EXISTS;
+  }
+
+  res = parcel->readUint32(&magic);
+  if (res != NO_ERROR) {
+    ALOGE("ChannelParcelable::readFromParcel: Failed to read magic: res=%d.",
+          res);
+    return res;
+  }
+
+  if (magic != kUdsMagicParcelHeader) {
+    ALOGE(
+        "ChannelParcelable::readFromParcel: Unknown magic: 0x%x, epxected: "
+        "0x%x",
+        magic, kUdsMagicParcelHeader);
+    return BAD_VALUE;
+  }
+
+  // TODO(b/69010509): We have to dup() the FD from android::Parcel as it
+  // doesn't support taking out the FD's ownership. We can remove the dup() here
+  // once android::Parcel support such operation.
+  data_fd_.Reset(dup(parcel->readFileDescriptor()));
+  pollin_event_fd_.Reset(dup(parcel->readFileDescriptor()));
+  pollhup_event_fd_.Reset(dup(parcel->readFileDescriptor()));
+  if (!IsValid()) {
+    ALOGE(
+        "ChannelParcelable::readFromParcel: Cannot read fd from parcel: "
+        "data_fd=%d, pollin_event_fd=%d, pollhup_event_fd=%d.",
+        data_fd_.Get(), pollin_event_fd_.Get(), pollhup_event_fd_.Get());
+    return DEAD_OBJECT;
+  }
+
+  return res;
+}
+
+}  // namespace uds
+}  // namespace pdx
+}  // namespace android
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 2e9c1de..6073c3c 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -1,3 +1,4 @@
+#include "uds/channel_parcelable.h"
 #include "uds/client_channel.h"
 
 #include <errno.h>
@@ -292,6 +293,29 @@
   return state->GetLocalChannelHandle(ref, handle);
 }
 
+std::unique_ptr<pdx::ChannelParcelable> ClientChannel::TakeChannelParcelable()
+    {
+  if (!channel_handle_)
+    return nullptr;
+
+  if (auto* channel_data =
+          ChannelManager::Get().GetChannelData(channel_handle_.value())) {
+    auto fds = channel_data->TakeFds();
+    auto parcelable = std::make_unique<ChannelParcelable>(
+        std::move(std::get<0>(fds)), std::move(std::get<1>(fds)),
+        std::move(std::get<2>(fds)));
+
+    // Here we need to explicitly close the channel handle so that the channel
+    // won't get shutdown in the destructor, while the FDs in ChannelParcelable
+    // can keep the channel alive so that new client can be created from it
+    // later.
+    channel_handle_.Close();
+    return parcelable;
+  } else {
+    return nullptr;
+  }
+}
+
 }  // namespace uds
 }  // namespace pdx
 }  // namespace android
diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
index 99e7502..e960740 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
@@ -54,6 +54,14 @@
   BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
   BorrowedHandle data_fd() const { return data_fd_.Borrow(); }
 
+  // Moves file descriptors out of ChannelEventReceiver. Note these operations
+  // immediately invalidates the receiver.
+  std::tuple<LocalHandle, LocalHandle, LocalHandle> TakeFds() {
+    epoll_fd_.Close();
+    return {std::move(data_fd_), std::move(pollin_event_fd_),
+            std::move(pollhup_event_fd_)};
+  }
+
   Status<int> GetPendingEvents() const;
   Status<int> PollPendingEvents(int timeout_ms) const;
 
diff --git a/libs/vr/libpdx_uds/private/uds/channel_parcelable.h b/libs/vr/libpdx_uds/private/uds/channel_parcelable.h
new file mode 100644
index 0000000..1c3fae9
--- /dev/null
+++ b/libs/vr/libpdx_uds/private/uds/channel_parcelable.h
@@ -0,0 +1,35 @@
+#ifndef ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
+
+#include <pdx/channel_parcelable.h>
+#include <pdx/file_handle.h>
+
+namespace android {
+namespace pdx {
+namespace uds {
+
+class ChannelParcelable : public pdx::ChannelParcelable {
+ public:
+  ChannelParcelable() = default;
+  ChannelParcelable(LocalHandle data_fd, LocalHandle pollin_event_fd,
+                    LocalHandle pollhup_event_fd);
+
+  // Implements pdx::ChannelParcelable interface.
+  bool IsValid() const override;
+  LocalChannelHandle TakeChannelHandle() override;
+
+  // Implements android::Parcelable interface.
+  status_t writeToParcel(Parcel* parcel) const override;
+  status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+  LocalHandle data_fd_;
+  LocalHandle pollin_event_fd_;
+  LocalHandle pollhup_event_fd_;
+};
+
+}  // namespace uds
+}  // namespace pdx
+}  // namespace android
+
+#endif  // ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h
index 7a5ddf4..b5524d8 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel.h
@@ -74,6 +74,8 @@
   bool GetChannelHandle(void* transaction_state, ChannelReference ref,
                         LocalChannelHandle* handle) const override;
 
+  std::unique_ptr<pdx::ChannelParcelable> TakeChannelParcelable() override;
+
  private:
   explicit ClientChannel(LocalChannelHandle channel_handle);
 
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
index 6a46876..7c32dbb 100644
--- a/libs/vr/libperformance/Android.bp
+++ b/libs/vr/libperformance/Android.bp
@@ -23,6 +23,7 @@
 
 sharedLibraries = [
     "libbase",
+    "libbinder",
     "libcutils",
     "liblog",
     "libutils",
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index ac68a5e..a18ff1a 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -38,10 +38,12 @@
 namespace dvr {
 
 DisplayService::DisplayService(Hwc2::Composer* hidl,
+                               hwc2_display_t primary_display_id,
                                RequestDisplayCallback request_display_callback)
     : BASE("DisplayService",
            Endpoint::Create(display::DisplayProtocol::kClientPath)) {
-  hardware_composer_.Initialize(hidl, request_display_callback);
+    hardware_composer_.Initialize(
+        hidl, primary_display_id, request_display_callback);
 }
 
 bool DisplayService::IsInitialized() const {
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 55e33ab..a3ee7bb 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -81,6 +81,7 @@
   using RequestDisplayCallback = std::function<void(bool)>;
 
   DisplayService(android::Hwc2::Composer* hidl,
+                 hwc2_display_t primary_display_id,
                  RequestDisplayCallback request_display_callback);
 
   pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer(
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index fb69d5c..be17ecf 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -121,7 +121,8 @@
 }
 
 bool HardwareComposer::Initialize(
-    Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
+    Hwc2::Composer* composer, hwc2_display_t primary_display_id,
+    RequestDisplayCallback request_display_callback) {
   if (initialized_) {
     ALOGE("HardwareComposer::Initialize: already initialized.");
     return false;
@@ -134,7 +135,7 @@
   HWC::Error error = HWC::Error::None;
 
   Hwc2::Config config;
-  error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+  error = composer->getActiveConfig(primary_display_id, &config);
 
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -142,7 +143,7 @@
     return false;
   }
 
-  error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
+  error = GetDisplayMetrics(composer, primary_display_id, config,
                             &native_display_metrics_);
 
   if (error != HWC::Error::None) {
@@ -233,7 +234,10 @@
     composer_.reset(new Hwc2::Composer("default"));
     composer_callback_ = new ComposerCallback;
     composer_->registerCallback(composer_callback_);
+    LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(),
+        "Registered composer callback but didn't get primary display");
     Layer::SetComposer(composer_.get());
+    Layer::SetDisplayId(composer_callback_->GetDisplayId());
   } else {
     SetPowerMode(true);
   }
@@ -263,6 +267,7 @@
     composer_callback_ = nullptr;
     composer_.reset(nullptr);
     Layer::SetComposer(nullptr);
+    Layer::SetDisplayId(0);
   } else {
     SetPowerMode(false);
   }
@@ -290,7 +295,7 @@
 
 HWC::Error HardwareComposer::EnableVsync(bool enabled) {
   return composer_->setVsyncEnabled(
-      HWC_DISPLAY_PRIMARY,
+      composer_callback_->GetDisplayId(),
       (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
                                              : HWC2_VSYNC_DISABLE));
 }
@@ -298,7 +303,8 @@
 HWC::Error HardwareComposer::SetPowerMode(bool active) {
   HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
   return composer_->setPowerMode(
-      HWC_DISPLAY_PRIMARY, power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+      composer_callback_->GetDisplayId(),
+      power_mode.cast<Hwc2::IComposerClient::PowerMode>());
 }
 
 HWC::Error HardwareComposer::Present(hwc2_display_t display) {
@@ -419,7 +425,7 @@
     layer.Prepare();
   }
 
-  HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
+  HWC::Error error = Validate(composer_callback_->GetDisplayId());
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
           error.to_string().c_str());
@@ -466,7 +472,7 @@
   }
 #endif
 
-  error = Present(HWC_DISPLAY_PRIMARY);
+  error = Present(composer_callback_->GetDisplayId());
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer::PostLayers: Present failed: %s",
           error.to_string().c_str());
@@ -475,8 +481,8 @@
 
   std::vector<Hwc2::Layer> out_layers;
   std::vector<int> out_fences;
-  error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
-                                      &out_fences);
+  error = composer_->getReleaseFences(composer_callback_->GetDisplayId(),
+                                      &out_layers, &out_fences);
   ALOGE_IF(error != HWC::Error::None,
            "HardwareComposer::PostLayers: Failed to get release fences: %s",
            error.to_string().c_str());
@@ -570,6 +576,9 @@
   // Copy from latest record in shared_config_ring_ to local copy.
   DvrConfig record;
   if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
+    ALOGI("DvrConfig updated: sequence %u, post offset %d",
+          shared_config_ring_sequence_, record.frame_post_offset_ns);
+    ++shared_config_ring_sequence_;
     post_thread_config_ = record;
   }
 }
@@ -612,14 +621,6 @@
   }
 }
 
-Status<int64_t> HardwareComposer::GetVSyncTime() {
-  auto status = composer_callback_->GetVsyncTime(HWC_DISPLAY_PRIMARY);
-  ALOGE_IF(!status,
-           "HardwareComposer::GetVSyncTime: Failed to get vsync timestamp: %s",
-           status.GetErrorMessage().c_str());
-  return status;
-}
-
 // Waits for the next vsync and returns the timestamp of the vsync event. If
 // vsync already passed since the last call, returns the latest vsync timestamp
 // instead of blocking.
@@ -792,8 +793,7 @@
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
-      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
-                      /*frame_time_estimate*/ 0, vsync_count_);
+      vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_);
 
     {
       // Sleep until shortly before vsync.
@@ -816,7 +816,7 @@
             // If the layer config changed we need to validateDisplay() even if
             // we're going to drop the frame, to flush the Composer object's
             // internal command buffer and apply our layer changes.
-            Validate(HWC_DISPLAY_PRIMARY);
+            Validate(composer_callback_->GetDisplayId());
           }
           continue;
         }
@@ -824,7 +824,7 @@
     }
 
     {
-      auto status = GetVSyncTime();
+      auto status = composer_callback_->GetVsyncTime();
       if (!status) {
         ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s",
               status.GetErrorMessage().c_str());
@@ -943,10 +943,17 @@
 }
 
 Return<void> HardwareComposer::ComposerCallback::onHotplug(
-    Hwc2::Display display, IComposerCallback::Connection /*conn*/) {
-  // See if the driver supports the vsync_event node in sysfs.
-  if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES &&
-      !displays_[display].driver_vsync_event_fd) {
+    Hwc2::Display display, IComposerCallback::Connection conn) {
+  // Our first onHotplug callback is always for the primary display.
+  //
+  // Ignore any other hotplug callbacks since the primary display is never
+  // disconnected and we don't care about other displays.
+  if (!has_display_id_) {
+    LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
+        "Initial onHotplug callback should be primary display connected");
+    has_display_id_ = true;
+    display_id_ = display;
+
     std::array<char, 1024> buffer;
     snprintf(buffer.data(), buffer.size(),
              "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
@@ -955,7 +962,7 @@
           "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
           "vsync_event node for display %" PRIu64,
           display);
-      displays_[display].driver_vsync_event_fd = std::move(handle);
+      driver_vsync_event_fd_ = std::move(handle);
     } else {
       ALOGI(
           "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
@@ -974,36 +981,23 @@
 
 Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
                                                          int64_t timestamp) {
-  TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
-               display, timestamp);
-  if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
-    displays_[display].callback_vsync_timestamp = timestamp;
-  } else {
-    ALOGW(
-        "HardwareComposer::ComposerCallback::onVsync: Received vsync on "
-        "non-physical display: display=%" PRId64,
-        display);
+  // Ignore any onVsync callbacks for the non-primary display.
+  if (has_display_id_ && display == display_id_) {
+    TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
+                 display, timestamp);
+    callback_vsync_timestamp_ = timestamp;
   }
   return Void();
 }
 
-Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
-    Hwc2::Display display) {
-  if (display >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
-    ALOGE(
-        "HardwareComposer::ComposerCallback::GetVsyncTime: Invalid physical "
-        "display requested: display=%" PRIu64,
-        display);
-    return ErrorStatus(EINVAL);
-  }
-
+Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime() {
   // See if the driver supports direct vsync events.
-  LocalHandle& event_fd = displays_[display].driver_vsync_event_fd;
+  LocalHandle& event_fd = driver_vsync_event_fd_;
   if (!event_fd) {
     // Fall back to returning the last timestamp returned by the vsync
     // callback.
     std::lock_guard<std::mutex> autolock(vsync_mutex_);
-    return displays_[display].callback_vsync_timestamp;
+    return callback_vsync_timestamp_;
   }
 
   // When the driver supports the vsync_event sysfs node we can use it to
@@ -1053,10 +1047,11 @@
 
 Hwc2::Composer* Layer::composer_{nullptr};
 HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
+hwc2_display_t Layer::display_id_{0};
 
 void Layer::Reset() {
   if (hardware_composer_layer_) {
-    composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+    composer_->destroyLayer(display_id_, hardware_composer_layer_);
     hardware_composer_layer_ = 0;
   }
 
@@ -1151,17 +1146,16 @@
     pending_visibility_settings_ = false;
 
     HWC::Error error;
-    hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
     error = composer_->setLayerBlendMode(
-        display, hardware_composer_layer_,
+        display_id_, hardware_composer_layer_,
         blending_.cast<Hwc2::IComposerClient::BlendMode>());
     ALOGE_IF(error != HWC::Error::None,
              "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
              error.to_string().c_str());
 
-    error =
-        composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+    error = composer_->setLayerZOrder(display_id_, hardware_composer_layer_,
+                                      z_order_);
     ALOGE_IF(error != HWC::Error::None,
              "Layer::UpdateLayerSettings: Error setting z_ order: %s",
              error.to_string().c_str());
@@ -1170,36 +1164,35 @@
 
 void Layer::UpdateLayerSettings() {
   HWC::Error error;
-  hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
   UpdateVisibilitySettings();
 
   // TODO(eieio): Use surface attributes or some other mechanism to control
   // the layer display frame.
   error = composer_->setLayerDisplayFrame(
-      display, hardware_composer_layer_,
+      display_id_, hardware_composer_layer_,
       {0, 0, display_metrics_.width, display_metrics_.height});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
            error.to_string().c_str());
 
   error = composer_->setLayerVisibleRegion(
-      display, hardware_composer_layer_,
+      display_id_, hardware_composer_layer_,
       {{0, 0, display_metrics_.width, display_metrics_.height}});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
            error.to_string().c_str());
 
-  error =
-      composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+  error = composer_->setLayerPlaneAlpha(display_id_, hardware_composer_layer_,
+                                        1.0f);
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
            error.to_string().c_str());
 }
 
 void Layer::CommonLayerSetup() {
-  HWC::Error error =
-      composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+  HWC::Error error = composer_->createLayer(display_id_,
+                                            &hardware_composer_layer_);
   ALOGE_IF(error != HWC::Error::None,
            "Layer::CommonLayerSetup: Failed to create layer on primary "
            "display: %s",
@@ -1243,10 +1236,10 @@
     if (composition_type_ == HWC::Composition::Invalid) {
       composition_type_ = HWC::Composition::SolidColor;
       composer_->setLayerCompositionType(
-          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          display_id_, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
       Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
-      composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+      composer_->setLayerColor(display_id_, hardware_composer_layer_,
                                layer_color);
     } else {
       // The composition type is already set. Nothing else to do until a
@@ -1256,7 +1249,7 @@
     if (composition_type_ != target_composition_type_) {
       composition_type_ = target_composition_type_;
       composer_->setLayerCompositionType(
-          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          display_id_, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
     }
 
@@ -1267,7 +1260,7 @@
 
     HWC::Error error{HWC::Error::None};
     error =
-        composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+        composer_->setLayerBuffer(display_id_, hardware_composer_layer_,
                                   slot, handle, acquire_fence_.Get());
 
     ALOGE_IF(error != HWC::Error::None,
@@ -1277,7 +1270,7 @@
     if (!surface_rect_functions_applied_) {
       const float float_right = right;
       const float float_bottom = bottom;
-      error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+      error = composer_->setLayerSourceCrop(display_id_,
                                             hardware_composer_layer_,
                                             {0, 0, float_right, float_bottom});
 
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 7010db9..9ed4b22 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -152,6 +152,11 @@
     display_metrics_ = display_metrics;
   }
 
+  // Sets the display id used by all Layer instances.
+  static void SetDisplayId(hwc2_display_t display_id) {
+    display_id_ = display_id;
+  }
+
  private:
   void CommonLayerSetup();
 
@@ -180,6 +185,11 @@
   // thereafter.
   static HWCDisplayMetrics display_metrics_;
 
+  // Id of the primary display. Shared by all instances of Layer. This must be
+  // set whenever the primary display id changes. This can be left unset as long
+  // as there are no instances of Layer that might need to use it.
+  static hwc2_display_t display_id_;
+
   // The hardware composer layer and metrics to use during the prepare cycle.
   hwc2_layer_t hardware_composer_layer_ = 0;
 
@@ -298,13 +308,14 @@
 class HardwareComposer {
  public:
   // Type for vsync callback.
-  using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
+  using VSyncCallback = std::function<void(int64_t, int64_t, uint32_t)>;
   using RequestDisplayCallback = std::function<void(bool)>;
 
   HardwareComposer();
   ~HardwareComposer();
 
   bool Initialize(Hwc2::Composer* composer,
+                  hwc2_display_t primary_display_id,
                   RequestDisplayCallback request_display_callback);
 
   bool IsInitialized() const { return initialized_; }
@@ -362,16 +373,16 @@
     hardware::Return<void> onVsync(Hwc2::Display display,
                                    int64_t timestamp) override;
 
-    pdx::Status<int64_t> GetVsyncTime(Hwc2::Display display);
+    bool HasDisplayId() { return has_display_id_; }
+    hwc2_display_t GetDisplayId() { return display_id_; }
+    pdx::Status<int64_t> GetVsyncTime();
 
    private:
     std::mutex vsync_mutex_;
-
-    struct Display {
-      pdx::LocalHandle driver_vsync_event_fd;
-      int64_t callback_vsync_timestamp{0};
-    };
-    std::array<Display, HWC_NUM_PHYSICAL_DISPLAY_TYPES> displays_;
+    bool has_display_id_ = false;
+    hwc2_display_t display_id_;
+    pdx::LocalHandle driver_vsync_event_fd_;
+    int64_t callback_vsync_timestamp_{0};
   };
 
   HWC::Error Validate(hwc2_display_t display);
@@ -412,7 +423,6 @@
   // kPostThreadInterrupted.
   int ReadWaitPPState();
   pdx::Status<int64_t> WaitForVSync();
-  pdx::Status<int64_t> GetVSyncTime();
   int SleepUntil(int64_t wakeup_timestamp);
 
   // Reconfigures the layer stack if the display surfaces changed since the last
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index 33cbc84..c740dde 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -4,6 +4,12 @@
 #include <thread>
 #include <memory>
 
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
 #include <pdx/service_dispatcher.h>
 #include <vr/vr_manager/vr_manager.h>
 
@@ -21,7 +27,9 @@
  public:
   using RequestDisplayCallback = std::function<void(bool)>;
   static std::unique_ptr<VrFlinger> Create(
-      Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback);
+      Hwc2::Composer* hidl,
+      hwc2_display_t primary_display_id,
+      RequestDisplayCallback request_display_callback);
   ~VrFlinger();
 
   // These functions are all called on surface flinger's main thread.
@@ -35,6 +43,7 @@
  private:
   VrFlinger();
   bool Init(Hwc2::Composer* hidl,
+            hwc2_display_t primary_display_id,
             RequestDisplayCallback request_display_callback);
 
   // Needs to be a separate class for binder's ref counting
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 85dc586..5e7abd7 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -29,9 +29,10 @@
 namespace dvr {
 
 std::unique_ptr<VrFlinger> VrFlinger::Create(
-    Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
+    Hwc2::Composer* hidl, hwc2_display_t primary_display_id,
+    RequestDisplayCallback request_display_callback) {
   std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
-  if (vr_flinger->Init(hidl, request_display_callback))
+  if (vr_flinger->Init(hidl, primary_display_id, request_display_callback))
     return vr_flinger;
   else
     return nullptr;
@@ -56,6 +57,7 @@
 }
 
 bool VrFlinger::Init(Hwc2::Composer* hidl,
+                     hwc2_display_t primary_display_id,
                      RequestDisplayCallback request_display_callback) {
   if (!hidl || !request_display_callback)
     return false;
@@ -74,8 +76,8 @@
   dispatcher_ = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
 
-  display_service_ =
-      android::dvr::DisplayService::Create(hidl, request_display_callback);
+  display_service_ = android::dvr::DisplayService::Create(
+      hidl, primary_display_id, request_display_callback);
   CHECK_ERROR(!display_service_, error, "Failed to create display service.");
   dispatcher_->AddService(display_service_);
 
@@ -91,7 +93,7 @@
       std::bind(&android::dvr::VSyncService::VSyncEvent,
                 std::static_pointer_cast<android::dvr::VSyncService>(service),
                 std::placeholders::_1, std::placeholders::_2,
-                std::placeholders::_3, std::placeholders::_4));
+                std::placeholders::_3));
 
   dispatcher_thread_ = std::thread([this]() {
     prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index fdeb899..b8d8b08 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -32,21 +32,19 @@
 
 VSyncService::~VSyncService() {}
 
-void VSyncService::VSyncEvent(int display, int64_t timestamp_ns,
+void VSyncService::VSyncEvent(int64_t timestamp_ns,
                               int64_t compositor_time_ns,
                               uint32_t vsync_count) {
   ATRACE_NAME("VSyncService::VSyncEvent");
   std::lock_guard<std::mutex> autolock(mutex_);
 
-  if (display == HWC_DISPLAY_PRIMARY) {
-    last_vsync_ = current_vsync_;
-    current_vsync_ = timestamp_ns;
-    compositor_time_ns_ = compositor_time_ns;
-    current_vsync_count_ = vsync_count;
+  last_vsync_ = current_vsync_;
+  current_vsync_ = timestamp_ns;
+  compositor_time_ns_ = compositor_time_ns;
+  current_vsync_count_ = vsync_count;
 
-    NotifyWaiters();
-    UpdateClients();
-  }
+  NotifyWaiters();
+  UpdateClients();
 }
 
 std::shared_ptr<Channel> VSyncService::OnChannelOpen(pdx::Message& message) {
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index 215948e..822f02b 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -63,9 +63,10 @@
                       const std::shared_ptr<pdx::Channel>& channel) override;
 
   // Called by the hardware composer HAL, or similar, whenever a vsync event
-  // occurs. |compositor_time_ns| is the number of ns before the next vsync when
-  // the compositor will preempt the GPU to do EDS and lens warp.
-  void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns,
+  // occurs on the primary display. |compositor_time_ns| is the number of ns
+  // before the next vsync when the compositor will preempt the GPU to do EDS
+  // and lens warp.
+  void VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns,
                   uint32_t vsync_count);
 
  private:
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index e92178a..fe54b4b 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -14,7 +14,6 @@
 
 sourceFiles = [
     "pose_client.cpp",
-    "sensor_client.cpp",
     "latency_model.cpp",
 ]
 
@@ -33,6 +32,7 @@
 
 sharedLibraries = [
     "libbase",
+    "libbinder",
     "libcutils",
     "libhardware",
     "liblog",
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h b/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
deleted file mode 100644
index b2ebd95..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_IPC_H_
-#define ANDROID_DVR_SENSOR_IPC_H_
-
-#define DVR_SENSOR_SERVICE_BASE "system/vr/sensors"
-
-#define DVR_SENSOR_SERVICE_CLIENT (DVR_SENSOR_SERVICE_BASE "/client")
-
-/*
- * Endpoint ops
- */
-enum {
-  DVR_SENSOR_START = 0,
-  DVR_SENSOR_STOP,
-  DVR_SENSOR_POLL,
-};
-
-#endif  // ANDROID_DVR_SENSOR_IPC_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_client.h b/libs/vr/libvrsensor/include/private/dvr/sensor_client.h
deleted file mode 100644
index 15a9b8f..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_client.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CLIENT_H_
-#define ANDROID_DVR_SENSOR_CLIENT_H_
-
-#include <hardware/sensors.h>
-#include <pdx/client.h>
-#include <poll.h>
-
-namespace android {
-namespace dvr {
-
-// SensorClient is a remote interface to the sensor service in sensord.
-class SensorClient : public pdx::ClientBase<SensorClient> {
- public:
-  ~SensorClient();
-
-  int StartSensor();
-  int StopSensor();
-  int Poll(sensors_event_t* events, int max_count);
-
- private:
-  friend BASE;
-
-  // Set up a channel associated with the sensor of the indicated type.
-  // NOTE(segal): If our hardware ends up with multiple sensors of the same
-  // type, we'll have to change this.
-  explicit SensorClient(int sensor_type);
-
-  int sensor_type_;
-
-  SensorClient(const SensorClient&);
-  SensorClient& operator=(const SensorClient&);
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSOR_CLIENT_H_
diff --git a/libs/vr/libvrsensor/sensor_client.cpp b/libs/vr/libvrsensor/sensor_client.cpp
deleted file mode 100644
index 04e88cc..0000000
--- a/libs/vr/libvrsensor/sensor_client.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#define LOG_TAG "SensorClient"
-#include <private/dvr/sensor_client.h>
-
-#include <log/log.h>
-#include <poll.h>
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/sensor-ipc.h>
-
-using android::pdx::Transaction;
-
-namespace android {
-namespace dvr {
-
-SensorClient::SensorClient(int sensor_type)
-    : BASE(pdx::default_transport::ClientChannelFactory::Create(
-          DVR_SENSOR_SERVICE_CLIENT)),
-      sensor_type_(sensor_type) {}
-
-SensorClient::~SensorClient() {}
-
-int SensorClient::StartSensor() {
-  Transaction trans{*this};
-  auto status = trans.Send<int>(DVR_SENSOR_START, &sensor_type_,
-                                sizeof(sensor_type_), nullptr, 0);
-  ALOGE_IF(!status, "startSensor() failed because: %s\n",
-           status.GetErrorMessage().c_str());
-  return ReturnStatusOrError(status);
-}
-
-int SensorClient::StopSensor() {
-  Transaction trans{*this};
-  auto status = trans.Send<int>(DVR_SENSOR_STOP);
-  ALOGE_IF(!status, "stopSensor() failed because: %s\n",
-           status.GetErrorMessage().c_str());
-  return ReturnStatusOrError(status);
-}
-
-int SensorClient::Poll(sensors_event_t* events, int max_events) {
-  int num_events = 0;
-  struct iovec rvec[] = {
-      {.iov_base = &num_events, .iov_len = sizeof(int)},
-      {.iov_base = events, .iov_len = max_events * sizeof(sensors_event_t)},
-  };
-  Transaction trans{*this};
-  auto status = trans.SendVector<int>(DVR_SENSOR_POLL, nullptr, rvec);
-  ALOGE_IF(!status, "Sensor poll() failed because: %s\n",
-           status.GetErrorMessage().c_str());
-  return !status ? -status.error() : num_events;
-}
-
-}  // namespace dvr
-}  // namespace android
-
-// Entrypoints to simplify using the library when programmatically dynamicly
-// loading it.
-// Allows us to call this library without linking it, as, for instance,
-// when compiling GVR in Google3.
-// NOTE(segal): It's kind of a hack.
-
-extern "C" uint64_t dvrStartSensor(int type) {
-  android::dvr::SensorClient* service =
-      android::dvr::SensorClient::Create(type).release();
-  service->StartSensor();
-  return (uint64_t)service;
-}
-
-extern "C" void dvrStopSensor(uint64_t service) {
-  android::dvr::SensorClient* iss =
-      reinterpret_cast<android::dvr::SensorClient*>(service);
-  iss->StopSensor();
-  delete iss;
-}
-
-extern "C" int dvrPollSensor(uint64_t service, int max_count,
-                             sensors_event_t* events) {
-  return reinterpret_cast<android::dvr::SensorClient*>(service)->Poll(
-      events, max_count);
-}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 32c2d7e..d43c164 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -122,6 +122,16 @@
     },
 }
 
+cc_library_static {
+    name: "libEGL_blobCache",
+    defaults: ["egl_libs_defaults"],
+    srcs: [
+        "EGL/BlobCache.cpp",
+        "EGL/FileBlobCache.cpp",
+    ],
+    export_include_dirs: ["EGL"],
+}
+
 cc_library_shared {
     name: "libEGL",
     defaults: ["egl_libs_defaults"],
@@ -133,7 +143,6 @@
         "EGL/egl.cpp",
         "EGL/eglApi.cpp",
         "EGL/Loader.cpp",
-        "EGL/BlobCache.cpp",
     ],
     shared_libs: [
         "libvndksupport",
@@ -143,7 +152,10 @@
         "libhidltransport",
         "libutils",
     ],
-    static_libs: ["libEGL_getProcAddress"],
+    static_libs: [
+        "libEGL_getProcAddress",
+        "libEGL_blobCache",
+    ],
     ldflags: ["-Wl,--exclude-libs=ALL"],
     export_include_dirs: ["EGL/include"],
 }
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 0624b60..b3752f5 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -37,9 +37,9 @@
 static const uint32_t blobCacheDeviceVersion = 1;
 
 BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+        mMaxTotalSize(maxTotalSize),
         mMaxKeySize(maxKeySize),
         mMaxValueSize(maxValueSize),
-        mMaxTotalSize(maxTotalSize),
         mTotalSize(0) {
     int64_t now = std::chrono::steady_clock::now().time_since_epoch().count();
 #ifdef _WIN32
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index a0a270a..1f5d535 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -97,6 +97,14 @@
     //
     int unflatten(void const* buffer, size_t size);
 
+protected:
+    // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+    // includes space for both keys and values. When a call to BlobCache::set
+    // would otherwise cause this limit to be exceeded, either the key/value
+    // pair passed to BlobCache::set will not be cached or other cache entries
+    // will be evicted from the cache to make room for the new entry.
+    const size_t mMaxTotalSize;
+
 private:
     // Copying is disallowed.
     BlobCache(const BlobCache&);
@@ -220,13 +228,6 @@
     // simply not add the key/value pair to the cache.
     const size_t mMaxValueSize;
 
-    // mMaxTotalSize is the maximum size that all cache entries can occupy. This
-    // includes space for both keys and values. When a call to BlobCache::set
-    // would otherwise cause this limit to be exceeded, either the key/value
-    // pair passed to BlobCache::set will not be cached or other cache entries
-    // will be evicted from the cache to make room for the new entry.
-    const size_t mMaxTotalSize;
-
     // mTotalSize is the total combined size of all keys and values currently in
     // the cache.
     size_t mTotalSize;
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
new file mode 100644
index 0000000..ff608a3
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -0,0 +1,185 @@
+/*
+ ** Copyright 2017, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "FileBlobCache.h"
+
+#include <inttypes.h>
+#include <log/log.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+
+// Cache file header
+static const char* cacheFileMagic = "EGL$";
+static const size_t cacheFileHeaderSize = 8;
+
+namespace android {
+
+static uint32_t crc32c(const uint8_t* buf, size_t len) {
+    const uint32_t polyBits = 0x82F63B78;
+    uint32_t r = 0;
+    for (size_t i = 0; i < len; i++) {
+        r ^= buf[i];
+        for (int j = 0; j < 8; j++) {
+            if (r & 1) {
+                r = (r >> 1) ^ polyBits;
+            } else {
+                r >>= 1;
+            }
+        }
+    }
+    return r;
+}
+
+FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+        const std::string& filename)
+        : BlobCache(maxKeySize, maxValueSize, maxTotalSize)
+        , mFilename(filename) {
+    if (mFilename.length() > 0) {
+        size_t headerSize = cacheFileHeaderSize;
+
+        int fd = open(mFilename.c_str(), O_RDONLY, 0);
+        if (fd == -1) {
+            if (errno != ENOENT) {
+                ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
+                        strerror(errno), errno);
+            }
+            return;
+        }
+
+        struct stat statBuf;
+        if (fstat(fd, &statBuf) == -1) {
+            ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
+            close(fd);
+            return;
+        }
+
+        // Sanity check the size before trying to mmap it.
+        size_t fileSize = statBuf.st_size;
+        if (fileSize > mMaxTotalSize * 2) {
+            ALOGE("cache file is too large: %#" PRIx64,
+                  static_cast<off64_t>(statBuf.st_size));
+            close(fd);
+            return;
+        }
+
+        uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
+                PROT_READ, MAP_PRIVATE, fd, 0));
+        if (buf == MAP_FAILED) {
+            ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
+                    errno);
+            close(fd);
+            return;
+        }
+
+        // Check the file magic and CRC
+        size_t cacheSize = fileSize - headerSize;
+        if (memcmp(buf, cacheFileMagic, 4) != 0) {
+            ALOGE("cache file has bad mojo");
+            close(fd);
+            return;
+        }
+        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+        if (crc32c(buf + headerSize, cacheSize) != *crc) {
+            ALOGE("cache file failed CRC check");
+            close(fd);
+            return;
+        }
+
+        int err = unflatten(buf + headerSize, cacheSize);
+        if (err < 0) {
+            ALOGE("error reading cache contents: %s (%d)", strerror(-err),
+                    -err);
+            munmap(buf, fileSize);
+            close(fd);
+            return;
+        }
+
+        munmap(buf, fileSize);
+        close(fd);
+    }
+}
+
+void FileBlobCache::writeToFile() {
+    if (mFilename.length() > 0) {
+        size_t cacheSize = getFlattenedSize();
+        size_t headerSize = cacheFileHeaderSize;
+        const char* fname = mFilename.c_str();
+
+        // Try to create the file with no permissions so we can write it
+        // without anyone trying to read it.
+        int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+        if (fd == -1) {
+            if (errno == EEXIST) {
+                // The file exists, delete it and try again.
+                if (unlink(fname) == -1) {
+                    // No point in retrying if the unlink failed.
+                    ALOGE("error unlinking cache file %s: %s (%d)", fname,
+                            strerror(errno), errno);
+                    return;
+                }
+                // Retry now that we've unlinked the file.
+                fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+            }
+            if (fd == -1) {
+                ALOGE("error creating cache file %s: %s (%d)", fname,
+                        strerror(errno), errno);
+                return;
+            }
+        }
+
+        size_t fileSize = headerSize + cacheSize;
+
+        uint8_t* buf = new uint8_t [fileSize];
+        if (!buf) {
+            ALOGE("error allocating buffer for cache contents: %s (%d)",
+                    strerror(errno), errno);
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        int err = flatten(buf + headerSize, cacheSize);
+        if (err < 0) {
+            ALOGE("error writing cache contents: %s (%d)", strerror(-err),
+                    -err);
+            delete [] buf;
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        // Write the file magic and CRC
+        memcpy(buf, cacheFileMagic, 4);
+        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+        *crc = crc32c(buf + headerSize, cacheSize);
+
+        if (write(fd, buf, fileSize) == -1) {
+            ALOGE("error writing cache file: %s (%d)", strerror(errno),
+                    errno);
+            delete [] buf;
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        delete [] buf;
+        fchmod(fd, S_IRUSR);
+        close(fd);
+    }
+}
+
+}
\ No newline at end of file
diff --git a/opengl/libs/EGL/FileBlobCache.h b/opengl/libs/EGL/FileBlobCache.h
new file mode 100644
index 0000000..393703f
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.h
@@ -0,0 +1,43 @@
+/*
+ ** Copyright 2017, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_FILE_BLOB_CACHE_H
+#define ANDROID_FILE_BLOB_CACHE_H
+
+#include "BlobCache.h"
+#include <string>
+
+namespace android {
+
+class FileBlobCache : public BlobCache {
+public:
+    // FileBlobCache attempts to load the saved cache contents from disk into
+    // BlobCache.
+    FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+            const std::string& filename);
+
+    // writeToFile attempts to save the current contents of BlobCache to
+    // disk.
+    void writeToFile();
+
+private:
+    // mFilename is the name of the file for storing cache contents.
+    std::string mFilename;
+};
+
+} // namespace android
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 579e422..ec548f3 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -20,12 +20,8 @@
 
 #include "egl_display.h"
 
-
 #include <private/EGL/cache.h>
 
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
 #include <unistd.h>
 
 #include <thread>
@@ -37,10 +33,6 @@
 static const size_t maxValueSize = 64 * 1024;
 static const size_t maxTotalSize = 2 * 1024 * 1024;
 
-// Cache file header
-static const char* cacheFileMagic = "EGL$";
-static const size_t cacheFileHeaderSize = 8;
-
 // The time in seconds to wait before saving newly inserted cache entries.
 static const unsigned int deferredSaveDelay = 4;
 
@@ -124,7 +116,9 @@
 
 void egl_cache_t::terminate() {
     std::lock_guard<std::mutex> lock(mMutex);
-    saveBlobCacheLocked();
+    if (mBlobCache) {
+        mBlobCache->writeToFile();
+    }
     mBlobCache = NULL;
 }
 
@@ -146,8 +140,8 @@
             std::thread deferredSaveThread([this]() {
                 sleep(deferredSaveDelay);
                 std::lock_guard<std::mutex> lock(mMutex);
-                if (mInitialized) {
-                    saveBlobCacheLocked();
+                if (mInitialized && mBlobCache) {
+                    mBlobCache->writeToFile();
                 }
                 mSavePending = false;
             });
@@ -179,163 +173,11 @@
 
 BlobCache* egl_cache_t::getBlobCacheLocked() {
     if (mBlobCache == nullptr) {
-        mBlobCache.reset(new BlobCache(maxKeySize, maxValueSize, maxTotalSize));
-        loadBlobCacheLocked();
+        mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
     }
     return mBlobCache.get();
 }
 
-static uint32_t crc32c(const uint8_t* buf, size_t len) {
-    const uint32_t polyBits = 0x82F63B78;
-    uint32_t r = 0;
-    for (size_t i = 0; i < len; i++) {
-        r ^= buf[i];
-        for (int j = 0; j < 8; j++) {
-            if (r & 1) {
-                r = (r >> 1) ^ polyBits;
-            } else {
-                r >>= 1;
-            }
-        }
-    }
-    return r;
-}
-
-void egl_cache_t::saveBlobCacheLocked() {
-    if (mFilename.length() > 0 && mBlobCache != NULL) {
-        size_t cacheSize = mBlobCache->getFlattenedSize();
-        size_t headerSize = cacheFileHeaderSize;
-        const char* fname = mFilename.c_str();
-
-        // Try to create the file with no permissions so we can write it
-        // without anyone trying to read it.
-        int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
-        if (fd == -1) {
-            if (errno == EEXIST) {
-                // The file exists, delete it and try again.
-                if (unlink(fname) == -1) {
-                    // No point in retrying if the unlink failed.
-                    ALOGE("error unlinking cache file %s: %s (%d)", fname,
-                            strerror(errno), errno);
-                    return;
-                }
-                // Retry now that we've unlinked the file.
-                fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
-            }
-            if (fd == -1) {
-                ALOGE("error creating cache file %s: %s (%d)", fname,
-                        strerror(errno), errno);
-                return;
-            }
-        }
-
-        size_t fileSize = headerSize + cacheSize;
-
-        uint8_t* buf = new uint8_t [fileSize];
-        if (!buf) {
-            ALOGE("error allocating buffer for cache contents: %s (%d)",
-                    strerror(errno), errno);
-            close(fd);
-            unlink(fname);
-            return;
-        }
-
-        int err = mBlobCache->flatten(buf + headerSize, cacheSize);
-        if (err < 0) {
-            ALOGE("error writing cache contents: %s (%d)", strerror(-err),
-                    -err);
-            delete [] buf;
-            close(fd);
-            unlink(fname);
-            return;
-        }
-
-        // Write the file magic and CRC
-        memcpy(buf, cacheFileMagic, 4);
-        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
-        *crc = crc32c(buf + headerSize, cacheSize);
-
-        if (write(fd, buf, fileSize) == -1) {
-            ALOGE("error writing cache file: %s (%d)", strerror(errno),
-                    errno);
-            delete [] buf;
-            close(fd);
-            unlink(fname);
-            return;
-        }
-
-        delete [] buf;
-        fchmod(fd, S_IRUSR);
-        close(fd);
-    }
-}
-
-void egl_cache_t::loadBlobCacheLocked() {
-    if (mFilename.length() > 0) {
-        size_t headerSize = cacheFileHeaderSize;
-
-        int fd = open(mFilename.c_str(), O_RDONLY, 0);
-        if (fd == -1) {
-            if (errno != ENOENT) {
-                ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
-                        strerror(errno), errno);
-            }
-            return;
-        }
-
-        struct stat statBuf;
-        if (fstat(fd, &statBuf) == -1) {
-            ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
-            close(fd);
-            return;
-        }
-
-        // Sanity check the size before trying to mmap it.
-        size_t fileSize = statBuf.st_size;
-        if (fileSize > maxTotalSize * 2) {
-            ALOGE("cache file is too large: %#" PRIx64,
-                  static_cast<off64_t>(statBuf.st_size));
-            close(fd);
-            return;
-        }
-
-        uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
-                PROT_READ, MAP_PRIVATE, fd, 0));
-        if (buf == MAP_FAILED) {
-            ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
-                    errno);
-            close(fd);
-            return;
-        }
-
-        // Check the file magic and CRC
-        size_t cacheSize = fileSize - headerSize;
-        if (memcmp(buf, cacheFileMagic, 4) != 0) {
-            ALOGE("cache file has bad mojo");
-            close(fd);
-            return;
-        }
-        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
-        if (crc32c(buf + headerSize, cacheSize) != *crc) {
-            ALOGE("cache file failed CRC check");
-            close(fd);
-            return;
-        }
-
-        int err = mBlobCache->unflatten(buf + headerSize, cacheSize);
-        if (err < 0) {
-            ALOGE("error reading cache contents: %s (%d)", strerror(-err),
-                    -err);
-            munmap(buf, fileSize);
-            close(fd);
-            return;
-        }
-
-        munmap(buf, fileSize);
-        close(fd);
-    }
-}
-
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 56360f0..7382b91 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -20,7 +20,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include "BlobCache.h"
+#include "FileBlobCache.h"
 
 #include <memory>
 #include <mutex>
@@ -82,14 +82,6 @@
     // possible.
     BlobCache* getBlobCacheLocked();
 
-    // saveBlobCache attempts to save the current contents of mBlobCache to
-    // disk.
-    void saveBlobCacheLocked();
-
-    // loadBlobCache attempts to load the saved cache contents from disk into
-    // mBlobCache.
-    void loadBlobCacheLocked();
-
     // mInitialized indicates whether the egl_cache_t is in the initialized
     // state.  It is initialized to false at construction time, and gets set to
     // true when initialize is called.  It is set back to false when terminate
@@ -101,7 +93,7 @@
     // mBlobCache is the cache in which the key/value blob pairs are stored.  It
     // is initially NULL, and will be initialized by getBlobCacheLocked the
     // first time it's needed.
-    std::unique_ptr<BlobCache> mBlobCache;
+    std::unique_ptr<FileBlobCache> mBlobCache;
 
     // mFilename is the name of the file for storing cache contents in between
     // program invocations.  It is initialized to an empty string at
diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp
index 1428945..2b76279 100644
--- a/opengl/tests/lib/WindowSurface.cpp
+++ b/opengl/tests/lib/WindowSurface.cpp
@@ -62,19 +62,10 @@
         return;
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    err = sc->setLayer(0x7FFFFFFF);     // always on top
-    if (err != NO_ERROR) {
-        fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err);
-        return;
-    }
-
-    err = sc->show();
-    if (err != NO_ERROR) {
-        fprintf(stderr, "SurfaceComposer::show error: %#x\n", err);
-        return;
-    }
-    SurfaceComposerClient::closeGlobalTransaction();
+    SurfaceComposerClient::Transaction{}
+            .setLayer(sc, 0x7FFFFFFF)
+            .show(sc)
+            .apply();
 
     mSurfaceControl = sc;
 }
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 22b084a..12ad47e 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -3,7 +3,6 @@
 
     srcs: [
         "IAudioManager.cpp",
-        "IPlayer.cpp",
     ],
 
     shared_libs: [
diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp
deleted file mode 100644
index e8a9c34..0000000
--- a/services/audiomanager/IPlayer.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-**
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "IPlayer"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <audiomanager/IPlayer.h>
-
-namespace android {
-
-enum {
-    START      = IBinder::FIRST_CALL_TRANSACTION,
-    PAUSE      = IBinder::FIRST_CALL_TRANSACTION + 1,
-    STOP       = IBinder::FIRST_CALL_TRANSACTION + 2,
-    SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3,
-    SET_PAN    = IBinder::FIRST_CALL_TRANSACTION + 4,
-    SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5,
-    APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6,
-};
-
-class BpPlayer : public BpInterface<IPlayer>
-{
-public:
-    explicit BpPlayer(const sp<IBinder>& impl)
-        : BpInterface<IPlayer>(impl)
-    {
-    }
-
-    virtual void start()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        remote()->transact(START, data, &reply);
-    }
-
-    virtual void pause()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        remote()->transact(PAUSE, data, &reply);
-    }
-
-    virtual void stop()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        remote()->transact(STOP, data, &reply);
-    }
-
-    virtual void setVolume(float vol)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        data.writeFloat(vol);
-        remote()->transact(SET_VOLUME, data, &reply);
-    }
-
-    virtual void setPan(float pan)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        data.writeFloat(pan);
-        remote()->transact(SET_PAN, data, &reply);
-    }
-
-    virtual void setStartDelayMs(int32_t delayMs) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-        data.writeInt32(delayMs);
-        remote()->transact(SET_START_DELAY_MS, data, &reply);
-    }
-
-    virtual void applyVolumeShaper(
-            const sp<VolumeShaper::Configuration>& configuration,
-            const sp<VolumeShaper::Operation>& operation) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-
-        status_t status = configuration.get() == nullptr
-                ? data.writeInt32(0)
-                :  data.writeInt32(1)
-                    ?: configuration->writeToParcel(&data);
-        if (status != NO_ERROR) {
-            ALOGW("applyVolumeShaper failed configuration parceling: %d", status);
-            return; // ignore error
-        }
-
-        status = operation.get() == nullptr
-                ? status = data.writeInt32(0)
-                : data.writeInt32(1)
-                    ?: operation->writeToParcel(&data);
-        if (status != NO_ERROR) {
-            ALOGW("applyVolumeShaper failed operation parceling: %d", status);
-            return; // ignore error
-        }
-
-        status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply);
-
-        ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status);
-        return; // one way transaction, ignore error
-    }
-};
-
-IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer");
-
-// ----------------------------------------------------------------------
-
-status_t BnPlayer::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case START: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            start();
-            return NO_ERROR;
-        } break;
-        case PAUSE: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            pause();
-            return NO_ERROR;
-        }
-        case STOP: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            stop();
-            return NO_ERROR;
-        } break;
-        case SET_VOLUME: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            setVolume(data.readFloat());
-            return NO_ERROR;
-        } break;
-        case SET_PAN: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            setPan(data.readFloat());
-            return NO_ERROR;
-        } break;
-        case SET_START_DELAY_MS: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            setStartDelayMs(data.readInt32());
-            return NO_ERROR;
-        } break;
-        case APPLY_VOLUME_SHAPER: {
-            CHECK_INTERFACE(IPlayer, data, reply);
-            sp<VolumeShaper::Configuration> configuration;
-            sp<VolumeShaper::Operation> operation;
-
-            int32_t present;
-            status_t status = data.readInt32(&present);
-            if (status == NO_ERROR && present != 0) {
-                configuration = new VolumeShaper::Configuration();
-                status = configuration->readFromParcel(data);
-            }
-            status = status ?: data.readInt32(&present);
-            if (status == NO_ERROR && present != 0) {
-                operation = new VolumeShaper::Operation();
-                status = operation->readFromParcel(data);
-            }
-            if (status == NO_ERROR) {
-                // one way transaction, no error returned
-                applyVolumeShaper(configuration, operation);
-            }
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-} // namespace android
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 4c7265b..186f399 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -5,29 +5,3 @@
     header_libs: ["libbinder_headers"],
     export_header_lib_headers: ["libbinder_headers"],
 }
-
-cc_library {
-    name: "libbatteryservice",
-
-    srcs: [
-        "BatteryProperties.cpp",
-        "BatteryProperty.cpp",
-        "IBatteryPropertiesListener.cpp",
-        "IBatteryPropertiesRegistrar.cpp",
-    ],
-
-    header_libs: ["libbatteryservice_headers"],
-    export_header_lib_headers: ["libbatteryservice_headers"],
-
-    shared_libs: [
-        "libutils",
-        "libbinder",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused",
-        "-Wunreachable-code",
-    ],
-}
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
deleted file mode 100644
index 8fa111d..0000000
--- a/services/batteryservice/BatteryProperties.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/BatteryService.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-namespace android {
-
-/*
- * Parcel read/write code must be kept in sync with
- * frameworks/base/core/java/android/os/BatteryProperties.java
- */
-
-status_t BatteryProperties::readFromParcel(Parcel* p) {
-    chargerAcOnline = p->readInt32() == 1 ? true : false;
-    chargerUsbOnline = p->readInt32() == 1 ? true : false;
-    chargerWirelessOnline = p->readInt32() == 1 ? true : false;
-    maxChargingCurrent = p->readInt32();
-    maxChargingVoltage = p->readInt32();
-    batteryStatus = p->readInt32();
-    batteryHealth = p->readInt32();
-    batteryPresent = p->readInt32() == 1 ? true : false;
-    batteryLevel = p->readInt32();
-    batteryVoltage = p->readInt32();
-    batteryTemperature = p->readInt32();
-    batteryFullCharge = p->readInt32();
-    batteryChargeCounter = p->readInt32();
-    batteryTechnology = String8((p->readString16()).string());
-    return OK;
-}
-
-status_t BatteryProperties::writeToParcel(Parcel* p) const {
-    p->writeInt32(chargerAcOnline ? 1 : 0);
-    p->writeInt32(chargerUsbOnline ? 1 : 0);
-    p->writeInt32(chargerWirelessOnline ? 1 : 0);
-    p->writeInt32(maxChargingCurrent);
-    p->writeInt32(maxChargingVoltage);
-    p->writeInt32(batteryStatus);
-    p->writeInt32(batteryHealth);
-    p->writeInt32(batteryPresent ? 1 : 0);
-    p->writeInt32(batteryLevel);
-    p->writeInt32(batteryVoltage);
-    p->writeInt32(batteryTemperature);
-    p->writeInt32(batteryFullCharge);
-    p->writeInt32(batteryChargeCounter);
-    p->writeString16(String16(batteryTechnology));
-    return OK;
-}
-
-}; // namespace android
diff --git a/services/batteryservice/BatteryProperty.cpp b/services/batteryservice/BatteryProperty.cpp
deleted file mode 100644
index 483d925..0000000
--- a/services/batteryservice/BatteryProperty.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/BatteryService.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-/*
- * Parcel read/write code must be kept in sync with
- * frameworks/base/core/java/android/os/BatteryProperty.java
- */
-
-status_t BatteryProperty::readFromParcel(Parcel* p) {
-    valueInt64 = p->readInt64();
-    return OK;
-}
-
-status_t BatteryProperty::writeToParcel(Parcel* p) const {
-    p->writeInt64(valueInt64);
-    return OK;
-}
-
-}; // namespace android
diff --git a/services/batteryservice/IBatteryPropertiesListener.cpp b/services/batteryservice/IBatteryPropertiesListener.cpp
deleted file mode 100644
index 6e5bcfe..0000000
--- a/services/batteryservice/IBatteryPropertiesListener.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/IBatteryPropertiesListener.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener>
-{
-public:
-    explicit BpBatteryPropertiesListener(const sp<IBinder>& impl)
-        : BpInterface<IBatteryPropertiesListener>(impl)
-    {
-    }
-
-    void batteryPropertiesChanged(struct BatteryProperties props)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor());
-        data.writeInt32(1);
-        props.writeToParcel(&data);
-        remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(BatteryPropertiesListener, "android.os.IBatteryPropertiesListener");
-
-// ----------------------------------------------------------------------------
-
-status_t BnBatteryPropertiesListener::onTransact(uint32_t code, const Parcel& data,
-                                                 Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case TRANSACT_BATTERYPROPERTIESCHANGED: {
-            CHECK_INTERFACE(IBatteryPropertiesListener, data, reply);
-            struct BatteryProperties props = {};
-            if (data.readInt32() != 0) {
-                props.readFromParcel((Parcel*)&data);
-            }
-            batteryPropertiesChanged(props);
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-};
-
-}; // namespace android
diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
deleted file mode 100644
index 01a65ae..0000000
--- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IBatteryPropertiesRegistrar"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <batteryservice/IBatteryPropertiesListener.h>
-#include <batteryservice/IBatteryPropertiesRegistrar.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> {
-public:
-    explicit BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)
-        : BpInterface<IBatteryPropertiesRegistrar>(impl) {}
-
-        void registerListener(const sp<IBatteryPropertiesListener>& listener) {
-            Parcel data;
-            data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
-            data.writeStrongBinder(IInterface::asBinder(listener));
-            remote()->transact(REGISTER_LISTENER, data, NULL);
-        }
-
-        void unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
-            Parcel data;
-            data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
-            data.writeStrongBinder(IInterface::asBinder(listener));
-            remote()->transact(UNREGISTER_LISTENER, data, NULL);
-        }
-
-        status_t getProperty(int id, struct BatteryProperty *val) {
-            Parcel data, reply;
-            data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
-            data.writeInt32(id);
-            remote()->transact(GET_PROPERTY, data, &reply);
-            int32_t ret = reply.readExceptionCode();
-            if (ret != 0) {
-                return ret;
-            }
-            ret = reply.readInt32();
-            int parcelpresent = reply.readInt32();
-            if (parcelpresent)
-                val->readFromParcel(&reply);
-            return ret;
-        }
-
-        void scheduleUpdate() {
-            Parcel data;
-            data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
-            remote()->transact(SCHEDULE_UPDATE, data, NULL);
-        }
-};
-
-IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar");
-
-status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code,
-                                                  const Parcel& data,
-                                                  Parcel* reply,
-                                                  uint32_t flags)
-{
-    switch(code) {
-        case REGISTER_LISTENER: {
-            CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
-            sp<IBatteryPropertiesListener> listener =
-                interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
-            registerListener(listener);
-            return OK;
-        }
-
-        case UNREGISTER_LISTENER: {
-            CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
-            sp<IBatteryPropertiesListener> listener =
-                interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
-            unregisterListener(listener);
-            return OK;
-        }
-
-        case GET_PROPERTY: {
-            CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
-            int id = data.readInt32();
-            struct BatteryProperty val;
-            status_t result = getProperty(id, &val);
-            reply->writeNoException();
-            reply->writeInt32(result);
-            reply->writeInt32(1);
-            val.writeToParcel(reply);
-            return OK;
-        }
-
-        case SCHEDULE_UPDATE: {
-            CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
-            scheduleUpdate();
-            return OK;
-        }
-    }
-    return BBinder::onTransact(code, data, reply, flags);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 42f9ba9..8ab30e8 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -685,7 +685,7 @@
 bool InputDispatcher::dispatchConfigurationChangedLocked(
         nsecs_t currentTime, ConfigurationChangedEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
+    ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry->eventTime);
 #endif
 
     // Reset key repeating in case a keyboard device was added or removed or something.
@@ -701,7 +701,8 @@
 bool InputDispatcher::dispatchDeviceResetLocked(
         nsecs_t currentTime, DeviceResetEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
+    ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry->eventTime,
+            entry->deviceId);
 #endif
 
     CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
@@ -811,9 +812,9 @@
 
 void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
             "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
-            "repeatCount=%d, downTime=%lld",
+            "repeatCount=%d, downTime=%" PRId64,
             prefix,
             entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
             entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
@@ -884,10 +885,10 @@
 
 void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-    ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+    ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
             "action=0x%x, actionButton=0x%x, flags=0x%x, "
             "metaState=0x%x, buttonState=0x%x,"
-            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
             prefix,
             entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
             entry->action, entry->actionButton, entry->flags,
@@ -1992,10 +1993,10 @@
             const PointerCoords* usingCoords = motionEntry->pointerCoords;
 
             // Set the X and Y offset depending on the input source.
-            float xOffset, yOffset, scaleFactor;
+            float xOffset, yOffset;
             if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                     && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
-                scaleFactor = dispatchEntry->scaleFactor;
+                float scaleFactor = dispatchEntry->scaleFactor;
                 xOffset = dispatchEntry->xOffset * scaleFactor;
                 yOffset = dispatchEntry->yOffset * scaleFactor;
                 if (scaleFactor != 1.0f) {
@@ -2008,7 +2009,6 @@
             } else {
                 xOffset = 0.0f;
                 yOffset = 0.0f;
-                scaleFactor = 1.0f;
 
                 // We don't want the dispatch target to know.
                 if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
@@ -2231,7 +2231,7 @@
 
     if (!cancelationEvents.isEmpty()) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-        ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
+        ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
                 "with reality: %s, mode=%d.",
                 connection->getInputChannelName(), cancelationEvents.size(),
                 options.reason, options.mode);
@@ -2367,7 +2367,7 @@
 
 void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);
+    ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
 #endif
 
     bool needWake;
@@ -2385,8 +2385,9 @@
 
 void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
-            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
+    ALOGD("notifyKey - eventTime=%" PRId64
+            ", deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
+            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
             args->eventTime, args->deviceId, args->source, args->policyFlags,
             args->action, args->flags, args->keyCode, args->scanCode,
             args->metaState, args->downTime);
@@ -2480,9 +2481,9 @@
 
 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+    ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
             "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
-            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
             args->eventTime, args->deviceId, args->source, args->policyFlags,
             args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
             args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
@@ -2560,9 +2561,9 @@
 
 void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
-            args->eventTime, args->policyFlags,
-            args->switchValues, args->switchMask);
+    ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
+            "switchMask=0x%08x",
+            args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
 #endif
 
     uint32_t policyFlags = args->policyFlags;
@@ -2573,7 +2574,7 @@
 
 void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
+    ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d",
             args->eventTime, args->deviceId);
 #endif
 
@@ -2902,7 +2903,7 @@
 
         for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
             TouchState& state = mTouchStatesByDisplay.editValueAt(d);
-            for (size_t i = 0; i < state.windows.size(); i++) {
+            for (size_t i = 0; i < state.windows.size(); ) {
                 TouchedWindow& touchedWindow = state.windows.editItemAt(i);
                 if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
@@ -2917,7 +2918,9 @@
                         synthesizeCancelationEventsForInputChannelLocked(
                                 touchedInputChannel, options);
                     }
-                    state.windows.removeAt(i--);
+                    state.windows.removeAt(i);
+                } else {
+                  ++i;
                 }
             }
         }
@@ -3741,7 +3744,7 @@
                     msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
                             fallbackKeys.valueAt(i));
                 }
-                ALOGD("Unhandled key event: %d currently tracked fallback keys%s.",
+                ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
                         fallbackKeys.size(), msg.string());
             }
 #endif
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index d4266f6..591f8d7 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -429,7 +429,7 @@
                 batchSize += 1;
             }
 #if DEBUG_RAW_EVENTS
-            ALOGD("BatchSize: %d Count: %d", batchSize, count);
+            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
 #endif
             processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
         } else {
@@ -1174,9 +1174,9 @@
     // gamepad button presses are handled by different mappers but they should be dispatched
     // in the order received.
     size_t numMappers = mMappers.size();
-    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
+    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
 #if DEBUG_RAW_EVENTS
-        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
+        ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
                 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
                 rawEvent->when);
 #endif
@@ -1202,6 +1202,7 @@
                 mapper->process(rawEvent);
             }
         }
+        --count;
     }
 }
 
@@ -1851,7 +1852,7 @@
 #if DEBUG_POINTERS
             if (newSlot) {
                 ALOGW("MultiTouch device emitted invalid slot index %d but it "
-                        "should be between 0 and %d; ignoring this slot.",
+                        "should be between 0 and %zd; ignoring this slot.",
                         mCurrentSlot, mSlotCount - 1);
             }
 #endif
@@ -2147,9 +2148,9 @@
         if (i != 0) {
             patternStr.append(", ");
         }
-        patternStr.appendFormat("%lld", pattern[i]);
+        patternStr.appendFormat("%" PRId64, pattern[i]);
     }
-    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
+    ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
             getDeviceId(), patternStr.string(), repeat, token);
 #endif
 
@@ -2198,8 +2199,7 @@
     nsecs_t duration = mPattern[mIndex];
     if (vibratorOn) {
 #if DEBUG_VIBRATOR
-        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
-                getDeviceId(), duration);
+        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
 #endif
         getEventHub()->vibrate(getDeviceId(), duration);
     } else {
@@ -2259,7 +2259,7 @@
     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
     dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
     dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
-    dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+    dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
 }
 
 
@@ -2620,7 +2620,7 @@
     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
     dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
     dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
-    dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+    dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
 }
 
 void CursorInputMapper::configure(nsecs_t when,
@@ -5509,18 +5509,15 @@
     // Otherwise choose an arbitrary remaining pointer.
     // This guarantees we always have an active touch id when there is at least one pointer.
     // We keep the same active touch id for as long as possible.
-    bool activeTouchChanged = false;
     int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
     int32_t activeTouchId = lastActiveTouchId;
     if (activeTouchId < 0) {
         if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
-            activeTouchChanged = true;
             activeTouchId = mPointerGesture.activeTouchId =
                     mCurrentCookedState.fingerIdBits.firstMarkedBit();
             mPointerGesture.firstTouchTime = when;
         }
     } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
-        activeTouchChanged = true;
         if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
             activeTouchId = mPointerGesture.activeTouchId =
                     mCurrentCookedState.fingerIdBits.firstMarkedBit();
@@ -5616,7 +5613,6 @@
             }
             if (bestId >= 0 && bestId != activeTouchId) {
                 mPointerGesture.activeTouchId = activeTouchId = bestId;
-                activeTouchChanged = true;
 #if DEBUG_GESTURES
                 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
                         "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
@@ -6631,7 +6627,7 @@
 #if DEBUG_POINTER_ASSIGNMENT
     ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
     for (size_t i = 0; i < heapSize; i++) {
-        ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
+        ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
                 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
                 heap[i].distance);
     }
@@ -6677,7 +6673,7 @@
 #if DEBUG_POINTER_ASSIGNMENT
                 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
                 for (size_t i = 0; i < heapSize; i++) {
-                    ALOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
+                    ALOGD("  heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
                             i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
                             heap[i].distance);
                 }
@@ -6703,7 +6699,8 @@
             usedIdBits.markBit(id);
 
 #if DEBUG_POINTER_ASSIGNMENT
-            ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
+            ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
+                    ", id=%" PRIu32 ", distance=%" PRIu64,
                     lastPointerIndex, currentPointerIndex, id, heap[0].distance);
 #endif
             break;
@@ -6721,8 +6718,7 @@
                 current->rawPointerData.isHovering(currentPointerIndex));
 
 #if DEBUG_POINTER_ASSIGNMENT
-        ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
-                currentPointerIndex, id);
+        ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
 #endif
     }
 }
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a49c8c8..8a35509 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -19,7 +19,6 @@
         "libhardware",
         "libhardware_legacy",
         "libui",
-        "libskia",
         "libinput",
         "libinputflinger",
         "libinputservice",
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 452c8c6..330861d 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -78,12 +78,13 @@
     if (checkService()) {
         Mutex::Autolock _l(mActivationsLock);
         int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-        for (size_t i=0 ; i<mActivations.size() ; i++) {
+        for (size_t i=0 ; i<mActivations.size() ; ) {
             const Info& info(mActivations[i]);
             if (info.uid == uid) {
                 mBatteryStatService->noteStopSensor(info.uid, info.handle);
                 mActivations.removeAt(i);
-                i--;
+            } else {
+              i++;
             }
         }
         IPCThreadState::self()->restoreCallingIdentity(identity);
@@ -105,4 +106,3 @@
 
 // ---------------------------------------------------------------------------
 }; // namespace android
-
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
new file mode 100644
index 0000000..6a38a1f
--- /dev/null
+++ b/services/sensorservice/OWNERS
@@ -0,0 +1,2 @@
+ashutoshj@google.com
+pengxu@google.com
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 535d0db..fdb69d3 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -217,8 +217,13 @@
 }
 
 void SensorDevice::autoDisable(void *ident, int handle) {
-    Info& info( mActivationCount.editValueFor(handle) );
     Mutex::Autolock _l(mLock);
+    ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+    if (activationIndex < 0) {
+        ALOGW("Handle %d cannot be found in activation record", handle);
+        return;
+    }
+    Info& info(mActivationCount.editValueAt(activationIndex));
     info.removeBatchParamsForIdent(ident);
 }
 
@@ -229,7 +234,12 @@
     bool actuateHardware = false;
 
     Mutex::Autolock _l(mLock);
-    Info& info( mActivationCount.editValueFor(handle) );
+    ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+    if (activationIndex < 0) {
+        ALOGW("Handle %d cannot be found in activation record", handle);
+        return BAD_VALUE;
+    }
+    Info& info(mActivationCount.editValueAt(activationIndex));
 
     ALOGD_IF(DEBUG_CONNECTIONS,
              "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
@@ -323,7 +333,12 @@
              ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
 
     Mutex::Autolock _l(mLock);
-    Info& info(mActivationCount.editValueFor(handle));
+    ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+    if (activationIndex < 0) {
+        ALOGW("Handle %d cannot be found in activation record", handle);
+        return BAD_VALUE;
+    }
+    Info& info(mActivationCount.editValueAt(activationIndex));
 
     if (info.batchParams.indexOfKey(ident) < 0) {
         BatchParams params(samplingPeriodNs, maxBatchReportLatencyNs);
diff --git a/services/sensorservice/SensorDeviceUtils.cpp b/services/sensorservice/SensorDeviceUtils.cpp
index b1344be..dbafffe 100644
--- a/services/sensorservice/SensorDeviceUtils.cpp
+++ b/services/sensorservice/SensorDeviceUtils.cpp
@@ -28,8 +28,13 @@
 namespace android {
 namespace SensorDeviceUtils {
 
-HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter()
-        : mRegistered(ISensors::registerForNotifications("default", this)) {
+HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter() {
+}
+
+void HidlServiceRegistrationWaiter::onFirstRef() {
+    // Creating sp<...>(this) in the constructor should be avoided, hence
+    // registerForNotifications is called in onFirstRef callback.
+    mRegistered = ISensors::registerForNotifications("default", this);
 }
 
 Return<void> HidlServiceRegistrationWaiter::onRegistration(
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index da36928..e2eb606 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -46,8 +46,10 @@
      * @return true if service is restart since last reset(); false otherwise.
      */
     bool wait();
+protected:
+    void onFirstRef() override;
 private:
-    const bool mRegistered;
+    bool mRegistered;
 
     std::mutex mLock;
     std::condition_variable mCondition;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 4775e4e..bd7f0ea 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,6 +1,8 @@
 cc_library_static {
     name: "libsurfaceflingerincludes",
     export_include_dirs: ["."],
+    static_libs = ["libserviceutils"],
+    export_static_lib_headers = ["libserviceutils"],
 }
 
-subdirs = ["tests/fakehwc"]
\ No newline at end of file
+subdirs = ["tests/fakehwc", "layerproto"]
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 38529b6..deead06 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -14,17 +14,21 @@
     FrameTracker.cpp \
     GpuService.cpp \
     Layer.cpp \
-    LayerDim.cpp \
+    BufferLayer.cpp \
+    ColorLayer.cpp \
     LayerRejecter.cpp \
     LayerVector.cpp \
     MessageQueue.cpp \
     MonitoredProducer.cpp \
+    SurfaceFlinger.cpp \
     SurfaceFlingerConsumer.cpp \
     SurfaceInterceptor.cpp \
+    SurfaceTracing.cpp \
     Transform.cpp \
     DisplayHardware/ComposerHal.cpp \
     DisplayHardware/FramebufferSurface.cpp \
     DisplayHardware/HWC2.cpp \
+    DisplayHardware/HWComposer.cpp \
     DisplayHardware/HWComposerBufferCache.cpp \
     DisplayHardware/PowerHAL.cpp \
     DisplayHardware/VirtualDisplaySurface.cpp \
@@ -37,8 +41,11 @@
     RenderEngine/ProgramCache.cpp \
     RenderEngine/GLExtensions.cpp \
     RenderEngine/RenderEngine.cpp \
+    RenderEngine/Surface.cpp \
     RenderEngine/Texture.cpp \
     RenderEngine/GLES20RenderEngine.cpp \
+    LayerProtoHelper.cpp \
+    RenderArea.cpp \
 
 LOCAL_MODULE := libsurfaceflinger
 LOCAL_C_INCLUDES := \
@@ -49,17 +56,6 @@
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
-ifeq ($(TARGET_USES_HWC2),true)
-    LOCAL_CFLAGS += -DUSE_HWC2
-    LOCAL_SRC_FILES += \
-        SurfaceFlinger.cpp \
-        DisplayHardware/HWComposer.cpp
-else
-    LOCAL_SRC_FILES += \
-        SurfaceFlinger_hwc1.cpp \
-        DisplayHardware/HWComposer_hwc1.cpp
-endif
-
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 
 LOCAL_STATIC_LIBRARIES := \
@@ -67,7 +63,10 @@
     libtrace_proto \
     libvkjson \
     libvr_manager \
-    libvrflinger
+    libvrflinger \
+    libserviceutils
+
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils
 
 LOCAL_SHARED_LIBRARIES := \
     android.frameworks.vr.composer@1.0 \
@@ -95,7 +94,8 @@
     libsync \
     libprotobuf-cpp-lite \
     libbase \
-    android.hardware.power@1.0
+    android.hardware.power@1.0 \
+    liblayers_proto
 
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
     android.hardware.graphics.allocator@2.0 \
@@ -120,10 +120,6 @@
 
 LOCAL_INIT_RC := surfaceflinger.rc
 
-ifeq ($(TARGET_USES_HWC2),true)
-    LOCAL_CFLAGS += -DUSE_HWC2
-endif
-
 LOCAL_SRC_FILES := \
     main_surfaceflinger.cpp
 
@@ -142,10 +138,12 @@
     libutils \
     libui \
     libgui \
-    libdl
+    libdl \
+    liblayers_proto
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_STATIC_LIBRARIES := libtrace_proto
+LOCAL_STATIC_LIBRARIES := libtrace_proto \
+    libserviceutils
 
 LOCAL_MODULE := surfaceflinger
 
@@ -153,7 +151,7 @@
 LOCAL_32_BIT_ONLY := true
 endif
 
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
new file mode 100644
index 0000000..0d947b1
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BufferLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BufferLayer.h"
+#include "Colorizer.h"
+#include "DisplayDevice.h"
+#include "LayerRejecter.h"
+#include "clz.h"
+
+#include "RenderEngine/RenderEngine.h"
+
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+
+#include <ui/DebugUtils.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include <utils/StopWatch.h>
+#include <utils/Trace.h>
+
+#include <cutils/compiler.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <mutex>
+
+namespace android {
+
+BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+                         uint32_t w, uint32_t h, uint32_t flags)
+      : Layer(flinger, client, name, w, h, flags),
+        mSurfaceFlingerConsumer(nullptr),
+        mTextureName(UINT32_MAX),
+        mFormat(PIXEL_FORMAT_NONE),
+        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+        mBufferLatched(false),
+        mPreviousFrameNumber(0),
+        mUpdateTexImageFailed(false),
+        mRefreshPending(false) {
+    ALOGV("Creating Layer %s", name.string());
+
+    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
+    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
+
+    if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
+
+    mCurrentState.requested = mCurrentState.active;
+
+    // drawing state & current state are identical
+    mDrawingState = mCurrentState;
+}
+
+BufferLayer::~BufferLayer() {
+    sp<Client> c(mClientRef.promote());
+    if (c != 0) {
+        c->detachLayer(this);
+    }
+
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    for (auto& point : mLocalSyncPoints) {
+        point->setFrameAvailable();
+    }
+    mFlinger->deleteTextureAsync(mTextureName);
+
+    if (!getBE().mHwcLayers.empty()) {
+        ALOGE("Found stale hardware composer layers when destroying "
+              "surface flinger layer %s",
+              mName.string());
+        destroyAllHwcLayers();
+    }
+}
+
+void BufferLayer::useSurfaceDamage() {
+    if (mFlinger->mForceFullDamage) {
+        surfaceDamageRegion = Region::INVALID_REGION;
+    } else {
+        surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
+    }
+}
+
+void BufferLayer::useEmptyDamage() {
+    surfaceDamageRegion.clear();
+}
+
+bool BufferLayer::isProtected() const {
+    const sp<GraphicBuffer>& buffer(getBE().mBuffer);
+    return (buffer != 0) &&
+            (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+}
+
+bool BufferLayer::isVisible() const {
+    return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
+            (getBE().mBuffer != NULL || getBE().mSidebandStream != NULL);
+}
+
+bool BufferLayer::isFixedSize() const {
+    return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+}
+
+status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
+    uint32_t const maxSurfaceDims =
+            min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
+
+    // never allow a surface larger than what our underlying GL implementation
+    // can handle.
+    if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) {
+        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
+        return BAD_VALUE;
+    }
+
+    mFormat = format;
+
+    mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
+    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
+    mCurrentOpacity = getOpacityForFormat(format);
+
+    mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+    mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
+    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+
+    return NO_ERROR;
+}
+
+static constexpr mat4 inverseOrientation(uint32_t transform) {
+    const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+    const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+    const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+    mat4 tr;
+
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        tr = tr * rot90;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+        tr = tr * flipH;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+        tr = tr * flipV;
+    }
+    return inverse(tr);
+}
+
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
+void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
+                         bool useIdentityTransform) const {
+    ATRACE_CALL();
+
+    if (CC_UNLIKELY(getBE().mBuffer == 0)) {
+        // the texture has not been created yet, this Layer has
+        // in fact never been drawn into. This happens frequently with
+        // SurfaceView because the WindowManager can't know when the client
+        // has drawn the first time.
+
+        // If there is nothing under us, we paint the screen in black, otherwise
+        // we just skip this update.
+
+        // figure out if there is something below us
+        Region under;
+        bool finished = false;
+        mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
+            if (finished || layer == static_cast<BufferLayer const*>(this)) {
+                finished = true;
+                return;
+            }
+            under.orSelf(renderArea.getTransform().transform(layer->visibleRegion));
+        });
+        // if not everything below us is covered, we plug the holes!
+        Region holes(clip.subtract(under));
+        if (!holes.isEmpty()) {
+            clearWithOpenGL(renderArea, 0, 0, 0, 1);
+        }
+        return;
+    }
+
+    // Bind the current buffer to the GL texture, and wait for it to be
+    // ready for us to draw into.
+    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
+    if (err != NO_ERROR) {
+        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
+        // Go ahead and draw the buffer anyway; no matter what we do the screen
+        // is probably going to have something visibly wrong.
+    }
+
+    bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
+
+    RenderEngine& engine(mFlinger->getRenderEngine());
+
+    if (!blackOutLayer) {
+        // TODO: we could be more subtle with isFixedSize()
+        const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+
+        // Query the texture matrix given our current filtering mode.
+        float textureMatrix[16];
+        mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
+        mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
+
+        if (getTransformToDisplayInverse()) {
+            /*
+             * the code below applies the primary display's inverse transform to
+             * the texture transform
+             */
+            uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+            mat4 tr = inverseOrientation(transform);
+
+            /**
+             * TODO(b/36727915): This is basically a hack.
+             *
+             * Ensure that regardless of the parent transformation,
+             * this buffer is always transformed from native display
+             * orientation to display orientation. For example, in the case
+             * of a camera where the buffer remains in native orientation,
+             * we want the pixels to always be upright.
+             */
+            sp<Layer> p = mDrawingParent.promote();
+            if (p != nullptr) {
+                const auto parentTransform = p->getTransform();
+                tr = tr * inverseOrientation(parentTransform.getOrientation());
+            }
+
+            // and finally apply it to the original texture matrix
+            const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
+            memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
+        }
+
+        // Set things up for texturing.
+        mTexture.setDimensions(getBE().mBuffer->getWidth(),
+                               getBE().mBuffer->getHeight());
+        mTexture.setFiltering(useFiltering);
+        mTexture.setMatrix(textureMatrix);
+
+        engine.setupLayerTexturing(mTexture);
+    } else {
+        engine.setupLayerBlackedOut();
+    }
+    drawWithOpenGL(renderArea, useIdentityTransform);
+    engine.disableTexturing();
+}
+
+void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+    mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
+}
+
+void BufferLayer::abandon() {
+    mSurfaceFlingerConsumer->abandon();
+}
+
+bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const {
+    if (mSidebandStreamChanged || mAutoRefresh) {
+        return true;
+    }
+
+    Mutex::Autolock lock(mQueueItemLock);
+    if (mQueueItems.empty()) {
+        return false;
+    }
+    auto timestamp = mQueueItems[0].mTimestamp;
+    nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
+
+    // Ignore timestamps more than a second in the future
+    bool isPlausible = timestamp < (expectedPresent + s2ns(1));
+    ALOGW_IF(!isPlausible,
+             "[%s] Timestamp %" PRId64 " seems implausible "
+             "relative to expectedPresent %" PRId64,
+             mName.string(), timestamp, expectedPresent);
+
+    bool isDue = timestamp < expectedPresent;
+    return isDue || !isPlausible;
+}
+
+void BufferLayer::setTransformHint(uint32_t orientation) const {
+    mSurfaceFlingerConsumer->setTransformHint(orientation);
+}
+
+bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
+    if (mBufferLatched) {
+        Mutex::Autolock lock(mFrameEventHistoryMutex);
+        mFrameEventHistory.addPreComposition(mCurrentFrameNumber,
+                                             refreshStartTime);
+    }
+    mRefreshPending = false;
+    return mQueuedFrames > 0 || mSidebandStreamChanged ||
+            mAutoRefresh;
+}
+bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+                                    const std::shared_ptr<FenceTime>& presentFence,
+                                    const CompositorTiming& compositorTiming) {
+    // mFrameLatencyNeeded is true when a new frame was latched for the
+    // composition.
+    if (!mFrameLatencyNeeded) return false;
+
+    // Update mFrameEventHistory.
+    {
+        Mutex::Autolock lock(mFrameEventHistoryMutex);
+        mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence,
+                                              presentFence, compositorTiming);
+    }
+
+    // Update mFrameTracker.
+    nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
+    mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+
+    std::shared_ptr<FenceTime> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime();
+    if (frameReadyFence->isValid()) {
+        mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
+    } else {
+        // There was no fence for this frame, so assume that it was ready
+        // to be presented at the desired present time.
+        mFrameTracker.setFrameReadyTime(desiredPresentTime);
+    }
+
+    if (presentFence->isValid()) {
+        mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+    } else {
+        // The HWC doesn't support present fences, so use the refresh
+        // timestamp instead.
+        mFrameTracker.setActualPresentTime(
+                mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY));
+    }
+
+    mFrameTracker.advanceFrame();
+    mFrameLatencyNeeded = false;
+    return true;
+}
+
+std::vector<OccupancyTracker::Segment> BufferLayer::getOccupancyHistory(bool forceFlush) {
+    std::vector<OccupancyTracker::Segment> history;
+    status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history);
+    if (result != NO_ERROR) {
+        ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+        return {};
+    }
+    return history;
+}
+
+bool BufferLayer::getTransformToDisplayInverse() const {
+    return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
+}
+
+void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
+    if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
+        return;
+    }
+
+    auto releaseFenceTime =
+            std::make_shared<FenceTime>(mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+    mReleaseTimeline.updateSignalTimes();
+    mReleaseTimeline.push(releaseFenceTime);
+
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    if (mPreviousFrameNumber != 0) {
+        mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime,
+                                      std::move(releaseFenceTime));
+    }
+}
+
+Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+    ATRACE_CALL();
+
+    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
+        // mSidebandStreamChanged was true
+        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
+        // replicated in LayerBE until FE/BE is ready to be synchronized
+        getBE().mSidebandStream = mSidebandStream;
+        if (getBE().mSidebandStream != NULL) {
+            setTransactionFlags(eTransactionNeeded);
+            mFlinger->setTransactionFlags(eTraversalNeeded);
+        }
+        recomputeVisibleRegions = true;
+
+        const State& s(getDrawingState());
+        return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
+    }
+
+    Region outDirtyRegion;
+    if (mQueuedFrames <= 0 && !mAutoRefresh) {
+        return outDirtyRegion;
+    }
+
+    // if we've already called updateTexImage() without going through
+    // a composition step, we have to skip this layer at this point
+    // because we cannot call updateTeximage() without a corresponding
+    // compositionComplete() call.
+    // we'll trigger an update in onPreComposition().
+    if (mRefreshPending) {
+        return outDirtyRegion;
+    }
+
+    // If the head buffer's acquire fence hasn't signaled yet, return and
+    // try again later
+    if (!headFenceHasSignaled()) {
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    }
+
+    // Capture the old state of the layer for comparisons later
+    const State& s(getDrawingState());
+    const bool oldOpacity = isOpaque(s);
+    sp<GraphicBuffer> oldBuffer = getBE().mBuffer;
+
+    if (!allTransactionsSignaled()) {
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    }
+
+    // This boolean is used to make sure that SurfaceFlinger's shadow copy
+    // of the buffer queue isn't modified when the buffer queue is returning
+    // BufferItem's that weren't actually queued. This can happen in shared
+    // buffer mode.
+    bool queuedBuffer = false;
+    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
+                    getProducerStickyTransform() != 0, mName.string(),
+                    mOverrideScalingMode, mFreezeGeometryUpdates);
+    status_t updateResult =
+            mSurfaceFlingerConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync,
+                                                    &mAutoRefresh, &queuedBuffer,
+                                                    mLastFrameNumberReceived);
+    if (updateResult == BufferQueue::PRESENT_LATER) {
+        // Producer doesn't want buffer to be displayed yet.  Signal a
+        // layer update so we check again at the next opportunity.
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
+        // If the buffer has been rejected, remove it from the shadow queue
+        // and return early
+        if (queuedBuffer) {
+            Mutex::Autolock lock(mQueueItemLock);
+            mQueueItems.removeAt(0);
+            android_atomic_dec(&mQueuedFrames);
+        }
+        return outDirtyRegion;
+    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
+        // This can occur if something goes wrong when trying to create the
+        // EGLImage for this buffer. If this happens, the buffer has already
+        // been released, so we need to clean up the queue and bug out
+        // early.
+        if (queuedBuffer) {
+            Mutex::Autolock lock(mQueueItemLock);
+            mQueueItems.clear();
+            android_atomic_and(0, &mQueuedFrames);
+        }
+
+        // Once we have hit this state, the shadow queue may no longer
+        // correctly reflect the incoming BufferQueue's contents, so even if
+        // updateTexImage starts working, the only safe course of action is
+        // to continue to ignore updates.
+        mUpdateTexImageFailed = true;
+
+        return outDirtyRegion;
+    }
+
+    if (queuedBuffer) {
+        // Autolock scope
+        auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+        Mutex::Autolock lock(mQueueItemLock);
+
+        // Remove any stale buffers that have been dropped during
+        // updateTexImage
+        while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+            mQueueItems.removeAt(0);
+            android_atomic_dec(&mQueuedFrames);
+        }
+
+        mQueueItems.removeAt(0);
+    }
+
+    // Decrement the queued-frames count.  Signal another event if we
+    // have more frames pending.
+    if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) ||
+        mAutoRefresh) {
+        mFlinger->signalLayerUpdate();
+    }
+
+    // update the active buffer
+    getBE().mBuffer =
+            mSurfaceFlingerConsumer->getCurrentBuffer(&getBE().mBufferSlot);
+    // replicated in LayerBE until FE/BE is ready to be synchronized
+    mActiveBuffer = getBE().mBuffer;
+    if (getBE().mBuffer == NULL) {
+        // this can only happen if the very first buffer was rejected.
+        return outDirtyRegion;
+    }
+
+    mBufferLatched = true;
+    mPreviousFrameNumber = mCurrentFrameNumber;
+    mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+    {
+        Mutex::Autolock lock(mFrameEventHistoryMutex);
+        mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
+    }
+
+    mRefreshPending = true;
+    mFrameLatencyNeeded = true;
+    if (oldBuffer == NULL) {
+        // the first time we receive a buffer, we need to trigger a
+        // geometry invalidation.
+        recomputeVisibleRegions = true;
+    }
+
+    setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
+
+    Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
+    const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
+    const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
+    if ((crop != mCurrentCrop) ||
+        (transform != mCurrentTransform) ||
+        (scalingMode != mCurrentScalingMode)) {
+        mCurrentCrop = crop;
+        mCurrentTransform = transform;
+        mCurrentScalingMode = scalingMode;
+        recomputeVisibleRegions = true;
+    }
+
+    if (oldBuffer != NULL) {
+        uint32_t bufWidth = getBE().mBuffer->getWidth();
+        uint32_t bufHeight = getBE().mBuffer->getHeight();
+        if (bufWidth != uint32_t(oldBuffer->width) ||
+            bufHeight != uint32_t(oldBuffer->height)) {
+            recomputeVisibleRegions = true;
+        }
+    }
+
+    mCurrentOpacity = getOpacityForFormat(getBE().mBuffer->format);
+    if (oldOpacity != isOpaque(s)) {
+        recomputeVisibleRegions = true;
+    }
+
+    // Remove any sync points corresponding to the buffer which was just
+    // latched
+    {
+        Mutex::Autolock lock(mLocalSyncPointMutex);
+        auto point = mLocalSyncPoints.begin();
+        while (point != mLocalSyncPoints.end()) {
+            if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
+                // This sync point must have been added since we started
+                // latching. Don't drop it yet.
+                ++point;
+                continue;
+            }
+
+            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+                point = mLocalSyncPoints.erase(point);
+            } else {
+                ++point;
+            }
+        }
+    }
+
+    // FIXME: postedRegion should be dirty & bounds
+    Region dirtyRegion(Rect(s.active.w, s.active.h));
+
+    // transform the dirty region to window-manager space
+    outDirtyRegion = (getTransform().transform(dirtyRegion));
+
+    return outDirtyRegion;
+}
+
+void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
+    mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+}
+
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+    // Apply this display's projection's viewport to the visible region
+    // before giving it to the HWC HAL.
+    const Transform& tr = displayDevice->getTransform();
+    const auto& viewport = displayDevice->getViewport();
+    Region visible = tr.transform(visibleRegion.intersect(viewport));
+    auto hwcId = displayDevice->getHwcDisplayId();
+    auto& hwcInfo = getBE().mHwcLayers[hwcId];
+    auto& hwcLayer = hwcInfo.layer;
+    auto error = hwcLayer->setVisibleRegion(visible);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+        visible.dump(LOG_TAG);
+    }
+
+    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+        surfaceDamageRegion.dump(LOG_TAG);
+    }
+
+    // Sideband layers
+    if (getBE().mSidebandStream.get()) {
+        setCompositionType(hwcId, HWC2::Composition::Sideband);
+        ALOGV("[%s] Requesting Sideband composition", mName.string());
+        error = hwcLayer->setSidebandStream(getBE().mSidebandStream->handle());
+        if (error != HWC2::Error::None) {
+            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
+                  getBE().mSidebandStream->handle(), to_string(error).c_str(),
+                  static_cast<int32_t>(error));
+        }
+        return;
+    }
+
+    // Device or Cursor layers
+    if (mPotentialCursor) {
+        ALOGV("[%s] Requesting Cursor composition", mName.string());
+        setCompositionType(hwcId, HWC2::Composition::Cursor);
+    } else {
+        ALOGV("[%s] Requesting Device composition", mName.string());
+        setCompositionType(hwcId, HWC2::Composition::Device);
+    }
+
+    ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
+    error = hwcLayer->setDataspace(mCurrentState.dataSpace);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentState.dataSpace,
+              to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    uint32_t hwcSlot = 0;
+    sp<GraphicBuffer> hwcBuffer;
+    hwcInfo.bufferCache.getHwcBuffer(getBE().mBufferSlot,
+                                     getBE().mBuffer, &hwcSlot, &hwcBuffer);
+
+    auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
+              getBE().mBuffer->handle, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+bool BufferLayer::isOpaque(const Layer::State& s) const {
+    // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
+    // layer's opaque flag.
+    if ((getBE().mSidebandStream == nullptr) && (getBE().mBuffer == nullptr)) {
+        return false;
+    }
+
+    // if the layer has the opaque flag, then we're always opaque,
+    // otherwise we use the current buffer's format.
+    return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
+}
+
+void BufferLayer::onFirstRef() {
+    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer, true);
+    mProducer = new MonitoredProducer(producer, mFlinger, this);
+    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
+    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+    mSurfaceFlingerConsumer->setContentsChangedListener(this);
+    mSurfaceFlingerConsumer->setName(mName);
+
+    if (mFlinger->isLayerTripleBufferingDisabled()) {
+        mProducer->setMaxDequeuedBufferCount(2);
+    }
+
+    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
+    updateTransformHint(hw);
+}
+
+// ---------------------------------------------------------------------------
+// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
+// ---------------------------------------------------------------------------
+
+void BufferLayer::onFrameAvailable(const BufferItem& item) {
+    // Add this buffer from our internal queue tracker
+    { // Autolock scope
+        Mutex::Autolock lock(mQueueItemLock);
+        mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+                                                item.mGraphicBuffer->getHeight(),
+                                                item.mFrameNumber);
+        // Reset the frame number tracker when we receive the first buffer after
+        // a frame number reset
+        if (item.mFrameNumber == 1) {
+            mLastFrameNumberReceived = 0;
+        }
+
+        // Ensure that callbacks are handled in order
+        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+                                                               ms2ns(500));
+            if (result != NO_ERROR) {
+                ALOGE("[%s] Timed out waiting on callback", mName.string());
+            }
+        }
+
+        mQueueItems.push_back(item);
+        android_atomic_inc(&mQueuedFrames);
+
+        // Wake up any pending callbacks
+        mLastFrameNumberReceived = item.mFrameNumber;
+        mQueueItemCondition.broadcast();
+    }
+
+    mFlinger->signalLayerUpdate();
+}
+
+void BufferLayer::onFrameReplaced(const BufferItem& item) {
+    { // Autolock scope
+        Mutex::Autolock lock(mQueueItemLock);
+
+        // Ensure that callbacks are handled in order
+        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+                                                               ms2ns(500));
+            if (result != NO_ERROR) {
+                ALOGE("[%s] Timed out waiting on callback", mName.string());
+            }
+        }
+
+        if (mQueueItems.empty()) {
+            ALOGE("Can't replace a frame on an empty queue");
+            return;
+        }
+        mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
+
+        // Wake up any pending callbacks
+        mLastFrameNumberReceived = item.mFrameNumber;
+        mQueueItemCondition.broadcast();
+    }
+}
+
+void BufferLayer::onSidebandStreamChanged() {
+    if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
+        // mSidebandStreamChanged was false
+        mFlinger->signalLayerUpdate();
+    }
+}
+
+bool BufferLayer::needsFiltering(const RenderArea& renderArea) const {
+    return mNeedsFiltering || renderArea.needsFiltering();
+}
+
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool BufferLayer::getOpacityForFormat(uint32_t format) {
+    if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+        return true;
+    }
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+            return false;
+    }
+    // in all other case, we have no blending (also for unknown formats)
+    return true;
+}
+
+void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
+    const State& s(getDrawingState());
+
+    computeGeometry(renderArea, getBE().mMesh, useIdentityTransform);
+
+    /*
+     * NOTE: the way we compute the texture coordinates here produces
+     * different results than when we take the HWC path -- in the later case
+     * the "source crop" is rounded to texel boundaries.
+     * This can produce significantly different results when the texture
+     * is scaled by a large amount.
+     *
+     * The GL code below is more logical (imho), and the difference with
+     * HWC is due to a limitation of the HWC API to integers -- a question
+     * is suspend is whether we should ignore this problem or revert to
+     * GL composition when a buffer scaling is applied (maybe with some
+     * minimal value)? Or, we could make GL behave like HWC -- but this feel
+     * like more of a hack.
+     */
+    Rect win(computeBounds());
+
+    Transform t = getTransform();
+    if (!s.finalCrop.isEmpty()) {
+        win = t.transform(win);
+        if (!win.intersect(s.finalCrop, &win)) {
+            win.clear();
+        }
+        win = t.inverse().transform(win);
+        if (!win.intersect(computeBounds(), &win)) {
+            win.clear();
+        }
+    }
+
+    float left = float(win.left) / float(s.active.w);
+    float top = float(win.top) / float(s.active.h);
+    float right = float(win.right) / float(s.active.w);
+    float bottom = float(win.bottom) / float(s.active.h);
+
+    // TODO: we probably want to generate the texture coords with the mesh
+    // here we assume that we only have 4 vertices
+    Mesh::VertexArray<vec2> texCoords(getBE().mMesh.getTexCoordArray<vec2>());
+    texCoords[0] = vec2(left, 1.0f - top);
+    texCoords[1] = vec2(left, 1.0f - bottom);
+    texCoords[2] = vec2(right, 1.0f - bottom);
+    texCoords[3] = vec2(right, 1.0f - top);
+
+    RenderEngine& engine(mFlinger->getRenderEngine());
+    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
+                              getColor());
+    engine.setSourceDataSpace(mCurrentState.dataSpace);
+    engine.drawMesh(getBE().mMesh);
+    engine.disableBlending();
+}
+
+uint32_t BufferLayer::getProducerStickyTransform() const {
+    int producerStickyTransform = 0;
+    int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
+    if (ret != OK) {
+        ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
+              strerror(-ret), ret);
+        return 0;
+    }
+    return static_cast<uint32_t>(producerStickyTransform);
+}
+
+bool BufferLayer::latchUnsignaledBuffers() {
+    static bool propertyLoaded = false;
+    static bool latch = false;
+    static std::mutex mutex;
+    std::lock_guard<std::mutex> lock(mutex);
+    if (!propertyLoaded) {
+        char value[PROPERTY_VALUE_MAX] = {};
+        property_get("debug.sf.latch_unsignaled", value, "0");
+        latch = atoi(value);
+        propertyLoaded = true;
+    }
+    return latch;
+}
+
+uint64_t BufferLayer::getHeadFrameNumber() const {
+    Mutex::Autolock lock(mQueueItemLock);
+    if (!mQueueItems.empty()) {
+        return mQueueItems[0].mFrameNumber;
+    } else {
+        return mCurrentFrameNumber;
+    }
+}
+
+bool BufferLayer::headFenceHasSignaled() const {
+    if (latchUnsignaledBuffers()) {
+        return true;
+    }
+
+    Mutex::Autolock lock(mQueueItemLock);
+    if (mQueueItems.empty()) {
+        return true;
+    }
+    if (mQueueItems[0].mIsDroppable) {
+        // Even though this buffer's fence may not have signaled yet, it could
+        // be replaced by another buffer before it has a chance to, which means
+        // that it's possible to get into a situation where a buffer is never
+        // able to be latched. To avoid this, grab this buffer anyway.
+        return true;
+    }
+    return mQueueItems[0].mFenceTime->getSignalTime() !=
+            Fence::SIGNAL_TIME_PENDING;
+}
+
+uint32_t BufferLayer::getEffectiveScalingMode() const {
+    if (mOverrideScalingMode >= 0) {
+        return mOverrideScalingMode;
+    }
+    return mCurrentScalingMode;
+}
+
+// ----------------------------------------------------------------------------
+// transaction
+// ----------------------------------------------------------------------------
+
+void BufferLayer::notifyAvailableFrames() {
+    auto headFrameNumber = getHeadFrameNumber();
+    bool headFenceSignaled = headFenceHasSignaled();
+    Mutex::Autolock lock(mLocalSyncPointMutex);
+    for (auto& point : mLocalSyncPoints) {
+        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
+            point->setFrameAvailable();
+        }
+    }
+}
+
+sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
+    return mProducer;
+}
+
+// ---------------------------------------------------------------------------
+// h/w composer set-up
+// ---------------------------------------------------------------------------
+
+bool BufferLayer::allTransactionsSignaled() {
+    auto headFrameNumber = getHeadFrameNumber();
+    bool matchingFramesFound = false;
+    bool allTransactionsApplied = true;
+    Mutex::Autolock lock(mLocalSyncPointMutex);
+
+    for (auto& point : mLocalSyncPoints) {
+        if (point->getFrameNumber() > headFrameNumber) {
+            break;
+        }
+        matchingFramesFound = true;
+
+        if (!point->frameIsAvailable()) {
+            // We haven't notified the remote layer that the frame for
+            // this point is available yet. Notify it now, and then
+            // abort this attempt to latch.
+            point->setFrameAvailable();
+            allTransactionsApplied = false;
+            break;
+        }
+
+        allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
+    }
+    return !matchingFramesFound || allTransactionsApplied;
+}
+
+} // namespace android
+
+#if defined(__gl_h_)
+#error "don't include gl/gl.h in this file"
+#endif
+
+#if defined(__gl2_h_)
+#error "don't include gl2/gl2.h in this file"
+#endif
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
new file mode 100644
index 0000000..1127952
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Client.h"
+#include "Layer.h"
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
+#include "FrameTracker.h"
+#include "LayerVector.h"
+#include "MonitoredProducer.h"
+#include "RenderEngine/Mesh.h"
+#include "RenderEngine/Texture.h"
+#include "SurfaceFlinger.h"
+#include "SurfaceFlingerConsumer.h"
+#include "Transform.h"
+
+#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+
+#include <ui/FrameStats.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <list>
+
+namespace android {
+
+/*
+ * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
+ * BufferLayer is first referenced.
+ *
+ * This also implements onFrameAvailable(), which notifies SurfaceFlinger
+ * that new data has arrived.
+ */
+class BufferLayer : public Layer, public SurfaceFlingerConsumer::ContentsChangedListener {
+public:
+    BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+                uint32_t h, uint32_t flags);
+
+    ~BufferLayer() override;
+
+    // If we have received a new buffer this frame, we will pass its surface
+    // damage down to hardware composer. Otherwise, we must send a region with
+    // one empty rect.
+    void useSurfaceDamage();
+    void useEmptyDamage();
+
+    // -----------------------------------------------------------------------
+    // Overriden from Layer
+    // -----------------------------------------------------------------------
+
+    /*
+     * getTypeId - Provide unique string for each class type in the Layer
+     * hierarchy
+     */
+    const char* getTypeId() const override { return "BufferLayer"; }
+
+    /*
+     * isProtected - true if the layer may contain protected content in the
+     * GRALLOC_USAGE_PROTECTED sense.
+     */
+    bool isProtected() const;
+
+    /*
+     * isVisible - true if this layer is visible, false otherwise
+     */
+    bool isVisible() const override;
+
+    /*
+     * isFixedSize - true if content has a fixed size
+     */
+    bool isFixedSize() const override;
+
+    // the this layer's size and format
+    status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+    /*
+     * onDraw - draws the surface.
+     */
+    void onDraw(const RenderArea& renderArea, const Region& clip,
+                bool useIdentityTransform) const override;
+
+    void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+
+    void abandon() override;
+    bool shouldPresentNow(const DispSync& dispSync) const override;
+    void setTransformHint(uint32_t orientation) const override;
+    bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+                           const std::shared_ptr<FenceTime>& presentFence,
+                           const CompositorTiming& compositorTiming) override;
+    std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
+    bool getTransformToDisplayInverse() const override;
+
+public:
+    bool onPreComposition(nsecs_t refreshStartTime) override;
+
+    // If a buffer was replaced this frame, release the former buffer
+    void releasePendingBuffer(nsecs_t dequeueReadyTime);
+
+    /*
+     * latchBuffer - called each time the screen is redrawn and returns whether
+     * the visible regions need to be recomputed (this is a fairly heavy
+     * operation, so this should be set only if needed). Typically this is used
+     * to figure out if the content or size of a surface has changed.
+     */
+    Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+    bool isBufferLatched() const override { return mRefreshPending; }
+    void setDefaultBufferSize(uint32_t w, uint32_t h) override;
+
+    void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+
+    bool isOpaque(const Layer::State& s) const override;
+
+private:
+    void onFirstRef() override;
+
+    // Interface implementation for
+    // SurfaceFlingerConsumer::ContentsChangedListener
+    void onFrameAvailable(const BufferItem& item) override;
+    void onFrameReplaced(const BufferItem& item) override;
+    void onSidebandStreamChanged() override;
+
+    // needsLinearFiltering - true if this surface's state requires filtering
+    bool needsFiltering(const RenderArea& renderArea) const;
+
+    static bool getOpacityForFormat(uint32_t format);
+
+    // drawing
+    void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
+
+    // Temporary - Used only for LEGACY camera mode.
+    uint32_t getProducerStickyTransform() const;
+
+    // Loads the corresponding system property once per process
+    static bool latchUnsignaledBuffers();
+
+    uint64_t getHeadFrameNumber() const;
+    bool headFenceHasSignaled() const;
+
+    // Returns the current scaling mode, unless mOverrideScalingMode
+    // is set, in which case, it returns mOverrideScalingMode
+    uint32_t getEffectiveScalingMode() const override;
+
+public:
+    void notifyAvailableFrames() override;
+
+    PixelFormat getPixelFormat() const override { return mFormat; }
+    sp<IGraphicBufferProducer> getProducer() const;
+
+private:
+    sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
+
+    // Check all of the local sync points to ensure that all transactions
+    // which need to have been applied prior to the frame which is about to
+    // be latched have signaled
+    bool allTransactionsSignaled();
+    sp<IGraphicBufferProducer> mProducer;
+
+    // constants
+    uint32_t mTextureName; // from GLES
+    PixelFormat mFormat;
+
+    // main thread
+    uint32_t mCurrentScalingMode;
+    bool mBufferLatched = false;   // TODO: Use mActiveBuffer?
+    uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
+    // The texture used to draw the layer in GLES composition mode
+    mutable Texture mTexture;
+
+    bool mUpdateTexImageFailed; // This is only accessed on the main thread.
+    bool mRefreshPending;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 8ba6cb9..ea6541a 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -140,7 +140,8 @@
 {
     sp<Layer> parent = nullptr;
     if (parentHandle != nullptr) {
-        parent = getLayerUser(parentHandle);
+        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
+        parent = layerHandle->owner.promote();
         if (parent == nullptr) {
             return NAME_NOT_FOUND;
         }
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
new file mode 100644
index 0000000..b784c8d
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "ColorLayer"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include "ColorLayer.h"
+#include "DisplayDevice.h"
+#include "RenderEngine/RenderEngine.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+                       uint32_t w, uint32_t h, uint32_t flags)
+      : Layer(flinger, client, name, w, h, flags) {
+    // drawing state & current state are identical
+    mDrawingState = mCurrentState;
+}
+
+void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
+                        bool useIdentityTransform) const {
+    const State& s(getDrawingState());
+    if (s.color.a > 0) {
+        Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+        computeGeometry(renderArea, mesh, useIdentityTransform);
+        RenderEngine& engine(mFlinger->getRenderEngine());
+        engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
+                                  true /* disableTexture */, s.color);
+        engine.drawMesh(mesh);
+        engine.disableBlending();
+    }
+}
+
+bool ColorLayer::isVisible() const {
+    const Layer::State& s(getDrawingState());
+    return !isHiddenByPolicy() && s.color.a;
+}
+
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+    const Transform& tr = displayDevice->getTransform();
+    const auto& viewport = displayDevice->getViewport();
+    Region visible = tr.transform(visibleRegion.intersect(viewport));
+    auto hwcId = displayDevice->getHwcDisplayId();
+    auto& hwcInfo = getBE().mHwcLayers[hwcId];
+    auto& hwcLayer = hwcInfo.layer;
+    auto error = hwcLayer->setVisibleRegion(visible);
+
+    setCompositionType(hwcId, HWC2::Composition::SolidColor);
+
+    half4 color = getColor();
+    error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
+                                static_cast<uint8_t>(std::round(255.0f * color.g)),
+                                static_cast<uint8_t>(std::round(255.0f * color.b)), 255});
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+
+    // Clear out the transform, because it doesn't make sense absent a source buffer
+    error = hwcLayer->setTransform(HWC2::Transform::None);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
new file mode 100644
index 0000000..4022b31
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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_COLOR_LAYER_H
+#define ANDROID_COLOR_LAYER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "Layer.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class ColorLayer : public Layer {
+public:
+    ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+               uint32_t h, uint32_t flags);
+    virtual ~ColorLayer() = default;
+
+    virtual const char* getTypeId() const { return "ColorLayer"; }
+    virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+                        bool useIdentityTransform) const;
+    bool isVisible() const override;
+    virtual bool isOpaque(const Layer::State&) const { return false; }
+    virtual bool isFixedSize() const { return true; }
+
+    void notifyAvailableFrames() override {}
+    PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; }
+    uint32_t getEffectiveScalingMode() const override { return 0; }
+    void releasePendingBuffer(nsecs_t) override {}
+    Region latchBuffer(bool&, nsecs_t) override { return Region(); }
+    void useSurfaceDamage() override {}
+    void useEmptyDamage() override {}
+    bool isBufferLatched() const override { return false; }
+    bool onPreComposition(nsecs_t) override { return true; }
+    void abandon() override {}
+    void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+    void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) override {}
+    bool shouldPresentNow(const DispSync& /*dispSync*/) const override { return false; }
+    bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+                           const std::shared_ptr<FenceTime>& /*presentFence*/,
+                           const CompositorTiming& /*compositorTiming*/) override {
+        return false;
+    }
+    void setTransformHint(uint32_t /*orientation*/) const override {}
+    std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool /*forceFlush*/) override {
+        return {};
+    }
+    bool getTransformToDisplayInverse() const override { return false; }
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_COLOR_LAYER_H
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 95802bd..2753f11 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -28,6 +28,7 @@
 #include <utils/RefBase.h>
 #include <utils/Log.h>
 
+#include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
 
@@ -37,9 +38,7 @@
 
 #include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
-#ifdef USE_HWC2
 #include "DisplayHardware/HWC2.h"
-#endif
 #include "RenderEngine/RenderEngine.h"
 
 #include "clz.h"
@@ -54,12 +53,6 @@
 using namespace android;
 // ----------------------------------------------------------------------------
 
-#ifdef EGL_ANDROID_swap_rectangle
-static constexpr bool kEGLAndroidSwapRectangle = true;
-#else
-static constexpr bool kEGLAndroidSwapRectangle = false;
-#endif
-
 // retrieve triple buffer setting from configstore
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
@@ -67,12 +60,6 @@
 static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
         &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3;
 
-#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
-// Dummy implementation in case it is missing.
-inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
-}
-#endif
-
 /*
  * Initialize the display to the specified values.
  *
@@ -85,14 +72,10 @@
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
         int32_t hwcId,
-#ifndef USE_HWC2
-        int format,
-#endif
         bool isSecure,
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer,
-        EGLConfig config,
         bool supportWideColor)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
@@ -100,14 +83,9 @@
       mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
-      mDisplay(EGL_NO_DISPLAY),
-      mSurface(EGL_NO_SURFACE),
+      mSurface{flinger->getRenderEngine()},
       mDisplayWidth(),
       mDisplayHeight(),
-#ifndef USE_HWC2
-      mFormat(),
-#endif
-      mFlags(),
       mPageFlipCount(),
       mIsSecure(isSecure),
       mLayerStack(NO_LAYER_STACK),
@@ -120,30 +98,16 @@
     mNativeWindow = surface = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
-#ifdef USE_HWC2
     mActiveColorMode = HAL_COLOR_MODE_NATIVE;
     mDisplayHasWideColor = supportWideColor;
-#else
-    (void) supportWideColor;
-#endif
     /*
      * Create our display's surface
      */
-
-    EGLSurface eglSurface;
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (config == EGL_NO_CONFIG) {
-#ifdef USE_HWC2
-        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
-                                               /*logConfig*/ false);
-#else
-        config = RenderEngine::chooseEglConfig(display, format,
-                                               /*logConfig*/ false);
-#endif
-    }
-    eglSurface = eglCreateWindowSurface(display, config, window, NULL);
-    eglQuerySurface(display, eglSurface, EGL_WIDTH,  &mDisplayWidth);
-    eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
+    mSurface.setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
+    mSurface.setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
+    mSurface.setNativeWindow(window);
+    mDisplayWidth = mSurface.queryWidth();
+    mDisplayHeight = mSurface.queryHeight();
 
     // 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
@@ -155,12 +119,6 @@
     if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
         window->setSwapInterval(window, 0);
 
-    mConfig = config;
-    mDisplay = display;
-    mSurface = eglSurface;
-#ifndef USE_HWC2
-    mFormat = format;
-#endif
     mPageFlipCount = 0;
     mViewport.makeInvalid();
     mFrame.makeInvalid();
@@ -192,19 +150,11 @@
 }
 
 DisplayDevice::~DisplayDevice() {
-    if (mSurface != EGL_NO_SURFACE) {
-        eglDestroySurface(mDisplay, mSurface);
-        mSurface = EGL_NO_SURFACE;
-    }
 }
 
 void DisplayDevice::disconnect(HWComposer& hwc) {
     if (mHwcDisplayId >= 0) {
         hwc.disconnectDisplay(mHwcDisplayId);
-#ifndef USE_HWC2
-        if (mHwcDisplayId >= DISPLAY_VIRTUAL)
-            hwc.freeDisplayId(mHwcDisplayId);
-#endif
         mHwcDisplayId = -1;
     }
 }
@@ -221,16 +171,6 @@
     return mDisplayHeight;
 }
 
-#ifndef USE_HWC2
-PixelFormat DisplayDevice::getFormat() const {
-    return mFormat;
-}
-#endif
-
-EGLSurface DisplayDevice::getEGLSurface() const {
-    return mSurface;
-}
-
 void DisplayDevice::setDisplayName(const String8& displayName) {
     if (!displayName.isEmpty()) {
         // never override the name with an empty name
@@ -242,25 +182,9 @@
     return mPageFlipCount;
 }
 
-#ifndef USE_HWC2
-status_t DisplayDevice::compositionComplete() const {
-    return mDisplaySurface->compositionComplete();
-}
-#endif
-
-void DisplayDevice::flip(const Region& dirty) const
+void DisplayDevice::flip() const
 {
     mFlinger->getRenderEngine().checkErrors();
-
-    if (kEGLAndroidSwapRectangle) {
-        if (mFlags & SWAP_RECTANGLE) {
-            const Region newDirty(dirty.intersect(bounds()));
-            const Rect b(newDirty.getBounds());
-            eglSetSwapRectangleANDROID(mDisplay, mSurface,
-                    b.left, b.top, b.width(), b.height());
-        }
-    }
-
     mPageFlipCount++;
 }
 
@@ -268,7 +192,6 @@
     return mDisplaySurface->beginFrame(mustRecompose);
 }
 
-#ifdef USE_HWC2
 status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
     status_t error = hwc.prepare(*this);
     if (error != NO_ERROR) {
@@ -292,53 +215,10 @@
     }
     return mDisplaySurface->prepareFrame(compositionType);
 }
-#else
-status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
-    DisplaySurface::CompositionType compositionType;
-    bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
-    bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
-    if (haveGles && haveHwc) {
-        compositionType = DisplaySurface::COMPOSITION_MIXED;
-    } else if (haveGles) {
-        compositionType = DisplaySurface::COMPOSITION_GLES;
-    } else if (haveHwc) {
-        compositionType = DisplaySurface::COMPOSITION_HWC;
-    } else {
-        // Nothing to do -- when turning the screen off we get a frame like
-        // this. Call it a HWC frame since we won't be doing any GLES work but
-        // will do a prepare/set cycle.
-        compositionType = DisplaySurface::COMPOSITION_HWC;
-    }
-    return mDisplaySurface->prepareFrame(compositionType);
-}
-#endif
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
-#ifdef USE_HWC2
     if (hwc.hasClientComposition(mHwcDisplayId)) {
-#else
-    // We need to call eglSwapBuffers() if:
-    //  (1) we don't have a hardware composer, or
-    //  (2) we did GLES composition this frame, and either
-    //    (a) we have framebuffer target support (not present on legacy
-    //        devices, where HWComposer::commit() handles things); or
-    //    (b) this is a virtual display
-    if (hwc.initCheck() != NO_ERROR ||
-            (hwc.hasGlesComposition(mHwcDisplayId) &&
-             (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
-#endif
-        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
-        if (!success) {
-            EGLint error = eglGetError();
-            if (error == EGL_CONTEXT_LOST ||
-                    mType == DisplayDevice::DISPLAY_PRIMARY) {
-                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
-                        mDisplay, mSurface, error);
-            } else {
-                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
-                        mDisplay, mSurface, error);
-            }
-        }
+        mSurface.swapBuffers();
     }
 
     status_t result = mDisplaySurface->advanceFrame();
@@ -348,35 +228,14 @@
     }
 }
 
-#ifdef USE_HWC2
 void DisplayDevice::onSwapBuffersCompleted() const {
     mDisplaySurface->onFrameCommitted();
 }
-#else
-void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
-    if (hwc.initCheck() == NO_ERROR) {
-        mDisplaySurface->onFrameCommitted();
-    }
-}
-#endif
 
-uint32_t DisplayDevice::getFlags() const
-{
-    return mFlags;
-}
-
-EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
-    EGLBoolean result = EGL_TRUE;
-    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
-    if (sur != mSurface) {
-        result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
-        if (result == EGL_TRUE) {
-            if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
-                eglSwapInterval(dpy, 0);
-        }
-    }
+bool DisplayDevice::makeCurrent() const {
+    bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface);
     setViewportAndProjection();
-    return result;
+    return success;
 }
 
 void DisplayDevice::setViewportAndProjection() const {
@@ -444,7 +303,6 @@
 }
 
 // ----------------------------------------------------------------------------
-#ifdef USE_HWC2
 void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
     mActiveColorMode = mode;
 }
@@ -457,7 +315,6 @@
     ANativeWindow* const window = mNativeWindow.get();
     native_window_set_buffers_data_space(window, dataspace);
 }
-#endif
 
 // ----------------------------------------------------------------------------
 
@@ -514,17 +371,14 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
-    if (mSurface != EGL_NO_SURFACE) {
-        eglDestroySurface(mDisplay, mSurface);
-        mSurface = EGL_NO_SURFACE;
-    }
+    mSurface.setNativeWindow(nullptr);
 
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
     ANativeWindow* const window = mNativeWindow.get();
-    mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
-    eglQuerySurface(mDisplay, mSurface, EGL_WIDTH,  &mDisplayWidth);
-    eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
+    mSurface.setNativeWindow(window);
+    mDisplayWidth = mSurface.queryWidth();
+    mDisplayHeight = mSurface.queryHeight();
 
     LOG_FATAL_IF(mDisplayWidth != newWidth,
                 "Unable to set new width to %d", newWidth);
@@ -625,18 +479,15 @@
 
 void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
-    EGLint redSize, greenSize, blueSize, alphaSize;
-    eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
-    eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
-    eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &blueSize);
-    eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &alphaSize);
+    ANativeWindow* const window = mNativeWindow.get();
     result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
     result.appendFormat("   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
                         "(%d:%d:%d:%d), orient=%2d (type=%08x), "
                         "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
-                        mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight,
-                        mNativeWindow.get(), redSize, greenSize, blueSize, alphaSize, mOrientation,
-                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
+                        mSurface.queryRedSize(), mSurface.queryGreenSize(), mSurface.queryBlueSize(),
+                        mSurface.queryAlphaSize(), mOrientation, tr.getType(),
+                        getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
                         mVisibleLayersSortedByZ.size());
     result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
                         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
@@ -644,6 +495,9 @@
                         mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
                         mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
                         tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
+    auto const surface = static_cast<Surface*>(window);
+    android_dataspace dataspace = surface->getBuffersDataSpace();
+    result.appendFormat("   dataspace: %s (%d)\n", dataspaceDetails(dataspace).c_str(), dataspace);
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e8a5929..499bf8e 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -21,27 +21,20 @@
 
 #include <stdlib.h>
 
-#ifndef USE_HWC2
-#include <ui/PixelFormat.h>
-#endif
 #include <ui/Region.h>
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#ifdef USE_HWC2
 #include <binder/IBinder.h>
 #include <utils/RefBase.h>
-#endif
 #include <utils/Mutex.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
+#include <gui/ISurfaceComposer.h>
 #include <hardware/hwcomposer_defs.h>
+#include "RenderArea.h"
+#include "RenderEngine/Surface.h"
 
-#ifdef USE_HWC2
 #include <memory>
-#endif
 
 struct ANativeWindow;
 
@@ -61,8 +54,6 @@
     // region in layer-stack space
     mutable Region dirtyRegion;
     // region in screen space
-    mutable Region swapRegion;
-    // region in screen space
     Region undefinedRegion;
     bool lastCompositionHadVisibleLayers;
 
@@ -75,11 +66,6 @@
     };
 
     enum {
-        PARTIAL_UPDATES = 0x00020000, // video driver feature
-        SWAP_RECTANGLE  = 0x00080000,
-    };
-
-    enum {
         NO_LAYER_STACK = 0xFFFFFFFF,
     };
 
@@ -88,14 +74,10 @@
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
             int32_t hwcId,
-#ifndef USE_HWC2
-            int format,
-#endif
             bool isSecure,
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
             const sp<IGraphicBufferProducer>& producer,
-            EGLConfig config,
             bool supportWideColor);
     // clang-format on
 
@@ -111,16 +93,10 @@
 
     // Flip the front and back buffers if the back buffer is "dirty".  Might
     // be instantaneous, might involve copying the frame buffer around.
-    void flip(const Region& dirty) const;
+    void flip() const;
 
     int         getWidth() const;
     int         getHeight() const;
-#ifndef USE_HWC2
-    PixelFormat getFormat() const;
-#endif
-    uint32_t    getFlags() const;
-
-    EGLSurface  getEGLSurface() const;
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
@@ -150,24 +126,13 @@
     // We pass in mustRecompose so we can keep VirtualDisplaySurface's state
     // machine happy without actually queueing a buffer if nothing has changed
     status_t beginFrame(bool mustRecompose) const;
-#ifdef USE_HWC2
     status_t prepareFrame(HWComposer& hwc);
     bool getWideColorSupport() const { return mDisplayHasWideColor; }
-#else
-    status_t prepareFrame(const HWComposer& hwc) const;
-#endif
 
     void swapBuffers(HWComposer& hwc) const;
-#ifndef USE_HWC2
-    status_t compositionComplete() const;
-#endif
 
     // called after h/w composer has completed its set() call
-#ifdef USE_HWC2
     void onSwapBuffersCompleted() const;
-#else
-    void onSwapBuffersCompleted(HWComposer& hwc) const;
-#endif
 
     Rect getBounds() const {
         return Rect(mDisplayWidth, mDisplayHeight);
@@ -177,7 +142,7 @@
     void setDisplayName(const String8& displayName);
     const String8& getDisplayName() const { return mDisplayName; }
 
-    EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const;
+    bool makeCurrent() const;
     void setViewportAndProjection() const;
 
     const sp<Fence>& getClientTargetAcquireFence() const;
@@ -189,11 +154,9 @@
     void setPowerMode(int mode);
     bool isDisplayOn() const;
 
-#ifdef USE_HWC2
     android_color_mode_t getActiveColorMode() const;
     void setActiveColorMode(android_color_mode_t mode);
     void setCompositionDataSpace(android_dataspace dataspace);
-#endif
 
     /* ------------------------------------------------------------------------
      * Display active config management.
@@ -223,15 +186,9 @@
     sp<ANativeWindow> mNativeWindow;
     sp<DisplaySurface> mDisplaySurface;
 
-    EGLConfig       mConfig;
-    EGLDisplay      mDisplay;
-    EGLSurface      mSurface;
+    RE::Surface     mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
-#ifndef USE_HWC2
-    PixelFormat     mFormat;
-#endif
-    uint32_t        mFlags;
     mutable uint32_t mPageFlipCount;
     String8         mDisplayName;
     bool            mIsSecure;
@@ -271,7 +228,6 @@
     int mPowerMode;
     // Current active config
     int mActiveConfig;
-#ifdef USE_HWC2
     // current active color mode
     android_color_mode_t mActiveColorMode;
 
@@ -279,7 +235,6 @@
     // Initialized by SurfaceFlinger when the DisplayDevice is created.
     // Fed to RenderEngine during composition.
     bool mDisplayHasWideColor;
-#endif
 };
 
 struct DisplayDeviceState {
@@ -304,6 +259,33 @@
     bool isSecure = false;
 };
 
+class DisplayRenderArea : public RenderArea {
+public:
+    DisplayRenderArea(const sp<const DisplayDevice> device,
+                      ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
+          : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
+                              rotation) {}
+    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
+                      uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
+          : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {}
+
+    const Transform& getTransform() const override { return mDevice->getTransform(); }
+    Rect getBounds() const override { return mDevice->getBounds(); }
+    int getHeight() const override { return mDevice->getHeight(); }
+    int getWidth() const override { return mDevice->getWidth(); }
+    bool isSecure() const override { return mDevice->isSecure(); }
+    bool needsFiltering() const override { return mDevice->needsFiltering(); }
+    Rect getSourceCrop() const override { return mSourceCrop; }
+    bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
+    android_color_mode_t getActiveColorMode() const override {
+        return mDevice->getActiveColorMode();
+    }
+
+private:
+    const sp<const DisplayDevice> mDevice;
+    const Rect mSourceCrop;
+};
+
 }; // namespace android
 
 #endif // ANDROID_DISPLAY_DEVICE_H
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 7d6d988..c707e3c 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -223,6 +223,10 @@
     mWriter.reset();
 }
 
+Error Composer::executeCommands() {
+    return execute();
+}
+
 uint32_t Composer::getMaxVirtualDisplayCount()
 {
     auto ret = mClient->getMaxVirtualDisplayCount();
@@ -750,6 +754,11 @@
         }
     }
 
+    if (commandLength == 0) {
+        mWriter.reset();
+        return Error::NONE;
+    }
+
     Error error = kDefaultError;
     auto ret = mClient->executeCommands(commandLength, commandHandles,
             [&](const auto& tmpError, const auto& tmpOutChanged,
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 31a3c1d..104ca60 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -152,6 +152,9 @@
     // skip a frame but have already queued some commands.
     void resetCommands();
 
+    // Explicitly flush all pending commands in the command buffer.
+    Error executeCommands();
+
     uint32_t getMaxVirtualDisplayCount();
     bool isUsingVrComposer() const { return mIsUsingVrComposer; }
     Error createVirtualDisplay(uint32_t width, uint32_t height,
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index cb08f08..f744f5c 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -50,14 +50,6 @@
     };
     virtual status_t prepareFrame(CompositionType compositionType) = 0;
 
-#ifndef USE_HWC2
-    // Should be called when composition rendering is complete for a frame (but
-    // eglSwapBuffers hasn't necessarily been called). Required by certain
-    // older drivers for synchronization.
-    // TODO: Remove this when we drop support for HWC 1.0.
-    virtual status_t compositionComplete() = 0;
-#endif
-
     // Inform the surface that GLES composition is complete for this frame, and
     // the surface should make sure that HWComposer has the correct buffer for
     // this frame. Some implementations may only push a new buffer to
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 93c6d54..8b5d4c9 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -27,8 +27,6 @@
 #include <utils/String8.h>
 #include <log/log.h>
 
-#include <EGL/egl.h>
-
 #include <hardware/hardware.h>
 #include <gui/BufferItem.h>
 #include <gui/BufferQueue.h>
@@ -59,32 +57,21 @@
     mCurrentBufferSlot(-1),
     mCurrentBuffer(),
     mCurrentFence(Fence::NO_FENCE),
-#ifdef USE_HWC2
     mHwc(hwc),
     mHasPendingRelease(false),
     mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
     mPreviousBuffer()
-#else
-    mHwc(hwc)
-#endif
 {
-#ifdef USE_HWC2
     ALOGV("Creating for display %d", disp);
-#endif
 
     mName = "FramebufferSurface";
     mConsumer->setConsumerName(mName);
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                        GRALLOC_USAGE_HW_RENDER |
                                        GRALLOC_USAGE_HW_COMPOSER);
-#ifdef USE_HWC2
     const auto& activeConfig = mHwc.getActiveConfig(disp);
     mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
             activeConfig->getHeight());
-#else
-    mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
-    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
-#endif
     mConsumer->setMaxAcquiredBufferCount(
             SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
 }
@@ -98,7 +85,6 @@
 }
 
 status_t FramebufferSurface::advanceFrame() {
-#ifdef USE_HWC2
     uint32_t slot = 0;
     sp<GraphicBuffer> buf;
     sp<Fence> acquireFence(Fence::NO_FENCE);
@@ -110,32 +96,18 @@
                 strerror(-result), result);
     }
     return result;
-#else
-    // Once we remove FB HAL support, we can call nextBuffer() from here
-    // instead of using onFrameAvailable(). No real benefit, except it'll be
-    // more like VirtualDisplaySurface.
-    return NO_ERROR;
-#endif
 }
 
-#ifdef USE_HWC2
 status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
         sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
         android_dataspace_t& outDataspace) {
-#else
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
-#endif
     Mutex::Autolock lock(mMutex);
 
     BufferItem item;
     status_t err = acquireBufferLocked(&item, 0);
     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-#ifdef USE_HWC2
         mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
                 &outSlot, &outBuffer);
-#else
-        outBuffer = mCurrentBuffer;
-#endif
         return NO_ERROR;
     } else if (err != NO_ERROR) {
         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
@@ -152,26 +124,15 @@
     // had released the old buffer first.
     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
         item.mSlot != mCurrentBufferSlot) {
-#ifdef USE_HWC2
         mHasPendingRelease = true;
         mPreviousBufferSlot = mCurrentBufferSlot;
         mPreviousBuffer = mCurrentBuffer;
-#else
-        // Release the previous buffer.
-        err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
-                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
-        if (err < NO_ERROR) {
-            ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
-            return err;
-        }
-#endif
     }
     mCurrentBufferSlot = item.mSlot;
     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
     mCurrentFence = item.mFence;
 
     outFence = item.mFence;
-#ifdef USE_HWC2
     mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
             &outSlot, &outBuffer);
     outDataspace = item.mDataSpace;
@@ -181,31 +142,10 @@
         ALOGE("error posting framebuffer: %d", result);
         return result;
     }
-#else
-    outBuffer = mCurrentBuffer;
-#endif
 
     return NO_ERROR;
 }
 
-#ifndef USE_HWC2
-// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
-void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
-    sp<GraphicBuffer> buf;
-    sp<Fence> acquireFence;
-    status_t err = nextBuffer(buf, acquireFence);
-    if (err != NO_ERROR) {
-        ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
-                strerror(-err), err);
-        return;
-    }
-    err = mHwc.fbPost(mDisplayType, acquireFence, buf);
-    if (err != NO_ERROR) {
-        ALOGE("error posting framebuffer: %d", err);
-    }
-}
-#endif
-
 void FramebufferSurface::freeBufferLocked(int slotIndex) {
     ConsumerBase::freeBufferLocked(slotIndex);
     if (slotIndex == mCurrentBufferSlot) {
@@ -214,7 +154,6 @@
 }
 
 void FramebufferSurface::onFrameCommitted() {
-#ifdef USE_HWC2
     if (mHasPendingRelease) {
         sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
         if (fence->isValid()) {
@@ -223,33 +162,15 @@
             ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
                     " fence: %s (%d)", strerror(-result), result);
         }
-        status_t result = releaseBufferLocked(mPreviousBufferSlot,
-                mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+        status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer);
         ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
                 " %s (%d)", strerror(-result), result);
 
         mPreviousBuffer.clear();
         mHasPendingRelease = false;
     }
-#else
-    sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
-    if (fence->isValid() &&
-            mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t err = addReleaseFence(mCurrentBufferSlot,
-                mCurrentBuffer, fence);
-        ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
-                strerror(-err), err);
-    }
-#endif
 }
 
-#ifndef USE_HWC2
-status_t FramebufferSurface::compositionComplete()
-{
-    return mHwc.fbCompositionComplete();
-}
-#endif
-
 void FramebufferSurface::dumpAsString(String8& result) const {
     Mutex::Autolock lock(mMutex);
     result.appendFormat("FramebufferSurface: dataspace: %s(%d)\n",
@@ -259,9 +180,6 @@
 
 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
 {
-#ifndef USE_HWC2
-    mHwc.fbDump(result);
-#endif
     ConsumerBase::dumpLocked(result, prefix);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index a1756ca..4186b7a 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -42,9 +42,6 @@
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
-#ifndef USE_HWC2
-    virtual status_t compositionComplete();
-#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
@@ -58,9 +55,6 @@
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
 
-#ifndef USE_HWC2
-    virtual void onFrameAvailable(const BufferItem& item);
-#endif
     virtual void freeBufferLocked(int slotIndex);
 
     virtual void dumpLocked(String8& result, const char* prefix) const;
@@ -68,12 +62,8 @@
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
-#ifdef USE_HWC2
     status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer,
             sp<Fence>& outFence, android_dataspace_t& outDataspace);
-#else
-    status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
-#endif
 
     // mDisplayType must match one of the HWC display types
     int mDisplayType;
@@ -100,14 +90,12 @@
     // Hardware composer, owned by SurfaceFlinger.
     HWComposer& mHwc;
 
-#ifdef USE_HWC2
     HWComposerBufferCache mHwcBufferCache;
 
     // Previous buffer to release after getting an updated retire fence
     bool mHasPendingRelease;
     int mPreviousBufferSlot;
     sp<GraphicBuffer> mPreviousBuffer;
-#endif
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 78c0c85..ab4a4b2 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -221,6 +221,11 @@
     }
 }
 
+Error Device::flushCommands()
+{
+    return static_cast<Error>(mComposer->executeCommands());
+}
+
 // Display methods
 
 Display::Display(android::Hwc2::Composer& composer,
@@ -632,11 +637,6 @@
     return error;
 }
 
-void Display::discardCommands()
-{
-    mComposer.resetCommands();
-}
-
 // For use by Device
 
 void Display::setConnected(bool connected) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index fbe4c7e..a15c6d9 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -106,6 +106,11 @@
 
     android::Hwc2::Composer* getComposer() { return mComposer.get(); }
 
+    // We buffer most state changes and flush them implicitly with
+    // Display::validate, Display::present, and Display::presentOrValidate.
+    // This method provides an explicit way to flush state changes to HWC.
+    Error flushCommands();
+
 private:
     // Initialization methods
 
@@ -244,12 +249,6 @@
                                                  uint32_t* outNumRequests,
                                                           android::sp<android::Fence>* outPresentFence, uint32_t* state);
 
-    // Most methods in this class write a command to a command buffer.  The
-    // command buffer is implicitly submitted in validate, present, and
-    // presentOrValidate.  This method provides a way to discard the commands,
-    // which can be used to discard stale commands.
-    void discardCommands();
-
     // Other Display methods
 
     hwc2_display_t getId() const { return mId; }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b096a3a..60b85c5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -605,8 +605,11 @@
     auto& hwcDisplay = displayData.hwcDisplay;
 
     if (displayData.validateWasSkipped) {
-        hwcDisplay->discardCommands();
-        auto error = displayData.presentError;
+        // explicitly flush all pending commands
+        auto error = mHwcDevice->flushCommands();
+        if (displayData.presentError != HWC2::Error::None) {
+            error = displayData.presentError;
+        }
         if (error != HWC2::Error::None) {
             ALOGE("skipValidate: failed for display %d: %s (%d)",
                   displayId, to_string(error).c_str(), static_cast<int32_t>(error));
@@ -865,6 +868,14 @@
     result.append(mHwcDevice->dump().c_str());
 }
 
+std::optional<hwc2_display_t>
+HWComposer::getHwcDisplayId(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        return {};
+    }
+    return mDisplayData[displayId].hwcDisplay->getId();
+}
+
 // ---------------------------------------------------------------------------
 
 HWComposer::DisplayData::DisplayData()
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3640bb5..74b3a38 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef USE_HWC2
-#include "HWComposer_hwc1.h"
-#else
-
 #ifndef ANDROID_SF_HWCOMPOSER_H
 #define ANDROID_SF_HWCOMPOSER_H
 
@@ -37,6 +33,7 @@
 #include <utils/Vector.h>
 
 #include <memory>
+#include <optional>
 #include <set>
 #include <vector>
 
@@ -165,6 +162,8 @@
     void dump(String8& out) const;
 
     android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
+
+    std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const;
 private:
     static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
@@ -219,5 +218,3 @@
 }; // namespace android
 
 #endif // ANDROID_SF_HWCOMPOSER_H
-
-#endif // #ifdef USE_HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
deleted file mode 100644
index dcb2913..0000000
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/misc.h>
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-#include <utils/Thread.h>
-#include <utils/Trace.h>
-#include <utils/Vector.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-
-#include <android/configuration.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-#include <system/graphics.h>
-
-#include "HWComposer.h"
-
-#include "../Layer.h"           // needed only for debugging
-#include "../SurfaceFlinger.h"
-
-namespace android {
-
-#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
-
-static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-}
-
-static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
-}
-
-static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
-        uint32_t version) {
-    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
-}
-
-// ---------------------------------------------------------------------------
-
-struct HWComposer::cb_context {
-    struct callbacks : public hwc_procs_t {
-        // these are here to facilitate the transition when adding
-        // new callbacks (an implementation can check for NULL before
-        // calling a new callback).
-        void (*zero[4])(void);
-    };
-    callbacks procs;
-    HWComposer* hwc;
-};
-
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer(
-        const sp<SurfaceFlinger>& flinger,
-        EventHandler& handler)
-    : mFlinger(flinger),
-      mFbDev(0), mHwc(0), mNumDisplays(1),
-      mCBContext(new cb_context),
-      mEventHandler(handler),
-      mDebugForceFakeVSync(false)
-{
-    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
-        mLists[i] = 0;
-    }
-
-    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
-        mLastHwVSync[i] = 0;
-        mVSyncCounts[i] = 0;
-    }
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.no_hw_vsync", value, "0");
-    mDebugForceFakeVSync = atoi(value);
-
-    bool needVSyncThread = true;
-
-    // Note: some devices may insist that the FB HAL be opened before HWC.
-    int fberr = loadFbHalModule();
-    loadHwcModule();
-
-    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // close FB HAL if we don't needed it.
-        // FIXME: this is temporary until we're not forced to open FB HAL
-        // before HWC.
-        framebuffer_close(mFbDev);
-        mFbDev = NULL;
-    }
-
-    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
-    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-            && !mFbDev) {
-        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
-                strerror(-fberr));
-        abort();
-    }
-
-    // these display IDs are always reserved
-    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-        mAllocatedDisplayIDs.markBit(i);
-    }
-
-    if (mHwc) {
-        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
-              (hwcApiVersion(mHwc) >> 24) & 0xff,
-              (hwcApiVersion(mHwc) >> 16) & 0xff);
-        if (mHwc->registerProcs) {
-            mCBContext->hwc = this;
-            mCBContext->procs.invalidate = &hook_invalidate;
-            mCBContext->procs.vsync = &hook_vsync;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-                mCBContext->procs.hotplug = &hook_hotplug;
-            else
-                mCBContext->procs.hotplug = NULL;
-            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
-            mHwc->registerProcs(mHwc, &mCBContext->procs);
-        }
-
-        // don't need a vsync thread if we have a hardware composer
-        needVSyncThread = false;
-        // always turn vsync off when we start
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-
-        // the number of displays we actually have depends on the
-        // hw composer version
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            // 1.3 adds support for virtual displays
-            mNumDisplays = MAX_HWC_DISPLAYS;
-        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // 1.1 adds support for multiple displays
-            mNumDisplays = NUM_BUILTIN_DISPLAYS;
-        } else {
-            mNumDisplays = 1;
-        }
-    }
-
-    if (mFbDev) {
-        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
-                "should only have fbdev if no hwc or hwc is 1.0");
-
-        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
-        disp.connected = true;
-        disp.format = mFbDev->format;
-        DisplayConfig config = DisplayConfig();
-        config.width = mFbDev->width;
-        config.height = mFbDev->height;
-        config.xdpi = mFbDev->xdpi;
-        config.ydpi = mFbDev->ydpi;
-        config.refresh = nsecs_t(1e9 / mFbDev->fps);
-        disp.configs.push_back(config);
-        disp.currentConfig = 0;
-    } else if (mHwc) {
-        // here we're guaranteed to have at least HWC 1.1
-        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-            queryDisplayProperties(i);
-        }
-    }
-
-    if (needVSyncThread) {
-        // we don't have VSYNC support, we need to fake it
-        mVSyncThread = new VSyncThread(*this);
-    }
-}
-
-HWComposer::~HWComposer() {
-    if (mHwc) {
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-    }
-    if (mVSyncThread != NULL) {
-        mVSyncThread->requestExitAndWait();
-    }
-    if (mHwc) {
-        hwc_close_1(mHwc);
-    }
-    if (mFbDev) {
-        framebuffer_close(mFbDev);
-    }
-    delete mCBContext;
-}
-
-// Load and prepare the hardware composer module.  Sets mHwc.
-void HWComposer::loadHwcModule()
-{
-    hw_module_t const* module;
-
-    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
-        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
-        return;
-    }
-
-    int err = hwc_open_1(module, &mHwc);
-    if (err) {
-        ALOGE("%s device failed to initialize (%s)",
-              HWC_HARDWARE_COMPOSER, strerror(-err));
-        return;
-    }
-
-    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
-            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
-            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
-        ALOGE("%s device version %#x unsupported, will not be used",
-              HWC_HARDWARE_COMPOSER, mHwc->common.version);
-        hwc_close_1(mHwc);
-        mHwc = NULL;
-        return;
-    }
-}
-
-// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
-int HWComposer::loadFbHalModule()
-{
-    hw_module_t const* module;
-
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err != 0) {
-        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
-        return err;
-    }
-
-    return framebuffer_open(module, &mFbDev);
-}
-
-status_t HWComposer::initCheck() const {
-    return mHwc ? NO_ERROR : NO_INIT;
-}
-
-void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->invalidate();
-}
-
-void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
-        int64_t timestamp) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->vsync(disp, timestamp);
-}
-
-void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
-        int connected) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->hotplug(disp, connected);
-}
-
-void HWComposer::invalidate() {
-    mEventHandler.onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(int disp, int64_t timestamp) {
-    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
-        {
-            Mutex::Autolock _l(mLock);
-
-            // There have been reports of HWCs that signal several vsync events
-            // with the same timestamp when turning the display off and on. This
-            // is a bug in the HWC implementation, but filter the extra events
-            // out here so they don't cause havoc downstream.
-            if (timestamp == mLastHwVSync[disp]) {
-                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
-                        timestamp);
-                return;
-            }
-
-            mLastHwVSync[disp] = timestamp;
-        }
-
-        char tag[16];
-        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
-        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
-
-        mEventHandler.onVSyncReceived(this, disp, timestamp);
-    }
-}
-
-void HWComposer::hotplug(int disp, int connected) {
-    if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
-        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
-                disp, connected);
-        return;
-    }
-    queryDisplayProperties(disp);
-    // Do not teardown or recreate the primary display
-    if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(this, disp, bool(connected));
-    }
-}
-
-static float getDefaultDensity(uint32_t width, uint32_t height) {
-    // Default density is based on TVs: 1080p displays get XHIGH density,
-    // lower-resolution displays get TV density. Maybe eventually we'll need
-    // to update it for 4K displays, though hopefully those just report
-    // accurate DPI information to begin with. This is also used for virtual
-    // displays and even primary displays with older hwcomposers, so be
-    // careful about orientation.
-
-    uint32_t h = width < height ? width : height;
-    if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
-    else           return ACONFIGURATION_DENSITY_TV;
-}
-
-static const uint32_t DISPLAY_ATTRIBUTES[] = {
-    HWC_DISPLAY_VSYNC_PERIOD,
-    HWC_DISPLAY_WIDTH,
-    HWC_DISPLAY_HEIGHT,
-    HWC_DISPLAY_DPI_X,
-    HWC_DISPLAY_DPI_Y,
-    HWC_DISPLAY_COLOR_TRANSFORM,
-    HWC_DISPLAY_NO_ATTRIBUTE,
-};
-#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-
-static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
-    HWC_DISPLAY_VSYNC_PERIOD,
-    HWC_DISPLAY_WIDTH,
-    HWC_DISPLAY_HEIGHT,
-    HWC_DISPLAY_DPI_X,
-    HWC_DISPLAY_DPI_Y,
-    HWC_DISPLAY_NO_ATTRIBUTE,
-};
-
-status_t HWComposer::queryDisplayProperties(int disp) {
-
-    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-
-    // use zero as default value for unspecified attributes
-    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
-    memset(values, 0, sizeof(values));
-
-    const size_t MAX_NUM_CONFIGS = 128;
-    uint32_t configs[MAX_NUM_CONFIGS] = {0};
-    size_t numConfigs = MAX_NUM_CONFIGS;
-    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
-    if (err != NO_ERROR) {
-        // this can happen if an unpluggable display is not connected
-        mDisplayData[disp].connected = false;
-        return err;
-    }
-
-    mDisplayData[disp].currentConfig = 0;
-    for (size_t c = 0; c < numConfigs; ++c) {
-        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                DISPLAY_ATTRIBUTES, values);
-        // If this is a pre-1.5 HWC, it may not know about color transform, so
-        // try again with a smaller set of attributes
-        if (err != NO_ERROR) {
-            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
-        }
-        if (err != NO_ERROR) {
-            // we can't get this display's info. turn it off.
-            mDisplayData[disp].connected = false;
-            return err;
-        }
-
-        DisplayConfig config = DisplayConfig();
-        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
-            switch (DISPLAY_ATTRIBUTES[i]) {
-                case HWC_DISPLAY_VSYNC_PERIOD:
-                    config.refresh = nsecs_t(values[i]);
-                    break;
-                case HWC_DISPLAY_WIDTH:
-                    config.width = values[i];
-                    break;
-                case HWC_DISPLAY_HEIGHT:
-                    config.height = values[i];
-                    break;
-                case HWC_DISPLAY_DPI_X:
-                    config.xdpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_DPI_Y:
-                    config.ydpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_COLOR_TRANSFORM:
-                    config.colorMode = static_cast<android_color_mode_t>(values[i]);
-                    break;
-                default:
-                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
-                            i, DISPLAY_ATTRIBUTES[i]);
-                    break;
-            }
-        }
-
-        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
-            float dpi = getDefaultDensity(config.width, config.height);
-            config.xdpi = dpi;
-            config.ydpi = dpi;
-        }
-
-        mDisplayData[disp].configs.push_back(config);
-    }
-
-    // FIXME: what should we set the format to?
-    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
-    mDisplayData[disp].connected = true;
-    return NO_ERROR;
-}
-
-status_t HWComposer::setVirtualDisplayProperties(int32_t id,
-        uint32_t w, uint32_t h, uint32_t format) {
-    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
-            !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-    size_t configId = mDisplayData[id].currentConfig;
-    mDisplayData[id].format = format;
-    DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
-    config.width = w;
-    config.height = h;
-    config.xdpi = config.ydpi = getDefaultDensity(w, h);
-    return NO_ERROR;
-}
-
-int32_t HWComposer::allocateDisplayId() {
-    if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
-        return NO_MEMORY;
-    }
-    int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
-    mAllocatedDisplayIDs.markBit(id);
-    mDisplayData[id].connected = true;
-    mDisplayData[id].configs.resize(1);
-    mDisplayData[id].currentConfig = 0;
-    return id;
-}
-
-status_t HWComposer::freeDisplayId(int32_t id) {
-    if (id < NUM_BUILTIN_DISPLAYS) {
-        // cannot free the reserved IDs
-        return BAD_VALUE;
-    }
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-    mAllocatedDisplayIDs.clearBit(id);
-    mDisplayData[id].connected = false;
-    return NO_ERROR;
-}
-
-nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
-    // this returns the last refresh timestamp.
-    // if the last one is not available, we estimate it based on
-    // the refresh period and whatever closest timestamp we have.
-    Mutex::Autolock _l(mLock);
-    nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    size_t configId = mDisplayData[disp].currentConfig;
-    return now - ((now - mLastHwVSync[disp]) %
-            mDisplayData[disp].configs[configId].refresh);
-}
-
-sp<Fence> HWComposer::getDisplayFence(int disp) const {
-    return mDisplayData[disp].lastDisplayFence;
-}
-
-uint32_t HWComposer::getFormat(int disp) const {
-    if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-    } else {
-        return mDisplayData[disp].format;
-    }
-}
-
-bool HWComposer::isConnected(int disp) const {
-    return mDisplayData[disp].connected;
-}
-
-uint32_t HWComposer::getWidth(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].width;
-}
-
-uint32_t HWComposer::getHeight(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].height;
-}
-
-float HWComposer::getDpiX(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].xdpi;
-}
-
-float HWComposer::getDpiY(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].ydpi;
-}
-
-nsecs_t HWComposer::getRefreshPeriod(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].refresh;
-}
-
-android_color_mode_t HWComposer::getColorMode(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].colorMode;
-}
-
-const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
-    return mDisplayData[disp].configs;
-}
-
-size_t HWComposer::getCurrentConfig(int disp) const {
-    return mDisplayData[disp].currentConfig;
-}
-
-void HWComposer::eventControl(int disp, int event, int enabled) {
-    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
-        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    if (event != EVENT_VSYNC) {
-        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    status_t err = NO_ERROR;
-    if (mHwc && !mDebugForceFakeVSync) {
-        // NOTE: we use our own internal lock here because we have to call
-        // into the HWC with the lock held, and we want to make sure
-        // that even if HWC blocks (which it shouldn't), it won't
-        // affect other threads.
-        Mutex::Autolock _l(mEventControlLock);
-        const int32_t eventBit = 1UL << event;
-        const int32_t newValue = enabled ? eventBit : 0;
-        const int32_t oldValue = mDisplayData[disp].events & eventBit;
-        if (newValue != oldValue) {
-            ATRACE_CALL();
-            err = mHwc->eventControl(mHwc, disp, event, enabled);
-            if (!err) {
-                int32_t& events(mDisplayData[disp].events);
-                events = (events & ~eventBit) | newValue;
-
-                char tag[16];
-                snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
-                ATRACE_INT(tag, enabled);
-            }
-        }
-        // error here should not happen -- not sure what we should
-        // do if it does.
-        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
-                event, enabled, strerror(-err));
-    }
-
-    if (err == NO_ERROR && mVSyncThread != NULL) {
-        mVSyncThread->setEnabled(enabled);
-    }
-}
-
-status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-
-    if (mHwc) {
-        DisplayData& disp(mDisplayData[id]);
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // we need space for the HWC_FRAMEBUFFER_TARGET
-            numLayers++;
-        }
-        if (disp.capacity < numLayers || disp.list == NULL) {
-            size_t size = sizeof(hwc_display_contents_1_t)
-                    + numLayers * sizeof(hwc_layer_1_t);
-            free(disp.list);
-            disp.list = (hwc_display_contents_1_t*)malloc(size);
-            disp.capacity = numLayers;
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
-            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
-            const DisplayConfig& currentConfig =
-                    disp.configs[disp.currentConfig];
-            const hwc_rect_t r = { 0, 0,
-                    (int) currentConfig.width, (int) currentConfig.height };
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-            disp.framebufferTarget->hints = 0;
-            disp.framebufferTarget->flags = 0;
-            disp.framebufferTarget->handle = disp.fbTargetHandle;
-            disp.framebufferTarget->transform = 0;
-            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                disp.framebufferTarget->sourceCropf.left = 0;
-                disp.framebufferTarget->sourceCropf.top = 0;
-                disp.framebufferTarget->sourceCropf.right =
-                        currentConfig.width;
-                disp.framebufferTarget->sourceCropf.bottom =
-                        currentConfig.height;
-            } else {
-                disp.framebufferTarget->sourceCrop = r;
-            }
-            disp.framebufferTarget->displayFrame = r;
-            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
-            disp.framebufferTarget->visibleRegionScreen.rects =
-                &disp.framebufferTarget->displayFrame;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
-            disp.framebufferTarget->planeAlpha = 0xFF;
-        }
-        disp.list->retireFenceFd = -1;
-        disp.list->flags = HWC_GEOMETRY_CHANGED;
-        disp.list->numHwLayers = numLayers;
-    }
-    return NO_ERROR;
-}
-
-status_t HWComposer::setFramebufferTarget(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-    DisplayData& disp(mDisplayData[id]);
-    if (!disp.framebufferTarget) {
-        // this should never happen, but apparently eglCreateWindowSurface()
-        // triggers a Surface::queueBuffer()  on some
-        // devices (!?) -- log and ignore.
-        ALOGE("HWComposer: framebufferTarget is null");
-        return NO_ERROR;
-    }
-
-    int acquireFenceFd = -1;
-    if (acquireFence->isValid()) {
-        acquireFenceFd = acquireFence->dup();
-    }
-
-    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
-    disp.fbTargetHandle = buf->handle;
-    disp.framebufferTarget->handle = disp.fbTargetHandle;
-    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
-    return NO_ERROR;
-}
-
-status_t HWComposer::prepare() {
-    Mutex::Autolock _l(mDisplayLock);
-    for (size_t i=0 ; i<mNumDisplays ; i++) {
-        DisplayData& disp(mDisplayData[i]);
-        if (disp.framebufferTarget) {
-            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
-            // DO NOT reset the handle field to NULL, because it's possible
-            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
-            // in which case, we should continue to use the same buffer.
-            LOG_FATAL_IF(disp.list == NULL);
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-        }
-        if (!disp.connected && disp.list != NULL) {
-            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
-                  i, disp.list->numHwLayers);
-        }
-        mLists[i] = disp.list;
-        if (mLists[i]) {
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd = -1;
-            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // garbage data to catch improper use
-                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
-                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
-            } else {
-                mLists[i]->dpy = EGL_NO_DISPLAY;
-                mLists[i]->sur = EGL_NO_SURFACE;
-            }
-        }
-    }
-
-    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
-    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
-
-    if (err == NO_ERROR) {
-        // here we're just making sure that "skip" layers are set
-        // to HWC_FRAMEBUFFER and we're also counting how many layers
-        // we have of each type.
-        //
-        // If there are no window layers, we treat the display has having FB
-        // composition, because SurfaceFlinger will use GLES to draw the
-        // wormhole region.
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.hasFbComp = false;
-            disp.hasOvComp = false;
-            if (disp.list) {
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    hwc_layer_1_t& l = disp.list->hwLayers[i];
-
-                    //ALOGD("prepare: %d, type=%d, handle=%p",
-                    //        i, l.compositionType, l.handle);
-
-                    if (l.flags & HWC_SKIP_LAYER) {
-                        l.compositionType = HWC_FRAMEBUFFER;
-                    }
-                    if (l.compositionType == HWC_FRAMEBUFFER) {
-                        disp.hasFbComp = true;
-                    }
-                    if (l.compositionType == HWC_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                }
-                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
-                    disp.hasFbComp = true;
-                }
-            } else {
-                disp.hasFbComp = true;
-            }
-        }
-    }
-    return (status_t)err;
-}
-
-bool HWComposer::hasHwcComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return false;
-    return mDisplayData[id].hasOvComp;
-}
-
-bool HWComposer::hasGlesComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return true;
-    return mDisplayData[id].hasFbComp;
-}
-
-sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return Fence::NO_FENCE;
-
-    int fd = INVALID_OPERATION;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (disp.framebufferTarget) {
-            fd = disp.framebufferTarget->releaseFenceFd;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
-        }
-    }
-    return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
-}
-
-status_t HWComposer::commit() {
-    int err = NO_ERROR;
-    if (mHwc) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // On version 1.0, the OpenGL ES target surface is communicated
-            // by the (dpy, sur) fields and we are guaranteed to have only
-            // a single display.
-            mLists[0]->dpy = eglGetCurrentDisplay();
-            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
-        }
-
-        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            if (disp.outbufHandle) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd =
-                        disp.outbufAcquireFence->dup();
-            }
-        }
-
-        err = mHwc->set(mHwc, mNumDisplays, mLists);
-
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.lastDisplayFence = disp.lastRetireFence;
-            disp.lastRetireFence = Fence::NO_FENCE;
-            if (disp.list) {
-                if (disp.list->retireFenceFd != -1) {
-                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
-                    disp.list->retireFenceFd = -1;
-                }
-                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
-            }
-        }
-    }
-    return (status_t)err;
-}
-
-status_t HWComposer::setPowerMode(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    if (mHwc) {
-        if (mode == HWC_POWER_MODE_OFF) {
-            eventControl(disp, HWC_EVENT_VSYNC, 0);
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
-        } else {
-            return (status_t)mHwc->blank(mHwc, disp,
-                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
-        }
-    }
-    return NO_ERROR;
-}
-
-status_t HWComposer::setActiveConfig(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    DisplayData& dd(mDisplayData[disp]);
-    dd.currentConfig = mode;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-        return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
-    } else {
-        LOG_FATAL_IF(mode != 0);
-    }
-    return NO_ERROR;
-}
-
-void HWComposer::disconnectDisplay(int disp) {
-    LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
-    DisplayData& dd(mDisplayData[disp]);
-    free(dd.list);
-    dd.list = NULL;
-    dd.framebufferTarget = NULL;    // points into dd.list
-    dd.fbTargetHandle = NULL;
-    dd.outbufHandle = NULL;
-    dd.lastRetireFence = Fence::NO_FENCE;
-    dd.lastDisplayFence = Fence::NO_FENCE;
-    dd.outbufAcquireFence = Fence::NO_FENCE;
-    // clear all the previous configs and repopulate when a new
-    // device is added
-    dd.configs.clear();
-}
-
-int HWComposer::getVisualID() const {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
-        // is supported by the implementation. we can only be in this case
-        // if we have HWC 1.1
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    } else {
-        return mFbDev->format;
-    }
-}
-
-bool HWComposer::supportsFramebufferTarget() const {
-    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-}
-
-int HWComposer::fbPost(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        return setFramebufferTarget(id, acquireFence, buffer);
-    } else {
-        acquireFence->waitForever("HWComposer::fbPost");
-        return mFbDev->post(mFbDev, buffer->handle);
-    }
-}
-
-int HWComposer::fbCompositionComplete() {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-        return NO_ERROR;
-
-    if (mFbDev->compositionComplete) {
-        return mFbDev->compositionComplete(mFbDev);
-    } else {
-        return INVALID_OPERATION;
-    }
-}
-
-void HWComposer::fbDump(String8& result) {
-    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mFbDev->dump(mFbDev, buffer, SIZE);
-        result.append(buffer);
-    }
-}
-
-status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
-        const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return BAD_INDEX;
-    if (id < VIRTUAL_DISPLAY_ID_BASE)
-        return INVALID_OPERATION;
-
-    DisplayData& disp(mDisplayData[id]);
-    disp.outbufHandle = buf->handle;
-    disp.outbufAcquireFence = acquireFence;
-    return NO_ERROR;
-}
-
-sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return Fence::NO_FENCE;
-    return mDisplayData[id].lastRetireFence;
-}
-
-status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
-{
-    if (mHwc->setCursorPositionAsync) {
-        return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
-    }
-    else {
-        return NO_ERROR;
-    }
-}
-
-/*
- * Helper template to implement a concrete HWCLayer
- * This holds the pointer to the concrete hwc layer type
- * and implements the "iterable" side of HWCLayer.
- */
-template<typename CONCRETE, typename HWCTYPE>
-class Iterable : public HWComposer::HWCLayer {
-protected:
-    HWCTYPE* const mLayerList;
-    HWCTYPE* mCurrentLayer;
-    explicit Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
-            mIndex(0) { }
-    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
-    inline HWCTYPE* getLayer() { return mCurrentLayer; }
-    virtual ~Iterable() { }
-    size_t mIndex;
-private:
-    // returns a copy of ourselves
-    virtual HWComposer::HWCLayer* dup() {
-        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
-    }
-    virtual status_t setLayer(size_t index) {
-        mIndex = index;
-        mCurrentLayer = &mLayerList[index];
-        return NO_ERROR;
-    }
-};
-
-/*
- * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
- * This implements the HWCLayer side of HWCIterableLayer.
- */
-class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
-    struct hwc_composer_device_1* mHwc;
-public:
-    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer,
-            Vector<Region>* visibleRegions,
-            Vector<Region>* surfaceDamageRegions)
-        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc),
-          mVisibleRegions(visibleRegions),
-          mSurfaceDamageRegions(surfaceDamageRegions) {}
-
-    virtual int32_t getCompositionType() const {
-        return getLayer()->compositionType;
-    }
-    virtual uint32_t getHints() const {
-        return getLayer()->hints;
-    }
-    virtual sp<Fence> getAndResetReleaseFence() {
-        int fd = getLayer()->releaseFenceFd;
-        getLayer()->releaseFenceFd = -1;
-        return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
-    }
-    virtual void setAcquireFenceFd(int fenceFd) {
-        getLayer()->acquireFenceFd = fenceFd;
-    }
-    virtual void setPerFrameDefaultState() {
-        //getLayer()->compositionType = HWC_FRAMEBUFFER;
-    }
-    virtual void setPlaneAlpha(uint8_t alpha) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
-            getLayer()->planeAlpha = alpha;
-        } else {
-            if (alpha < 0xFF) {
-                getLayer()->flags |= HWC_SKIP_LAYER;
-            }
-        }
-    }
-    virtual void setDefaultState() {
-        hwc_layer_1_t* const l = getLayer();
-        l->compositionType = HWC_FRAMEBUFFER;
-        l->hints = 0;
-        l->flags = HWC_SKIP_LAYER;
-        l->handle = 0;
-        l->transform = 0;
-        l->blending = HWC_BLENDING_NONE;
-        l->visibleRegionScreen.numRects = 0;
-        l->visibleRegionScreen.rects = NULL;
-        l->acquireFenceFd = -1;
-        l->releaseFenceFd = -1;
-        l->planeAlpha = 0xFF;
-    }
-    virtual void setSkip(bool skip) {
-        if (skip) {
-            getLayer()->flags |= HWC_SKIP_LAYER;
-        } else {
-            getLayer()->flags &= ~HWC_SKIP_LAYER;
-        }
-    }
-    virtual void setIsCursorLayerHint(bool isCursor) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            if (isCursor) {
-                getLayer()->flags |= HWC_IS_CURSOR_LAYER;
-            }
-            else {
-                getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
-            }
-        }
-    }
-    virtual void setBlending(uint32_t blending) {
-        getLayer()->blending = blending;
-    }
-    virtual void setTransform(uint32_t transform) {
-        getLayer()->transform = transform;
-    }
-    virtual void setFrame(const Rect& frame) {
-        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
-    }
-    virtual void setCrop(const FloatRect& crop) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
-        } else {
-            /*
-             * Since h/w composer didn't support a flot crop rect before version 1.3,
-             * using integer coordinates instead produces a different output from the GL code in
-             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
-             * window size ratio is large and a window crop is defined
-             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
-             */
-            hwc_rect_t& r = getLayer()->sourceCrop;
-            r.left  = int(ceilf(crop.left));
-            r.top   = int(ceilf(crop.top));
-            r.right = int(floorf(crop.right));
-            r.bottom= int(floorf(crop.bottom));
-        }
-    }
-    virtual void setVisibleRegionScreen(const Region& reg) {
-        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
-        mVisibleRegions->editItemAt(mIndex) = reg;
-        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
-                mVisibleRegions->itemAt(mIndex).getArray(
-                &visibleRegion.numRects));
-    }
-    virtual void setSurfaceDamage(const Region& reg) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
-            return;
-        }
-        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
-        // We encode default full-screen damage as INVALID_RECT upstream, but as
-        // 0 rects for HWComposer
-        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
-            surfaceDamage.numRects = 0;
-            surfaceDamage.rects = NULL;
-            return;
-        }
-        mSurfaceDamageRegions->editItemAt(mIndex) = reg;
-        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
-                mSurfaceDamageRegions->itemAt(mIndex).getArray(
-                &surfaceDamage.numRects));
-    }
-    virtual void setSidebandStream(const sp<NativeHandle>& stream) {
-        ALOG_ASSERT(stream->handle() != NULL);
-        getLayer()->compositionType = HWC_SIDEBAND;
-        getLayer()->sidebandStream = stream->handle();
-    }
-    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
-        if (buffer == 0 || buffer->handle == 0) {
-            getLayer()->compositionType = HWC_FRAMEBUFFER;
-            getLayer()->flags |= HWC_SKIP_LAYER;
-            getLayer()->handle = 0;
-        } else {
-            if (getLayer()->compositionType == HWC_SIDEBAND) {
-                // If this was a sideband layer but the stream was removed, reset
-                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
-                getLayer()->compositionType = HWC_FRAMEBUFFER;
-            }
-            getLayer()->handle = buffer->handle;
-        }
-    }
-    virtual void onDisplayed() {
-        getLayer()->acquireFenceFd = -1;
-    }
-
-protected:
-    // Pointers to the vectors of Region backing-memory held in DisplayData.
-    // Only the Region at mIndex corresponds to this Layer.
-    Vector<Region>* mVisibleRegions;
-    Vector<Region>* mSurfaceDamageRegions;
-};
-
-/*
- * returns an iterator initialized at a given index in the layer list
- */
-HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return LayerListIterator();
-    }
-    DisplayData& disp(mDisplayData[id]);
-    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
-        return LayerListIterator();
-    }
-    if (disp.visibleRegions.size() < disp.list->numHwLayers) {
-        disp.visibleRegions.resize(disp.list->numHwLayers);
-    }
-    if (disp.surfaceDamageRegions.size() < disp.list->numHwLayers) {
-        disp.surfaceDamageRegions.resize(disp.list->numHwLayers);
-    }
-    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers,
-            &disp.visibleRegions, &disp.surfaceDamageRegions), index);
-}
-
-/*
- * returns an iterator on the beginning of the layer list
- */
-HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
-    return getLayerIterator(id, 0);
-}
-
-/*
- * returns an iterator on the end of the layer list
- */
-HWComposer::LayerListIterator HWComposer::end(int32_t id) {
-    size_t numLayers = 0;
-    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (mHwc && disp.list) {
-            numLayers = disp.list->numHwLayers;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
-                // which we ignore when iterating through the layer list.
-                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
-                if (numLayers) {
-                    numLayers--;
-                }
-            }
-        }
-    }
-    return getLayerIterator(id, numLayers);
-}
-
-// Converts a PixelFormat to a human-readable string.  Max 11 chars.
-// (Could use a table of prefab String8 objects.)
-static String8 getFormatStr(PixelFormat format) {
-    switch (format) {
-    case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
-    case PIXEL_FORMAT_RGBX_8888:    return String8("RGBx_8888");
-    case PIXEL_FORMAT_RGBA_FP16:    return String8("RGBA_FP16");
-    case PIXEL_FORMAT_RGBA_1010102: return String8("RGBA_1010102");
-    case PIXEL_FORMAT_RGB_888:      return String8("RGB_888");
-    case PIXEL_FORMAT_RGB_565:      return String8("RGB_565");
-    case PIXEL_FORMAT_BGRA_8888:    return String8("BGRA_8888");
-    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-                                    return String8("ImplDef");
-    default:
-        String8 result;
-        result.appendFormat("? %08x", format);
-        return result;
-    }
-}
-
-void HWComposer::dump(String8& result) const {
-    Mutex::Autolock _l(mDisplayLock);
-    if (mHwc) {
-        result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
-        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            const DisplayData& disp(mDisplayData[i]);
-            if (!disp.connected)
-                continue;
-
-            const Vector< sp<Layer> >& visibleLayersSortedByZ =
-                    mFlinger->getLayerSortedByZForHwcDisplay(i);
-
-
-            result.appendFormat("  Display[%zd] configurations (* current):\n", i);
-            for (size_t c = 0; c < disp.configs.size(); ++c) {
-                const DisplayConfig& config(disp.configs[c]);
-                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
-                        ", refresh=%" PRId64 ", colorMode=%d\n",
-                        c == disp.currentConfig ? "* " : "", c,
-                        config.width, config.height, config.xdpi, config.ydpi,
-                        config.refresh, config.colorMode);
-            }
-
-            if (disp.list) {
-                result.appendFormat(
-                        "  numHwLayers=%zu, flags=%08x\n",
-                        disp.list->numHwLayers, disp.list->flags);
-
-                result.append(
-                        "    type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name \n"
-                        "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
-                //      " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    const hwc_layer_1_t&l = disp.list->hwLayers[i];
-                    int32_t format = -1;
-                    String8 name("unknown");
-
-                    if (i < visibleLayersSortedByZ.size()) {
-                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
-                        const sp<GraphicBuffer>& buffer(
-                                layer->getActiveBuffer());
-                        if (buffer != NULL) {
-                            format = buffer->getPixelFormat();
-                        }
-                        name = layer->getName();
-                    }
-
-                    int type = l.compositionType;
-                    if (type == HWC_FRAMEBUFFER_TARGET) {
-                        name = "HWC_FRAMEBUFFER_TARGET";
-                        format = disp.format;
-                    }
-
-                    static char const* compositionTypeName[] = {
-                            "GLES",
-                            "HWC",
-                            "BKGND",
-                            "FB TARGET",
-                            "SIDEBAND",
-                            "HWC_CURSOR",
-                            "UNKNOWN"};
-                    if (type >= NELEM(compositionTypeName))
-                        type = NELEM(compositionTypeName) - 1;
-
-                    String8 formatStr = getFormatStr(format);
-                    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    } else {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    }
-                }
-            }
-        }
-    }
-
-    if (mHwc && mHwc->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mHwc->dump(mHwc, buffer, SIZE);
-        result.append(buffer);
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
-    : mHwc(hwc), mEnabled(false),
-      mNextFakeVSync(0),
-      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
-{
-}
-
-void HWComposer::VSyncThread::setEnabled(bool enabled) {
-    Mutex::Autolock _l(mLock);
-    if (mEnabled != enabled) {
-        mEnabled = enabled;
-        mCondition.signal();
-    }
-}
-
-void HWComposer::VSyncThread::onFirstRef() {
-    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
-}
-
-bool HWComposer::VSyncThread::threadLoop() {
-    { // scope for lock
-        Mutex::Autolock _l(mLock);
-        while (!mEnabled) {
-            mCondition.wait(mLock);
-        }
-    }
-
-    const nsecs_t period = mRefreshPeriod;
-    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    nsecs_t next_vsync = mNextFakeVSync;
-    nsecs_t sleep = next_vsync - now;
-    if (sleep < 0) {
-        // we missed, find where the next vsync should be
-        sleep = (period - ((now - next_vsync) % period));
-        next_vsync = now + sleep;
-    }
-    mNextFakeVSync = next_vsync + period;
-
-    struct timespec spec;
-    spec.tv_sec  = next_vsync / 1000000000;
-    spec.tv_nsec = next_vsync % 1000000000;
-
-    int err;
-    do {
-        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
-    } while (err<0 && errno == EINTR);
-
-    if (err == 0) {
-        mHwc.mEventHandler.onVSyncReceived(&mHwc, 0, next_vsync);
-    }
-
-    return true;
-}
-
-HWComposer::DisplayData::DisplayData()
-:   configs(),
-    currentConfig(0),
-    format(HAL_PIXEL_FORMAT_RGBA_8888),
-    connected(false),
-    hasFbComp(false), hasOvComp(false),
-    capacity(0), list(NULL),
-    framebufferTarget(NULL), fbTargetHandle(0),
-    lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
-    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
-    events(0)
-{}
-
-HWComposer::DisplayData::~DisplayData() {
-    free(list);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 1de5e48..cde96e4 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -176,12 +176,6 @@
     return NO_ERROR;
 }
 
-#ifndef USE_HWC2
-status_t VirtualDisplaySurface::compositionComplete() {
-    return NO_ERROR;
-}
-#endif
-
 status_t VirtualDisplaySurface::advanceFrame() {
     if (mDisplayId < 0)
         return NO_ERROR;
@@ -221,7 +215,6 @@
 
     status_t result = NO_ERROR;
     if (fbBuffer != NULL) {
-#ifdef USE_HWC2
         uint32_t hwcSlot = 0;
         sp<GraphicBuffer> hwcBuffer;
         mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer,
@@ -230,9 +223,6 @@
         // TODO: Correctly propagate the dataspace from GL composition
         result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence,
                 hwcBuffer, HAL_DATASPACE_UNKNOWN);
-#else
-        result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
-#endif
     }
 
     return result;
@@ -246,32 +236,20 @@
             "Unexpected onFrameCommitted() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_IDLE;
 
-#ifdef USE_HWC2
     sp<Fence> retireFence = mHwc.getPresentFence(mDisplayId);
-#else
-    sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
-#endif
     if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
         // release the scratch buffer back to the pool
         Mutex::Autolock lock(mMutex);
         int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
         VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
-#ifdef USE_HWC2
         addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
                 retireFence);
-#else
-        addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
-#endif
-        releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
-                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+        releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]);
     }
 
     if (mOutputProducerSlot >= 0) {
         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
         QueueBufferOutput qbo;
-#ifndef USE_HWC2
-        sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
-#endif
         VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
         if (mMustRecompose) {
             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
@@ -280,11 +258,7 @@
                         HAL_DATASPACE_UNKNOWN,
                         Rect(mSinkBufferWidth, mSinkBufferHeight),
                         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
-#ifdef USE_HWC2
                         retireFence),
-#else
-                        outFence),
-#endif
                     &qbo);
             if (result == NO_ERROR) {
                 updateQueueBufferOutput(std::move(qbo));
@@ -294,11 +268,7 @@
             // through the motions of updating the display to keep our state
             // machine happy. We cancel the buffer to avoid triggering another
             // re-composition and causing an infinite loop.
-#ifdef USE_HWC2
             mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
-#else
-            mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
-#endif
         }
     }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 1671aba..5c8acea 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -84,9 +84,6 @@
     //
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
-#ifndef USE_HWC2
-    virtual status_t compositionComplete();
-#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
@@ -253,10 +250,7 @@
 
     bool mMustRecompose;
 
-#ifdef USE_HWC2
     HWComposerBufferCache mHwcBufferCache;
-#endif
-
 
     bool mForceHwcCopy;
 };
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index 052a959..02eea47 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -53,12 +53,7 @@
         }
 
         bool enable = requestedVsyncState == VsyncState::On;
-#ifdef USE_HWC2
         mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
-#else
-        mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
-                SurfaceFlinger::EVENT_VSYNC, enable);
-#endif
         currentVsyncState = requestedVsyncState;
     }
 
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index a9bb2ba..f647742 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -248,7 +248,7 @@
 
         // find out connections waiting for events
         size_t count = mDisplayEventConnections.size();
-        for (size_t i=0 ; i<count ; i++) {
+        for (size_t i=0 ; i<count ; ) {
             sp<Connection> connection(mDisplayEventConnections[i].promote());
             if (connection != NULL) {
                 bool added = false;
@@ -279,11 +279,12 @@
                     // messages.
                     signalConnections.add(connection);
                 }
+                ++i;
             } else {
                 // we couldn't promote this reference, the connection has
                 // died, so clean-up!
                 mDisplayEventConnections.removeAt(i);
-                --i; --count;
+                --count;
             }
         }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
old mode 100755
new mode 100644
index ca9a546..2a4abcb
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,10 +19,10 @@
 #define LOG_TAG "Layer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
 #include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
 
 #include <cutils/compiler.h>
 #include <cutils/native_handle.h>
@@ -43,37 +43,41 @@
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
 
-#include "clz.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
+#include "clz.h"
 
 #include "DisplayHardware/HWComposer.h"
 
 #include "RenderEngine/RenderEngine.h"
 
 #include <mutex>
+#include "LayerProtoHelper.h"
 
-#define DEBUG_RESIZE    0
+#define DEBUG_RESIZE 0
 
 namespace android {
 
-// ---------------------------------------------------------------------------
+LayerBE::LayerBE()
+      : mBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
+        mBuffer(nullptr),
+        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+}
+
 
 int32_t Layer::sSequence = 1;
 
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
-        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
-    :   contentDirty(false),
+Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+             uint32_t h, uint32_t flags)
+      : contentDirty(false),
         sequence(uint32_t(android_atomic_inc(&sSequence))),
         mFlinger(flinger),
-        mTextureName(-1U),
         mPremultipliedAlpha(true),
-        mName("unnamed"),
-        mFormat(PIXEL_FORMAT_NONE),
+        mName(name),
         mTransactionFlags(0),
         mPendingStateMutex(),
         mPendingStates(),
@@ -81,69 +85,43 @@
         mSidebandStreamChanged(false),
         mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
         mCurrentTransform(0),
-        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
         mOverrideScalingMode(-1),
         mCurrentOpacity(true),
-        mBufferLatched(false),
         mCurrentFrameNumber(0),
-        mPreviousFrameNumber(0),
-        mRefreshPending(false),
         mFrameLatencyNeeded(false),
         mFiltering(false),
         mNeedsFiltering(false),
-        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
-#ifndef USE_HWC2
-        mIsGlesComposition(false),
-#endif
         mProtectedByApp(false),
-        mHasSurface(false),
         mClientRef(client),
         mPotentialCursor(false),
         mQueueItemLock(),
         mQueueItemCondition(),
         mQueueItems(),
         mLastFrameNumberReceived(0),
-        mUpdateTexImageFailed(false),
         mAutoRefresh(false),
-        mFreezeGeometryUpdates(false)
-{
-#ifdef USE_HWC2
-    ALOGV("Creating Layer %s", name.string());
-#endif
+        mFreezeGeometryUpdates(false) {
 
     mCurrentCrop.makeInvalid();
-    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
-    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
 
     uint32_t layerFlags = 0;
-    if (flags & ISurfaceComposerClient::eHidden)
-        layerFlags |= layer_state_t::eLayerHidden;
-    if (flags & ISurfaceComposerClient::eOpaque)
-        layerFlags |= layer_state_t::eLayerOpaque;
-    if (flags & ISurfaceComposerClient::eSecure)
-        layerFlags |= layer_state_t::eLayerSecure;
-
-    if (flags & ISurfaceComposerClient::eNonPremultiplied)
-        mPremultipliedAlpha = false;
+    if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
+    if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
+    if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
 
     mName = name;
     mTransactionName = String8("TX - ") + mName;
 
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
+    mCurrentState.flags = layerFlags;
     mCurrentState.active.transform.set(0, 0);
     mCurrentState.crop.makeInvalid();
     mCurrentState.finalCrop.makeInvalid();
     mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
     mCurrentState.requestedCrop = mCurrentState.crop;
     mCurrentState.z = 0;
-#ifdef USE_HWC2
-    mCurrentState.alpha = 1.0f;
-#else
-    mCurrentState.alpha = 0xFF;
-#endif
+    mCurrentState.color.a = 1.0f;
     mCurrentState.layerStack = 0;
-    mCurrentState.flags = layerFlags;
     mCurrentState.sequence = 0;
     mCurrentState.requested = mCurrentState.active;
     mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN;
@@ -153,149 +131,39 @@
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
 
-#ifdef USE_HWC2
     const auto& hwc = flinger->getHwComposer();
     const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
     nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
-#else
-    nsecs_t displayPeriod =
-            flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-#endif
     mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
 
     CompositorTiming compositorTiming;
     flinger->getCompositorTiming(&compositorTiming);
     mFrameEventHistory.initializeCompositorTiming(compositorTiming);
+
 }
 
-void Layer::onFirstRef() {
-    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
-    sp<IGraphicBufferProducer> producer;
-    sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer, true);
-    mProducer = new MonitoredProducer(producer, mFlinger, this);
-    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
-    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-    mSurfaceFlingerConsumer->setContentsChangedListener(this);
-    mSurfaceFlingerConsumer->setName(mName);
-
-    if (mFlinger->isLayerTripleBufferingDisabled()) {
-        mProducer->setMaxDequeuedBufferCount(2);
-    }
-
-    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
-    updateTransformHint(hw);
-}
+void Layer::onFirstRef() {}
 
 Layer::~Layer() {
-  sp<Client> c(mClientRef.promote());
-    if (c != 0) {
-        c->detachLayer(this);
-    }
-
-    for (auto& point : mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    for (auto& point : mLocalSyncPoints) {
-        point->setFrameAvailable();
-    }
-    mFlinger->deleteTextureAsync(mTextureName);
     mFrameTracker.logAndResetStats(mName);
-
-#ifdef USE_HWC2
-    if (!mHwcLayers.empty()) {
-        ALOGE("Found stale hardware composer layers when destroying "
-                "surface flinger layer %s", mName.string());
-        destroyAllHwcLayers();
-    }
-#endif
 }
 
 // ---------------------------------------------------------------------------
 // callbacks
 // ---------------------------------------------------------------------------
 
-#ifdef USE_HWC2
-void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
-    mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
-}
-#else
-void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
-        HWComposer::HWCLayerInterface* layer) {
-    if (layer) {
-        layer->onDisplayed();
-        mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
-    }
-}
-#endif
-
-void Layer::onFrameAvailable(const BufferItem& item) {
-    // Add this buffer from our internal queue tracker
-    { // Autolock scope
-        Mutex::Autolock lock(mQueueItemLock);
-        mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
-                item.mGraphicBuffer->getHeight(), item.mFrameNumber);
-        // Reset the frame number tracker when we receive the first buffer after
-        // a frame number reset
-        if (item.mFrameNumber == 1) {
-            mLastFrameNumberReceived = 0;
-        }
-
-        // Ensure that callbacks are handled in order
-        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
-            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
-                    ms2ns(500));
-            if (result != NO_ERROR) {
-                ALOGE("[%s] Timed out waiting on callback", mName.string());
-            }
-        }
-
-        mQueueItems.push_back(item);
-        android_atomic_inc(&mQueuedFrames);
-
-        // Wake up any pending callbacks
-        mLastFrameNumberReceived = item.mFrameNumber;
-        mQueueItemCondition.broadcast();
-    }
-
-    mFlinger->signalLayerUpdate();
-}
-
-void Layer::onFrameReplaced(const BufferItem& item) {
-    { // Autolock scope
-        Mutex::Autolock lock(mQueueItemLock);
-
-        // Ensure that callbacks are handled in order
-        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
-            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
-                    ms2ns(500));
-            if (result != NO_ERROR) {
-                ALOGE("[%s] Timed out waiting on callback", mName.string());
-            }
-        }
-
-        if (mQueueItems.empty()) {
-            ALOGE("Can't replace a frame on an empty queue");
-            return;
-        }
-        mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
-
-        // Wake up any pending callbacks
-        mLastFrameNumberReceived = item.mFrameNumber;
-        mQueueItemCondition.broadcast();
-    }
-}
-
-void Layer::onSidebandStreamChanged() {
-    if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
-        // mSidebandStreamChanged was false
-        mFlinger->signalLayerUpdate();
-    }
-}
+/*
+ * onLayerDisplayed is only meaningful for BufferLayer, but, is called through
+ * Layer.  So, the implementation is done in BufferLayer.  When called on a
+ * ColorLayer object, it's essentially a NOP.
+ */
+void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
 
 void Layer::onRemovedFromCurrentState() {
     // the layer is removed from SF mCurrentState to mLayersPendingRemoval
 
+    mPendingRemoval = true;
+
     if (mCurrentState.zOrderRelativeOf != nullptr) {
         sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
         if (strongRelative != nullptr) {
@@ -312,11 +180,9 @@
 
 void Layer::onRemoved() {
     // the layer is removed from SF mLayersPendingRemoval
+    abandon();
 
-    mSurfaceFlingerConsumer->abandon();
-#ifdef USE_HWC2
     destroyAllHwcLayers();
-#endif
 
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
@@ -331,94 +197,58 @@
     return mName;
 }
 
-status_t Layer::setBuffers( uint32_t w, uint32_t h,
-                            PixelFormat format, uint32_t flags)
-{
-    uint32_t const maxSurfaceDims = min(
-            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
-
-    // never allow a surface larger than what our underlying GL implementation
-    // can handle.
-    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
-        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
-        return BAD_VALUE;
-    }
-
-    mFormat = format;
-
-    mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
-    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
-    mCurrentOpacity = getOpacityForFormat(format);
-
-    mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
-    mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
-    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-
-    return NO_ERROR;
+bool Layer::getPremultipledAlpha() const {
+    return mPremultipliedAlpha;
 }
 
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
-
-    LOG_ALWAYS_FATAL_IF(mHasSurface,
-            "Layer::getHandle() has already been called");
-
-    mHasSurface = true;
-
     return new Handle(mFlinger, this);
 }
 
-sp<IGraphicBufferProducer> Layer::getProducer() const {
-    return mProducer;
-}
-
 // ---------------------------------------------------------------------------
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
-#ifdef USE_HWC2
 bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
-    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
-                "Already have a layer for hwcId %d", hwcId);
+    LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0,
+                        "Already have a layer for hwcId %d", hwcId);
     HWC2::Layer* layer = hwc->createLayer(hwcId);
     if (!layer) {
         return false;
     }
-    HWCInfo& hwcInfo = mHwcLayers[hwcId];
+    LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId];
     hwcInfo.hwc = hwc;
     hwcInfo.layer = layer;
     layer->setLayerDestroyedListener(
-            [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+            [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); });
     return true;
 }
 
 bool Layer::destroyHwcLayer(int32_t hwcId) {
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         return false;
     }
-    auto& hwcInfo = mHwcLayers[hwcId];
-    LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
-            "Attempt to destroy null layer");
+    auto& hwcInfo = getBE().mHwcLayers[hwcId];
+    LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
     LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
     hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
     // The layer destroyed listener should have cleared the entry from
     // mHwcLayers. Verify that.
-    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
-            "Stale layer entry in mHwcLayers");
-
+    LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0,
+                        "Stale layer entry in getBE().mHwcLayers");
     return true;
 }
 
 void Layer::destroyAllHwcLayers() {
-    size_t numLayers = mHwcLayers.size();
+    size_t numLayers = getBE().mHwcLayers.size();
     for (size_t i = 0; i < numLayers; ++i) {
-        LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
-        destroyHwcLayer(mHwcLayers.begin()->first);
+        LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
+        destroyHwcLayer(getBE().mHwcLayers.begin()->first);
     }
-    LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
-            "All hardware composer layers should have been destroyed");
+    LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
+                        "All hardware composer layers should have been destroyed");
 }
-#endif
 
 Rect Layer::getContentCrop() const {
     // this is the crop rectangle that applies to the buffer
@@ -427,9 +257,9 @@
     if (!mCurrentCrop.isEmpty()) {
         // if the buffer crop is defined, we use that
         crop = mCurrentCrop;
-    } else if (mActiveBuffer != NULL) {
+    } else if (getBE().mBuffer != NULL) {
         // otherwise we use the whole buffer
-        crop = mActiveBuffer->getBounds();
+        crop = getBE().mBuffer->getBounds();
     } else {
         // if we don't have a buffer yet, we use an empty/invalid crop
         crop.makeInvalid();
@@ -540,10 +370,17 @@
         activeCrop.clear();
     }
     if (!s.finalCrop.isEmpty()) {
-        if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
+        if (!activeCrop.intersect(s.finalCrop, &activeCrop)) {
             activeCrop.clear();
         }
     }
+
+    const auto& p = mDrawingParent.promote();
+    if (p != nullptr) {
+        auto parentCrop = p->computeInitialCrop(hw);
+        activeCrop.intersect(parentCrop, &activeCrop);
+    }
+
     return activeCrop;
 }
 
@@ -557,11 +394,6 @@
 
     // Screen space to make reduction to parent crop clearer.
     Rect activeCrop = computeInitialCrop(hw);
-    const auto& p = mDrawingParent.promote();
-    if (p != nullptr) {
-        auto parentCrop = p->computeInitialCrop(hw);
-        activeCrop.intersect(parentCrop, &activeCrop);
-    }
     Transform t = getTransform();
     // Back to layer space to work with the content crop.
     activeCrop = t.inverse().transform(activeCrop);
@@ -588,16 +420,13 @@
          * the code below applies the primary display's inverse transform to the
          * buffer
          */
-        uint32_t invTransformOrient =
-                DisplayDevice::getPrimaryDisplayOrientationTransform();
+        uint32_t invTransformOrient = DisplayDevice::getPrimaryDisplayOrientationTransform();
         // calculate the inverse transform
         if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
         }
         // and apply to the current transform
-        invTransform = (Transform(invTransformOrient) * Transform(invTransform))
-                .getOrientation();
+        invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation();
     }
 
     int winWidth = s.active.w;
@@ -611,49 +440,36 @@
         bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
         bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
         if (is_h_flipped == is_v_flipped) {
-            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
         }
         winWidth = s.active.h;
         winHeight = s.active.w;
     }
-    const Rect winCrop = activeCrop.transform(
-            invTransform, s.active.w, s.active.h);
+    const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h);
 
     // below, crop is intersected with winCrop expressed in crop's coordinate space
-    float xScale = crop.getWidth()  / float(winWidth);
+    float xScale = crop.getWidth() / float(winWidth);
     float yScale = crop.getHeight() / float(winHeight);
 
-    float insetL = winCrop.left                 * xScale;
-    float insetT = winCrop.top                  * yScale;
-    float insetR = (winWidth - winCrop.right )  * xScale;
+    float insetL = winCrop.left * xScale;
+    float insetT = winCrop.top * yScale;
+    float insetR = (winWidth - winCrop.right) * xScale;
     float insetB = (winHeight - winCrop.bottom) * yScale;
 
-    crop.left   += insetL;
-    crop.top    += insetT;
-    crop.right  -= insetR;
+    crop.left += insetL;
+    crop.top += insetT;
+    crop.right -= insetR;
     crop.bottom -= insetB;
 
     return crop;
 }
 
-#ifdef USE_HWC2
 void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
-#else
-void Layer::setGeometry(
-    const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface& layer)
-#endif
 {
-#ifdef USE_HWC2
     const auto hwcId = displayDevice->getHwcDisplayId();
-    auto& hwcInfo = mHwcLayers[hwcId];
-#else
-    layer.setDefaultState();
-#endif
+    auto& hwcInfo = getBE().mHwcLayers[hwcId];
 
     // enable this layer
-#ifdef USE_HWC2
     hwcInfo.forceClientComposition = false;
 
     if (isSecure() && !displayDevice->isSecure()) {
@@ -661,33 +477,20 @@
     }
 
     auto& hwcLayer = hwcInfo.layer;
-#else
-    layer.setSkip(false);
-
-    if (isSecure() && !hw->isSecure()) {
-        layer.setSkip(true);
-    }
-#endif
 
     // this gives us only the "orientation" component of the transform
     const State& s(getDrawingState());
-#ifdef USE_HWC2
     auto blendMode = HWC2::BlendMode::None;
     if (!isOpaque(s) || getAlpha() != 1.0f) {
-        blendMode = mPremultipliedAlpha ?
-                HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
+        blendMode =
+                mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
     }
     auto error = hwcLayer->setBlendMode(blendMode);
-    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:"
-             " %s (%d)", mName.string(), to_string(blendMode).c_str(),
-             to_string(error).c_str(), static_cast<int32_t>(error));
-#else
-    if (!isOpaque(s) || getAlpha() != 0xFF) {
-        layer.setBlending(mPremultipliedAlpha ?
-                HWC_BLENDING_PREMULT :
-                HWC_BLENDING_COVERAGE);
-    }
-#endif
+    ALOGE_IF(error != HWC2::Error::None,
+             "[%s] Failed to set blend mode %s:"
+             " %s (%d)",
+             mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(),
+             static_cast<int32_t>(error));
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
@@ -696,11 +499,7 @@
     if (!s.crop.isEmpty()) {
         Rect activeCrop(s.crop);
         activeCrop = t.transform(activeCrop);
-#ifdef USE_HWC2
-        if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
-#else
-        if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
-#endif
+        if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
             activeCrop.clear();
         }
         activeCrop = t.inverse().transform(activeCrop, true);
@@ -710,26 +509,23 @@
         // transform.inverse().transform(transform.transform(Rect)) != Rect
         // in which case we need to make sure the final rect is clipped to the
         // display bounds.
-        if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+        if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
             activeCrop.clear();
         }
         // mark regions outside the crop as transparent
         activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
-        activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
-                s.active.w, s.active.h));
-        activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
-                activeCrop.left, activeCrop.bottom));
-        activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
-                s.active.w, activeCrop.bottom));
+        activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h));
+        activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
+        activeTransparentRegion.orSelf(
+                Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom));
     }
 
     Rect frame(t.transform(computeBounds(activeTransparentRegion)));
     if (!s.finalCrop.isEmpty()) {
-        if(!frame.intersect(s.finalCrop, &frame)) {
+        if (!frame.intersect(s.finalCrop, &frame)) {
             frame.clear();
         }
     }
-#ifdef USE_HWC2
     if (!frame.intersect(displayDevice->getViewport(), &frame)) {
         frame.clear();
     }
@@ -737,10 +533,9 @@
     Rect transformedFrame = tr.transform(frame);
     error = hwcLayer->setDisplayFrame(transformedFrame);
     if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
-                mName.string(), transformedFrame.left, transformedFrame.top,
-                transformedFrame.right, transformedFrame.bottom,
-                to_string(error).c_str(), static_cast<int32_t>(error));
+        ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", mName.string(),
+              transformedFrame.left, transformedFrame.top, transformedFrame.right,
+              transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
     } else {
         hwcInfo.displayFrame = transformedFrame;
     }
@@ -749,23 +544,23 @@
     error = hwcLayer->setSourceCrop(sourceCrop);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
-                "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
-                sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
-                static_cast<int32_t>(error));
+              "%s (%d)",
+              mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom,
+              to_string(error).c_str(), static_cast<int32_t>(error));
     } else {
         hwcInfo.sourceCrop = sourceCrop;
     }
 
-    float alpha = getAlpha();
+    float alpha = static_cast<float>(getAlpha());
     error = hwcLayer->setPlaneAlpha(alpha);
-    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
-            "%s (%d)", mName.string(), alpha, to_string(error).c_str(),
-            static_cast<int32_t>(error));
+    ALOGE_IF(error != HWC2::Error::None,
+             "[%s] Failed to set plane alpha %.3f: "
+             "%s (%d)",
+             mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error));
 
     error = hwcLayer->setZOrder(z);
-    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)",
-            mName.string(), z, to_string(error).c_str(),
-            static_cast<int32_t>(error));
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
+             to_string(error).c_str(), static_cast<int32_t>(error));
 
     int type = s.type;
     int appId = s.appId;
@@ -777,17 +572,8 @@
     }
 
     error = hwcLayer->setInfo(type, appId);
-    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)",
-             mName.string(), static_cast<int32_t>(error));
-#else
-    if (!frame.intersect(hw->getViewport(), &frame)) {
-        frame.clear();
-    }
-    const Transform& tr(hw->getTransform());
-    layer.setFrame(tr.transform(frame));
-    layer.setCrop(computeCrop(hw));
-    layer.setPlaneAlpha(getAlpha());
-#endif
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
+             static_cast<int32_t>(error));
 
     /*
      * Transformations are applied in this order:
@@ -805,12 +591,10 @@
          * the code below applies the primary display's inverse transform to the
          * buffer
          */
-        uint32_t invTransform =
-                DisplayDevice::getPrimaryDisplayOrientationTransform();
+        uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
         // calculate the inverse transform
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
         }
 
         /*
@@ -824,163 +608,42 @@
 
     // this gives us only the "orientation" component of the transform
     const uint32_t orientation = transform.getOrientation();
-#ifdef USE_HWC2
     if (orientation & Transform::ROT_INVALID) {
         // we can only handle simple transformation
         hwcInfo.forceClientComposition = true;
     } else {
         auto transform = static_cast<HWC2::Transform>(orientation);
         auto error = hwcLayer->setTransform(transform);
-        ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: "
-                "%s (%d)", mName.string(), to_string(transform).c_str(),
-                to_string(error).c_str(), static_cast<int32_t>(error));
+        ALOGE_IF(error != HWC2::Error::None,
+                 "[%s] Failed to set transform %s: "
+                 "%s (%d)",
+                 mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
+                 static_cast<int32_t>(error));
     }
-#else
-    if (orientation & Transform::ROT_INVALID) {
-        // we can only handle simple transformation
-        layer.setSkip(true);
-    } else {
-        layer.setTransform(orientation);
-    }
-#endif
 }
 
-#ifdef USE_HWC2
 void Layer::forceClientComposition(int32_t hwcId) {
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
         return;
     }
 
-    mHwcLayers[hwcId].forceClientComposition = true;
+    getBE().mHwcLayers[hwcId].forceClientComposition = true;
 }
 
-void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
-    // Apply this display's projection's viewport to the visible region
-    // before giving it to the HWC HAL.
-    const Transform& tr = displayDevice->getTransform();
-    const auto& viewport = displayDevice->getViewport();
-    Region visible = tr.transform(visibleRegion.intersect(viewport));
-    auto hwcId = displayDevice->getHwcDisplayId();
-    auto& hwcInfo = mHwcLayers[hwcId];
-    auto& hwcLayer = hwcInfo.layer;
-    auto error = hwcLayer->setVisibleRegion(visible);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
-                to_string(error).c_str(), static_cast<int32_t>(error));
-        visible.dump(LOG_TAG);
+bool Layer::getForceClientComposition(int32_t hwcId) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
+        ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId);
+        return false;
     }
 
-    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
-                to_string(error).c_str(), static_cast<int32_t>(error));
-        surfaceDamageRegion.dump(LOG_TAG);
-    }
-
-    // Sideband layers
-    if (mSidebandStream.get()) {
-        setCompositionType(hwcId, HWC2::Composition::Sideband);
-        ALOGV("[%s] Requesting Sideband composition", mName.string());
-        error = hwcLayer->setSidebandStream(mSidebandStream->handle());
-        if (error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)",
-                    mName.string(), mSidebandStream->handle(),
-                    to_string(error).c_str(), static_cast<int32_t>(error));
-        }
-        return;
-    }
-
-    // Client layers
-    if (hwcInfo.forceClientComposition ||
-            (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
-        ALOGV("[%s] Requesting Client composition", mName.string());
-        setCompositionType(hwcId, HWC2::Composition::Client);
-        return;
-    }
-
-    // SolidColor layers
-    if (mActiveBuffer == nullptr) {
-        setCompositionType(hwcId, HWC2::Composition::SolidColor);
-
-        // For now, we only support black for DimLayer
-        error = hwcLayer->setColor({0, 0, 0, 255});
-        if (error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set color: %s (%d)", mName.string(),
-                    to_string(error).c_str(), static_cast<int32_t>(error));
-        }
-
-        // Clear out the transform, because it doesn't make sense absent a
-        // source buffer
-        error = hwcLayer->setTransform(HWC2::Transform::None);
-        if (error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(),
-                    to_string(error).c_str(), static_cast<int32_t>(error));
-        }
-
-        return;
-    }
-
-    // Device or Cursor layers
-    if (mPotentialCursor) {
-        ALOGV("[%s] Requesting Cursor composition", mName.string());
-        setCompositionType(hwcId, HWC2::Composition::Cursor);
-    } else {
-        ALOGV("[%s] Requesting Device composition", mName.string());
-        setCompositionType(hwcId, HWC2::Composition::Device);
-    }
-
-    ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
-    error = hwcLayer->setDataspace(mCurrentState.dataSpace);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(),
-              mCurrentState.dataSpace, to_string(error).c_str(),
-              static_cast<int32_t>(error));
-    }
-
-    uint32_t hwcSlot = 0;
-    sp<GraphicBuffer> hwcBuffer;
-    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
-            &hwcSlot, &hwcBuffer);
-
-    auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
-                mActiveBuffer->handle, to_string(error).c_str(),
-                static_cast<int32_t>(error));
-    }
+    return getBE().mHwcLayers[hwcId].forceClientComposition;
 }
 
-#else
-void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface& layer) {
-    // we have to set the visible region on every frame because
-    // we currently free it during onLayerDisplayed(), which is called
-    // after HWComposer::commit() -- every frame.
-    // Apply this display's projection's viewport to the visible region
-    // before giving it to the HWC HAL.
-    const Transform& tr = hw->getTransform();
-    Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
-    layer.setVisibleRegionScreen(visible);
-    layer.setSurfaceDamage(surfaceDamageRegion);
-    mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER);
-
-    if (mSidebandStream.get()) {
-        layer.setSidebandStream(mSidebandStream);
-    } else {
-        // NOTE: buffer can be NULL if the client never drew into this
-        // layer yet, or if we ran out of memory
-        layer.setBuffer(mActiveBuffer);
-    }
-}
-#endif
-
-#ifdef USE_HWC2
 void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) {
     auto hwcId = displayDevice->getHwcDisplayId();
-    if (mHwcLayers.count(hwcId) == 0 ||
-            getCompositionType(hwcId) != HWC2::Composition::Cursor) {
+    if (getBE().mHwcLayers.count(hwcId) == 0 ||
+        getCompositionType(hwcId) != HWC2::Composition::Cursor) {
         return;
     }
 
@@ -1003,284 +666,62 @@
     auto& displayTransform(displayDevice->getTransform());
     auto position = displayTransform.transform(frame);
 
-    auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left,
-            position.top);
-    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position "
-            "to (%d, %d): %s (%d)", mName.string(), position.left,
-            position.top, to_string(error).c_str(),
-            static_cast<int32_t>(error));
+    auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left,
+                                                                              position.top);
+    ALOGE_IF(error != HWC2::Error::None,
+             "[%s] Failed to set cursor position "
+             "to (%d, %d): %s (%d)",
+             mName.string(), position.left, position.top, to_string(error).c_str(),
+             static_cast<int32_t>(error));
 }
-#else
-void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
-        HWComposer::HWCLayerInterface& layer) {
-    int fenceFd = -1;
-
-    // TODO: there is a possible optimization here: we only need to set the
-    // acquire fence the first time a new buffer is acquired on EACH display.
-
-    if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
-        sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
-        if (fence->isValid()) {
-            fenceFd = fence->dup();
-            if (fenceFd == -1) {
-                ALOGW("failed to dup layer fence, skipping sync: %d", errno);
-            }
-        }
-    }
-    layer.setAcquireFenceFd(fenceFd);
-}
-
-Rect Layer::getPosition(
-    const sp<const DisplayDevice>& hw)
-{
-    // this gives us only the "orientation" component of the transform
-    const State& s(getCurrentState());
-
-    // apply the layer's transform, followed by the display's global transform
-    // here we're guaranteed that the layer's transform preserves rects
-    Rect win(s.active.w, s.active.h);
-    if (!s.crop.isEmpty()) {
-        win.intersect(s.crop, &win);
-    }
-    // subtract the transparent region and snap to the bounds
-    Rect bounds = reduce(win, s.activeTransparentRegion);
-    Rect frame(getTransform().transform(bounds));
-    frame.intersect(hw->getViewport(), &frame);
-    if (!s.finalCrop.isEmpty()) {
-        frame.intersect(s.finalCrop, &frame);
-    }
-    const Transform& tr(hw->getTransform());
-    return Rect(tr.transform(frame));
-}
-#endif
 
 // ---------------------------------------------------------------------------
 // drawing...
 // ---------------------------------------------------------------------------
 
-void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
-    onDraw(hw, clip, false);
+void Layer::draw(const RenderArea& renderArea, const Region& clip) const {
+    onDraw(renderArea, clip, false);
 }
 
-void Layer::draw(const sp<const DisplayDevice>& hw,
-        bool useIdentityTransform) const {
-    onDraw(hw, Region(hw->bounds()), useIdentityTransform);
+void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const {
+    onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform);
 }
 
-void Layer::draw(const sp<const DisplayDevice>& hw) const {
-    onDraw(hw, Region(hw->bounds()), false);
+void Layer::draw(const RenderArea& renderArea) const {
+    onDraw(renderArea, Region(renderArea.getBounds()), false);
 }
 
-static constexpr mat4 inverseOrientation(uint32_t transform) {
-    const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1);
-    const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);
-    const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
-    mat4 tr;
-
-    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-        tr = tr * rot90;
-    }
-    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
-        tr = tr * flipH;
-    }
-    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
-        tr = tr * flipV;
-    }
-    return inverse(tr);
-}
-
-/*
- * onDraw will draw the current layer onto the presentable buffer
- */
-void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
-        bool useIdentityTransform) const
-{
-    ATRACE_CALL();
-
-    if (CC_UNLIKELY(mActiveBuffer == 0)) {
-        // the texture has not been created yet, this Layer has
-        // in fact never been drawn into. This happens frequently with
-        // SurfaceView because the WindowManager can't know when the client
-        // has drawn the first time.
-
-        // If there is nothing under us, we paint the screen in black, otherwise
-        // we just skip this update.
-
-        // figure out if there is something below us
-        Region under;
-        bool finished = false;
-        mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
-            if (finished || layer == static_cast<Layer const*>(this)) {
-                finished = true;
-                return;
-            }
-            under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
-        });
-        // if not everything below us is covered, we plug the holes!
-        Region holes(clip.subtract(under));
-        if (!holes.isEmpty()) {
-            clearWithOpenGL(hw, 0, 0, 0, 1);
-        }
-        return;
-    }
-
-    // Bind the current buffer to the GL texture, and wait for it to be
-    // ready for us to draw into.
-    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
-    if (err != NO_ERROR) {
-        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
-        // Go ahead and draw the buffer anyway; no matter what we do the screen
-        // is probably going to have something visibly wrong.
-    }
-
-    bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
-
+void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
+                            float alpha) const {
     RenderEngine& engine(mFlinger->getRenderEngine());
-
-    if (!blackOutLayer) {
-        // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
-
-        // Query the texture matrix given our current filtering mode.
-        float textureMatrix[16];
-        mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
-        mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
-
-        if (getTransformToDisplayInverse()) {
-
-            /*
-             * the code below applies the primary display's inverse transform to
-             * the texture transform
-             */
-            uint32_t transform =
-                    DisplayDevice::getPrimaryDisplayOrientationTransform();
-            mat4 tr = inverseOrientation(transform);
-
-            /**
-             * TODO(b/36727915): This is basically a hack.
-             *
-             * Ensure that regardless of the parent transformation,
-             * this buffer is always transformed from native display
-             * orientation to display orientation. For example, in the case
-             * of a camera where the buffer remains in native orientation,
-             * we want the pixels to always be upright.
-             */
-            sp<Layer> p = mDrawingParent.promote();
-            if (p != nullptr) {
-                const auto parentTransform = p->getTransform();
-                tr = tr * inverseOrientation(parentTransform.getOrientation());
-            }
-
-            // and finally apply it to the original texture matrix
-            const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
-            memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
-        }
-
-        // Set things up for texturing.
-        mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
-        mTexture.setFiltering(useFiltering);
-        mTexture.setMatrix(textureMatrix);
-
-        engine.setupLayerTexturing(mTexture);
-    } else {
-        engine.setupLayerBlackedOut();
-    }
-    drawWithOpenGL(hw, useIdentityTransform);
-    engine.disableTexturing();
-}
-
-
-void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw,
-        float red, float green, float blue,
-        float alpha) const
-{
-    RenderEngine& engine(mFlinger->getRenderEngine());
-    computeGeometry(hw, mMesh, false);
+    computeGeometry(renderArea, getBE().mMesh, false);
     engine.setupFillWithColor(red, green, blue, alpha);
-    engine.drawMesh(mMesh);
+    engine.drawMesh(getBE().mMesh);
 }
 
-void Layer::clearWithOpenGL(
-        const sp<const DisplayDevice>& hw) const {
-    clearWithOpenGL(hw, 0,0,0,0);
+void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
+    clearWithOpenGL(renderArea, 0, 0, 0, 0);
 }
 
-void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
-        bool useIdentityTransform) const {
-    const State& s(getDrawingState());
-
-    computeGeometry(hw, mMesh, useIdentityTransform);
-
-    /*
-     * NOTE: the way we compute the texture coordinates here produces
-     * different results than when we take the HWC path -- in the later case
-     * the "source crop" is rounded to texel boundaries.
-     * This can produce significantly different results when the texture
-     * is scaled by a large amount.
-     *
-     * The GL code below is more logical (imho), and the difference with
-     * HWC is due to a limitation of the HWC API to integers -- a question
-     * is suspend is whether we should ignore this problem or revert to
-     * GL composition when a buffer scaling is applied (maybe with some
-     * minimal value)? Or, we could make GL behave like HWC -- but this feel
-     * like more of a hack.
-     */
-    Rect win(computeBounds());
-
-    Transform t = getTransform();
-    if (!s.finalCrop.isEmpty()) {
-        win = t.transform(win);
-        if (!win.intersect(s.finalCrop, &win)) {
-            win.clear();
-        }
-        win = t.inverse().transform(win);
-        if (!win.intersect(computeBounds(), &win)) {
-            win.clear();
-        }
-    }
-
-    float left   = float(win.left)   / float(s.active.w);
-    float top    = float(win.top)    / float(s.active.h);
-    float right  = float(win.right)  / float(s.active.w);
-    float bottom = float(win.bottom) / float(s.active.h);
-
-    // TODO: we probably want to generate the texture coords with the mesh
-    // here we assume that we only have 4 vertices
-    Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
-    texCoords[0] = vec2(left, 1.0f - top);
-    texCoords[1] = vec2(left, 1.0f - bottom);
-    texCoords[2] = vec2(right, 1.0f - bottom);
-    texCoords[3] = vec2(right, 1.0f - top);
-
-    RenderEngine& engine(mFlinger->getRenderEngine());
-    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
-#ifdef USE_HWC2
-    engine.setSourceDataSpace(mCurrentState.dataSpace);
-#endif
-    engine.drawMesh(mMesh);
-    engine.disableBlending();
-}
-
-#ifdef USE_HWC2
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type,
-        bool callIntoHwc) {
-    if (mHwcLayers.count(hwcId) == 0) {
+void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("setCompositionType called without a valid HWC layer");
         return;
     }
-    auto& hwcInfo = mHwcLayers[hwcId];
+    auto& hwcInfo = getBE().mHwcLayers[hwcId];
     auto& hwcLayer = hwcInfo.layer;
-    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(),
-            to_string(type).c_str(), static_cast<int>(callIntoHwc));
+    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
+          static_cast<int>(callIntoHwc));
     if (hwcInfo.compositionType != type) {
         ALOGV("    actually setting");
         hwcInfo.compositionType = type;
         if (callIntoHwc) {
             auto error = hwcLayer->setCompositionType(type);
-            ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set "
-                    "composition type %s: %s (%d)", mName.string(),
-                    to_string(type).c_str(), to_string(error).c_str(),
-                    static_cast<int32_t>(error));
+            ALOGE_IF(error != HWC2::Error::None,
+                     "[%s] Failed to set "
+                     "composition type %s: %s (%d)",
+                     mName.string(), to_string(type).c_str(), to_string(error).c_str(),
+                     static_cast<int32_t>(error));
         }
     }
 }
@@ -1291,86 +732,27 @@
         // have a HWC counterpart, then it will always be Client
         return HWC2::Composition::Client;
     }
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("getCompositionType called with an invalid HWC layer");
         return HWC2::Composition::Invalid;
     }
-    return mHwcLayers.at(hwcId).compositionType;
+    return getBE().mHwcLayers.at(hwcId).compositionType;
 }
 
 void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("setClearClientTarget called without a valid HWC layer");
         return;
     }
-    mHwcLayers[hwcId].clearClientTarget = clear;
+    getBE().mHwcLayers[hwcId].clearClientTarget = clear;
 }
 
 bool Layer::getClearClientTarget(int32_t hwcId) const {
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("getClearClientTarget called without a valid HWC layer");
         return false;
     }
-    return mHwcLayers.at(hwcId).clearClientTarget;
-}
-#endif
-
-uint32_t Layer::getProducerStickyTransform() const {
-    int producerStickyTransform = 0;
-    int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
-    if (ret != OK) {
-        ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
-                strerror(-ret), ret);
-        return 0;
-    }
-    return static_cast<uint32_t>(producerStickyTransform);
-}
-
-bool Layer::latchUnsignaledBuffers() {
-    static bool propertyLoaded = false;
-    static bool latch = false;
-    static std::mutex mutex;
-    std::lock_guard<std::mutex> lock(mutex);
-    if (!propertyLoaded) {
-        char value[PROPERTY_VALUE_MAX] = {};
-        property_get("debug.sf.latch_unsignaled", value, "0");
-        latch = atoi(value);
-        propertyLoaded = true;
-    }
-    return latch;
-}
-
-uint64_t Layer::getHeadFrameNumber() const {
-    Mutex::Autolock lock(mQueueItemLock);
-    if (!mQueueItems.empty()) {
-        return mQueueItems[0].mFrameNumber;
-    } else {
-        return mCurrentFrameNumber;
-    }
-}
-
-bool Layer::headFenceHasSignaled() const {
-#ifdef USE_HWC2
-    if (latchUnsignaledBuffers()) {
-        return true;
-    }
-
-    Mutex::Autolock lock(mQueueItemLock);
-    if (mQueueItems.empty()) {
-        return true;
-    }
-    if (mQueueItems[0].mIsDroppable) {
-        // Even though this buffer's fence may not have signaled yet, it could
-        // be replaced by another buffer before it has a chance to, which means
-        // that it's possible to get into a situation where a buffer is never
-        // able to be latched. To avoid this, grab this buffer anyway.
-        return true;
-    }
-    return mQueueItems[0].mFenceTime->getSignalTime() !=
-            Fence::SIGNAL_TIME_PENDING;
-#else
-    return true;
-#endif
+    return getBE().mHwcLayers.at(hwcId).clearClientTarget;
 }
 
 bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
@@ -1393,28 +775,6 @@
     return mFiltering;
 }
 
-// As documented in libhardware header, formats in the range
-// 0x100 - 0x1FF are specific to the HAL implementation, and
-// are known to have no alpha channel
-// TODO: move definition for device-specific range into
-// hardware.h, instead of using hard-coded values here.
-#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-
-bool Layer::getOpacityForFormat(uint32_t format) {
-    if (HARDWARE_IS_DEVICE_FORMAT(format)) {
-        return true;
-    }
-    switch (format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            return false;
-    }
-    // in all other case, we have no blending (also for unknown formats)
-    return true;
-}
-
 // ----------------------------------------------------------------------------
 // local state
 // ----------------------------------------------------------------------------
@@ -1434,12 +794,11 @@
     }
 }
 
-void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
-        bool useIdentityTransform) const
-{
+void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh,
+                            bool useIdentityTransform) const {
     const Layer::State& s(getDrawingState());
-    const Transform hwTransform(hw->getTransform());
-    const uint32_t hw_h = hw->getHeight();
+    const Transform renderAreaTransform(renderArea.getTransform());
+    const uint32_t height = renderArea.getHeight();
     Rect win = computeBounds();
 
     vec2 lt = vec2(win.left, win.top);
@@ -1463,53 +822,20 @@
     }
 
     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    position[0] = hwTransform.transform(lt);
-    position[1] = hwTransform.transform(lb);
-    position[2] = hwTransform.transform(rb);
-    position[3] = hwTransform.transform(rt);
-    for (size_t i=0 ; i<4 ; i++) {
-        position[i].y = hw_h - position[i].y;
+    position[0] = renderAreaTransform.transform(lt);
+    position[1] = renderAreaTransform.transform(lb);
+    position[2] = renderAreaTransform.transform(rb);
+    position[3] = renderAreaTransform.transform(rt);
+    for (size_t i = 0; i < 4; i++) {
+        position[i].y = height - position[i].y;
     }
 }
 
-bool Layer::isOpaque(const Layer::State& s) const
-{
-    // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
-    // layer's opaque flag.
-    if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
-        return false;
-    }
-
-    // if the layer has the opaque flag, then we're always opaque,
-    // otherwise we use the current buffer's format.
-    return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
-}
-
-bool Layer::isSecure() const
-{
+bool Layer::isSecure() const {
     const Layer::State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
 }
 
-bool Layer::isProtected() const
-{
-    const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
-    return (activeBuffer != 0) &&
-            (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-}
-
-bool Layer::isFixedSize() const {
-    return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-}
-
-bool Layer::isCropped() const {
-    return !mCurrentCrop.isEmpty();
-}
-
-bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
-    return mNeedsFiltering || hw->needsFiltering();
-}
-
 void Layer::setVisibleRegion(const Region& visibleRegion) {
     // always called from main thread
     this->visibleRegion = visibleRegion;
@@ -1520,8 +846,7 @@
     this->coveredRegion = coveredRegion;
 }
 
-void Layer::setVisibleNonTransparentRegion(const Region&
-        setVisibleNonTransparentRegion) {
+void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) {
     // always called from main thread
     this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
 }
@@ -1546,8 +871,7 @@
             // to be applied as per normal (no synchronization).
             mCurrentState.barrierLayer = nullptr;
         } else {
-            auto syncPoint = std::make_shared<SyncPoint>(
-                    mCurrentState.frameNumber);
+            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber);
             if (barrierLayer->addSyncPoint(syncPoint)) {
                 mRemoteSyncPoints.push_back(std::move(syncPoint));
             } else {
@@ -1568,8 +892,8 @@
 void Layer::popPendingState(State* stateToCommit) {
     auto oldFlags = stateToCommit->flags;
     *stateToCommit = mPendingStates[0];
-    stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
-            (stateToCommit->flags & stateToCommit->mask);
+    stateToCommit->flags =
+            (oldFlags & ~stateToCommit->mask) | (stateToCommit->flags & stateToCommit->mask);
 
     mPendingStates.removeAt(0);
     ATRACE_INT(mTransactionName.string(), mPendingStates.size());
@@ -1589,10 +913,8 @@
                 continue;
             }
 
-            if (mRemoteSyncPoints.front()->getFrameNumber() !=
-                    mPendingStates[0].frameNumber) {
-                ALOGE("[%s] Unexpected sync point frame number found",
-                        mName.string());
+            if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) {
+                ALOGE("[%s] Unexpected sync point frame number found", mName.string());
 
                 // Signal our end of the sync point and then dispose of it
                 mRemoteSyncPoints.front()->setTransactionApplied();
@@ -1628,17 +950,6 @@
     return stateUpdateAvailable;
 }
 
-void Layer::notifyAvailableFrames() {
-    auto headFrameNumber = getHeadFrameNumber();
-    bool headFenceSignaled = headFenceHasSignaled();
-    Mutex::Autolock lock(mLocalSyncPointMutex);
-    for (auto& point : mLocalSyncPoints) {
-        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
-            point->setFrameAvailable();
-        }
-    }
-}
-
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
@@ -1650,59 +961,50 @@
 
     const Layer::State& s(getDrawingState());
 
-    const bool sizeChanged = (c.requested.w != s.requested.w) ||
-                             (c.requested.h != s.requested.h);
+    const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h);
 
     if (sizeChanged) {
         // the size changed, we need to ask our client to request a new buffer
         ALOGD_IF(DEBUG_RESIZE,
-                "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
-                "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} }}\n"
-                "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} }}\n",
-                this, getName().string(), mCurrentTransform,
-                getEffectiveScalingMode(),
-                c.active.w, c.active.h,
-                c.crop.left,
-                c.crop.top,
-                c.crop.right,
-                c.crop.bottom,
-                c.crop.getWidth(),
-                c.crop.getHeight(),
-                c.requested.w, c.requested.h,
-                s.active.w, s.active.h,
-                s.crop.left,
-                s.crop.top,
-                s.crop.right,
-                s.crop.bottom,
-                s.crop.getWidth(),
-                s.crop.getHeight(),
-                s.requested.w, s.requested.h);
+                 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
+                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+                 "            requested={ wh={%4u,%4u} }}\n"
+                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+                 "            requested={ wh={%4u,%4u} }}\n",
+                 this, getName().string(), mCurrentTransform,
+                 getEffectiveScalingMode(), c.active.w, c.active.h, c.crop.left, c.crop.top,
+                 c.crop.right, c.crop.bottom, c.crop.getWidth(), c.crop.getHeight(), c.requested.w,
+                 c.requested.h, s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right,
+                 s.crop.bottom, s.crop.getWidth(), s.crop.getHeight(), s.requested.w,
+                 s.requested.h);
 
         // record the new size, form this point on, when the client request
         // a buffer, it'll get the new size.
-        mSurfaceFlingerConsumer->setDefaultBufferSize(
-                c.requested.w, c.requested.h);
+        setDefaultBufferSize(c.requested.w, c.requested.h);
     }
 
-    const bool resizePending = (c.requested.w != c.active.w) ||
-            (c.requested.h != c.active.h);
+    // Don't let Layer::doTransaction update the drawing state
+    // if we have a pending resize, unless we are in fixed-size mode.
+    // the drawing state will be updated only once we receive a buffer
+    // with the correct size.
+    //
+    // In particular, we want to make sure the clip (which is part
+    // of the geometry state) is latched together with the size but is
+    // latched immediately when no resizing is involved.
+    //
+    // If a sideband stream is attached, however, we want to skip this
+    // optimization so that transactions aren't missed when a buffer
+    // never arrives
+    //
+    // In the case that we don't have a buffer we ignore other factors
+    // and avoid entering the resizePending state. At a high level the
+    // resizePending state is to avoid applying the state of the new buffer
+    // to the old buffer. However in the state where we don't have an old buffer
+    // there is no such concern but we may still be being used as a parent layer.
+    const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) &&
+            (getBE().mBuffer != nullptr);
     if (!isFixedSize()) {
-        if (resizePending && mSidebandStream == NULL) {
-            // don't let Layer::doTransaction update the drawing state
-            // if we have a pending resize, unless we are in fixed-size mode.
-            // the drawing state will be updated only once we receive a buffer
-            // with the correct size.
-            //
-            // in particular, we want to make sure the clip (which is part
-            // of the geometry state) is latched together with the size but is
-            // latched immediately when no resizing is involved.
-            //
-            // If a sideband stream is attached, however, we want to skip this
-            // optimization so that transactions aren't missed when a buffer
-            // never arrives
-
+        if (resizePending && getBE().mSidebandStream == NULL) {
             flags |= eDontUpdateGeometryState;
         }
     }
@@ -1749,8 +1051,7 @@
 
         // we may use linear filtering, if the matrix scales us
         const uint8_t type = c.active.transform.getType();
-        mNeedsFiltering = (!c.active.transform.preserveRects() ||
-                (type >= Transform::SCALE));
+        mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE));
     }
 
     // If the layer is hidden, signal and clear out all local sync points so
@@ -1812,9 +1113,21 @@
     return true;
 }
 
-bool Layer::setLayer(int32_t z) {
-    if (mCurrentState.z == z)
+bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer,
+        const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
+    ssize_t idx = mCurrentChildren.indexOf(childLayer);
+    if (idx < 0) {
         return false;
+    }
+    if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) {
+        mCurrentChildren.removeAt(idx);
+        mCurrentChildren.add(childLayer);
+    }
+    return true;
+}
+
+bool Layer::setLayer(int32_t z) {
+    if (mCurrentState.z == z) return false;
     mCurrentState.sequence++;
     mCurrentState.z = z;
     mCurrentState.modified = true;
@@ -1859,6 +1172,10 @@
     mCurrentState.modified = true;
     mCurrentState.z = z;
 
+    auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
+    if (oldZOrderRelativeOf != nullptr) {
+        oldZOrderRelativeOf->removeZOrderRelative(this);
+    }
     mCurrentState.zOrderRelativeOf = relative;
     relative->addZOrderRelative(this);
 
@@ -1868,31 +1185,39 @@
 }
 
 bool Layer::setSize(uint32_t w, uint32_t h) {
-    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
-        return false;
+    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false;
     mCurrentState.requested.w = w;
     mCurrentState.requested.h = h;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
-#ifdef USE_HWC2
 bool Layer::setAlpha(float alpha) {
-#else
-bool Layer::setAlpha(uint8_t alpha) {
-#endif
-    if (mCurrentState.alpha == alpha)
-        return false;
+    if (mCurrentState.color.a == alpha) return false;
     mCurrentState.sequence++;
-    mCurrentState.alpha = alpha;
+    mCurrentState.color.a = alpha;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
+
+bool Layer::setColor(const half3& color) {
+    if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
+        color.b == mCurrentState.color.b)
+        return false;
+
+    mCurrentState.sequence++;
+    mCurrentState.color.r = color.r;
+    mCurrentState.color.g = color.g;
+    mCurrentState.color.b = color.b;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
 bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
     mCurrentState.sequence++;
-    mCurrentState.requested.transform.set(
-            matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+    mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
@@ -1905,8 +1230,7 @@
 }
 bool Layer::setFlags(uint8_t flags, uint8_t mask) {
     const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
-    if (mCurrentState.flags == newFlags)
-        return false;
+    if (mCurrentState.flags == newFlags) return false;
     mCurrentState.sequence++;
     mCurrentState.flags = newFlags;
     mCurrentState.mask = mask;
@@ -1916,8 +1240,7 @@
 }
 
 bool Layer::setCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.requestedCrop == crop)
-        return false;
+    if (mCurrentState.requestedCrop == crop) return false;
     mCurrentState.sequence++;
     mCurrentState.requestedCrop = crop;
     if (immediate && !mFreezeGeometryUpdates) {
@@ -1931,8 +1254,7 @@
 }
 
 bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.requestedFinalCrop == crop)
-        return false;
+    if (mCurrentState.requestedFinalCrop == crop) return false;
     mCurrentState.sequence++;
     mCurrentState.requestedFinalCrop = crop;
     if (immediate && !mFreezeGeometryUpdates) {
@@ -1946,30 +1268,21 @@
 }
 
 bool Layer::setOverrideScalingMode(int32_t scalingMode) {
-    if (scalingMode == mOverrideScalingMode)
-        return false;
+    if (scalingMode == mOverrideScalingMode) return false;
     mOverrideScalingMode = scalingMode;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 void Layer::setInfo(uint32_t type, uint32_t appId) {
-  mCurrentState.appId = appId;
-  mCurrentState.type = type;
-  mCurrentState.modified = true;
-  setTransactionFlags(eTransactionNeeded);
-}
-
-uint32_t Layer::getEffectiveScalingMode() const {
-    if (mOverrideScalingMode >= 0) {
-      return mOverrideScalingMode;
-    }
-    return mCurrentScalingMode;
+    mCurrentState.appId = appId;
+    mCurrentState.type = type;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
 }
 
 bool Layer::setLayerStack(uint32_t layerStack) {
-    if (mCurrentState.layerStack == layerStack)
-        return false;
+    if (mCurrentState.layerStack == layerStack) return false;
     mCurrentState.sequence++;
     mCurrentState.layerStack = layerStack;
     mCurrentState.modified = true;
@@ -1978,8 +1291,7 @@
 }
 
 bool Layer::setDataSpace(android_dataspace dataSpace) {
-    if (mCurrentState.dataSpace == dataSpace)
-        return false;
+    if (mCurrentState.dataSpace == dataSpace) return false;
     mCurrentState.sequence++;
     mCurrentState.dataSpace = dataSpace;
     mCurrentState.modified = true;
@@ -1999,8 +1311,7 @@
     return p->getLayerStack();
 }
 
-void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer,
-        uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
     mCurrentState.barrierLayer = barrierLayer;
     mCurrentState.frameNumber = frameNumber;
     // We don't set eTransactionNeeded, because just receiving a deferral
@@ -2012,124 +1323,16 @@
     mCurrentState.modified = false;
 }
 
-void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle,
-        uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
     sp<Handle> handle = static_cast<Handle*>(barrierHandle.get());
     deferTransactionUntil(handle->owner.promote(), frameNumber);
 }
 
-void Layer::useSurfaceDamage() {
-    if (mFlinger->mForceFullDamage) {
-        surfaceDamageRegion = Region::INVALID_REGION;
-    } else {
-        surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
-    }
-}
-
-void Layer::useEmptyDamage() {
-    surfaceDamageRegion.clear();
-}
 
 // ----------------------------------------------------------------------------
 // pageflip handling...
 // ----------------------------------------------------------------------------
 
-bool Layer::shouldPresentNow(const DispSync& dispSync) const {
-    if (mSidebandStreamChanged || mAutoRefresh) {
-        return true;
-    }
-
-    Mutex::Autolock lock(mQueueItemLock);
-    if (mQueueItems.empty()) {
-        return false;
-    }
-    auto timestamp = mQueueItems[0].mTimestamp;
-    nsecs_t expectedPresent =
-            mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
-
-    // Ignore timestamps more than a second in the future
-    bool isPlausible = timestamp < (expectedPresent + s2ns(1));
-    ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
-            "relative to expectedPresent %" PRId64, mName.string(), timestamp,
-            expectedPresent);
-
-    bool isDue = timestamp < expectedPresent;
-    return isDue || !isPlausible;
-}
-
-bool Layer::onPreComposition(nsecs_t refreshStartTime) {
-    if (mBufferLatched) {
-        Mutex::Autolock lock(mFrameEventHistoryMutex);
-        mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
-    }
-    mRefreshPending = false;
-    return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
-}
-
-bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
-        const std::shared_ptr<FenceTime>& presentFence,
-        const CompositorTiming& compositorTiming) {
-    // mFrameLatencyNeeded is true when a new frame was latched for the
-    // composition.
-    if (!mFrameLatencyNeeded)
-        return false;
-
-    // Update mFrameEventHistory.
-    {
-        Mutex::Autolock lock(mFrameEventHistoryMutex);
-        mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
-                glDoneFence, presentFence, compositorTiming);
-    }
-
-    // Update mFrameTracker.
-    nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
-    mFrameTracker.setDesiredPresentTime(desiredPresentTime);
-
-    std::shared_ptr<FenceTime> frameReadyFence =
-            mSurfaceFlingerConsumer->getCurrentFenceTime();
-    if (frameReadyFence->isValid()) {
-        mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
-    } else {
-        // There was no fence for this frame, so assume that it was ready
-        // to be presented at the desired present time.
-        mFrameTracker.setFrameReadyTime(desiredPresentTime);
-    }
-
-    if (presentFence->isValid()) {
-        mFrameTracker.setActualPresentFence(
-                std::shared_ptr<FenceTime>(presentFence));
-    } else {
-        // The HWC doesn't support present fences, so use the refresh
-        // timestamp instead.
-        mFrameTracker.setActualPresentTime(
-            mFlinger->getHwComposer().getRefreshTimestamp(
-                HWC_DISPLAY_PRIMARY));
-    }
-
-    mFrameTracker.advanceFrame();
-    mFrameLatencyNeeded = false;
-    return true;
-}
-
-#ifdef USE_HWC2
-void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
-    if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
-        return;
-    }
-
-    auto releaseFenceTime = std::make_shared<FenceTime>(
-            mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
-    mReleaseTimeline.updateSignalTimes();
-    mReleaseTimeline.push(releaseFenceTime);
-
-    Mutex::Autolock lock(mFrameEventHistoryMutex);
-    if (mPreviousFrameNumber != 0) {
-        mFrameEventHistory.addRelease(mPreviousFrameNumber,
-                dequeueReadyTime, std::move(releaseFenceTime));
-    }
-}
-#endif
-
 bool Layer::isHiddenByPolicy() const {
     const Layer::State& s(mDrawingState);
     const auto& parent = mDrawingParent.promote();
@@ -2139,256 +1342,7 @@
     return s.flags & layer_state_t::eLayerHidden;
 }
 
-bool Layer::isVisible() const {
-#ifdef USE_HWC2
-    return !(isHiddenByPolicy()) && getAlpha() > 0.0f
-            && (mActiveBuffer != NULL || mSidebandStream != NULL);
-#else
-    return !(isHiddenByPolicy()) && getAlpha()
-            && (mActiveBuffer != NULL || mSidebandStream != NULL);
-#endif
-}
-
-bool Layer::allTransactionsSignaled() {
-    auto headFrameNumber = getHeadFrameNumber();
-    bool matchingFramesFound = false;
-    bool allTransactionsApplied = true;
-    Mutex::Autolock lock(mLocalSyncPointMutex);
-
-    for (auto& point : mLocalSyncPoints) {
-        if (point->getFrameNumber() > headFrameNumber) {
-            break;
-        }
-        matchingFramesFound = true;
-
-        if (!point->frameIsAvailable()) {
-           // We haven't notified the remote layer that the frame for
-           // this point is available yet. Notify it now, and then
-           // abort this attempt to latch.
-           point->setFrameAvailable();
-           allTransactionsApplied = false;
-           break;
-        }
-
-        allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
-    }
-    return !matchingFramesFound || allTransactionsApplied;
-}
-
-Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
-{
-    ATRACE_CALL();
-
-    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
-        // mSidebandStreamChanged was true
-        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
-        if (mSidebandStream != NULL) {
-            setTransactionFlags(eTransactionNeeded);
-            mFlinger->setTransactionFlags(eTraversalNeeded);
-        }
-        recomputeVisibleRegions = true;
-
-        const State& s(getDrawingState());
-        return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
-    }
-
-    Region outDirtyRegion;
-    if (mQueuedFrames <= 0 && !mAutoRefresh) {
-        return outDirtyRegion;
-    }
-
-    // if we've already called updateTexImage() without going through
-    // a composition step, we have to skip this layer at this point
-    // because we cannot call updateTeximage() without a corresponding
-    // compositionComplete() call.
-    // we'll trigger an update in onPreComposition().
-    if (mRefreshPending) {
-        return outDirtyRegion;
-    }
-
-    // If the head buffer's acquire fence hasn't signaled yet, return and
-    // try again later
-    if (!headFenceHasSignaled()) {
-        mFlinger->signalLayerUpdate();
-        return outDirtyRegion;
-    }
-
-    // Capture the old state of the layer for comparisons later
-    const State& s(getDrawingState());
-    const bool oldOpacity = isOpaque(s);
-    sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
-
-    if (!allTransactionsSignaled()) {
-        mFlinger->signalLayerUpdate();
-        return outDirtyRegion;
-    }
-
-    // This boolean is used to make sure that SurfaceFlinger's shadow copy
-    // of the buffer queue isn't modified when the buffer queue is returning
-    // BufferItem's that weren't actually queued. This can happen in shared
-    // buffer mode.
-    bool queuedBuffer = false;
-    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                    getProducerStickyTransform() != 0, mName.string(),
-                    mOverrideScalingMode, mFreezeGeometryUpdates);
-    status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
-            mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
-            mLastFrameNumberReceived);
-    if (updateResult == BufferQueue::PRESENT_LATER) {
-        // Producer doesn't want buffer to be displayed yet.  Signal a
-        // layer update so we check again at the next opportunity.
-        mFlinger->signalLayerUpdate();
-        return outDirtyRegion;
-    } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
-        // If the buffer has been rejected, remove it from the shadow queue
-        // and return early
-        if (queuedBuffer) {
-            Mutex::Autolock lock(mQueueItemLock);
-            mQueueItems.removeAt(0);
-            android_atomic_dec(&mQueuedFrames);
-        }
-        return outDirtyRegion;
-    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
-        // This can occur if something goes wrong when trying to create the
-        // EGLImage for this buffer. If this happens, the buffer has already
-        // been released, so we need to clean up the queue and bug out
-        // early.
-        if (queuedBuffer) {
-            Mutex::Autolock lock(mQueueItemLock);
-            mQueueItems.clear();
-            android_atomic_and(0, &mQueuedFrames);
-        }
-
-        // Once we have hit this state, the shadow queue may no longer
-        // correctly reflect the incoming BufferQueue's contents, so even if
-        // updateTexImage starts working, the only safe course of action is
-        // to continue to ignore updates.
-        mUpdateTexImageFailed = true;
-
-        return outDirtyRegion;
-    }
-
-    if (queuedBuffer) {
-        // Autolock scope
-        auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
-        Mutex::Autolock lock(mQueueItemLock);
-
-        // Remove any stale buffers that have been dropped during
-        // updateTexImage
-        while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
-            mQueueItems.removeAt(0);
-            android_atomic_dec(&mQueuedFrames);
-        }
-
-        mQueueItems.removeAt(0);
-    }
-
-
-    // Decrement the queued-frames count.  Signal another event if we
-    // have more frames pending.
-    if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
-            || mAutoRefresh) {
-        mFlinger->signalLayerUpdate();
-    }
-
-    // update the active buffer
-    mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(
-            &mActiveBufferSlot);
-    if (mActiveBuffer == NULL) {
-        // this can only happen if the very first buffer was rejected.
-        return outDirtyRegion;
-    }
-
-    mBufferLatched = true;
-    mPreviousFrameNumber = mCurrentFrameNumber;
-    mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
-    {
-        Mutex::Autolock lock(mFrameEventHistoryMutex);
-        mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
-#ifndef USE_HWC2
-        auto releaseFenceTime = std::make_shared<FenceTime>(
-                mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
-        mReleaseTimeline.updateSignalTimes();
-        mReleaseTimeline.push(releaseFenceTime);
-        if (mPreviousFrameNumber != 0) {
-            mFrameEventHistory.addRelease(mPreviousFrameNumber,
-                    latchTime, std::move(releaseFenceTime));
-        }
-#endif
-    }
-
-    mRefreshPending = true;
-    mFrameLatencyNeeded = true;
-    if (oldActiveBuffer == NULL) {
-         // the first time we receive a buffer, we need to trigger a
-         // geometry invalidation.
-        recomputeVisibleRegions = true;
-     }
-
-    setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
-
-    Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
-    const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
-    const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
-    if ((crop != mCurrentCrop) ||
-        (transform != mCurrentTransform) ||
-        (scalingMode != mCurrentScalingMode))
-    {
-        mCurrentCrop = crop;
-        mCurrentTransform = transform;
-        mCurrentScalingMode = scalingMode;
-        recomputeVisibleRegions = true;
-    }
-
-    if (oldActiveBuffer != NULL) {
-        uint32_t bufWidth  = mActiveBuffer->getWidth();
-        uint32_t bufHeight = mActiveBuffer->getHeight();
-        if (bufWidth != uint32_t(oldActiveBuffer->width) ||
-            bufHeight != uint32_t(oldActiveBuffer->height)) {
-            recomputeVisibleRegions = true;
-        }
-    }
-
-    mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
-    if (oldOpacity != isOpaque(s)) {
-        recomputeVisibleRegions = true;
-    }
-
-    // Remove any sync points corresponding to the buffer which was just
-    // latched
-    {
-        Mutex::Autolock lock(mLocalSyncPointMutex);
-        auto point = mLocalSyncPoints.begin();
-        while (point != mLocalSyncPoints.end()) {
-            if (!(*point)->frameIsAvailable() ||
-                    !(*point)->transactionIsApplied()) {
-                // This sync point must have been added since we started
-                // latching. Don't drop it yet.
-                ++point;
-                continue;
-            }
-
-            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
-                point = mLocalSyncPoints.erase(point);
-            } else {
-                ++point;
-            }
-        }
-    }
-
-    // FIXME: postedRegion should be dirty & bounds
-    Region dirtyRegion(Rect(s.active.w, s.active.h));
-
-    // transform the dirty region to window-manager space
-    outDirtyRegion = (getTransform().transform(dirtyRegion));
-
-    return outDirtyRegion;
-}
-
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const {
     // TODO: should we do something special if mSecure is set?
     if (mProtectedByApp) {
         // need a hardware-protected path to external video sink
@@ -2413,7 +1367,7 @@
             orientation = 0;
         }
     }
-    mSurfaceFlingerConsumer->setTransformHint(orientation);
+    setTransformHint(orientation);
 }
 
 // ----------------------------------------------------------------------------
@@ -2438,7 +1392,7 @@
     info.mHeight = ds.active.h;
     info.mCrop = ds.crop;
     info.mFinalCrop = ds.finalCrop;
-    info.mAlpha = ds.alpha;
+    info.mColor = ds.color;
     info.mFlags = ds.flags;
     info.mPixelFormat = getPixelFormat();
     info.mDataSpace = getDataSpace();
@@ -2447,12 +1401,12 @@
     info.mMatrix[1][0] = ds.active.transform[1][0];
     info.mMatrix[1][1] = ds.active.transform[1][1];
     {
-        sp<const GraphicBuffer> activeBuffer = getActiveBuffer();
-        if (activeBuffer != 0) {
-            info.mActiveBufferWidth = activeBuffer->getWidth();
-            info.mActiveBufferHeight = activeBuffer->getHeight();
-            info.mActiveBufferStride = activeBuffer->getStride();
-            info.mActiveBufferFormat = activeBuffer->format;
+        sp<const GraphicBuffer> buffer = getBE().mBuffer;
+        if (buffer != 0) {
+            info.mActiveBufferWidth = buffer->getWidth();
+            info.mActiveBufferHeight = buffer->getHeight();
+            info.mActiveBufferStride = buffer->getStride();
+            info.mActiveBufferFormat = buffer->format;
         } else {
             info.mActiveBufferWidth = 0;
             info.mActiveBufferHeight = 0;
@@ -2467,7 +1421,6 @@
     return info;
 }
 
-#ifdef USE_HWC2
 void Layer::miniDumpHeader(String8& result) {
     result.append("----------------------------------------");
     result.append("---------------------------------------\n");
@@ -2481,7 +1434,7 @@
 }
 
 void Layer::miniDump(String8& result, int32_t hwcId) const {
-    if (mHwcLayers.count(hwcId) == 0) {
+    if (getBE().mHwcLayers.count(hwcId) == 0) {
         return;
     }
 
@@ -2499,21 +1452,17 @@
     result.appendFormat(" %s\n", name.string());
 
     const Layer::State& layerState(getDrawingState());
-    const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
-    result.appendFormat("  %10u | ", layerState.z);
-    result.appendFormat("%10s | ",
-            to_string(getCompositionType(hwcId)).c_str());
+    const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId);
+    result.appendFormat("  %10d | ", layerState.z);
+    result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
     const Rect& frame = hwcInfo.displayFrame;
-    result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
-            frame.right, frame.bottom);
+    result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
     const FloatRect& crop = hwcInfo.sourceCrop;
-    result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
-            crop.right, crop.bottom);
+    result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
 
     result.append("- - - - - - - - - - - - - - - - - - - - ");
     result.append("- - - - - - - - - - - - - - - - - - - -\n");
 }
-#endif
 
 void Layer::dumpFrameStats(String8& result) const {
     mFrameTracker.dumpStats(result);
@@ -2532,8 +1481,7 @@
 }
 
 void Layer::dumpFrameEvents(String8& result) {
-    result.appendFormat("- Layer %s (%s, %p)\n",
-            getName().string(), getTypeId(), this);
+    result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     mFrameEventHistory.checkFencesForCompletion();
     mFrameEventHistory.dump(result);
@@ -2545,7 +1493,7 @@
 }
 
 void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
-        FrameEventHistoryDelta *outDelta) {
+                                     FrameEventHistoryDelta* outDelta) {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     if (newTimestamps) {
         // If there are any unsignaled fences in the aquire timeline at this
@@ -2563,23 +1511,6 @@
     }
 }
 
-std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory(
-        bool forceFlush) {
-    std::vector<OccupancyTracker::Segment> history;
-    status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush,
-            &history);
-    if (result != NO_ERROR) {
-        ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(),
-                result);
-        return {};
-    }
-    return history;
-}
-
-bool Layer::getTransformToDisplayInverse() const {
-    return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
-}
-
 size_t Layer::getChildrenCount() const {
     size_t count = 0;
     for (const sp<Layer>& child : mCurrentChildren) {
@@ -2624,17 +1555,43 @@
     return true;
 }
 
-bool Layer::detachChildren() {
-    traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
-        if (child == this) {
-            return;
-        }
+bool Layer::reparent(const sp<IBinder>& newParentHandle) {
+    if (newParentHandle == nullptr) {
+        return false;
+    }
 
+    auto handle = static_cast<Handle*>(newParentHandle.get());
+    sp<Layer> newParent = handle->owner.promote();
+    if (newParent == nullptr) {
+        ALOGE("Unable to promote Layer handle");
+        return false;
+    }
+
+    sp<Layer> parent = getParent();
+    if (parent != nullptr) {
+        parent->removeChild(this);
+    }
+    newParent->addChild(this);
+
+    sp<Client> client(mClientRef.promote());
+    sp<Client> newParentClient(newParent->mClientRef.promote());
+
+    if (client != newParentClient) {
+        client->setParentLayer(newParent);
+    }
+
+    return true;
+}
+
+bool Layer::detachChildren() {
+    for (const sp<Layer>& child : mCurrentChildren) {
+        sp<Client> parentClient = mClientRef.promote();
         sp<Client> client(child->mClientRef.promote());
-        if (client != nullptr) {
-            client->detachLayer(child);
+        if (client != nullptr && parentClient != client) {
+            client->detachLayer(child.get());
+            child->detachChildren();
         }
-    });
+    }
 
     return true;
 }
@@ -2659,18 +1616,15 @@
     return mDrawingState.z;
 }
 
-LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) {
+__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(
+        LayerVector::StateSet stateSet) {
     LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
                         "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
 
-    if (state.zOrderRelatives.size() == 0) {
-        return children;
-    }
     LayerVector traverse;
-
     for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
         sp<Layer> strongRelative = weakRelative.promote();
         if (strongRelative != nullptr) {
@@ -2679,6 +1633,10 @@
     }
 
     for (const sp<Layer>& child : children) {
+        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
+        if (childState.zOrderRelativeOf != nullptr) {
+            continue;
+        }
         traverse.add(child);
     }
 
@@ -2714,7 +1672,7 @@
     LayerVector list = makeTraversalList(stateSet);
 
     int32_t i = 0;
-    for (i = list.size()-1; i>=0; i--) {
+    for (i = int32_t(list.size()) - 1; i >= 0; i--) {
         const auto& relative = list[i];
         if (relative->getZ() < 0) {
             break;
@@ -2722,12 +1680,35 @@
         relative->traverseInReverseZOrder(stateSet, visitor);
     }
     visitor(this);
-    for (; i>=0; i--) {
+    for (; i >= 0; i--) {
         const auto& relative = list[i];
         relative->traverseInReverseZOrder(stateSet, visitor);
     }
 }
 
+/**
+ * Traverse only children in z order, ignoring relative layers.
+ */
+void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet,
+                                     const LayerVector::Visitor& visitor) {
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+
+    size_t i = 0;
+    for (; i < children.size(); i++) {
+        const auto& relative = children[i];
+        if (relative->getZ() >= 0) {
+            break;
+        }
+        relative->traverseChildrenInZOrder(stateSet, visitor);
+    }
+    visitor(this);
+    for (; i < children.size(); i++) {
+        const auto& relative = children[i];
+        relative->traverseChildrenInZOrder(stateSet, visitor);
+    }
+}
+
 Transform Layer::getTransform() const {
     Transform t;
     const auto& p = mDrawingParent.promote();
@@ -2739,20 +1720,18 @@
         // for in the transform. We need to mirror this scaling in child surfaces
         // or we will break the contract where WM can treat child surfaces as
         // pixels in the parent surface.
-        if (p->isFixedSize() && p->mActiveBuffer != nullptr) {
+        if (p->isFixedSize() && p->getBE().mBuffer != nullptr) {
             int bufferWidth;
             int bufferHeight;
             if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
-                bufferWidth = p->mActiveBuffer->getWidth();
-                bufferHeight = p->mActiveBuffer->getHeight();
+                bufferWidth = p->getBE().mBuffer->getWidth();
+                bufferHeight = p->getBE().mBuffer->getHeight();
             } else {
-                bufferHeight = p->mActiveBuffer->getWidth();
-                bufferWidth = p->mActiveBuffer->getHeight();
+                bufferHeight = p->getBE().mBuffer->getWidth();
+                bufferWidth = p->getBE().mBuffer->getHeight();
             }
-            float sx = p->getDrawingState().active.w /
-                    static_cast<float>(bufferWidth);
-            float sy = p->getDrawingState().active.h /
-                    static_cast<float>(bufferHeight);
+            float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth);
+            float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight);
             Transform extraParentScaling;
             extraParentScaling.set(sx, 0, 0, sy);
             t = t * extraParentScaling;
@@ -2761,23 +1740,17 @@
     return t * getDrawingState().active.transform;
 }
 
-#ifdef USE_HWC2
-float Layer::getAlpha() const {
+half Layer::getAlpha() const {
     const auto& p = mDrawingParent.promote();
 
-    float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0;
-    return parentAlpha * getDrawingState().alpha;
+    half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
+    return parentAlpha * getDrawingState().color.a;
 }
-#else
-uint8_t Layer::getAlpha() const {
-    const auto& p = mDrawingParent.promote();
 
-    float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0;
-    float drawingAlpha = getDrawingState().alpha / 255.0f;
-    drawingAlpha = drawingAlpha * parentAlpha;
-    return static_cast<uint8_t>(std::round(drawingAlpha * 255));
+half4 Layer::getColor() const {
+    const half4 color(getDrawingState().color);
+    return half4(color.r, color.g, color.b, getAlpha());
 }
-#endif
 
 void Layer::commitChildList() {
     for (size_t i = 0; i < mCurrentChildren.size(); i++) {
@@ -2788,6 +1761,82 @@
     mDrawingParent = mCurrentParent;
 }
 
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+
+    Transform requestedTransform = state.active.transform;
+    Transform transform = getTransform();
+
+    layerInfo->set_id(sequence);
+    layerInfo->set_name(getName().c_str());
+    layerInfo->set_type(String8(getTypeId()));
+
+    for (const auto& child : children) {
+        layerInfo->add_children(child->sequence);
+    }
+
+    for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+        sp<Layer> strongRelative = weakRelative.promote();
+        if (strongRelative != nullptr) {
+            layerInfo->add_relatives(strongRelative->sequence);
+        }
+    }
+
+    LayerProtoHelper::writeToProto(state.activeTransparentRegion,
+                                   layerInfo->mutable_transparent_region());
+    LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region());
+    LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region());
+
+    layerInfo->set_layer_stack(getLayerStack());
+    layerInfo->set_z(state.z);
+
+    PositionProto* position = layerInfo->mutable_position();
+    position->set_x(transform.tx());
+    position->set_y(transform.ty());
+
+    PositionProto* requestedPosition = layerInfo->mutable_requested_position();
+    requestedPosition->set_x(requestedTransform.tx());
+    requestedPosition->set_y(requestedTransform.ty());
+
+    SizeProto* size = layerInfo->mutable_size();
+    size->set_w(state.active.w);
+    size->set_h(state.active.h);
+
+    LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop());
+    LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop());
+
+    layerInfo->set_is_opaque(isOpaque(state));
+    layerInfo->set_invalidate(contentDirty);
+    layerInfo->set_dataspace(dataspaceDetails(getDataSpace()));
+    layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
+    LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color());
+    LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color());
+    layerInfo->set_flags(state.flags);
+
+    LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+    LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform());
+
+    auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
+    if (parent != nullptr) {
+        layerInfo->set_parent(parent->sequence);
+    }
+
+    auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
+    if (zOrderRelativeOf != nullptr) {
+        layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
+    }
+
+    auto buffer = getBE().mBuffer;
+    if (buffer != nullptr) {
+        LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer());
+    }
+
+    layerInfo->set_queued_frames(getQueuedFrameCount());
+    layerInfo->set_refresh_pending(isBufferLatched());
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f7501a3..8ac5094 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,9 +20,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
@@ -33,24 +30,28 @@
 #include <ui/Region.h>
 
 #include <gui/ISurfaceComposerClient.h>
-
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
 
 #include <list>
 
-#include "FrameTracker.h"
 #include "Client.h"
+#include "FrameTracker.h"
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
-#include "SurfaceFlingerConsumer.h"
 #include "Transform.h"
 
+#include <layerproto/LayerProtoHeader.h>
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/HWComposerBufferCache.h"
+#include "RenderArea.h"
 #include "RenderEngine/Mesh.h"
 #include "RenderEngine/Texture.h"
 
+#include <math/vec4.h>
+
+using namespace android::surfaceflinger;
+
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -61,20 +62,54 @@
 class GraphicBuffer;
 class SurfaceFlinger;
 class LayerDebugInfo;
+class LayerBE;
 
 // ---------------------------------------------------------------------------
 
-/*
- * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
- * Layer is first referenced.
- *
- * This also implements onFrameAvailable(), which notifies SurfaceFlinger
- * that new data has arrived.
- */
-class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
+class LayerBE {
+public:
+    LayerBE();
+
+    // main thread
+    int mBufferSlot;
+    sp<GraphicBuffer> mBuffer;
+    sp<NativeHandle> mSidebandStream;
+
+    // The mesh used to draw the layer in GLES composition mode
+    Mesh mMesh;
+
+    // HWC items, accessed from the main thread
+    struct HWCInfo {
+        HWCInfo()
+              : hwc(nullptr),
+                layer(nullptr),
+                forceClientComposition(false),
+                compositionType(HWC2::Composition::Invalid),
+                clearClientTarget(false) {}
+
+        HWComposer* hwc;
+        HWC2::Layer* layer;
+        bool forceClientComposition;
+        HWC2::Composition compositionType;
+        bool clearClientTarget;
+        Rect displayFrame;
+        FloatRect sourceCrop;
+        HWComposerBufferCache bufferCache;
+    };
+
+    // A layer can be attached to multiple displays when operating in mirror mode
+    // (a.k.a: when several displays are attached with equal layerStack). In this
+    // case we need to keep track. In non-mirror mode, a layer will have only one
+    // HWCInfo. This map key is a display layerStack.
+    std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+};
+
+class Layer : public virtual RefBase {
     static int32_t sSequence;
 
 public:
+    LayerBE& getBE() { return mBE; }
+    LayerBE& getBE() const { return mBE; }
     mutable bool contentDirty;
     // regions below are in window-manager space
     Region visibleRegion;
@@ -97,14 +132,11 @@
         uint32_t h;
         Transform transform;
 
-        inline bool operator ==(const Geometry& rhs) const {
-            return (w == rhs.w && h == rhs.h) &&
-                    (transform.tx() == rhs.transform.tx()) &&
+        inline bool operator==(const Geometry& rhs) const {
+            return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) &&
                     (transform.ty() == rhs.transform.ty());
         }
-        inline bool operator !=(const Geometry& rhs) const {
-            return !operator ==(rhs);
-        }
+        inline bool operator!=(const Geometry& rhs) const { return !operator==(rhs); }
     };
 
     struct State {
@@ -119,11 +151,6 @@
         // to achieve mirroring.
         uint32_t layerStack;
 
-#ifdef USE_HWC2
-        float alpha;
-#else
-        uint8_t alpha;
-#endif
         uint8_t flags;
         uint8_t mask;
         uint8_t reserved[2];
@@ -158,20 +185,16 @@
 
         // A list of surfaces whose Z-order is interpreted relative to ours.
         SortedVector<wp<Layer>> zOrderRelatives;
+
+        half4 color;
     };
 
-    // -----------------------------------------------------------------------
-
-    Layer(SurfaceFlinger* flinger, const sp<Client>& client,
-            const String8& name, uint32_t w, uint32_t h, uint32_t flags);
-
+    Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+          uint32_t h, uint32_t flags);
     virtual ~Layer();
 
     void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
 
-    // the this layer's size and format
-    status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
-
     // ------------------------------------------------------------------------
     // Geometry setting functions.
     //
@@ -225,11 +248,8 @@
     bool setLayer(int32_t z);
     bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
-#ifdef USE_HWC2
     bool setAlpha(float alpha);
-#else
-    bool setAlpha(uint8_t alpha);
-#endif
+    bool setColor(const half3& color);
     bool setTransparentRegionHint(const Region& transparent);
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setLayerStack(uint32_t layerStack);
@@ -241,13 +261,14 @@
     bool setOverrideScalingMode(int32_t overrideScalingMode);
     void setInfo(uint32_t type, uint32_t appId);
     bool reparentChildren(const sp<IBinder>& layer);
+    bool reparent(const sp<IBinder>& newParentHandle);
     bool detachChildren();
 
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
     // one empty rect.
-    void useSurfaceDamage();
-    void useEmptyDamage();
+    virtual void useSurfaceDamage() = 0;
+    virtual void useEmptyDamage() = 0;
 
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags);
@@ -256,8 +277,7 @@
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
-    void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
-            bool useIdentityTransform) const;
+    void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const;
     Rect computeBounds(const Region& activeTransparentRegion) const;
     Rect computeBounds() const;
 
@@ -265,8 +285,7 @@
 
     // -----------------------------------------------------------------------
     // Virtuals
-
-    virtual const char* getTypeId() const { return "Layer"; }
+    virtual const char* getTypeId() const = 0;
 
     /*
      * isOpaque - true if this surface is opaque
@@ -275,24 +294,18 @@
      * pixel format includes an alpha channel) and the "opaque" flag set
      * on the layer.  It does not examine the current plane alpha value.
      */
-    virtual bool isOpaque(const Layer::State& s) const;
+    virtual bool isOpaque(const Layer::State& s) const = 0;
 
     /*
      * isSecure - true if this surface is secure, that is if it prevents
      * screenshots or VNC servers.
      */
-    virtual bool isSecure() const;
-
-    /*
-     * isProtected - true if the layer may contain protected content in the
-     * GRALLOC_USAGE_PROTECTED sense.
-     */
-    virtual bool isProtected() const;
+    bool isSecure() const;
 
     /*
      * isVisible - true if this layer is visible, false otherwise
      */
-    virtual bool isVisible() const;
+    virtual bool isVisible() const = 0;
 
     /*
      * isHiddenByPolicy - true if this layer has been forced invisible.
@@ -300,87 +313,75 @@
      * For example if this layer has no active buffer, it may not be hidden by
      * policy, but it still can not be visible.
      */
-    virtual bool isHiddenByPolicy() const;
+    bool isHiddenByPolicy() const;
 
     /*
      * isFixedSize - true if content has a fixed size
      */
-    virtual bool isFixedSize() const;
+    virtual bool isFixedSize() const = 0;
+
+    bool isPendingRemoval() const { return mPendingRemoval; }
+
+    void writeToProto(LayerProto* layerInfo,
+                      LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
 
 protected:
     /*
      * onDraw - draws the surface.
      */
-    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
-            bool useIdentityTransform) const;
+    virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+                        bool useIdentityTransform) const = 0;
 
 public:
-    // -----------------------------------------------------------------------
+    virtual void setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
 
-#ifdef USE_HWC2
     void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
     void forceClientComposition(int32_t hwcId);
-    void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+    bool getForceClientComposition(int32_t hwcId);
+    virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
 
     // callIntoHwc exists so we can update our local state and call
     // acceptDisplayChanges without unnecessarily updating the device's state
-    void setCompositionType(int32_t hwcId, HWC2::Composition type,
-            bool callIntoHwc = true);
+    void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true);
     HWC2::Composition getCompositionType(int32_t hwcId) const;
-
     void setClearClientTarget(int32_t hwcId, bool clear);
     bool getClearClientTarget(int32_t hwcId) const;
-
     void updateCursorPosition(const sp<const DisplayDevice>& hw);
-#else
-    void setGeometry(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    void setPerFrameData(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    void setAcquireFence(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-
-    Rect getPosition(const sp<const DisplayDevice>& hw);
-#endif
 
     /*
      * called after page-flip
      */
-#ifdef USE_HWC2
-    void onLayerDisplayed(const sp<Fence>& releaseFence);
-#else
-    void onLayerDisplayed(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface* layer);
-#endif
+    virtual void onLayerDisplayed(const sp<Fence>& releaseFence);
 
-    bool shouldPresentNow(const DispSync& dispSync) const;
+    virtual void abandon() = 0;
+
+    virtual bool shouldPresentNow(const DispSync& dispSync) const = 0;
+    virtual void setTransformHint(uint32_t orientation) const = 0;
 
     /*
      * called before composition.
      * returns true if the layer has pending updates.
      */
-    bool onPreComposition(nsecs_t refreshStartTime);
+    virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
 
     /*
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
-    bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
-            const std::shared_ptr<FenceTime>& presentFence,
-            const CompositorTiming& compositorTiming);
+    virtual bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+                                   const std::shared_ptr<FenceTime>& presentFence,
+                                   const CompositorTiming& compositorTiming) = 0;
 
-#ifdef USE_HWC2
     // If a buffer was replaced this frame, release the former buffer
-    void releasePendingBuffer(nsecs_t dequeueReadyTime);
-#endif
+    virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0;
 
     /*
      * draw - performs some global clipping optimizations
      * and calls onDraw().
      */
-    void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
-    void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform) const;
-    void draw(const sp<const DisplayDevice>& hw) const;
+    void draw(const RenderArea& renderArea, const Region& clip) const;
+    void draw(const RenderArea& renderArea, bool useIdentityTransform) const;
+    void draw(const RenderArea& renderArea) const;
 
     /*
      * doTransaction - process the transaction. This is a good place to figure
@@ -405,8 +406,7 @@
      * setVisibleNonTransparentRegion - called when the visible and
      * non-transparent region changes.
      */
-    void setVisibleNonTransparentRegion(const Region&
-            visibleNonTransparentRegion);
+    void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion);
 
     /*
      * latchBuffer - called each time the screen is redrawn and returns whether
@@ -414,11 +414,10 @@
      * operation, so this should be set only if needed). Typically this is used
      * to figure out if the content or size of a surface has changed.
      */
-    Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime);
-    bool isBufferLatched() const { return mRefreshPending; }
+    virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+    virtual bool isBufferLatched() const = 0;
 
-    bool isPotentialCursor() const { return mPotentialCursor;}
-
+    bool isPotentialCursor() const { return mPotentialCursor; }
     /*
      * called with the state lock from a binder thread when the layer is
      * removed from the current list to the pending removal list
@@ -431,7 +430,6 @@
      */
     void onRemoved();
 
-
     // Updates the transform hint in our SurfaceFlingerConsumer to match
     // the current orientation of the display device.
     void updateTransformHint(const sp<const DisplayDevice>& hw) const;
@@ -445,12 +443,12 @@
     /*
      * Returns if a frame is queued.
      */
-    bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
-            mSidebandStreamChanged || mAutoRefresh; }
+    bool hasQueuedFrame() const {
+        return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
+    }
 
     int32_t getQueuedFrameCount() const { return mQueuedFrames; }
 
-#ifdef USE_HWC2
     // -----------------------------------------------------------------------
 
     bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
@@ -458,66 +456,61 @@
     void destroyAllHwcLayers();
 
     bool hasHwcLayer(int32_t hwcId) {
-        return mHwcLayers.count(hwcId) > 0;
+        return getBE().mHwcLayers.count(hwcId) > 0;
     }
 
     HWC2::Layer* getHwcLayer(int32_t hwcId) {
-        if (mHwcLayers.count(hwcId) == 0) {
+        if (getBE().mHwcLayers.count(hwcId) == 0) {
             return nullptr;
         }
-        return mHwcLayers[hwcId].layer;
+        return getBE().mHwcLayers[hwcId].layer;
     }
 
-#endif
     // -----------------------------------------------------------------------
 
-    void clearWithOpenGL(const sp<const DisplayDevice>& hw) const;
+    void clearWithOpenGL(const RenderArea& renderArea) const;
     void setFiltering(bool filtering);
     bool getFiltering() const;
 
-    // only for debugging
-    inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
 
-    inline  const State&    getDrawingState() const { return mDrawingState; }
-    inline  const State&    getCurrentState() const { return mCurrentState; }
-    inline  State&          getCurrentState()       { return mCurrentState; }
+    inline const State& getDrawingState() const { return mDrawingState; }
+    inline const State& getCurrentState() const { return mCurrentState; }
+    inline State& getCurrentState() { return mCurrentState; }
 
     LayerDebugInfo getLayerDebugInfo() const;
 
     /* always call base class first */
-#ifdef USE_HWC2
     static void miniDumpHeader(String8& result);
     void miniDump(String8& result, int32_t hwcId) const;
-#endif
     void dumpFrameStats(String8& result) const;
     void dumpFrameEvents(String8& result);
     void clearFrameStats();
     void logFrameStats();
     void getFrameStats(FrameStats* outStats) const;
 
-    std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush);
+    virtual std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) = 0;
 
     void onDisconnect();
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
-            FrameEventHistoryDelta* outDelta);
+                                  FrameEventHistoryDelta* outDelta);
 
-    bool getTransformToDisplayInverse() const;
+    virtual bool getTransformToDisplayInverse() const = 0;
 
     Transform getTransform() const;
 
     // Returns the Alpha of the Surface, accounting for the Alpha
     // of parent Surfaces in the hierarchy (alpha's will be multiplied
     // down the hierarchy).
-#ifdef USE_HWC2
-    float getAlpha() const;
-#else
-    uint8_t getAlpha() const;
-#endif
+    half getAlpha() const;
+    half4 getColor() const;
 
     void traverseInReverseZOrder(LayerVector::StateSet stateSet,
                                  const LayerVector::Visitor& visitor);
     void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
 
+    void traverseChildrenInZOrder(LayerVector::StateSet stateSet,
+                                  const LayerVector::Visitor& visitor);
+
     size_t getChildrenCount() const;
     void addChild(const sp<Layer>& layer);
     // Returns index if removed, or negative value otherwise
@@ -525,15 +518,16 @@
     ssize_t removeChild(const sp<Layer>& layer);
     sp<Layer> getParent() const { return mCurrentParent.promote(); }
     bool hasParent() const { return getParent() != nullptr; }
-
     Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
     bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
+    bool setChildRelativeLayer(const sp<Layer>& childLayer,
+            const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
     // Copy the current list of children to the drawing state. Called by
     // SurfaceFlinger to complete a transaction.
     void commitChildList();
-
     int32_t getZ() const;
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -544,56 +538,36 @@
     class LayerCleaner {
         sp<SurfaceFlinger> mFlinger;
         wp<Layer> mLayer;
+
     protected:
         ~LayerCleaner() {
             // destroy client resources
             mFlinger->onLayerDestroyed(mLayer);
         }
-    public:
-        LayerCleaner(const sp<SurfaceFlinger>& flinger,
-                const sp<Layer>& layer)
-            : mFlinger(flinger), mLayer(layer) {
-        }
-    };
 
+    public:
+        LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+              : mFlinger(flinger), mLayer(layer) {}
+    };
 
     virtual void onFirstRef();
 
-
-
-private:
     friend class SurfaceInterceptor;
-    // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
-    virtual void onFrameAvailable(const BufferItem& item) override;
-    virtual void onFrameReplaced(const BufferItem& item) override;
-    virtual void onSidebandStreamChanged() override;
 
     void commitTransaction(const State& stateToCommit);
 
-    // needsLinearFiltering - true if this surface's state requires filtering
-    bool needsFiltering(const sp<const DisplayDevice>& hw) const;
-
     uint32_t getEffectiveUsage(uint32_t usage) const;
 
     FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
-    // Compute the initial crop as specified by parent layers and the SurfaceControl
-    // for this layer. Does not include buffer crop from the IGraphicBufferProducer
-    // client, as that should not affect child clipping. Returns in screen space.
+    // Compute the initial crop as specified by parent layers and the
+    // SurfaceControl for this layer. Does not include buffer crop from the
+    // IGraphicBufferProducer client, as that should not affect child clipping.
+    // Returns in screen space.
     Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const;
-    bool isCropped() const;
-    static bool getOpacityForFormat(uint32_t format);
 
     // drawing
-    void clearWithOpenGL(const sp<const DisplayDevice>& hw,
-            float r, float g, float b, float alpha) const;
-    void drawWithOpenGL(const sp<const DisplayDevice>& hw,
-            bool useIdentityTransform) const;
-
-    // Temporary - Used only for LEGACY camera mode.
-    uint32_t getProducerStickyTransform() const;
-
-    // Loads the corresponding system property once per process
-    static bool latchUnsignaledBuffers();
+    void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
+                         float alpha) const;
 
     void setParent(const sp<Layer>& layer);
 
@@ -601,33 +575,20 @@
     void addZOrderRelative(const wp<Layer>& relative);
     void removeZOrderRelative(const wp<Layer>& relative);
 
-    // -----------------------------------------------------------------------
-
-    class SyncPoint
-    {
+    class SyncPoint {
     public:
-        explicit SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber),
-                mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+        explicit SyncPoint(uint64_t frameNumber)
+              : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
 
-        uint64_t getFrameNumber() const {
-            return mFrameNumber;
-        }
+        uint64_t getFrameNumber() const { return mFrameNumber; }
 
-        bool frameIsAvailable() const {
-            return mFrameIsAvailable;
-        }
+        bool frameIsAvailable() const { return mFrameIsAvailable; }
 
-        void setFrameAvailable() {
-            mFrameIsAvailable = true;
-        }
+        void setFrameAvailable() { mFrameIsAvailable = true; }
 
-        bool transactionIsApplied() const {
-            return mTransactionIsApplied;
-        }
+        bool transactionIsApplied() const { return mTransactionIsApplied; }
 
-        void setTransactionApplied() {
-            mTransactionIsApplied = true;
-        }
+        void setTransactionApplied() { mTransactionIsApplied = true; }
 
     private:
         const uint64_t mFrameNumber;
@@ -645,9 +606,6 @@
     // is applied
     std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
 
-    uint64_t getHeadFrameNumber() const;
-    bool headFenceHasSignaled() const;
-
     // Returns false if the relevant frame has already been latched
     bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
 
@@ -660,7 +618,8 @@
     // Returns mCurrentScaling mode (originating from the
     // Client) or mOverrideScalingMode mode (originating from
     // the Surface Controller) if set.
-    uint32_t getEffectiveScalingMode() const;
+    virtual uint32_t getEffectiveScalingMode() const = 0;
+
 public:
     /*
      * The layer handle is just a BBinder object passed to the client
@@ -671,37 +630,25 @@
      * this layer when the handle is destroyed.
      */
     class Handle : public BBinder, public LayerCleaner {
-        public:
-            Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
-                : LayerCleaner(flinger, layer), owner(layer) {}
+    public:
+        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+              : LayerCleaner(flinger, layer), owner(layer) {}
 
-            wp<Layer> owner;
+        wp<Layer> owner;
     };
 
     sp<IBinder> getHandle();
-    sp<IGraphicBufferProducer> getProducer() const;
     const String8& getName() const;
-    void notifyAvailableFrames();
+    virtual void notifyAvailableFrames() = 0;
+    virtual PixelFormat getPixelFormat() const = 0;
+    bool getPremultipledAlpha() const;
 
-    PixelFormat getPixelFormat() const { return mFormat; }
-
-private:
-
+protected:
     // -----------------------------------------------------------------------
 
-    // Check all of the local sync points to ensure that all transactions
-    // which need to have been applied prior to the frame which is about to
-    // be latched have signaled
-    bool allTransactionsSignaled();
-
-    // constants
-    sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
-    sp<IGraphicBufferProducer> mProducer;
-    uint32_t mTextureName;      // from GLES
     bool mPremultipliedAlpha;
     String8 mName;
     String8 mTransactionName; // A cached version of "TX - " + mName for systraces
-    PixelFormat mFormat;
 
     bool mPrimaryDisplayOnly = false;
 
@@ -734,60 +681,24 @@
     sp<NativeHandle> mSidebandStream;
     Rect mCurrentCrop;
     uint32_t mCurrentTransform;
-    uint32_t mCurrentScalingMode;
     // We encode unset as -1.
     int32_t mOverrideScalingMode;
     bool mCurrentOpacity;
-    bool mBufferLatched = false;  // TODO: Use mActiveBuffer?
     std::atomic<uint64_t> mCurrentFrameNumber;
-    uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
-    bool mRefreshPending;
     bool mFrameLatencyNeeded;
     // Whether filtering is forced on or not
     bool mFiltering;
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering;
-    // The mesh used to draw the layer in GLES composition mode
-    mutable Mesh mMesh;
-    // The texture used to draw the layer in GLES composition mode
-    mutable Texture mTexture;
 
-#ifdef USE_HWC2
-    // HWC items, accessed from the main thread
-    struct HWCInfo {
-        HWCInfo()
-          : hwc(nullptr),
-            layer(nullptr),
-            forceClientComposition(false),
-            compositionType(HWC2::Composition::Invalid),
-            clearClientTarget(false) {}
-
-        HWComposer* hwc;
-        HWC2::Layer* layer;
-        bool forceClientComposition;
-        HWC2::Composition compositionType;
-        bool clearClientTarget;
-        Rect displayFrame;
-        FloatRect sourceCrop;
-        HWComposerBufferCache bufferCache;
-    };
-
-    // A layer can be attached to multiple displays when operating in mirror mode
-    // (a.k.a: when several displays are attached with equal layerStack). In this
-    // case we need to keep track. In non-mirror mode, a layer will have only one
-    // HWCInfo. This map key is a display layerStack.
-    std::unordered_map<int32_t, HWCInfo> mHwcLayers;
-#else
-    bool mIsGlesComposition;
-#endif
+    bool mPendingRemoval = false;
 
     // page-flip thread (currently main thread)
     bool mProtectedByApp; // application requires protected path to external sink
 
     // protected by mLock
     mutable Mutex mLock;
-    // Set to true once we've returned this surface's handle
-    mutable bool mHasSurface;
+
     const wp<Client> mClientRef;
 
     // This layer can be a cursor on some displays.
@@ -798,8 +709,6 @@
     Condition mQueueItemCondition;
     Vector<BufferItem> mQueueItems;
     std::atomic<uint64_t> mLastFrameNumberReceived;
-    bool mUpdateTexImageFailed; // This is only accessed on the main thread.
-
     bool mAutoRefresh;
     bool mFreezeGeometryUpdates;
 
@@ -810,6 +719,8 @@
 
     wp<Layer> mCurrentParent;
     wp<Layer> mDrawingParent;
+
+    mutable LayerBE mBE;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
deleted file mode 100644
index daebf8a..0000000
--- a/services/surfaceflinger/LayerDim.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// #define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "LayerDim"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "LayerDim.h"
-#include "SurfaceFlinger.h"
-#include "DisplayDevice.h"
-#include "RenderEngine/RenderEngine.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
-        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
-    : Layer(flinger, client, name, w, h, flags) {
-}
-
-LayerDim::~LayerDim() {
-}
-
-void LayerDim::onDraw(const sp<const DisplayDevice>& hw,
-        const Region& /* clip */, bool useIdentityTransform) const
-{
-    const State& s(getDrawingState());
-    if (s.alpha>0) {
-        Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
-        computeGeometry(hw, mesh, useIdentityTransform);
-        RenderEngine& engine(mFlinger->getRenderEngine());
-        engine.setupDimLayerBlending(s.alpha);
-        engine.drawMesh(mesh);
-        engine.disableBlending();
-    }
-}
-
-bool LayerDim::isVisible() const {
-    const Layer::State& s(getDrawingState());
-    return !isHiddenByPolicy() && s.alpha;
-}
-
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
deleted file mode 100644
index a0cfca9..0000000
--- a/services/surfaceflinger/LayerDim.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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_LAYER_DIM_H
-#define ANDROID_LAYER_DIM_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "Layer.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-class LayerDim : public Layer
-{
-public:
-                LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
-                        const String8& name, uint32_t w, uint32_t h, uint32_t flags);
-        virtual ~LayerDim();
-
-    virtual const char* getTypeId() const { return "LayerDim"; }
-    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
-            bool useIdentityTransform) const;
-    virtual bool isOpaque(const Layer::State&) const { return false; }
-    virtual bool isSecure() const         { return false; }
-    virtual bool isFixedSize() const      { return true; }
-    virtual bool isVisible() const;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_DIM_H
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
new file mode 100644
index 0000000..6a33148
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LayerProtoHelper.h"
+
+namespace android {
+namespace surfaceflinger {
+void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) {
+    Region::const_iterator head = region.begin();
+    Region::const_iterator const tail = region.end();
+    uint64_t address = reinterpret_cast<uint64_t>(&region);
+    regionProto->set_id(address);
+    while (head != tail) {
+        RectProto* rectProto = regionProto->add_rect();
+        writeToProto(*head, rectProto);
+        head++;
+    }
+}
+
+void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) {
+    rectProto->set_left(rect.left);
+    rectProto->set_top(rect.top);
+    rectProto->set_bottom(rect.bottom);
+    rectProto->set_right(rect.right);
+}
+
+void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) {
+    colorProto->set_r(color.r);
+    colorProto->set_g(color.g);
+    colorProto->set_b(color.b);
+    colorProto->set_a(color.a);
+}
+
+void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) {
+    transformProto->set_dsdx(transform[0][0]);
+    transformProto->set_dtdx(transform[0][1]);
+    transformProto->set_dsdy(transform[1][0]);
+    transformProto->set_dtdy(transform[1][1]);
+}
+
+void LayerProtoHelper::writeToProto(const sp<GraphicBuffer>& buffer,
+                                    ActiveBufferProto* activeBufferProto) {
+    activeBufferProto->set_width(buffer->getWidth());
+    activeBufferProto->set_height(buffer->getHeight());
+    activeBufferProto->set_stride(buffer->getStride());
+    activeBufferProto->set_format(buffer->format);
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
new file mode 100644
index 0000000..45a0b5d
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <Transform.h>
+
+#include <math/vec4.h>
+
+namespace android {
+namespace surfaceflinger {
+class LayerProtoHelper {
+public:
+    static void writeToProto(const Rect& rect, RectProto* rectProto);
+    static void writeToProto(const Region& region, RegionProto* regionProto);
+    static void writeToProto(const half4 color, ColorProto* colorProto);
+    static void writeToProto(const Transform& transform, TransformProto* transformProto);
+    static void writeToProto(const sp<GraphicBuffer>& buffer, ActiveBufferProto* activeBufferProto);
+};
+
+} // namespace surfaceflinger
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 2233e78..47156c1 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -35,14 +35,17 @@
     uint32_t ls = l->getCurrentState().layerStack;
     uint32_t rs = r->getCurrentState().layerStack;
     if (ls != rs)
-        return ls - rs;
+        return (ls > rs) ? 1 : -1;
 
-    uint32_t lz = l->getCurrentState().z;
-    uint32_t rz = r->getCurrentState().z;
+    int32_t lz = l->getCurrentState().z;
+    int32_t rz = r->getCurrentState().z;
     if (lz != rz)
-        return lz - rz;
+        return (lz > rz) ? 1 : -1;
 
-    return l->sequence - r->sequence;
+    if (l->sequence == r->sequence)
+        return 0;
+
+    return (l->sequence > r->sequence) ? 1 : -1;
 }
 
 void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
new file mode 100644
index 0000000..6225df1
--- /dev/null
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -0,0 +1,34 @@
+#include "RenderArea.h"
+
+namespace android {
+
+/*
+ * Checks that the requested width and height are valid and updates them to the render area
+ * dimensions if they are set to 0
+ */
+status_t RenderArea::updateDimensions() {
+    // get screen geometry
+
+    uint32_t width = getWidth();
+    uint32_t height = getHeight();
+
+    if (mRotationFlags & Transform::ROT_90) {
+        std::swap(width, height);
+    }
+
+    if ((mReqWidth > width) || (mReqHeight > height)) {
+        ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height);
+        return BAD_VALUE;
+    }
+
+    if (mReqWidth == 0) {
+        mReqWidth = width;
+    }
+    if (mReqHeight == 0) {
+        mReqHeight = height;
+    }
+
+    return NO_ERROR;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
new file mode 100644
index 0000000..fa4df83
--- /dev/null
+++ b/services/surfaceflinger/RenderArea.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "Transform.h"
+
+namespace android {
+
+class RenderArea {
+public:
+    RenderArea(uint32_t reqHeight, uint32_t reqWidth,
+               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
+          : mReqHeight(reqHeight), mReqWidth(reqWidth) {
+        mRotationFlags = Transform::fromRotation(rotation);
+    }
+
+    virtual ~RenderArea() = default;
+
+    virtual const Transform& getTransform() const = 0;
+    virtual Rect getBounds() const = 0;
+    virtual int getHeight() const = 0;
+    virtual int getWidth() const = 0;
+    virtual bool isSecure() const = 0;
+    virtual bool needsFiltering() const = 0;
+    virtual Rect getSourceCrop() const = 0;
+
+    int getReqHeight() const { return mReqHeight; };
+    int getReqWidth() const { return mReqWidth; };
+    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+    virtual bool getWideColorSupport() const = 0;
+    virtual android_color_mode_t getActiveColorMode() const = 0;
+
+    status_t updateDimensions();
+
+private:
+    uint32_t mReqHeight;
+    uint32_t mReqWidth;
+    Transform::orientation_flags mRotationFlags;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index effd319..e014406 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -27,21 +27,13 @@
 namespace android {
 
 Description::Description() {
-    mPlaneAlpha = 1.0f;
     mPremultipliedAlpha = false;
     mOpaque = true;
     mTextureEnabled = false;
     mColorMatrixEnabled = false;
-
-    memset(mColor, 0, sizeof(mColor));
 }
 
-Description::~Description() {
-}
-
-void Description::setPlaneAlpha(GLclampf planeAlpha) {
-    mPlaneAlpha = planeAlpha;
-}
+Description::~Description() {}
 
 void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
     mPremultipliedAlpha = premultipliedAlpha;
@@ -60,11 +52,8 @@
     mTextureEnabled = false;
 }
 
-void Description::setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
-    mColor[0] = red;
-    mColor[1] = green;
-    mColor[2] = blue;
-    mColor[3] = alpha;
+void Description::setColor(const half4& color) {
+    mColor = color;
 }
 
 void Description::setProjectionMatrix(const mat4& mtx) {
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 3beffdf..cbac855 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -35,8 +35,6 @@
     friend class Program;
     friend class ProgramCache;
 
-    // value of the plane-alpha, between 0 and 1
-    GLclampf mPlaneAlpha;
     // whether textures are premultiplied
     bool mPremultipliedAlpha;
     // whether this layer is marked as opaque
@@ -46,8 +44,8 @@
     Texture mTexture;
     bool mTextureEnabled;
 
-    // color used when texturing is disabled
-    GLclampf mColor[4];
+    // color used when texturing is disabled or when setting alpha.
+    half4 mColor;
     // projection matrix
     mat4 mProjectionMatrix;
 
@@ -60,12 +58,11 @@
     Description();
     ~Description();
 
-    void setPlaneAlpha(GLclampf planeAlpha);
     void setPremultipliedAlpha(bool premultipliedAlpha);
     void setOpaque(bool opaque);
     void setTexture(const Texture& texture);
     void disableTexture();
-    void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+    void setColor(const half4& color);
     void setProjectionMatrix(const mat4& mtx);
     void setColorMatrix(const mat4& mtx);
     const mat4& getColorMatrix() const;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 37a530b..3161888 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -33,18 +33,17 @@
 #include <gui/ISurfaceComposer.h>
 #include <math.h>
 
+#include "Description.h"
 #include "GLES20RenderEngine.h"
+#include "Mesh.h"
 #include "Program.h"
 #include "ProgramCache.h"
-#include "Description.h"
-#include "Mesh.h"
 #include "Texture.h"
 
-#include <sstream>
 #include <fstream>
+#include <sstream>
 
 // ---------------------------------------------------------------------------
-#ifdef USE_HWC2
 bool checkGlError(const char* op, int lineNumber) {
     bool errorFound = false;
     GLint error = glGetError();
@@ -103,41 +102,36 @@
     }
     file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
 }
-#endif
 
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
 
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) :
-         mVpWidth(0),
-         mVpHeight(0),
-         mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
-
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
+      : mVpWidth(0), mVpHeight(0), mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
-    const uint16_t protTexData[] = { 0 };
+    const uint16_t protTexData[] = {0};
     glGenTextures(1, &mProtectedTexName);
     glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
-            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
 
-    //mColorBlindnessCorrection = M;
+    // mColorBlindnessCorrection = M;
 
-#ifdef USE_HWC2
     if (mPlatformHasWideColor) {
         // Compute sRGB to DisplayP3 color transform
         // NOTE: For now, we are limiting wide-color support to
         // Display-P3 only.
-        mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
+        mat3 srgbToP3 =
+                ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
 
         // color transform needs to be expanded to 4x4 to be what the shader wants
         // mat has an initializer that expands mat3 to mat4, but
@@ -145,27 +139,21 @@
         mat4 gamutTransform(srgbToP3);
         mSrgbToDisplayP3 = gamutTransform;
     }
-#endif
 }
 
-GLES20RenderEngine::~GLES20RenderEngine() {
-}
-
+GLES20RenderEngine::~GLES20RenderEngine() {}
 
 size_t GLES20RenderEngine::getMaxTextureSize() const {
     return mMaxTextureSize;
 }
 
 size_t GLES20RenderEngine::getMaxViewportDims() const {
-    return
-        mMaxViewportDims[0] < mMaxViewportDims[1] ?
-            mMaxViewportDims[0] : mMaxViewportDims[1];
+    return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
 }
 
-void GLES20RenderEngine::setViewportAndProjection(
-        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap,
-        Transform::orientation_flags rotation) {
-
+void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+                                                  size_t hwh, bool yswap,
+                                                  Transform::orientation_flags rotation) {
     size_t l = sourceCrop.left;
     size_t r = sourceCrop.right;
 
@@ -186,13 +174,13 @@
         case Transform::ROT_0:
             break;
         case Transform::ROT_90:
-            m = mat4::rotate(rot90InRadians, vec3(0,0,1)) * m;
+            m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
             break;
         case Transform::ROT_180:
-            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0,0,1)) * m;
+            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
             break;
         case Transform::ROT_270:
-            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0,0,1)) * m;
+            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
             break;
         default:
             break;
@@ -204,25 +192,17 @@
     mVpHeight = vph;
 }
 
-#ifdef USE_HWC2
-void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha,
-        bool opaque, float alpha) {
-#else
-void GLES20RenderEngine::setupLayerBlending(
-    bool premultipliedAlpha, bool opaque, int alpha) {
-#endif
-
+void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque,
+                                            bool disableTexture, const half4& color) {
     mState.setPremultipliedAlpha(premultipliedAlpha);
     mState.setOpaque(opaque);
-#ifdef USE_HWC2
-    mState.setPlaneAlpha(alpha);
+    mState.setColor(color);
 
-    if (alpha < 1.0f || !opaque) {
-#else
-    mState.setPlaneAlpha(alpha / 255.0f);
+    if (disableTexture) {
+        mState.disableTexture();
+    }
 
-    if (alpha < 0xFF || !opaque) {
-#endif
+    if (color.a < 1.0f || !opaque) {
         glEnable(GL_BLEND);
         glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     } else {
@@ -230,34 +210,6 @@
     }
 }
 
-#ifdef USE_HWC2
-void GLES20RenderEngine::setupDimLayerBlending(float alpha) {
-#else
-void GLES20RenderEngine::setupDimLayerBlending(int alpha) {
-#endif
-    mState.setPlaneAlpha(1.0f);
-    mState.setPremultipliedAlpha(true);
-    mState.setOpaque(false);
-#ifdef USE_HWC2
-    mState.setColor(0, 0, 0, alpha);
-#else
-    mState.setColor(0, 0, 0, alpha/255.0f);
-#endif
-    mState.disableTexture();
-
-#ifdef USE_HWC2
-    if (alpha == 1.0f) {
-#else
-    if (alpha == 0xFF) {
-#endif
-        glDisable(GL_BLEND);
-    } else {
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    }
-}
-
-#ifdef USE_HWC2
 void GLES20RenderEngine::setColorMode(android_color_mode mode) {
     ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
 
@@ -291,7 +243,6 @@
 bool GLES20RenderEngine::usesWideColor() {
     return mUseWideColor;
 }
-#endif
 
 void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
     GLuint target = texture.getTextureTarget();
@@ -329,9 +280,8 @@
     glDisable(GL_BLEND);
 }
 
-
-void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
-        uint32_t* texName, uint32_t* fbName, uint32_t* status) {
+void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
+                                                uint32_t* fbName, uint32_t* status) {
     GLuint tname, name;
     // turn our EGLImage into a texture
     glGenTextures(1, &tname);
@@ -355,32 +305,23 @@
 }
 
 void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
-    mState.setPlaneAlpha(1.0f);
     mState.setPremultipliedAlpha(true);
     mState.setOpaque(false);
-    mState.setColor(r, g, b, a);
+    mState.setColor(half4(r, g, b, a));
     mState.disableTexture();
     glDisable(GL_BLEND);
 }
 
 void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
-
     if (mesh.getTexCoordsSize()) {
         glEnableVertexAttribArray(Program::texCoords);
-        glVertexAttribPointer(Program::texCoords,
-                mesh.getTexCoordsSize(),
-                GL_FLOAT, GL_FALSE,
-                mesh.getByteStride(),
-                mesh.getTexCoords());
+        glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE,
+                              mesh.getByteStride(), mesh.getTexCoords());
     }
 
-    glVertexAttribPointer(Program::position,
-            mesh.getVertexSize(),
-            GL_FLOAT, GL_FALSE,
-            mesh.getByteStride(),
-            mesh.getPositions());
+    glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
+                          mesh.getByteStride(), mesh.getPositions());
 
-#ifdef USE_HWC2
     if (usesWideColor()) {
         Description wideColorState = mState;
         if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
@@ -402,11 +343,6 @@
 
         glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
     }
-#else
-    ProgramCache::getInstance().useProgram(mState);
-
-    glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
-#endif
 
     if (mesh.getTexCoordsSize()) {
         glDisableVertexAttribArray(Program::texCoords);
@@ -415,13 +351,11 @@
 
 void GLES20RenderEngine::dump(String8& result) {
     RenderEngine::dump(result);
-#ifdef USE_HWC2
     if (usesWideColor()) {
         result.append("Wide-color: On\n");
     } else {
         result.append("Wide-color: Off\n");
     }
-#endif
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index eaf94af..5ee9326 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 #ifndef SF_GLES20RENDERENGINE_H_
 #define SF_GLES20RENDERENGINE_H_
 
@@ -24,9 +23,9 @@
 #include <GLES2/gl2.h>
 #include <Transform.h>
 
-#include "RenderEngine.h"
-#include "ProgramCache.h"
 #include "Description.h"
+#include "ProgramCache.h"
+#include "RenderEngine.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -54,24 +53,20 @@
     Description mState;
     Vector<Group> mGroupStack;
 
-    virtual void bindImageAsFramebuffer(EGLImageKHR image,
-            uint32_t* texName, uint32_t* fbName, uint32_t* status);
+    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+                                        uint32_t* status);
     virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
 
 public:
     GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
-
-protected:
     virtual ~GLES20RenderEngine();
 
+protected:
     virtual void dump(String8& result);
-    virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap,
-            Transform::orientation_flags rotation);
-#ifdef USE_HWC2
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
-            float alpha) override;
-    virtual void setupDimLayerBlending(float alpha) override;
+    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
+                                          bool yswap, Transform::orientation_flags rotation);
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                                    const half4& color) override;
 
     // Color management related functions and state
     void setColorMode(android_color_mode mode);
@@ -92,11 +87,6 @@
 
     // Currently only supporting sRGB and DisplayP3 color spaces
     mat4 mSrgbToDisplayP3;
-#else
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
-            int alpha);
-    virtual void setupDimLayerBlending(int alpha);
-#endif
     bool mPlatformHasWideColor = false;
 
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
index 76bbcc1..7ffcc96 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
@@ -14,42 +14,35 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
 #include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #include "GLExtensions.h"
 
 namespace android {
 // ---------------------------------------------------------------------------
 
-ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
+ANDROID_SINGLETON_STATIC_INSTANCE(GLExtensions)
 
-GLExtensions::GLExtensions()
-    : mHaveFramebufferObject(false)
-{
-}
+GLExtensions::GLExtensions() : mHaveFramebufferObject(false) {}
 
-void GLExtensions::initWithGLStrings(
-        GLubyte const* vendor,
-        GLubyte const* renderer,
-        GLubyte const* version,
-        GLubyte const* extensions)
-{
-    mVendor     = (char const*)vendor;
-    mRenderer   = (char const*)renderer;
-    mVersion    = (char const*)version;
+void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer,
+                                     GLubyte const* version, GLubyte const* extensions) {
+    mVendor = (char const*)vendor;
+    mRenderer = (char const*)renderer;
+    mVersion = (char const*)version;
     mExtensions = (char const*)extensions;
 
     char const* curr = (char const*)extensions;
     char const* head = curr;
     do {
         head = strchr(curr, ' ');
-        String8 s(curr, head ? head-curr : strlen(curr));
+        String8 s(curr, head ? head - curr : strlen(curr));
         if (s.length()) {
             mExtensionList.add(s);
         }
-        curr = head+1;
+        curr = head + 1;
     } while (head);
 
     if (hasExtension("GL_OES_framebuffer_object")) {
@@ -57,8 +50,7 @@
     }
 }
 
-bool GLExtensions::hasExtension(char const* extension) const
-{
+bool GLExtensions::hasExtension(char const* extension) const {
     const String8 s(extension);
     return mExtensionList.indexOf(s) >= 0;
 }
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h
index d81ed2a..ee7b446 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.h
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.h
@@ -20,9 +20,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/String8.h>
-#include <utils/SortedVector.h>
 #include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -32,8 +32,7 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class GLExtensions : public Singleton<GLExtensions>
-{
+class GLExtensions : public Singleton<GLExtensions> {
     friend class Singleton<GLExtensions>;
 
     bool mHaveFramebufferObject : 1;
@@ -45,22 +44,16 @@
     SortedVector<String8> mExtensionList;
 
     GLExtensions(const GLExtensions&);
-    GLExtensions& operator = (const GLExtensions&);
+    GLExtensions& operator=(const GLExtensions&);
 
 protected:
     GLExtensions();
 
 public:
+    inline bool haveFramebufferObject() const { return mHaveFramebufferObject; }
 
-    inline bool haveFramebufferObject() const {
-        return mHaveFramebufferObject;
-    }
-
-    void initWithGLStrings(
-            GLubyte const* vendor,
-            GLubyte const* renderer,
-            GLubyte const* version,
-            GLubyte const* extensions);
+    void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version,
+                           GLubyte const* extensions);
 
     char const* getVendor() const;
     char const* getRenderer() const;
@@ -70,7 +63,6 @@
     bool hasExtension(char const* extension) const;
 };
 
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index ffd9be2..6a62b1d 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -21,9 +21,10 @@
 namespace android {
 
 Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
-    : mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize),
-      mPrimitive(primitive)
-{
+      : mVertexCount(vertexCount),
+        mVertexSize(vertexSize),
+        mTexCoordsSize(texCoordSize),
+        mPrimitive(primitive) {
     if (vertexCount == 0) {
         mVertices = new float[1];
         mVertices[0] = 0.0f;
@@ -37,8 +38,7 @@
     // either vertexSize or texCoordSize, it must have overflowed. remainder
     // will be equal to stride as long as stride * vertexCount doesn't overflow.
     if ((stride < vertexSize) || (remainder != stride)) {
-        ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize,
-                texCoordSize);
+        ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize, texCoordSize);
         mVertices = new float[1];
         mVertices[0] = 0.0f;
         mVertexCount = 0;
@@ -53,14 +53,13 @@
 }
 
 Mesh::~Mesh() {
-    delete [] mVertices;
+    delete[] mVertices;
 }
 
 Mesh::Primitive Mesh::getPrimitive() const {
     return mPrimitive;
 }
 
-
 float const* Mesh::getPositions() const {
     return mVertices;
 }
@@ -75,7 +74,6 @@
     return mVertices + mVertexSize;
 }
 
-
 size_t Mesh::getVertexCount() const {
     return mVertexCount;
 }
@@ -89,7 +87,7 @@
 }
 
 size_t Mesh::getByteStride() const {
-    return mStride*sizeof(float);
+    return mStride * sizeof(float);
 }
 
 size_t Mesh::getStride() const {
diff --git a/services/surfaceflinger/RenderEngine/Mesh.h b/services/surfaceflinger/RenderEngine/Mesh.h
index b6d42b0..d0a9ac0 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.h
+++ b/services/surfaceflinger/RenderEngine/Mesh.h
@@ -24,9 +24,9 @@
 class Mesh {
 public:
     enum Primitive {
-        TRIANGLES       = 0x0004,       // GL_TRIANGLES
-        TRIANGLE_STRIP  = 0x0005,       // GL_TRIANGLE_STRIP
-        TRIANGLE_FAN    = 0x0006        // GL_TRIANGLE_FAN
+        TRIANGLES = 0x0004,      // GL_TRIANGLES
+        TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP
+        TRIANGLE_FAN = 0x0006    // GL_TRIANGLE_FAN
     };
 
     Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0);
@@ -40,21 +40,24 @@
         friend class Mesh;
         float* mData;
         size_t mStride;
-        VertexArray(float* data, size_t stride) : mData(data), mStride(stride) { }
+        VertexArray(float* data, size_t stride) : mData(data), mStride(stride) {}
+
     public:
-        TYPE& operator[](size_t index) {
-            return *reinterpret_cast<TYPE*>(&mData[index*mStride]);
-        }
+        TYPE& operator[](size_t index) { return *reinterpret_cast<TYPE*>(&mData[index * mStride]); }
         TYPE const& operator[](size_t index) const {
-            return *reinterpret_cast<TYPE const*>(&mData[index*mStride]);
+            return *reinterpret_cast<TYPE const*>(&mData[index * mStride]);
         }
     };
 
     template <typename TYPE>
-    VertexArray<TYPE> getPositionArray() { return VertexArray<TYPE>(getPositions(), mStride); }
+    VertexArray<TYPE> getPositionArray() {
+        return VertexArray<TYPE>(getPositions(), mStride);
+    }
 
     template <typename TYPE>
-    VertexArray<TYPE> getTexCoordArray() { return VertexArray<TYPE>(getTexCoords(), mStride); }
+    VertexArray<TYPE> getTexCoordArray() {
+        return VertexArray<TYPE>(getTexCoords(), mStride);
+    }
 
     Primitive getPrimitive() const;
 
@@ -81,8 +84,8 @@
 
 private:
     Mesh(const Mesh&);
-    Mesh& operator = (const Mesh&);
-    Mesh const& operator = (const Mesh&) const;
+    Mesh& operator=(const Mesh&);
+    Mesh const& operator=(const Mesh&) const;
 
     float* getPositions();
     float* getTexCoords();
@@ -94,6 +97,5 @@
     Primitive mPrimitive;
 };
 
-
 } /* namespace android */
 #endif /* SF_RENDER_ENGINE_MESH_H */
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 48a8da5..baf92eb 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -19,14 +19,15 @@
 #include <log/log.h>
 #include <utils/String8.h>
 
+#include <math/mat4.h>
+#include "Description.h"
 #include "Program.h"
 #include "ProgramCache.h"
-#include "Description.h"
 
 namespace android {
 
 Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
-        : mInitialized(false) {
+      : mInitialized(false) {
     GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
     GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
     GLuint programId = glCreateProgram();
@@ -63,18 +64,15 @@
         mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
         mSamplerLoc = glGetUniformLocation(programId, "sampler");
         mColorLoc = glGetUniformLocation(programId, "color");
-        mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
 
         // set-up the default values for our uniforms
         glUseProgram(programId);
-        const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
-        glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, m);
+        glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
         glEnableVertexAttribArray(0);
     }
 }
 
-Program::~Program() {
-}
+Program::~Program() {}
 
 bool Program::isValid() const {
     return mInitialized;
@@ -119,12 +117,11 @@
     char* src = new char[l];
     glGetShaderSource(shader, l, NULL, src);
     result.append(src);
-    delete [] src;
+    delete[] src;
     return result;
 }
 
 void Program::setUniforms(const Description& desc) {
-
     // TODO: we should have a mechanism here to not always reset uniforms that
     // didn't change for this program.
 
@@ -132,11 +129,9 @@
         glUniform1i(mSamplerLoc, 0);
         glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray());
     }
-    if (mAlphaPlaneLoc >= 0) {
-        glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha);
-    }
     if (mColorLoc >= 0) {
-        glUniform4fv(mColorLoc, 1, desc.mColor);
+        const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a};
+        glUniform4fv(mColorLoc, 1, color);
     }
     if (mColorMatrixLoc >= 0) {
         glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray());
diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h
index 36bd120..6e57fdd 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -34,7 +34,7 @@
 class Program {
 public:
     // known locations for position and texture coordinates
-    enum { position=0, texCoords=1 };
+    enum { position = 0, texCoords = 1 };
 
     Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
     ~Program();
@@ -54,7 +54,6 @@
     /* set-up uniforms from the description */
     void setUniforms(const Description& desc);
 
-
 private:
     GLuint buildShader(const char* source, GLenum type);
     String8& dumpShader(String8& result, GLenum type);
@@ -79,14 +78,10 @@
     /* location of the sampler uniform */
     GLint mSamplerLoc;
 
-    /* location of the alpha plane uniform */
-    GLint mAlphaPlaneLoc;
-
     /* location of the color uniform */
     GLint mColorLoc;
 };
 
-
 } /* namespace android */
 
 #endif /* SF_RENDER_ENGINE_PROGRAM_H */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 06b2252..4f138dc 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -19,14 +19,13 @@
 
 #include <utils/String8.h>
 
-#include "ProgramCache.h"
-#include "Program.h"
 #include "Description.h"
+#include "Program.h"
+#include "ProgramCache.h"
 
 namespace android {
 // -----------------------------------------------------------------------------------------------
 
-
 /*
  * A simple formatter class to automatically add the endl and
  * manage the indentation.
@@ -42,23 +41,22 @@
     typedef Formatter& (*FormaterManipFunc)(Formatter&);
     friend Formatter& indent(Formatter& f);
     friend Formatter& dedent(Formatter& f);
+
 public:
     Formatter() : mIndent(0) {}
 
-    String8 getString() const {
-        return mString;
-    }
+    String8 getString() const { return mString; }
 
-    friend Formatter& operator << (Formatter& out, const char* in) {
-        for (int i=0 ; i<out.mIndent ; i++) {
+    friend Formatter& operator<<(Formatter& out, const char* in) {
+        for (int i = 0; i < out.mIndent; i++) {
             out.mString.append("    ");
         }
         out.mString.append(in);
         out.mString.append("\n");
         return out;
     }
-    friend inline Formatter& operator << (Formatter& out, const String8& in) {
-        return operator << (out, in.string());
+    friend inline Formatter& operator<<(Formatter& out, const String8& in) {
+        return operator<<(out, in.string());
     }
     friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
         return (*func)(to);
@@ -83,13 +81,11 @@
     primeCache();
 }
 
-ProgramCache::~ProgramCache() {
-}
+ProgramCache::~ProgramCache() {}
 
 void ProgramCache::primeCache() {
     uint32_t shaderCount = 0;
-    uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK |
-                       Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK;
+    uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK;
     // Prime the cache for all combinations of the above masks,
     // leaving off the experimental color matrix mask options.
 
@@ -98,9 +94,7 @@
         Key shaderKey;
         shaderKey.set(keyMask, keyVal);
         uint32_t tex = shaderKey.getTextureTarget();
-        if (tex != Key::TEXTURE_OFF &&
-            tex != Key::TEXTURE_EXT &&
-            tex != Key::TEXTURE_2D) {
+        if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) {
             continue;
         }
         Program* program = mCache.valueFor(shaderKey);
@@ -118,34 +112,36 @@
 ProgramCache::Key ProgramCache::computeKey(const Description& description) {
     Key needs;
     needs.set(Key::TEXTURE_MASK,
-            !description.mTextureEnabled ? Key::TEXTURE_OFF :
-            description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_EXT :
-            description.mTexture.getTextureTarget() == GL_TEXTURE_2D           ? Key::TEXTURE_2D :
-            Key::TEXTURE_OFF)
-    .set(Key::PLANE_ALPHA_MASK,
-            (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE)
-    .set(Key::BLEND_MASK,
-            description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
-    .set(Key::OPACITY_MASK,
-            description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
-    .set(Key::COLOR_MATRIX_MASK,
-            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF)
-    .set(Key::WIDE_GAMUT_MASK,
-            description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
+              !description.mTextureEnabled
+                      ? Key::TEXTURE_OFF
+                      : description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES
+                              ? Key::TEXTURE_EXT
+                              : description.mTexture.getTextureTarget() == GL_TEXTURE_2D
+                                      ? Key::TEXTURE_2D
+                                      : Key::TEXTURE_OFF)
+            .set(Key::ALPHA_MASK,
+                 (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE)
+            .set(Key::BLEND_MASK,
+                 description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
+            .set(Key::OPACITY_MASK,
+                 description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
+            .set(Key::COLOR_MATRIX_MASK,
+                 description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
+            .set(Key::WIDE_GAMUT_MASK,
+                 description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
     return needs;
 }
 
 String8 ProgramCache::generateVertexShader(const Key& needs) {
     Formatter vs;
     if (needs.isTexturing()) {
-        vs  << "attribute vec4 texCoords;"
-            << "varying vec2 outTexCoords;";
+        vs << "attribute vec4 texCoords;"
+           << "varying vec2 outTexCoords;";
     }
     vs << "attribute vec4 position;"
        << "uniform mat4 projection;"
        << "uniform mat4 texture;"
-       << "void main(void) {" << indent
-       << "gl_Position = projection * position;";
+       << "void main(void) {" << indent << "gl_Position = projection * position;";
     if (needs.isTexturing()) {
         vs << "outTexCoords = (texture * texCoords).st;";
     }
@@ -168,12 +164,12 @@
     } else if (needs.getTextureTarget() == Key::TEXTURE_2D) {
         fs << "uniform sampler2D sampler;"
            << "varying vec2 outTexCoords;";
-    } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
+    }
+
+    if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) {
         fs << "uniform vec4 color;";
     }
-    if (needs.hasPlaneAlpha()) {
-        fs << "uniform float alphaPlane;";
-    }
+
     if (needs.hasColorMatrix()) {
         fs << "uniform mat4 colorMatrix;";
     }
@@ -225,18 +221,19 @@
     if (needs.isTexturing()) {
         fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
     } else {
-        fs << "gl_FragColor = color;";
+        fs << "gl_FragColor.rgb = color.rgb;";
+        fs << "gl_FragColor.a = 1.0;";
     }
     if (needs.isOpaque()) {
         fs << "gl_FragColor.a = 1.0;";
     }
-    if (needs.hasPlaneAlpha()) {
-        // modulate the alpha value with planeAlpha
+    if (needs.hasAlpha()) {
+        // modulate the current alpha value with alpha set
         if (needs.isPremultiplied()) {
             // ... and the color too if we're premultiplied
-            fs << "gl_FragColor *= alphaPlane;";
+            fs << "gl_FragColor *= color.a;";
         } else {
-            fs << "gl_FragColor.a *= alphaPlane;";
+            fs << "gl_FragColor.a *= color.a;";
         }
     }
 
@@ -271,11 +268,10 @@
 }
 
 void ProgramCache::useProgram(const Description& description) {
-
     // generate the key for the shader based on the description
     Key needs(computeKey(description));
 
-     // look-up the program in the cache
+    // look-up the program in the cache
     Program* program = mCache.valueFor(needs);
     if (program == NULL) {
         // we didn't find our program, so generate one...
@@ -284,7 +280,7 @@
         mCache.add(needs, program);
         time += systemTime();
 
-        //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
+        // ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
         //        needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
     }
 
@@ -295,5 +291,4 @@
     }
 }
 
-
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 5b0fbcd..54d3722 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -19,8 +19,8 @@
 
 #include <GLES2/gl2.h>
 
-#include <utils/Singleton.h>
 #include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
 #include <utils/TypeHelpers.h>
 
 #include "Description.h"
@@ -47,63 +47,50 @@
         friend class ProgramCache;
         typedef uint32_t key_t;
         key_t mKey;
+
     public:
         enum {
-            BLEND_PREMULT           =       0x00000001,
-            BLEND_NORMAL            =       0x00000000,
-            BLEND_MASK              =       0x00000001,
+            BLEND_PREMULT = 0x00000001,
+            BLEND_NORMAL = 0x00000000,
+            BLEND_MASK = 0x00000001,
 
-            OPACITY_OPAQUE          =       0x00000002,
-            OPACITY_TRANSLUCENT     =       0x00000000,
-            OPACITY_MASK            =       0x00000002,
+            OPACITY_OPAQUE = 0x00000002,
+            OPACITY_TRANSLUCENT = 0x00000000,
+            OPACITY_MASK = 0x00000002,
 
-            PLANE_ALPHA_LT_ONE      =       0x00000004,
-            PLANE_ALPHA_EQ_ONE      =       0x00000000,
-            PLANE_ALPHA_MASK        =       0x00000004,
+            ALPHA_LT_ONE = 0x00000004,
+            ALPHA_EQ_ONE = 0x00000000,
+            ALPHA_MASK = 0x00000004,
 
-            TEXTURE_OFF             =       0x00000000,
-            TEXTURE_EXT             =       0x00000008,
-            TEXTURE_2D              =       0x00000010,
-            TEXTURE_MASK            =       0x00000018,
+            TEXTURE_OFF = 0x00000000,
+            TEXTURE_EXT = 0x00000008,
+            TEXTURE_2D = 0x00000010,
+            TEXTURE_MASK = 0x00000018,
 
-            COLOR_MATRIX_OFF        =       0x00000000,
-            COLOR_MATRIX_ON         =       0x00000020,
-            COLOR_MATRIX_MASK       =       0x00000020,
+            COLOR_MATRIX_OFF = 0x00000000,
+            COLOR_MATRIX_ON = 0x00000020,
+            COLOR_MATRIX_MASK = 0x00000020,
 
-            WIDE_GAMUT_OFF          =       0x00000000,
-            WIDE_GAMUT_ON           =       0x00000040,
-            WIDE_GAMUT_MASK         =       0x00000040,
+            WIDE_GAMUT_OFF = 0x00000000,
+            WIDE_GAMUT_ON = 0x00000040,
+            WIDE_GAMUT_MASK = 0x00000040,
         };
 
-        inline Key() : mKey(0) { }
-        inline Key(const Key& rhs) : mKey(rhs.mKey) { }
+        inline Key() : mKey(0) {}
+        inline Key(const Key& rhs) : mKey(rhs.mKey) {}
 
         inline Key& set(key_t mask, key_t value) {
             mKey = (mKey & ~mask) | value;
             return *this;
         }
 
-        inline bool isTexturing() const {
-            return (mKey & TEXTURE_MASK) != TEXTURE_OFF;
-        }
-        inline int getTextureTarget() const {
-            return (mKey & TEXTURE_MASK);
-        }
-        inline bool isPremultiplied() const {
-            return (mKey & BLEND_MASK) == BLEND_PREMULT;
-        }
-        inline bool isOpaque() const {
-            return (mKey & OPACITY_MASK) == OPACITY_OPAQUE;
-        }
-        inline bool hasPlaneAlpha() const {
-            return (mKey & PLANE_ALPHA_MASK) == PLANE_ALPHA_LT_ONE;
-        }
-        inline bool hasColorMatrix() const {
-            return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
-        }
-        inline bool isWideGamut() const {
-            return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
-        }
+        inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
+        inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
+        inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
+        inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
+        inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
+        inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; }
+        inline bool isWideGamut() const { return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON; }
 
         // this is the definition of a friend function -- not a method of class Needs
         friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
@@ -135,7 +122,6 @@
     DefaultKeyedVector<Key, Program*> mCache;
 };
 
-
 ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key)
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 56e9ac0..883ae26 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -18,13 +18,13 @@
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
-#include "RenderEngine.h"
 #include "GLES20RenderEngine.h"
 #include "GLExtensions.h"
 #include "Mesh.h"
+#include "RenderEngine.h"
 
-#include <vector>
 #include <SurfaceFlinger.h>
+#include <vector>
 
 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
@@ -33,21 +33,25 @@
 // ---------------------------------------------------------------------------
 
 static bool findExtension(const char* exts, const char* name) {
-    if (!exts)
-        return false;
+    if (!exts) return false;
     size_t len = strlen(name);
 
     const char* pos = exts;
     while ((pos = strstr(pos, name)) != NULL) {
-        if (pos[len] == '\0' || pos[len] == ' ')
-            return true;
+        if (pos[len] == '\0' || pos[len] == ' ') return true;
         pos += len;
     }
 
     return false;
 }
 
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t featureFlags) {
+std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
+    // initialize EGL for the default display
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (!eglInitialize(display, NULL, NULL)) {
+        LOG_ALWAYS_FATAL("failed to initialize EGL");
+    }
+
     // EGL_ANDROIDX_no_config_context is an experimental extension with no
     // written specification. It will be replaced by something more formal.
     // SurfaceFlinger is using it to allow a single EGLContext to render to
@@ -70,8 +74,7 @@
     EGLint renderableType = 0;
     if (config == EGL_NO_CONFIG) {
         renderableType = EGL_OPENGL_ES2_BIT;
-    } else if (!eglGetConfigAttrib(display, config,
-            EGL_RENDERABLE_TYPE, &renderableType)) {
+    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
         LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
     }
     EGLint contextClientVersion = 0;
@@ -96,12 +99,10 @@
     contextAttributes.push_back(EGL_NONE);
     contextAttributes.push_back(EGL_NONE);
 
-    EGLContext ctxt = eglCreateContext(display, config, NULL,
-                                       contextAttributes.data());
+    EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes.data());
 
     // if can't create a GL context, we can only abort.
-    LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
-
+    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
 
     // now figure out what version of GL did we actually get
     // NOTE: a dummy surface is not needed if KHR_create_context is supported
@@ -110,35 +111,32 @@
     if (dummyConfig == EGL_NO_CONFIG) {
         dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
     }
-    EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
+    EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
     EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
-    LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
+    LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
     EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
     LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
 
     GLExtensions& extensions(GLExtensions::getInstance());
-    extensions.initWithGLStrings(
-            glGetString(GL_VENDOR),
-            glGetString(GL_RENDERER),
-            glGetString(GL_VERSION),
-            glGetString(GL_EXTENSIONS));
+    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
+                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
 
-    GlesVersion version = parseGlesVersion( extensions.getVersion() );
+    GlesVersion version = parseGlesVersion(extensions.getVersion());
 
     // initialize the renderer while GL is current
 
-    RenderEngine* engine = NULL;
+    std::unique_ptr<RenderEngine> engine;
     switch (version) {
-    case GLES_VERSION_1_0:
-    case GLES_VERSION_1_1:
-        LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
-        break;
-    case GLES_VERSION_2_0:
-    case GLES_VERSION_3_0:
-        engine = new GLES20RenderEngine(featureFlags);
-        break;
+        case GLES_VERSION_1_0:
+        case GLES_VERSION_1_1:
+            LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
+            break;
+        case GLES_VERSION_2_0:
+        case GLES_VERSION_3_0:
+            engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+            break;
     }
-    engine->setEGLHandles(config, ctxt);
+    engine->setEGLHandles(display, config, ctxt);
 
     ALOGI("OpenGL ES informations:");
     ALOGI("vendor    : %s", extensions.getVendor());
@@ -154,31 +152,50 @@
     return engine;
 }
 
-RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
-}
+RenderEngine::RenderEngine()
+      : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {}
 
 RenderEngine::~RenderEngine() {
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mEGLDisplay);
 }
 
-void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
+void RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+    mEGLDisplay = display;
     mEGLConfig = config;
     mEGLContext = ctxt;
 }
 
-EGLContext RenderEngine::getEGLConfig() const {
+EGLDisplay RenderEngine::getEGLDisplay() const {
+    return mEGLDisplay;
+}
+
+EGLConfig RenderEngine::getEGLConfig() const {
     return mEGLConfig;
 }
 
-EGLContext RenderEngine::getEGLContext() const {
-    return mEGLContext;
+bool RenderEngine::setCurrentSurface(const RE::Surface& surface) {
+    bool success = true;
+    EGLSurface eglSurface = surface.getEGLSurface();
+    if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
+        success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
+        if (success && surface.getAsync()) {
+            eglSwapInterval(mEGLDisplay, 0);
+        }
+    }
+
+    return success;
+}
+
+void RenderEngine::resetCurrentSurface() {
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 }
 
 void RenderEngine::checkErrors() const {
     do {
         // there could be more than one error flag
         GLenum error = glGetError();
-        if (error == GL_NO_ERROR)
-            break;
+        if (error == GL_NO_ERROR) break;
         ALOGE("GL error 0x%04x", int(error));
     } while (true);
 }
@@ -201,32 +218,74 @@
     return GLES_VERSION_1_0;
 }
 
-void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
-        float red, float green, float blue, float alpha) {
+void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
+                                       float green, float blue, float alpha) {
     size_t c;
     Rect const* r = region.getArray(&c);
-    Mesh mesh(Mesh::TRIANGLES, c*6, 2);
+    Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    for (size_t i=0 ; i<c ; i++, r++) {
-        position[i*6 + 0].x = r->left;
-        position[i*6 + 0].y = height - r->top;
-        position[i*6 + 1].x = r->left;
-        position[i*6 + 1].y = height - r->bottom;
-        position[i*6 + 2].x = r->right;
-        position[i*6 + 2].y = height - r->bottom;
-        position[i*6 + 3].x = r->left;
-        position[i*6 + 3].y = height - r->top;
-        position[i*6 + 4].x = r->right;
-        position[i*6 + 4].y = height - r->bottom;
-        position[i*6 + 5].x = r->right;
-        position[i*6 + 5].y = height - r->top;
+    for (size_t i = 0; i < c; i++, r++) {
+        position[i * 6 + 0].x = r->left;
+        position[i * 6 + 0].y = height - r->top;
+        position[i * 6 + 1].x = r->left;
+        position[i * 6 + 1].y = height - r->bottom;
+        position[i * 6 + 2].x = r->right;
+        position[i * 6 + 2].y = height - r->bottom;
+        position[i * 6 + 3].x = r->left;
+        position[i * 6 + 3].y = height - r->top;
+        position[i * 6 + 4].x = r->right;
+        position[i * 6 + 4].y = height - r->bottom;
+        position[i * 6 + 5].x = r->right;
+        position[i * 6 + 5].y = height - r->top;
     }
     setupFillWithColor(red, green, blue, alpha);
     drawMesh(mesh);
 }
 
-void RenderEngine::flush() {
-    glFlush();
+int RenderEngine::flush(bool wait) {
+    // Attempt to create a sync khr object that can produce a sync point. If that
+    // isn't available, create a non-dupable sync object in the fallback path and
+    // wait on it directly.
+    EGLSyncKHR sync;
+    if (!wait) {
+        EGLint syncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
+
+        sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+        if (sync != EGL_NO_SYNC_KHR) {
+            // native fence fd will not be populated until flush() is done.
+            glFlush();
+
+            // get the sync fd
+            syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+            if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+                ALOGW("failed to dup sync khr object");
+            }
+
+            eglDestroySyncKHR(mEGLDisplay, sync);
+        }
+
+        if (syncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+            return syncFd;
+        }
+    }
+
+    // fallback or explicit wait
+    sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+    if (sync != EGL_NO_SYNC_KHR) {
+        EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+                                             2000000000 /*2 sec*/);
+        EGLint eglErr = eglGetError();
+        if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+            ALOGW("fence wait timed out");
+        } else {
+            ALOGW_IF(eglErr != EGL_SUCCESS, "error waiting on EGL fence: %#x", eglErr);
+        }
+        eglDestroySyncKHR(mEGLDisplay, sync);
+    } else {
+        ALOGW("error creating EGL fence: %#x", eglGetError());
+    }
+
+    return -1;
 }
 
 void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
@@ -234,8 +293,7 @@
     glClear(GL_COLOR_BUFFER_BIT);
 }
 
-void RenderEngine::setScissor(
-        uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
+void RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
     glScissor(left, bottom, right, top);
     glEnable(GL_SCISSOR_TEST);
 }
@@ -257,38 +315,52 @@
 }
 
 void RenderEngine::dump(String8& result) {
+    result.appendFormat("EGL implementation : %s\n",
+                        eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
+    result.appendFormat("%s\n", eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
+
     const GLExtensions& extensions(GLExtensions::getInstance());
-    result.appendFormat("GLES: %s, %s, %s\n",
-            extensions.getVendor(),
-            extensions.getRenderer(),
-            extensions.getVersion());
+    result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+                        extensions.getVersion());
     result.appendFormat("%s\n", extensions.getExtension());
 }
 
 // ---------------------------------------------------------------------------
 
-RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
-        RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
-{
-    mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
+RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer(
+        RenderEngine& engine, ANativeWindowBuffer* buffer)
+      : mEngine(engine) {
+    mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                               buffer, NULL);
+    if (mImage == EGL_NO_IMAGE_KHR) {
+        mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+        return;
+    }
 
-    ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
-            "glCheckFramebufferStatusOES error %d", mStatus);
+    mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus);
+
+    ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
+             mStatus);
 }
 
-RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
+RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() {
+    if (mImage == EGL_NO_IMAGE_KHR) {
+        return;
+    }
+
     // back to main framebuffer
     mEngine.unbindFramebuffer(mTexName, mFbName);
+    eglDestroyImageKHR(mEngine.mEGLDisplay, mImage);
 }
 
-status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
+status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const {
     return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
 }
 
 // ---------------------------------------------------------------------------
 
-static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
-        EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
+static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
+                                         EGLint wanted, EGLConfig* outConfig) {
     EGLint numConfigs = -1, n = 0;
     eglGetConfigs(dpy, NULL, 0, &numConfigs);
     EGLConfig* const configs = new EGLConfig[numConfigs];
@@ -296,23 +368,23 @@
 
     if (n) {
         if (attribute != EGL_NONE) {
-            for (int i=0 ; i<n ; i++) {
+            for (int i = 0; i < n; i++) {
                 EGLint value = 0;
                 eglGetConfigAttrib(dpy, configs[i], attribute, &value);
                 if (wanted == value) {
                     *outConfig = configs[i];
-                    delete [] configs;
+                    delete[] configs;
                     return NO_ERROR;
                 }
             }
         } else {
             // just pick the first one
             *outConfig = configs[0];
-            delete [] configs;
+            delete[] configs;
             return NO_ERROR;
         }
     }
-    delete [] configs;
+    delete[] configs;
     return NAME_NOT_FOUND;
 }
 
@@ -322,10 +394,10 @@
     friend class Adder;
     KeyedVector<Attribute, EGLint> mList;
     struct Attribute {
-        Attribute() : v(0) {};
-        explicit Attribute(EGLint v) : v(v) { }
+        Attribute() : v(0){};
+        explicit Attribute(EGLint v) : v(v) {}
         EGLint v;
-        bool operator < (const Attribute& other) const {
+        bool operator<(const Attribute& other) const {
             // this places EGL_NONE at the end
             EGLint lhs(v);
             EGLint rhs(other.v);
@@ -338,39 +410,32 @@
         friend class EGLAttributeVector;
         EGLAttributeVector& v;
         EGLint attribute;
-        Adder(EGLAttributeVector& v, EGLint attribute)
-            : v(v), attribute(attribute) {
-        }
+        Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
+
     public:
-        void operator = (EGLint value) {
+        void operator=(EGLint value) {
             if (attribute != EGL_NONE) {
                 v.mList.add(Attribute(attribute), value);
             }
         }
-        operator EGLint () const { return v.mList[attribute]; }
+        operator EGLint() const { return v.mList[attribute]; }
     };
+
 public:
-    EGLAttributeVector() {
-        mList.add(Attribute(EGL_NONE), EGL_NONE);
-    }
+    EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
     void remove(EGLint attribute) {
         if (attribute != EGL_NONE) {
             mList.removeItem(Attribute(attribute));
         }
     }
-    Adder operator [] (EGLint attribute) {
-        return Adder(*this, attribute);
-    }
-    EGLint operator [] (EGLint attribute) const {
-       return mList[attribute];
-    }
+    Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
+    EGLint operator[](EGLint attribute) const { return mList[attribute]; }
     // cast-operator to (EGLint const*)
-    operator EGLint const* () const { return &mList.keyAt(0).v; }
+    operator EGLint const*() const { return &mList.keyAt(0).v; }
 };
 
-
-static status_t selectEGLConfig(EGLDisplay display, EGLint format,
-    EGLint renderableType, EGLConfig* config) {
+static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
+                                EGLConfig* config) {
     // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
     // it is to be used with WIFI displays
     status_t err;
@@ -379,24 +444,23 @@
 
     EGLAttributeVector attribs;
     if (renderableType) {
-        attribs[EGL_RENDERABLE_TYPE]            = renderableType;
-        attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
-        attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
+        attribs[EGL_RENDERABLE_TYPE] = renderableType;
+        attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
+        attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
         attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
-        attribs[EGL_RED_SIZE]                   = 8;
-        attribs[EGL_GREEN_SIZE]                 = 8;
-        attribs[EGL_BLUE_SIZE]                  = 8;
-        attribs[EGL_ALPHA_SIZE]                 = 8;
-        wantedAttribute                         = EGL_NONE;
-        wantedAttributeValue                    = EGL_NONE;
+        attribs[EGL_RED_SIZE] = 8;
+        attribs[EGL_GREEN_SIZE] = 8;
+        attribs[EGL_BLUE_SIZE] = 8;
+        attribs[EGL_ALPHA_SIZE] = 8;
+        wantedAttribute = EGL_NONE;
+        wantedAttributeValue = EGL_NONE;
     } else {
         // if no renderable type specified, fallback to a simplified query
-        wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
-        wantedAttributeValue                    = format;
+        wantedAttribute = EGL_NATIVE_VISUAL_ID;
+        wantedAttributeValue = format;
     }
 
-    err = selectConfigForAttribute(display, attribs,
-            wantedAttribute, wantedAttributeValue, config);
+    err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
     if (err == NO_ERROR) {
         EGLint caveat;
         if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
@@ -406,8 +470,7 @@
     return err;
 }
 
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
-                                        bool logConfig) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
     status_t err;
     EGLConfig config;
 
@@ -430,23 +493,22 @@
 
     if (logConfig) {
         // print some debugging info
-        EGLint r,g,b,a;
-        eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
+        EGLint r, g, b, a;
+        eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
         eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
+        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
         eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
         ALOGI("EGL information:");
         ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
         ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
         ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
-        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
         ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
     }
 
     return config;
 }
 
-
 void RenderEngine::primeCache() const {
     // Getting the ProgramCache instance causes it to prime its shader cache,
     // which is performed in its constructor
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 9544579..3847347 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -14,20 +14,24 @@
  * limitations under the License.
  */
 
-
 #ifndef SF_RENDERENGINE_H_
 #define SF_RENDERENGINE_H_
 
+#include <memory>
+
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <math/mat4.h>
 #include <Transform.h>
+#include <gui/SurfaceControl.h>
+#include <math/mat4.h>
 
 #define EGL_NO_CONFIG ((EGLConfig)0)
 
+struct ANativeWindowBuffer;
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -38,31 +42,38 @@
 class Mesh;
 class Texture;
 
+namespace RE {
+class Surface;
+}
+
 class RenderEngine {
     enum GlesVersion {
-        GLES_VERSION_1_0    = 0x10000,
-        GLES_VERSION_1_1    = 0x10001,
-        GLES_VERSION_2_0    = 0x20000,
-        GLES_VERSION_3_0    = 0x30000,
+        GLES_VERSION_1_0 = 0x10000,
+        GLES_VERSION_1_1 = 0x10001,
+        GLES_VERSION_2_0 = 0x20000,
+        GLES_VERSION_3_0 = 0x30000,
     };
     static GlesVersion parseGlesVersion(const char* str);
 
+    EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
     EGLContext mEGLContext;
-    void setEGLHandles(EGLConfig config, EGLContext ctxt);
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
 
-    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
+    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+                                        uint32_t* status) = 0;
     virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
 
 protected:
     RenderEngine();
-    virtual ~RenderEngine() = 0;
 
 public:
+    virtual ~RenderEngine() = 0;
+
     enum FeatureFlag {
         WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
     };
-    static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
+    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
 
     static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
@@ -72,10 +83,11 @@
     virtual void dump(String8& result);
 
     // helpers
-    void flush();
+    // flush returns -1 or a valid native fence fd owned by the caller
+    int flush(bool wait);
     void clearWithColor(float red, float green, float blue, float alpha);
-    void fillRegionWithColor(const Region& region, uint32_t height,
-            float red, float green, float blue, float alpha);
+    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                             float blue, float alpha);
 
     // common to all GL versions
     void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top);
@@ -84,38 +96,36 @@
     void deleteTextures(size_t count, uint32_t const* names);
     void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels);
 
-    class BindImageAsFramebuffer {
+    class BindNativeBufferAsFramebuffer {
         RenderEngine& mEngine;
+        EGLImageKHR mImage;
         uint32_t mTexName, mFbName;
         uint32_t mStatus;
+
     public:
-        BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
-        ~BindImageAsFramebuffer();
+        BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer);
+        ~BindNativeBufferAsFramebuffer();
         int getStatus() const;
     };
 
+    bool setCurrentSurface(const RE::Surface& surface);
+    void resetCurrentSurface();
+
     // set-up
     virtual void checkErrors() const;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0;
-#ifdef USE_HWC2
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
-    virtual void setupDimLayerBlending(float alpha) = 0;
+    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
+                                          bool yswap, Transform::orientation_flags rotation) = 0;
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                                    const half4& color) = 0;
     virtual void setColorMode(android_color_mode mode) = 0;
     virtual void setSourceDataSpace(android_dataspace source) = 0;
     virtual void setWideColor(bool hasWideColor) = 0;
     virtual bool usesWideColor() = 0;
-#else
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
-    virtual void setupDimLayerBlending(int alpha) = 0;
-#endif
     virtual void setupLayerTexturing(const Texture& texture) = 0;
     virtual void setupLayerBlackedOut() = 0;
     virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
 
-    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) {
-        return mat4();
-    }
+    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) { return mat4(); }
 
     virtual void disableTexturing() = 0;
     virtual void disableBlending() = 0;
@@ -127,8 +137,9 @@
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
 
+    // internal to RenderEngine
+    EGLDisplay getEGLDisplay() const;
     EGLConfig getEGLConfig() const;
-    EGLContext getEGLContext() const;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
new file mode 100644
index 0000000..a23d9fb
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Surface.h"
+
+#include "RenderEngine.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace RE {
+
+Surface::Surface(const RenderEngine& engine)
+      : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
+    // RE does not assume any config when EGL_KHR_no_config_context is supported
+    if (mEGLConfig == EGL_NO_CONFIG_KHR) {
+        mEGLConfig = RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
+    }
+}
+
+Surface::~Surface() {
+    setNativeWindow(nullptr);
+}
+
+void Surface::setNativeWindow(ANativeWindow* window) {
+    if (mEGLSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mEGLSurface);
+        mEGLSurface = EGL_NO_SURFACE;
+    }
+
+    mWindow = window;
+    if (mWindow) {
+        mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
+    }
+}
+
+void Surface::swapBuffers() const {
+    if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
+        EGLint error = eglGetError();
+
+        const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
+        if (mCritical || error == EGL_CONTEXT_LOST) {
+            LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
+        } else {
+            ALOGE(format, mEGLDisplay, mEGLSurface, error);
+        }
+    }
+}
+
+EGLint Surface::queryConfig(EGLint attrib) const {
+    EGLint value;
+    if (!eglGetConfigAttrib(mEGLConfig, mEGLConfig, attrib, &value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+EGLint Surface::querySurface(EGLint attrib) const {
+    EGLint value;
+    if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+int32_t Surface::queryRedSize() const {
+    return queryConfig(EGL_RED_SIZE);
+}
+
+int32_t Surface::queryGreenSize() const {
+    return queryConfig(EGL_GREEN_SIZE);
+}
+
+int32_t Surface::queryBlueSize() const {
+    return queryConfig(EGL_BLUE_SIZE);
+}
+
+int32_t Surface::queryAlphaSize() const {
+    return queryConfig(EGL_ALPHA_SIZE);
+}
+
+int32_t Surface::queryWidth() const {
+    return querySurface(EGL_WIDTH);
+}
+
+int32_t Surface::queryHeight() const {
+    return querySurface(EGL_HEIGHT);
+}
+
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h
new file mode 100644
index 0000000..8b10be9
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Surface.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+
+struct ANativeWindow;
+
+namespace android {
+
+class RenderEngine;
+
+namespace RE {
+
+class Surface {
+public:
+    Surface(const RenderEngine& engine);
+    ~Surface();
+
+    Surface(const Surface&) = delete;
+    Surface& operator=(const Surface&) = delete;
+
+    void setCritical(bool enable) { mCritical = enable; }
+    void setAsync(bool enable) { mAsync = enable; }
+
+    void setNativeWindow(ANativeWindow* window);
+    void swapBuffers() const;
+
+    int32_t queryRedSize() const;
+    int32_t queryGreenSize() const;
+    int32_t queryBlueSize() const;
+    int32_t queryAlphaSize() const;
+
+    int32_t queryWidth() const;
+    int32_t queryHeight() const;
+
+private:
+    EGLint queryConfig(EGLint attrib) const;
+    EGLint querySurface(EGLint attrib) const;
+
+    // methods internal to RenderEngine
+    friend class android::RenderEngine;
+    bool getAsync() const { return mAsync; }
+    EGLSurface getEGLSurface() const { return mEGLSurface; }
+
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+
+    bool mCritical = false;
+    bool mAsync = false;
+
+    ANativeWindow* mWindow = nullptr;
+    EGLSurface mEGLSurface = EGL_NO_SURFACE;
+};
+
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp
index 8875b6d..351430f 100644
--- a/services/surfaceflinger/RenderEngine/Texture.cpp
+++ b/services/surfaceflinger/RenderEngine/Texture.cpp
@@ -20,24 +20,22 @@
 
 namespace android {
 
-Texture::Texture() :
-    mTextureName(0), mTextureTarget(TEXTURE_2D),
-    mWidth(0), mHeight(0), mFiltering(false) {
-}
+Texture::Texture()
+      : mTextureName(0), mTextureTarget(TEXTURE_2D), mWidth(0), mHeight(0), mFiltering(false) {}
 
-Texture::Texture(Target textureTarget, uint32_t textureName) :
-            mTextureName(textureName), mTextureTarget(textureTarget),
-            mWidth(0), mHeight(0), mFiltering(false) {
-}
+Texture::Texture(Target textureTarget, uint32_t textureName)
+      : mTextureName(textureName),
+        mTextureTarget(textureTarget),
+        mWidth(0),
+        mHeight(0),
+        mFiltering(false) {}
 
 void Texture::init(Target textureTarget, uint32_t textureName) {
     mTextureName = textureName;
     mTextureTarget = textureTarget;
 }
 
-Texture::~Texture() {
-}
-
+Texture::~Texture() {}
 
 void Texture::setMatrix(float const* matrix) {
     mTextureMatrix = mat4(matrix);
diff --git a/services/surfaceflinger/RenderEngine/Texture.h b/services/surfaceflinger/RenderEngine/Texture.h
index a07e0c3..56b6b31 100644
--- a/services/surfaceflinger/RenderEngine/Texture.h
+++ b/services/surfaceflinger/RenderEngine/Texture.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
 #include <math/mat4.h>
+#include <stdint.h>
 
 #ifndef SF_RENDER_ENGINE_TEXTURE_H
 #define SF_RENDER_ENGINE_TEXTURE_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7a8737f..142892e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -28,8 +28,6 @@
 #include <stdatomic.h>
 #include <optional>
 
-#include <EGL/egl.h>
-
 #include <cutils/properties.h>
 #include <log/log.h>
 
@@ -72,8 +70,9 @@
 #include "EventControlThread.h"
 #include "EventThread.h"
 #include "Layer.h"
+#include "BufferLayer.h"
 #include "LayerVector.h"
-#include "LayerDim.h"
+#include "ColorLayer.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 
@@ -90,6 +89,8 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 
+#include <layerproto/LayerProtoParser.h>
+
 #define DISPLAY_COUNT       1
 
 /*
@@ -98,8 +99,6 @@
  */
 #define DEBUG_SCREENSHOTS   false
 
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
 namespace android {
 
 using namespace android::hardware::configstore;
@@ -282,9 +281,6 @@
 
 SurfaceFlinger::~SurfaceFlinger()
 {
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(display);
 }
 
 void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
@@ -568,7 +564,7 @@
 
     virtual void onInjectSyncEvent(nsecs_t when) {
         std::lock_guard<std::mutex> lock(mCallbackMutex);
-        if (mCallback != nullptr) {
+        if (mCallback) {
             mCallback->onVSyncEvent(when);
         }
     }
@@ -591,10 +587,6 @@
 
     Mutex::Autolock _l(mStateLock);
 
-    // initialize EGL for the default display
-    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglInitialize(mEGLDisplay, NULL, NULL);
-
     // start the EventThread
     sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
             vsyncPhaseOffsetNs, true, "app");
@@ -615,15 +607,9 @@
     }
 
     // Get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay,
-            HAL_PIXEL_FORMAT_RGBA_8888,
+    mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
             hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
-
-    // retrieve the EGL context that was selected/created
-    mEGLContext = mRenderEngine->getEGLContext();
-
-    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
-            "couldn't create EGLContext");
+    LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
             "Starting with vr flinger active is not currently supported.");
@@ -646,7 +632,8 @@
             postMessageAsync(message);
         };
         mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
-                                            vrFlingerRequestDisplayCallback);
+                mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
+                vrFlingerRequestDisplayCallback);
         if (!mVrFlinger) {
             ALOGE("Failed to start vrflinger");
         }
@@ -1065,42 +1052,29 @@
     return NO_ERROR;
 }
 
-void SurfaceFlinger::enableVSyncInjectionsInternal(bool enable) {
-    Mutex::Autolock _l(mStateLock);
-
-    if (mInjectVSyncs == enable) {
-        return;
-    }
-
-    if (enable) {
-        ALOGV("VSync Injections enabled");
-        if (mVSyncInjector.get() == nullptr) {
-            mVSyncInjector = new InjectVSyncSource();
-            mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
-        }
-        mEventQueue.setEventThread(mInjectorEventThread);
-    } else {
-        ALOGV("VSync Injections disabled");
-        mEventQueue.setEventThread(mSFEventThread);
-    }
-
-    mInjectVSyncs = enable;
-}
-
 status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
-    class MessageEnableVSyncInjections : public MessageBase {
-        SurfaceFlinger* mFlinger;
-        bool mEnable;
-    public:
-        MessageEnableVSyncInjections(SurfaceFlinger* flinger, bool enable)
-            : mFlinger(flinger), mEnable(enable) { }
-        virtual bool handler() {
-            mFlinger->enableVSyncInjectionsInternal(mEnable);
-            return true;
+    sp<LambdaMessage> enableVSyncInjections = new LambdaMessage([&]() {
+        Mutex::Autolock _l(mStateLock);
+
+        if (mInjectVSyncs == enable) {
+            return;
         }
-    };
-    sp<MessageBase> msg = new MessageEnableVSyncInjections(this, enable);
-    postMessageSync(msg);
+
+        if (enable) {
+            ALOGV("VSync Injections enabled");
+            if (mVSyncInjector.get() == nullptr) {
+                mVSyncInjector = new InjectVSyncSource();
+                mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
+            }
+            mEventQueue.setEventThread(mInjectorEventThread);
+        } else {
+            ALOGV("VSync Injections disabled");
+            mEventQueue.setEventThread(mSFEventThread);
+        }
+
+        mInjectVSyncs = enable;
+    });
+    postMessageSync(enableVSyncInjections);
     return NO_ERROR;
 }
 
@@ -1317,8 +1291,7 @@
     }
     bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode;
     sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
-                                             token, fbs, producer, mRenderEngine->getEGLConfig(),
-                                             useWideColorMode);
+                                             token, fbs, producer, useWideColorMode);
     mDisplays.add(token, hw);
     android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
     if (useWideColorMode) {
@@ -1333,7 +1306,7 @@
 
     // make the GLContext current so that we can create textures when creating
     // Layers (which may happens before we render something)
-    hw->makeCurrent(mEGLDisplay, mEGLContext);
+    hw->makeCurrent();
 }
 
 void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
@@ -1404,7 +1377,7 @@
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
-    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    getRenderEngine().resetCurrentSurface();
     mDisplays.clear();
 }
 
@@ -1531,6 +1504,7 @@
     rebuildLayerStacks();
     setUpHWComposer();
     doDebugFlashRegions();
+    doTracing("handleRefresh");
     doComposition();
     postComposition(refreshStartTime);
 
@@ -1560,7 +1534,7 @@
             const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
             if (!dirtyRegion.isEmpty()) {
                 // redraw the whole screen
-                doComposeSurfaces(hw, Region(hw->bounds()));
+                doComposeSurfaces(hw);
 
                 // and draw the dirty region
                 const int32_t height = hw->getHeight();
@@ -1590,6 +1564,14 @@
     }
 }
 
+void SurfaceFlinger::doTracing(const char* where) {
+    ATRACE_CALL();
+    ATRACE_NAME(where);
+    if (CC_UNLIKELY(mTracing.isEnabled())) {
+        mTracing.traceLayers(where, dumpProtoInfo(LayerVector::StateSet::Drawing));
+    }
+}
+
 void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
 {
     ATRACE_CALL();
@@ -1774,7 +1756,7 @@
 
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
-        ATRACE_CALL();
+        ATRACE_NAME("rebuildLayerStacks VR Dirty");
         mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
@@ -1973,6 +1955,12 @@
                     "display %zd: %d", displayId, result);
         }
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            if (layer->getForceClientComposition(hwcId)) {
+                ALOGV("[%s] Requesting Client composition", layer->getName().string());
+                layer->setCompositionType(hwcId, HWC2::Composition::Client);
+                continue;
+            }
+
             layer->setPerFrameData(displayDevice);
         }
 
@@ -2021,8 +2009,7 @@
             doDisplayComposition(hw, dirtyRegion);
 
             hw->dirtyRegion.clear();
-            hw->flip(hw->swapRegion);
-            hw->swapRegion.clear();
+            hw->flip();
         }
     }
     postFramebuffer();
@@ -2046,7 +2033,7 @@
             mHwc->presentAndGetReleaseFences(hwcId);
         }
         displayDevice->onSwapBuffersCompleted();
-        displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
+        displayDevice->makeCurrent();
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             // The layer buffer from the previous frame (if any) is released
             // by HWC only when the release fence from this frame (if any) is
@@ -2172,7 +2159,7 @@
                         // be sure that nothing associated with this display
                         // is current.
                         const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
-                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
+                        defaultDisplay->makeCurrent();
                         sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
@@ -2290,9 +2277,7 @@
                     if (dispSurface != NULL) {
                         sp<DisplayDevice> hw =
                                 new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
-                                                  dispSurface, producer,
-                                                  mRenderEngine->getEGLConfig(),
-                                                  hasWideColorDisplay);
+                                                  dispSurface, producer, hasWideColorDisplay);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -2512,7 +2497,7 @@
 
                 // compute the opaque region
                 const int32_t layerOrientation = tr.getOrientation();
-                if (s.alpha == 1.0f && !translucent &&
+                if (layer->getAlpha() == 1.0f && !translucent &&
                         ((layerOrientation & Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
                     opaqueRegion = visibleRegion;
@@ -2657,46 +2642,18 @@
     }
 
     ALOGV("doDisplayComposition");
-
-    Region dirtyRegion(inDirtyRegion);
-
-    // compute the invalid region
-    displayDevice->swapRegion.orSelf(dirtyRegion);
-
-    uint32_t flags = displayDevice->getFlags();
-    if (flags & DisplayDevice::SWAP_RECTANGLE) {
-        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
-        // takes a rectangle, we must make sure to update that whole
-        // rectangle in that case
-        dirtyRegion.set(displayDevice->swapRegion.bounds());
-    } else {
-        if (flags & DisplayDevice::PARTIAL_UPDATES) {
-            // We need to redraw the rectangle that will be updated
-            // (pushed to the framebuffer).
-            // This is needed because PARTIAL_UPDATES only takes one
-            // rectangle instead of a region (see DisplayDevice::flip())
-            dirtyRegion.set(displayDevice->swapRegion.bounds());
-        } else {
-            // we need to redraw everything (the whole screen)
-            dirtyRegion.set(displayDevice->bounds());
-            displayDevice->swapRegion = dirtyRegion;
-        }
-    }
-
-    if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
-
-    // update the swap region and clear the dirty region
-    displayDevice->swapRegion.orSelf(dirtyRegion);
+    if (!doComposeSurfaces(displayDevice)) return;
 
     // swap buffers (presentation)
     displayDevice->swapBuffers(getHwComposer());
 }
 
-bool SurfaceFlinger::doComposeSurfaces(
-        const sp<const DisplayDevice>& displayDevice, const Region& dirty)
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDevice)
 {
     ALOGV("doComposeSurfaces");
 
+    const Region bounds(displayDevice->bounds());
+    const DisplayRenderArea renderArea(displayDevice);
     const auto hwcId = displayDevice->getHwcDisplayId();
 
     mat4 oldColorMatrix;
@@ -2711,19 +2668,17 @@
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
-#ifdef USE_HWC2
         mRenderEngine->setWideColor(
                 displayDevice->getWideColorSupport() && !mForceNativeColorMode);
         mRenderEngine->setColorMode(mForceNativeColorMode ?
                 HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode());
-#endif
-        if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
+        if (!displayDevice->makeCurrent()) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   displayDevice->getDisplayName().string());
-            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            getRenderEngine().resetCurrentSurface();
 
             // |mStateLock| not needed as we are on the main thread
-            if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
+            if(!getDefaultDisplayDeviceLocked()->makeCurrent()) {
               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
             }
             return false;
@@ -2739,10 +2694,7 @@
             // We'll revisit later if needed.
             mRenderEngine->clearWithColor(0, 0, 0, 0);
         } else {
-            // we start with the whole screen area
-            const Region bounds(displayDevice->getBounds());
-
-            // we remove the scissor part
+            // we start with the whole screen area and remove the scissor part
             // we're left with the letterbox region
             // (common case is that letterbox ends-up being empty)
             const Region letterbox(bounds.subtract(displayDevice->getScissor()));
@@ -2750,9 +2702,6 @@
             // compute the area to clear
             Region region(displayDevice->undefinedRegion.merge(letterbox));
 
-            // but limit it to the dirty region
-            region.andSelf(dirty);
-
             // screen is already cleared here
             if (!region.isEmpty()) {
                 // can happen with SurfaceView
@@ -2789,7 +2738,7 @@
         // we're using h/w composer
         bool firstLayer = true;
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-            const Region clip(dirty.intersect(
+            const Region clip(bounds.intersect(
                     displayTransform.transform(layer->visibleRegion)));
             ALOGV("Layer: %s", layer->getName().string());
             ALOGV("  Composition type: %s",
@@ -2802,16 +2751,16 @@
                     case HWC2::Composition::SolidColor: {
                         const Layer::State& state(layer->getDrawingState());
                         if (layer->getClearClientTarget(hwcId) && !firstLayer &&
-                                layer->isOpaque(state) && (state.alpha == 1.0f)
+                                layer->isOpaque(state) && (state.color.a == 1.0f)
                                 && hasClientComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
-                            layer->clearWithOpenGL(displayDevice);
+                            layer->clearWithOpenGL(renderArea);
                         }
                         break;
                     }
                     case HWC2::Composition::Client: {
-                        layer->draw(displayDevice, clip);
+                        layer->draw(renderArea, clip);
                         break;
                     }
                     default:
@@ -2825,10 +2774,10 @@
     } else {
         // we're not using h/w composer
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-            const Region clip(dirty.intersect(
+            const Region clip(bounds.intersect(
                     displayTransform.transform(layer->visibleRegion)));
             if (!clip.isEmpty()) {
-                layer->draw(displayDevice, clip);
+                layer->draw(renderArea, clip);
             }
         }
     }
@@ -2865,7 +2814,7 @@
         if (parent == nullptr) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else {
-            if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+            if (parent->isPendingRemoval()) {
                 ALOGE("addClientLayer called with a removed parent");
                 return NAME_NOT_FOUND;
             }
@@ -2886,6 +2835,10 @@
 status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
     Mutex::Autolock _l(mStateLock);
 
+    if (layer->isPendingRemoval()) {
+        return NO_ERROR;
+    }
+
     const auto& p = layer->getParent();
     ssize_t index;
     if (p != nullptr) {
@@ -3089,122 +3042,153 @@
         const sp<Client>& client,
         const layer_state_t& s)
 {
-    uint32_t flags = 0;
     sp<Layer> layer(client->getLayerUser(s.surface));
-    if (layer != 0) {
-        const uint32_t what = s.what;
-        bool geometryAppliesWithResize =
-                what & layer_state_t::eGeometryAppliesWithResize;
-        if (what & layer_state_t::ePositionChanged) {
-            if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
-                flags |= eTraversalNeeded;
-            }
+    if (layer == nullptr) {
+        return 0;
+    }
+
+    if (layer->isPendingRemoval()) {
+        ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
+        return 0;
+    }
+
+    uint32_t flags = 0;
+
+    const uint32_t what = s.what;
+    bool geometryAppliesWithResize =
+            what & layer_state_t::eGeometryAppliesWithResize;
+    if (what & layer_state_t::ePositionChanged) {
+        if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
+            flags |= eTraversalNeeded;
         }
-        if (what & layer_state_t::eLayerChanged) {
-            // NOTE: index needs to be calculated before we update the state
-            const auto& p = layer->getParent();
-            if (p == nullptr) {
-                ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-                if (layer->setLayer(s.z) && idx >= 0) {
-                    mCurrentState.layersSortedByZ.removeAt(idx);
-                    mCurrentState.layersSortedByZ.add(layer);
-                    // we need traversal (state changed)
-                    // AND transaction (list changed)
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            } else {
-                if (p->setChildLayer(layer, s.z)) {
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            }
-        }
-        if (what & layer_state_t::eRelativeLayerChanged) {
+    }
+    if (what & layer_state_t::eLayerChanged) {
+        // NOTE: index needs to be calculated before we update the state
+        const auto& p = layer->getParent();
+        if (p == nullptr) {
             ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
-                mCurrentState.layersSortedByZ.removeAt(idx);
-                mCurrentState.layersSortedByZ.add(layer);
-                flags |= eTransactionNeeded|eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eSizeChanged) {
-            if (layer->setSize(s.w, s.h)) {
-                flags |= eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eAlphaChanged) {
-            if (layer->setAlpha(s.alpha))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eMatrixChanged) {
-            if (layer->setMatrix(s.matrix))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eTransparentRegionChanged) {
-            if (layer->setTransparentRegionHint(s.transparentRegion))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eFlagsChanged) {
-            if (layer->setFlags(s.flags, s.mask))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eCropChanged) {
-            if (layer->setCrop(s.crop, !geometryAppliesWithResize))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eFinalCropChanged) {
-            if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eLayerStackChanged) {
-            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            // We only allow setting layer stacks for top level layers,
-            // everything else inherits layer stack from its parent.
-            if (layer->hasParent()) {
-                ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
-                        layer->getName().string());
-            } else if (idx < 0) {
-                ALOGE("Attempt to set layer stack on layer without parent (%s) that "
-                        "that also does not appear in the top level layer list. Something"
-                        " has gone wrong.", layer->getName().string());
-            } else if (layer->setLayerStack(s.layerStack)) {
+            if (layer->setLayer(s.z) && idx >= 0) {
                 mCurrentState.layersSortedByZ.removeAt(idx);
                 mCurrentState.layersSortedByZ.add(layer);
                 // we need traversal (state changed)
                 // AND transaction (list changed)
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
-        }
-        if (what & layer_state_t::eDeferTransaction) {
-            if (s.barrierHandle != nullptr) {
-                layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
-            } else if (s.barrierGbp != nullptr) {
-                const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
-                if (authenticateSurfaceTextureLocked(gbp)) {
-                    const auto& otherLayer =
-                        (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
-                    layer->deferTransactionUntil(otherLayer, s.frameNumber);
-                } else {
-                    ALOGE("Attempt to defer transaction to to an"
-                            " unrecognized GraphicBufferProducer");
-                }
-            }
-            // We don't trigger a traversal here because if no other state is
-            // changed, we don't want this to cause any more work
-        }
-        if (what & layer_state_t::eReparentChildren) {
-            if (layer->reparentChildren(s.reparentHandle)) {
+        } else {
+            if (p->setChildLayer(layer, s.z)) {
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
-        if (what & layer_state_t::eDetachChildren) {
-            layer->detachChildren();
+    }
+    if (what & layer_state_t::eRelativeLayerChanged) {
+        // NOTE: index needs to be calculated before we update the state
+        const auto& p = layer->getParent();
+        if (p == nullptr) {
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z) && idx >= 0) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        } else {
+            if (p->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
         }
-        if (what & layer_state_t::eOverrideScalingModeChanged) {
-            layer->setOverrideScalingMode(s.overrideScalingMode);
-            // We don't trigger a traversal here because if no other state is
-            // changed, we don't want this to cause any more work
+    }
+    if (what & layer_state_t::eSizeChanged) {
+        if (layer->setSize(s.w, s.h)) {
+            flags |= eTraversalNeeded;
         }
     }
+    if (what & layer_state_t::eAlphaChanged) {
+        if (layer->setAlpha(s.alpha))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eColorChanged) {
+        if (layer->setColor(s.color))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eMatrixChanged) {
+        if (layer->setMatrix(s.matrix))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eTransparentRegionChanged) {
+        if (layer->setTransparentRegionHint(s.transparentRegion))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eFlagsChanged) {
+        if (layer->setFlags(s.flags, s.mask))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eCropChanged) {
+        if (layer->setCrop(s.crop, !geometryAppliesWithResize))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eFinalCropChanged) {
+        if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
+            flags |= eTraversalNeeded;
+    }
+    if (what & layer_state_t::eLayerStackChanged) {
+        ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+        // We only allow setting layer stacks for top level layers,
+        // everything else inherits layer stack from its parent.
+        if (layer->hasParent()) {
+            ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
+                    layer->getName().string());
+        } else if (idx < 0) {
+            ALOGE("Attempt to set layer stack on layer without parent (%s) that "
+                    "that also does not appear in the top level layer list. Something"
+                    " has gone wrong.", layer->getName().string());
+        } else if (layer->setLayerStack(s.layerStack)) {
+            mCurrentState.layersSortedByZ.removeAt(idx);
+            mCurrentState.layersSortedByZ.add(layer);
+            // we need traversal (state changed)
+            // AND transaction (list changed)
+            flags |= eTransactionNeeded|eTraversalNeeded;
+        }
+    }
+    if (what & layer_state_t::eDeferTransaction) {
+        if (s.barrierHandle != nullptr) {
+            layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
+        } else if (s.barrierGbp != nullptr) {
+            const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
+            if (authenticateSurfaceTextureLocked(gbp)) {
+                const auto& otherLayer =
+                    (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+                layer->deferTransactionUntil(otherLayer, s.frameNumber);
+            } else {
+                ALOGE("Attempt to defer transaction to to an"
+                        " unrecognized GraphicBufferProducer");
+            }
+        }
+        // We don't trigger a traversal here because if no other state is
+        // changed, we don't want this to cause any more work
+    }
+    if (what & layer_state_t::eReparent) {
+        bool hadParent = layer->hasParent();
+        if (layer->reparent(s.parentHandleForChild)) {
+            if (!hadParent) {
+                mCurrentState.layersSortedByZ.remove(layer);
+            }
+            flags |= eTransactionNeeded|eTraversalNeeded;
+        }
+    }
+    if (what & layer_state_t::eReparentChildren) {
+        if (layer->reparentChildren(s.reparentHandle)) {
+            flags |= eTransactionNeeded|eTraversalNeeded;
+        }
+    }
+    if (what & layer_state_t::eDetachChildren) {
+        layer->detachChildren();
+    }
+    if (what & layer_state_t::eOverrideScalingModeChanged) {
+        layer->setOverrideScalingMode(s.overrideScalingMode);
+        // We don't trigger a traversal here because if no other state is
+        // changed, we don't want this to cause any more work
+    }
     return flags;
 }
 
@@ -3229,14 +3213,15 @@
 
     switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
         case ISurfaceComposerClient::eFXSurfaceNormal:
-            result = createNormalLayer(client,
+            result = createBufferLayer(client,
                     uniqueName, w, h, flags, format,
                     handle, gbp, &layer);
+
             break;
-        case ISurfaceComposerClient::eFXSurfaceDim:
-            result = createDimLayer(client,
+        case ISurfaceComposerClient::eFXSurfaceColor:
+            result = createColorLayer(client,
                     uniqueName, w, h, flags,
-                    handle, gbp, &layer);
+                    handle, &layer);
             break;
         default:
             result = BAD_VALUE;
@@ -3290,7 +3275,7 @@
     return uniqueName;
 }
 
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
         const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
 {
@@ -3305,24 +3290,24 @@
         break;
     }
 
-    *outLayer = new Layer(this, client, name, w, h, flags);
-    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+    sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
+    status_t err = layer->setBuffers(w, h, format, flags);
     if (err == NO_ERROR) {
-        *handle = (*outLayer)->getHandle();
-        *gbp = (*outLayer)->getProducer();
+        *handle = layer->getHandle();
+        *gbp = layer->getProducer();
+        *outLayer = layer;
     }
 
-    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+    ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
     return err;
 }
 
-status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
         const String8& name, uint32_t w, uint32_t h, uint32_t flags,
-        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+        sp<IBinder>* handle, sp<Layer>* outLayer)
 {
-    *outLayer = new LayerDim(this, client, name, w, h, flags);
+    *outLayer = new ColorLayer(this, client, name, w, h, flags);
     *handle = (*outLayer)->getHandle();
-    *gbp = (*outLayer)->getProducer();
     return NO_ERROR;
 }
 
@@ -3450,7 +3435,8 @@
             ALOGW("Couldn't set SCHED_OTHER on display off");
         }
 
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
             disableHardwareVsync(true); // also cancels any in-progress resync
 
             // FIXME: eventthread only knows about the main display right now
@@ -3464,7 +3450,8 @@
                mode == HWC_POWER_MODE_NORMAL) {
         // Update display while dozing
         getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
             resyncToHardwareVsync(true);
@@ -3513,13 +3500,13 @@
 
 // ---------------------------------------------------------------------------
 
-status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
-{
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
     String8 result;
 
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
+
     if ((uid != AID_SHELL) &&
             !PermissionCache::checkPermission(sDump, pid, uid)) {
         result.appendFormat("Permission Denial: "
@@ -3539,6 +3526,13 @@
         bool dumpAll = true;
         size_t index = 0;
         size_t numArgs = args.size();
+
+        if (asProto) {
+            LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+            result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+            dumpAll = false;
+        }
+
         if (numArgs) {
             if ((index < numArgs) &&
                     (args[index] == String16("--list"))) {
@@ -3783,6 +3777,18 @@
     result.append("\n");
 }
 
+LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
+    LayersProto layersProto;
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+    state.traverseInZOrder([&](Layer* layer) {
+        LayerProto* layerProto = layersProto.add_layers();
+        layer->writeToProto(layerProto, stateSet);
+    });
+
+    return layersProto;
+}
+
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
 {
@@ -3847,9 +3853,10 @@
     colorizer.bold(result);
     result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
     colorizer.reset(result);
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        result.append(to_string(layer->getLayerDebugInfo()).c_str());
-    });
+
+    LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+    auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+    result.append(LayerProtoParser::layersToString(layerTree).c_str());
 
     /*
      * Dump Display state
@@ -3874,13 +3881,6 @@
     HWComposer& hwc(getHwComposer());
     sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
-    colorizer.bold(result);
-    result.appendFormat("EGL implementation : %s\n",
-            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
-    colorizer.reset(result);
-    result.appendFormat("%s\n",
-            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-
     mRenderEngine->dump(result);
 
     hw->undefinedRegion.dump(result, "undefinedRegion");
@@ -4043,6 +4043,17 @@
             }
             break;
         }
+        case CAPTURE_LAYERS: {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            if ((uid != AID_GRAPHICS) &&
+                !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+                ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+            break;
+        }
     }
     return OK;
 }
@@ -4226,6 +4237,20 @@
                 reply->writeBool(hasWideColorDisplay);
                 return NO_ERROR;
             }
+            case 1025: { // tracing
+                n = data.readInt32();
+                if (n) {
+                    ALOGV("LayerTracing enabled");
+                    mTracing.enable();
+                    doTracing("tracing.enable");
+                    reply->writeInt32(NO_ERROR);
+                } else {
+                    ALOGV("LayerTracing disabled");
+                    status_t err = mTracing.disable();
+                    reply->writeInt32(err);
+                }
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -4242,35 +4267,6 @@
     repaintEverythingLocked();
 }
 
-// Checks that the requested width and height are valid and updates them to the display dimensions
-// if they are set to 0
-static status_t updateDimensionsLocked(const sp<const DisplayDevice>& displayDevice,
-                                       Transform::orientation_flags rotation,
-                                       uint32_t* requestedWidth, uint32_t* requestedHeight) {
-    // get screen geometry
-    uint32_t displayWidth = displayDevice->getWidth();
-    uint32_t displayHeight = displayDevice->getHeight();
-
-    if (rotation & Transform::ROT_90) {
-        std::swap(displayWidth, displayHeight);
-    }
-
-    if ((*requestedWidth > displayWidth) || (*requestedHeight > displayHeight)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)",
-                *requestedWidth, *requestedHeight, displayWidth, displayHeight);
-        return BAD_VALUE;
-    }
-
-    if (*requestedWidth == 0) {
-        *requestedWidth = displayWidth;
-    }
-    if (*requestedHeight == 0) {
-        *requestedHeight = displayHeight;
-    }
-
-    return NO_ERROR;
-}
-
 // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
 class WindowDisconnector {
 public:
@@ -4284,111 +4280,109 @@
     const int mApi;
 };
 
-static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth,
-                                uint32_t requestedHeight, bool hasWideColorDisplay,
-                                bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) {
-    const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
-            GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
-    int err = 0;
-    err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight);
-    err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-    err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
-    err |= native_window_set_usage(window, usage);
-
-    if (hasWideColorDisplay) {
-        err |= native_window_set_buffers_data_space(window,
-                                                    renderEngineUsesWideColor
-                                                            ? HAL_DATASPACE_DISPLAY_P3
-                                                            : HAL_DATASPACE_V0_SRGB);
-    }
-
-    if (err != NO_ERROR) {
-        return BAD_VALUE;
-    }
-
-    /* TODO: Once we have the sync framework everywhere this can use
-     * server-side waits on the fence that dequeueBuffer returns.
-     */
-    err = native_window_dequeue_buffer_and_wait(window, outBuffer);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
-        const sp<IGraphicBufferProducer>& producer,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+                                       Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                                       int32_t minLayerZ, int32_t maxLayerZ,
+                                       bool useIdentityTransform,
+                                       ISurfaceComposer::Rotation rotation) {
     ATRACE_CALL();
 
-    if (CC_UNLIKELY(display == 0))
-        return BAD_VALUE;
+    if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
 
-    if (CC_UNLIKELY(producer == 0))
-        return BAD_VALUE;
+    const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+    DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
 
-    // if we have secure windows on this display, never allow the screen capture
-    // unless the producer interface is local (i.e.: we can take a screenshot for
-    // ourselves).
-    bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
+    auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
+                                    device, minLayerZ, maxLayerZ, std::placeholders::_1);
+    return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
+}
 
-    // Convert to surfaceflinger's internal rotation type.
-    Transform::orientation_flags rotationFlags;
-    switch (rotation) {
-        case ISurfaceComposer::eRotateNone:
-            rotationFlags = Transform::ROT_0;
-            break;
-        case ISurfaceComposer::eRotate90:
-            rotationFlags = Transform::ROT_90;
-            break;
-        case ISurfaceComposer::eRotate180:
-            rotationFlags = Transform::ROT_180;
-            break;
-        case ISurfaceComposer::eRotate270:
-            rotationFlags = Transform::ROT_270;
-            break;
-        default:
-            rotationFlags = Transform::ROT_0;
-            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
-            break;
+status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
+                                       sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop, 
+                                       float frameScale) {
+    ATRACE_CALL();
+
+    class LayerRenderArea : public RenderArea {
+    public:
+        LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
+                        int32_t reqHeight)
+              : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {}
+        const Transform& getTransform() const override {
+            // Make the top level transform the inverse the transform and it's parent so it sets
+            // the whole capture back to 0,0
+            return *new Transform(mLayer->getTransform().inverse());
+        }
+        Rect getBounds() const override {
+            const Layer::State& layerState(mLayer->getDrawingState());
+            return Rect(layerState.active.w, layerState.active.h);
+        }
+        int getHeight() const override { return mLayer->getDrawingState().active.h; }
+        int getWidth() const override { return mLayer->getDrawingState().active.w; }
+        bool isSecure() const override { return false; }
+        bool needsFiltering() const override { return false; }
+
+        Rect getSourceCrop() const override {
+            if (mCrop.isEmpty()) {
+                return getBounds();
+            } else {
+                return mCrop;
+            }
+        }
+        bool getWideColorSupport() const override { return false; }
+        android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; }
+
+    private:
+        const sp<Layer> mLayer;
+        const Rect mCrop;
+    };
+
+    auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+    auto parent = layerHandle->owner.promote();
+
+    if (parent == nullptr || parent->isPendingRemoval()) {
+        ALOGE("captureLayers called with a removed parent");
+        return NAME_NOT_FOUND;
     }
 
-    { // Autolock scope
-        Mutex::Autolock lock(mStateLock);
-        sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
-        updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight);
+    Rect crop(sourceCrop);
+    if (sourceCrop.width() <= 0) {
+        crop.left = 0;
+        crop.right = parent->getCurrentState().active.w;
     }
 
-    // create a surface (because we're a producer, and we need to
-    // dequeue/queue a buffer)
-    sp<Surface> surface = new Surface(producer, false);
-
-    // Put the screenshot Surface into async mode so that
-    // Layer::headFenceHasSignaled will always return true and we'll latch the
-    // first buffer regardless of whether or not its acquire fence has
-    // signaled. This is needed to avoid a race condition in the rotation
-    // animation. See b/30209608
-    surface->setAsyncMode(true);
-
-    ANativeWindow* window = surface.get();
-
-    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
-    if (result != NO_ERROR) {
-        return result;
+    if (sourceCrop.height() <= 0) {
+        crop.top = 0;
+        crop.bottom = parent->getCurrentState().active.h;
     }
-    WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
 
-    ANativeWindowBuffer* buffer = nullptr;
-    result = getWindowBuffer(window, reqWidth, reqHeight,
-            hasWideColorDisplay && !mForceNativeColorMode,
-            getRenderEngine().usesWideColor(), &buffer);
-    if (result != NO_ERROR) {
-        return result;
-    }
+    int32_t reqWidth = crop.width() * frameScale;
+    int32_t reqHeight = crop.height() * frameScale;
+
+    LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight);
+
+    auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
+        parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+            if (!layer->isVisible()) {
+                return;
+            }
+            visitor(layer);
+        });
+    };
+    return captureScreenCommon(renderArea, traverseLayers, outBuffer, false);
+}
+
+status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
+                                             TraverseLayersFunction traverseLayers,
+                                             sp<GraphicBuffer>* outBuffer,
+                                             bool useIdentityTransform) {
+    ATRACE_CALL();
+
+    renderArea.updateDimensions();
+
+    const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+            GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+    *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
+                                   HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot");
 
     // This mutex protects syncFd and captureResult for communication of the return values from the
     // main thread back to this Binder thread
@@ -4413,10 +4407,8 @@
         int fd = -1;
         {
             Mutex::Autolock _l(mStateLock);
-            sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
-            result = captureScreenImplLocked(device, buffer, sourceCrop, reqWidth, reqHeight,
-                                             minLayerZ, maxLayerZ, useIdentityTransform,
-                                             rotationFlags, isLocalScreenshot, &fd);
+            result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
+                                             useIdentityTransform, &fd);
         }
 
         {
@@ -4427,7 +4419,7 @@
         }
     });
 
-    result = postMessageAsync(message);
+    status_t result = postMessageAsync(message);
     if (result == NO_ERROR) {
         captureCondition.wait(captureLock, [&]() { return captureResult; });
         while (*captureResult == EAGAIN) {
@@ -4442,153 +4434,96 @@
     }
 
     if (result == NO_ERROR) {
-        // queueBuffer takes ownership of syncFd
-        result = window->queueBuffer(window, buffer, syncFd);
+        sync_wait(syncFd, -1);
+        close(syncFd);
     }
 
     return result;
 }
 
-
-void SurfaceFlinger::renderScreenImplLocked(
-        const sp<const DisplayDevice>& hw,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
-{
+void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
+                                            TraverseLayersFunction traverseLayers, bool yswap,
+                                            bool useIdentityTransform) {
     ATRACE_CALL();
+
     RenderEngine& engine(getRenderEngine());
 
     // get screen geometry
-    const int32_t hw_w = hw->getWidth();
-    const int32_t hw_h = hw->getHeight();
-    const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
-                           static_cast<int32_t>(reqHeight) != hw_h;
+    const auto raWidth = renderArea.getWidth();
+    const auto raHeight = renderArea.getHeight();
+
+    const auto reqWidth = renderArea.getReqWidth();
+    const auto reqHeight = renderArea.getReqHeight();
+    Rect sourceCrop = renderArea.getSourceCrop();
+
+    const bool filtering = static_cast<int32_t>(reqWidth) != raWidth ||
+            static_cast<int32_t>(reqHeight) != raHeight;
 
     // if a default or invalid sourceCrop is passed in, set reasonable values
-    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
-            !sourceCrop.isValid()) {
+    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) {
         sourceCrop.setLeftTop(Point(0, 0));
-        sourceCrop.setRightBottom(Point(hw_w, hw_h));
+        sourceCrop.setRightBottom(Point(raWidth, raHeight));
     }
 
     // ensure that sourceCrop is inside screen
     if (sourceCrop.left < 0) {
         ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
     }
-    if (sourceCrop.right > hw_w) {
-        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
+    if (sourceCrop.right > raWidth) {
+        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
     }
     if (sourceCrop.top < 0) {
         ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
     }
-    if (sourceCrop.bottom > hw_h) {
-        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
+    if (sourceCrop.bottom > raHeight) {
+        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
     }
 
-#ifdef USE_HWC2
-     engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode);
-     engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode());
-#endif
+    engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode);
+    engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE
+                                              : renderArea.getActiveColorMode());
 
     // make sure to clear all GL error flags
     engine.checkErrors();
 
     // set-up our viewport
-    engine.setViewportAndProjection(
-        reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
+    engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap,
+                                    renderArea.getRotationFlags());
     engine.disableTexturing();
 
     // redraw the screen entirely...
     engine.clearWithColor(0, 0, 0, 1);
 
-    // We loop through the first level of layers without traversing,
-    // as we need to interpret min/max layer Z in the top level Z space.
-    for (const auto& layer : mDrawingState.layersSortedByZ) {
-        if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
-            continue;
-        }
-        const Layer::State& state(layer->getDrawingState());
-        if (state.z < minLayerZ || state.z > maxLayerZ) {
-            continue;
-        }
-        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
-            if (!layer->isVisible()) {
-                return;
-            }
-            if (filtering) layer->setFiltering(true);
-            layer->draw(hw, useIdentityTransform);
-            if (filtering) layer->setFiltering(false);
-        });
-    }
-
-    hw->setViewportAndProjection();
+    traverseLayers([&](Layer* layer) {
+        if (filtering) layer->setFiltering(true);
+        layer->draw(renderArea, useIdentityTransform);
+        if (filtering) layer->setFiltering(false);
+    });
 }
 
-// A simple RAII class that holds an EGLImage and destroys it either:
-//   a) When the destroy() method is called
-//   b) When the object goes out of scope
-class ImageHolder {
-public:
-    ImageHolder(EGLDisplay display, EGLImageKHR image) : mDisplay(display), mImage(image) {}
-    ~ImageHolder() { destroy(); }
-
-    void destroy() {
-        if (mImage != EGL_NO_IMAGE_KHR) {
-            eglDestroyImageKHR(mDisplay, mImage);
-            mImage = EGL_NO_IMAGE_KHR;
-        }
-    }
-
-private:
-    const EGLDisplay mDisplay;
-    EGLImageKHR mImage;
-};
-
-status_t SurfaceFlinger::captureScreenImplLocked(const sp<const DisplayDevice>& hw,
-                                                 ANativeWindowBuffer* buffer, Rect sourceCrop,
-                                                 uint32_t reqWidth, uint32_t reqHeight,
-                                                 int32_t minLayerZ, int32_t maxLayerZ,
+status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
+                                                 TraverseLayersFunction traverseLayers,
+                                                 ANativeWindowBuffer* buffer,
                                                  bool useIdentityTransform,
-                                                 Transform::orientation_flags rotation,
-                                                 bool isLocalScreenshot, int* outSyncFd) {
+                                                 int* outSyncFd) {
     ATRACE_CALL();
 
     bool secureLayerIsVisible = false;
-    for (const auto& layer : mDrawingState.layersSortedByZ) {
-        const Layer::State& state(layer->getDrawingState());
-        if (!layer->belongsToDisplay(hw->getLayerStack(), false) ||
-                (state.z < minLayerZ || state.z > maxLayerZ)) {
-            continue;
-        }
-        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
-            secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
-                    layer->isSecure());
-        });
-    }
 
-    if (!isLocalScreenshot && secureLayerIsVisible) {
+    traverseLayers([&](Layer* layer) {
+        secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
+    });
+
+    if (secureLayerIsVisible) {
         ALOGW("FB is protected: PERMISSION_DENIED");
         return PERMISSION_DENIED;
     }
 
-    int syncFd = -1;
-    // create an EGLImage from the buffer so we can later
-    // turn it into a texture
-    EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
-            EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
-    if (image == EGL_NO_IMAGE_KHR) {
-        return BAD_VALUE;
-    }
-
-    // This will automatically destroy the image if we return before calling its destroy method
-    ImageHolder imageHolder(mEGLDisplay, image);
-
     // this binds the given EGLImage as a framebuffer for the
     // duration of this scope.
-    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
-    if (imageBond.getStatus() != NO_ERROR) {
-        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+    RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+    if (bufferBond.getStatus() != NO_ERROR) {
+        ALOGE("got ANWB binding error while taking screenshot");
         return INVALID_OPERATION;
     }
 
@@ -4596,89 +4531,43 @@
     // via an FBO, which means we didn't have to create
     // an EGLSurface and therefore we're not
     // dependent on the context's EGLConfig.
-    renderScreenImplLocked(
-        hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
-        useIdentityTransform, rotation);
+    renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform);
 
-    // Attempt to create a sync khr object that can produce a sync point. If that
-    // isn't available, create a non-dupable sync object in the fallback path and
-    // wait on it directly.
-    EGLSyncKHR sync = EGL_NO_SYNC_KHR;
-    if (!DEBUG_SCREENSHOTS) {
-       sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
-       // native fence fd will not be populated until flush() is done.
-       getRenderEngine().flush();
-    }
-
-    if (sync != EGL_NO_SYNC_KHR) {
-        // get the sync fd
-        syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
-        if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-            ALOGW("captureScreen: failed to dup sync khr object");
-            syncFd = -1;
-        }
-        eglDestroySyncKHR(mEGLDisplay, sync);
-    } else {
-        // fallback path
-        sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
-        if (sync != EGL_NO_SYNC_KHR) {
-            EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
-                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
-            EGLint eglErr = eglGetError();
-            if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-                ALOGW("captureScreen: fence wait timed out");
-            } else {
-                ALOGW_IF(eglErr != EGL_SUCCESS,
-                        "captureScreen: error waiting on EGL fence: %#x", eglErr);
-            }
-            eglDestroySyncKHR(mEGLDisplay, sync);
-        } else {
-            ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
-        }
-    }
-    *outSyncFd = syncFd;
+    *outSyncFd = getRenderEngine().flush(DEBUG_SCREENSHOTS);
 
     if (DEBUG_SCREENSHOTS) {
+        const auto reqWidth = renderArea.getReqWidth();
+        const auto reqHeight = renderArea.getReqHeight();
+
         uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
         getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
-        checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
-                hw, minLayerZ, maxLayerZ);
+        checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, traverseLayers);
         delete [] pixels;
     }
 
-    // destroy our image
-    imageHolder.destroy();
-
     return NO_ERROR;
 }
 
 void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
-        const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) {
+                                     TraverseLayersFunction traverseLayers) {
     if (DEBUG_SCREENSHOTS) {
-        for (size_t y=0 ; y<h ; y++) {
-            uint32_t const * p = (uint32_t const *)vaddr + y*s;
-            for (size_t x=0 ; x<w ; x++) {
+        for (size_t y = 0; y < h; y++) {
+            uint32_t const* p = (uint32_t const*)vaddr + y * s;
+            for (size_t x = 0; x < w; x++) {
                 if (p[x] != 0xFF000000) return;
             }
         }
-        ALOGE("*** we just took a black screenshot ***\n"
-                "requested minz=%d, maxz=%d, layerStack=%d",
-                minLayerZ, maxLayerZ, hw->getLayerStack());
+        ALOGE("*** we just took a black screenshot ***");
 
         size_t i = 0;
-        for (const auto& layer : mDrawingState.layersSortedByZ) {
+        traverseLayers([&](Layer* layer) {
             const Layer::State& state(layer->getDrawingState());
-            if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ &&
-                    state.z <= maxLayerZ) {
-                layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
-                    ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
-                            layer->isVisible() ? '+' : '-',
-                            i, layer->getName().string(), layer->getLayerStack(), state.z,
-                            layer->isVisible(), state.flags, state.alpha);
-                    i++;
-                });
-            }
-        }
+            ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
+                  layer->isVisible() ? '+' : '-', i, layer->getName().string(),
+                  layer->getLayerStack(), state.z, layer->isVisible(), state.flags,
+                  static_cast<float>(state.color.a));
+            i++;
+        });
     }
 }
 
@@ -4692,6 +4581,29 @@
     layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
 }
 
+void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, int32_t minLayerZ,
+                                             int32_t maxLayerZ,
+                                             const LayerVector::Visitor& visitor) {
+    // We loop through the first level of layers without traversing,
+    // as we need to interpret min/max layer Z in the top level Z space.
+    for (const auto& layer : mDrawingState.layersSortedByZ) {
+        if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
+            continue;
+        }
+        const Layer::State& state(layer->getDrawingState());
+        // relative layers are traversed in Layer::traverseInZOrder
+        if (state.zOrderRelativeOf != nullptr || state.z < minLayerZ || state.z > maxLayerZ) {
+            continue;
+        }
+        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+            if (!layer->isVisible()) {
+                return;
+            }
+            visitor(layer);
+        });
+    }
+}
+
 }; // namespace android
 
 
@@ -4701,4 +4613,4 @@
 
 #if defined(__gl2_h_)
 #error "don't include gl2/gl2.h in this file"
-#endif
+#endif
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 231709d..974de94 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -21,8 +21,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <EGL/egl.h>
-
 /*
  * NOTE: Make sure this file doesn't include  anything from <gl/ > or <gl2/ >
  */
@@ -43,13 +41,15 @@
 #include <gui/FrameTimestamps.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+
 #include <gui/OccupancyTracker.h>
 
 #include <hardware/hwcomposer_defs.h>
 
-#include <system/graphics.h>
+#include <serviceutils/PriorityDumper.h>
 
-#include <private/gui/LayerState.h>
+#include <system/graphics.h>
 
 #include "Barrier.h"
 #include "DisplayDevice.h"
@@ -58,14 +58,11 @@
 #include "LayerVector.h"
 #include "MessageQueue.h"
 #include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
 #include "StartPropertySetThread.h"
 
-#ifdef USE_HWC2
 #include "DisplayHardware/HWC2.h"
 #include "DisplayHardware/HWComposer.h"
-#else
-#include "DisplayHardware/HWComposer_hwc1.h"
-#endif
 
 #include "Effects/Daltonizer.h"
 
@@ -75,6 +72,11 @@
 #include <string>
 #include <thread>
 #include <utility>
+#include "RenderArea.h"
+
+#include <layerproto/LayerProtoHeader.h>
+
+using namespace android::surfaceflinger;
 
 namespace android {
 
@@ -84,13 +86,15 @@
 class DisplayEventConnection;
 class EventThread;
 class Layer;
-class LayerDim;
+class ColorLayer;
 class Surface;
 class RenderEngine;
 class EventControlThread;
 class VSyncSource;
 class InjectVSyncSource;
 
+typedef std::function<void(const LayerVector::Visitor&)> TraverseLayersFunction;
+
 namespace dvr {
 class VrFlinger;
 } // namespace dvr
@@ -105,12 +109,9 @@
 };
 
 class SurfaceFlinger : public BnSurfaceComposer,
+                       public PriorityDumper,
                        private IBinder::DeathRecipient,
-#ifdef USE_HWC2
                        private HWC2::ComposerCallback
-#else
-                       private HWComposer::EventHandler
-#endif
 {
 public:
 
@@ -206,11 +207,7 @@
 
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
-#ifdef USE_HWC2
     void setVsyncEnabled(int disp, int enabled);
-#else
-    void eventControl(int disp, int event, int enabled);
-#endif
 
     // called on the main thread by MessageQueue when an internal message
     // is received
@@ -233,6 +230,7 @@
     friend class DisplayEventConnection;
     friend class EventThread;
     friend class Layer;
+    friend class BufferLayer;
     friend class MonitoredProducer;
 
     // This value is specified in number of frames.  Log frame stats at most
@@ -272,7 +270,7 @@
      */
     virtual status_t onTransact(uint32_t code, const Parcel& data,
         Parcel* reply, uint32_t flags);
-    virtual status_t dump(int fd, const Vector<String16>& args);
+    virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
 
     /* ------------------------------------------------------------------------
      * ISurfaceComposer interface
@@ -291,11 +289,12 @@
             std::vector<FrameEvent>* outSupported) const;
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
             ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
-    virtual status_t captureScreen(const sp<IBinder>& display,
-            const sp<IGraphicBufferProducer>& producer,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
+    virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                                   int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+                                   ISurfaceComposer::Rotation rotation);
+    virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+                                   const Rect& sourceCrop, float frameScale);
     virtual status_t getDisplayStats(const sp<IBinder>& display,
             DisplayStatInfo* stats);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
@@ -329,18 +328,12 @@
     /* ------------------------------------------------------------------------
      * HWC2::ComposerCallback / HWComposer::EventHandler interface
      */
-#ifdef USE_HWC2
     void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
                          int64_t timestamp) override;
     void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
                            HWC2::Connection connection,
                            bool primaryDisplay) override;
     void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
-#else
-    void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
-    void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
-    void onInvalidateReceived(HWComposer* composer) override;
-#endif
 
     /* ------------------------------------------------------------------------
      * Message handling
@@ -357,19 +350,12 @@
     // called on the main thread in response to setActiveConfig()
     void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
     // called on the main thread in response to setPowerMode()
-#ifdef USE_HWC2
     void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
                               bool stateLockHeld);
-#else
-    void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
-#endif
 
     // Called on the main thread in response to setActiveColorMode()
     void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
 
-    // Called on the main thread in response to enableVSyncInjections()
-    void enableVSyncInjectionsInternal(bool enable);
-
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
 
@@ -408,14 +394,14 @@
             uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
             sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
 
-    status_t createNormalLayer(const sp<Client>& client, const String8& name,
+    status_t createBufferLayer(const sp<Client>& client, const String8& name,
             uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
             sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
             sp<Layer>* outLayer);
 
-    status_t createDimLayer(const sp<Client>& client, const String8& name,
+    status_t createColorLayer(const sp<Client>& client, const String8& name,
             uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
-            sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+            sp<Layer>* outLayer);
 
     String8 getUniqueLayerName(const String8& name);
 
@@ -444,28 +430,17 @@
 
     void startBootAnim();
 
-    void renderScreenImplLocked(
-            const sp<const DisplayDevice>& hw,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation);
-
-#ifdef USE_HWC2
-    status_t captureScreenImplLocked(const sp<const DisplayDevice>& device,
-                                     ANativeWindowBuffer* buffer, Rect sourceCrop,
-                                     uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
-                                     int32_t maxLayerZ, bool useIdentityTransform,
-                                     Transform::orientation_flags rotation, bool isLocalScreenshot,
+    void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+                                bool yswap, bool useIdentityTransform);
+    status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+                                 sp<GraphicBuffer>* outBuffer,
+                                 bool useIdentityTransform);
+    status_t captureScreenImplLocked(const RenderArea& renderArea,
+                                     TraverseLayersFunction traverseLayers,
+                                     ANativeWindowBuffer* buffer, bool useIdentityTransform,
                                      int* outSyncFd);
-#else
-    status_t captureScreenImplLocked(
-            const sp<const DisplayDevice>& hw,
-            const sp<IGraphicBufferProducer>& producer,
-            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-            int32_t minLayerZ, int32_t maxLayerZ,
-            bool useIdentityTransform, Transform::orientation_flags rotation,
-            bool isLocalScreenshot);
-#endif
+    void traverseLayersInDisplay(const sp<const DisplayDevice>& display, int32_t minLayerZ,
+                                 int32_t maxLayerZ, const LayerVector::Visitor& visitor);
 
     sp<StartPropertySetThread> mStartPropertySetThread = nullptr;
 
@@ -530,10 +505,6 @@
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
 
-#ifndef USE_HWC2
-    int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
-#endif
-
     /* ------------------------------------------------------------------------
      * H/W composer
      */
@@ -567,11 +538,12 @@
     void setUpHWComposer();
     void doComposition();
     void doDebugFlashRegions();
+    void doTracing(const char* where);
     void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion);
 
     // compose surfaces for display hw. this fails if using GL and the surface
     // has been destroyed and is no longer valid.
-    bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice, const Region& dirty);
+    bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice);
 
     void postFramebuffer();
     void drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const;
@@ -595,6 +567,16 @@
     /* ------------------------------------------------------------------------
      * Debugging & dumpsys
      */
+public:
+    status_t dumpCritical(int fd, const Vector<String16>& /*args*/, bool asProto) {
+        return doDump(fd, Vector<String16>(), asProto);
+    }
+
+    status_t dumpAll(int fd, const Vector<String16>& args, bool asProto) {
+        return doDump(fd, args, asProto);
+    }
+
+private:
     void listLayersLocked(const Vector<String16>& args, size_t& index, String8& result) const;
     void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result) const;
     void clearStatsLocked(const Vector<String16>& args, size_t& index, String8& result);
@@ -602,8 +584,7 @@
     bool startDdmConnection();
     void appendSfConfigString(String8& result) const;
     void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
-            const sp<const DisplayDevice>& hw,
-            int32_t minLayerZ, int32_t maxLayerZ);
+                         TraverseLayersFunction traverseLayers);
 
     void logFrameStats();
 
@@ -615,12 +596,13 @@
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
     void dumpWideColorInfo(String8& result) const;
+    LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
     }
+    status_t doDump(int fd, const Vector<String16>& args, bool asProto);
 
-#ifdef USE_HWC2
     /* ------------------------------------------------------------------------
      * VrFlinger
      */
@@ -628,7 +610,6 @@
 
     // Check to see if we should handoff to vr flinger.
     void updateVrFlinger();
-#endif
 
     /* ------------------------------------------------------------------------
      * Attributes
@@ -673,12 +654,10 @@
     // acquiring mStateLock.
     std::unique_ptr<HWComposer> mHwc;
 
-#ifdef USE_HWC2
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
-#endif
 
     // constant members (no synchronization needed for access)
-    RenderEngine* mRenderEngine;
+    std::unique_ptr<RenderEngine> mRenderEngine;
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;
     sp<EventThread> mEventThread;
@@ -686,25 +665,17 @@
     sp<EventThread> mInjectorEventThread;
     sp<InjectVSyncSource> mVSyncInjector;
     sp<EventControlThread> mEventControlThread;
-    EGLContext mEGLContext;
-    EGLDisplay mEGLDisplay;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
     bool mVisibleRegionsDirty;
-#ifndef USE_HWC2
-    bool mHwWorkListDirty;
-#else
     bool mGeometryInvalid;
-#endif
     bool mAnimCompositionPending;
-#ifdef USE_HWC2
     std::vector<sp<Layer>> mLayersWithQueuedFrames;
     sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
     bool mHadClientComposition = false;
-#endif
     FenceTimeline mGlCompositionDoneTimeline;
     FenceTimeline mDisplayTimeline;
 
@@ -723,10 +694,9 @@
     nsecs_t mLastTransactionTime;
     bool mBootFinished;
     bool mForceFullDamage;
-#ifdef USE_HWC2
     bool mPropagateBackpressure = true;
-#endif
     SurfaceInterceptor mInterceptor;
+    SurfaceTracing mTracing;
     bool mUseHwcVirtualDisplays = false;
 
     // Restrict layers to use two buffers in their bufferqueues.
@@ -766,9 +736,6 @@
     bool mInjectVSyncs;
 
     Daltonizer mDaltonizer;
-#ifndef USE_HWC2
-    bool mDaltonize;
-#endif
 
     mat4 mPreviousColorMatrix;
     mat4 mColorMatrix;
@@ -810,7 +777,6 @@
     // either AID_GRAPHICS or AID_SYSTEM.
     status_t CheckTransactCodeCredentials(uint32_t code);
 
-#ifdef USE_HWC2
     std::unique_ptr<dvr::VrFlinger> mVrFlinger;
     std::atomic<bool> mVrFlingerRequestsDisplay;
     static bool useVrFlinger;
@@ -819,7 +785,6 @@
     // use to differentiate callbacks from different hardware composer
     // instances. Each hardware composer instance gets a different sequence id.
     int32_t mComposerSequenceId;
-#endif
 
     float mSaturation = 1.0f;
     bool mForceNativeColorMode = false;
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index abc8fde..e17bb58 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -89,11 +89,7 @@
     }
 
     // Release the previous buffer.
-#ifdef USE_HWC2
     err = updateAndReleaseLocked(item, &mPendingRelease);
-#else
-    err = updateAndReleaseLocked(item);
-#endif
     if (err != NO_ERROR) {
         return err;
     }
@@ -197,7 +193,6 @@
     return ConsumerBase::mPrevFinalReleaseFence;
 }
 
-#ifdef USE_HWC2
 void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence)
 {
     if (!mPendingRelease.isPending) {
@@ -230,7 +225,6 @@
     mPendingRelease = PendingRelease();
     return true;
 }
-#endif
 
 void SurfaceFlingerConsumer::setContentsChangedListener(
         const wp<ContentsChangedListener>& listener) {
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 1126233..53b4915 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -81,10 +81,8 @@
     nsecs_t computeExpectedPresent(const DispSync& dispSync);
 
     sp<Fence> getPrevFinalReleaseFence() const;
-#ifdef USE_HWC2
     virtual void setReleaseFence(const sp<Fence>& fence) override;
     bool releasePendingBuffer();
-#endif
 
     void onDisconnect() override;
     void addAndGetFrameTimestamps(
@@ -104,11 +102,9 @@
     // The portion of this surface that has changed since the previous frame
     Region mSurfaceDamage;
 
-#ifdef USE_HWC2
     // A release that is pending on the receipt of a new release fence from
     // presentDisplay
     PendingRelease mPendingRelease;
-#endif
 
     // The layer for this SurfaceFlingerConsumer
     const wp<Layer> mLayer;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
deleted file mode 100644
index 1d6fbaf..0000000
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ /dev/null
@@ -1,4117 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <math.h>
-#include <stdatomic.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <mutex>
-
-#include <EGL/egl.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/PermissionCache.h>
-
-#include <ui/DisplayInfo.h>
-#include <ui/DisplayStatInfo.h>
-
-#include <gui/BufferQueue.h>
-#include <gui/GuiConfig.h>
-#include <gui/IDisplayEventConnection.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-
-#include <ui/GraphicBufferAllocator.h>
-#include <ui/HdrCapabilities.h>
-#include <ui/PixelFormat.h>
-#include <ui/UiConfig.h>
-
-#include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-#include <utils/StopWatch.h>
-#include <utils/Timers.h>
-#include <utils/Trace.h>
-
-#include <private/android_filesystem_config.h>
-#include <private/gui/SyncFeatures.h>
-
-#include <set>
-
-#include "Client.h"
-#include "clz.h"
-#include "Colorizer.h"
-#include "DdmConnection.h"
-#include "DisplayDevice.h"
-#include "DispSync.h"
-#include "EventControlThread.h"
-#include "EventThread.h"
-#include "Layer.h"
-#include "LayerVector.h"
-#include "LayerDim.h"
-#include "MonitoredProducer.h"
-#include "SurfaceFlinger.h"
-
-#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/VirtualDisplaySurface.h"
-
-#include "Effects/Daltonizer.h"
-
-#include "RenderEngine/RenderEngine.h"
-#include <cutils/compiler.h>
-
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
-#define DISPLAY_COUNT       1
-
-/*
- * DEBUG_SCREENSHOTS: set to true to check that screenshots are not all
- * black pixels.
- */
-#define DEBUG_SCREENSHOTS   false
-
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-using namespace android::hardware::configstore;
-using namespace android::hardware::configstore::V1_0;
-
-const String16 sHardwareTest("android.permission.HARDWARE_TEST");
-const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
-const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sDump("android.permission.DUMP");
-
-// ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
-int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
-bool SurfaceFlinger::useContextPriority;
-int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
-bool SurfaceFlinger::useHwcForRgbToYuv;
-uint64_t SurfaceFlinger::maxVirtualDisplaySize;
-bool SurfaceFlinger::hasSyncFramework;
-int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
-
-SurfaceFlinger::SurfaceFlinger()
-    :   BnSurfaceComposer(),
-        mTransactionFlags(0),
-        mTransactionPending(false),
-        mAnimTransactionPending(false),
-        mLayersRemoved(false),
-        mLayersAdded(false),
-        mRepaintEverything(0),
-        mRenderEngine(NULL),
-        mBootTime(systemTime()),
-        mVisibleRegionsDirty(false),
-        mHwWorkListDirty(false),
-        mAnimCompositionPending(false),
-        mDebugRegion(0),
-        mDebugDDMS(0),
-        mDebugDisableHWC(0),
-        mDebugDisableTransformHint(0),
-        mDebugInSwapBuffers(0),
-        mLastSwapBufferTime(0),
-        mDebugInTransaction(0),
-        mLastTransactionTime(0),
-        mBootFinished(false),
-        mForceFullDamage(false),
-        mInterceptor(this),
-        mPrimaryDispSync("PrimaryDispSync"),
-        mPrimaryHWVsyncEnabled(false),
-        mHWVsyncAvailable(false),
-        mDaltonize(false),
-        mHasColorMatrix(false),
-        mHasPoweredOff(false),
-        mFrameBuckets(),
-        mTotalTime(0),
-        mLastSwapTime(0),
-        mNumLayers(0)
-{
-    ALOGI("SurfaceFlinger is starting");
-
-    vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
-
-    sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
-
-    maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
-
-    hasSyncFramework = getBool< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::hasSyncFramework>(true);
-
-    useContextPriority = getBool< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::useContextPriority>(false);
-
-    dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0);
-
-    useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
-
-    maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
-
-    mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset);
-
-    char value[PROPERTY_VALUE_MAX];
-
-    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
-    mGpuToCpuSupported = !atoi(value);
-
-    property_get("debug.sf.showupdates", value, "0");
-    mDebugRegion = atoi(value);
-
-    property_get("debug.sf.ddms", value, "0");
-    mDebugDDMS = atoi(value);
-    if (mDebugDDMS) {
-        if (!startDdmConnection()) {
-            // start failed, and DDMS debugging not enabled
-            mDebugDDMS = 0;
-        }
-    }
-    ALOGI_IF(mDebugRegion, "showupdates enabled");
-    ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
-
-    property_get("debug.sf.enable_hwc_vds", value, "0");
-    mUseHwcVirtualDisplays = atoi(value);
-    ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
-
-    property_get("ro.sf.disable_triple_buffer", value, "1");
-    mLayerTripleBufferingDisabled = atoi(value);
-    ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
-}
-
-void SurfaceFlinger::onFirstRef()
-{
-    mEventQueue.init(this);
-}
-
-SurfaceFlinger::~SurfaceFlinger()
-{
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(display);
-}
-
-void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
-{
-    // the window manager died on us. prepare its eulogy.
-
-    // restore initial conditions (default device unblank, etc)
-    initializeDisplays();
-
-    // restart the boot-animation
-    startBootAnim();
-}
-
-static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
-    status_t err = client->initCheck();
-    if (err == NO_ERROR) {
-        return client;
-    }
-    return nullptr;
-}
-
-sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
-    return initClient(new Client(this));
-}
-
-sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
-        const sp<IGraphicBufferProducer>& gbp) {
-    if (authenticateSurfaceTexture(gbp) == false) {
-        return nullptr;
-    }
-    const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
-    if (layer == nullptr) {
-        return nullptr;
-    }
-
-   return initClient(new Client(this, layer));
-}
-
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
-        bool secure)
-{
-    class DisplayToken : public BBinder {
-        sp<SurfaceFlinger> flinger;
-        virtual ~DisplayToken() {
-             // no more references, this display must be terminated
-             Mutex::Autolock _l(flinger->mStateLock);
-             flinger->mCurrentState.displays.removeItem(this);
-             flinger->setTransactionFlags(eDisplayTransactionNeeded);
-         }
-     public:
-        explicit DisplayToken(const sp<SurfaceFlinger>& flinger)
-            : flinger(flinger) {
-        }
-    };
-
-    sp<BBinder> token = new DisplayToken(this);
-
-    Mutex::Autolock _l(mStateLock);
-    DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
-    info.displayName = displayName;
-    mCurrentState.displays.add(token, info);
-    mInterceptor.saveDisplayCreation(info);
-    return token;
-}
-
-void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) {
-    Mutex::Autolock _l(mStateLock);
-
-    ssize_t idx = mCurrentState.displays.indexOfKey(display);
-    if (idx < 0) {
-        ALOGW("destroyDisplay: invalid display token");
-        return;
-    }
-
-    const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
-    if (!info.isVirtualDisplay()) {
-        ALOGE("destroyDisplay called for non-virtual display");
-        return;
-    }
-    mInterceptor.saveDisplayDeletion(info.displayId);
-    mCurrentState.displays.removeItemsAt(idx);
-    setTransactionFlags(eDisplayTransactionNeeded);
-}
-
-void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
-    ALOGW_IF(mBuiltinDisplays[type],
-            "Overwriting display token for display type %d", type);
-    mBuiltinDisplays[type] = new BBinder();
-    // All non-virtual displays are currently considered secure.
-    DisplayDeviceState info(type, true);
-    mCurrentState.displays.add(mBuiltinDisplays[type], info);
-    mInterceptor.saveDisplayCreation(info);
-}
-
-sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
-    if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
-        return NULL;
-    }
-    return mBuiltinDisplays[id];
-}
-
-void SurfaceFlinger::bootFinished()
-{
-    if (mStartPropertySetThread->join() != NO_ERROR) {
-        ALOGE("Join StartPropertySetThread failed!");
-    }
-    const nsecs_t now = systemTime();
-    const nsecs_t duration = now - mBootTime;
-    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-    mBootFinished = true;
-
-    // wait patiently for the window manager death
-    const String16 name("window");
-    sp<IBinder> window(defaultServiceManager()->getService(name));
-    if (window != 0) {
-        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
-    }
-
-    // stop boot animation
-    // formerly we would just kill the process, but we now ask it to exit so it
-    // can choose where to stop the animation.
-    property_set("service.bootanim.exit", "1");
-
-    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
-    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
-                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-}
-
-void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
-    class MessageDestroyGLTexture : public MessageBase {
-        RenderEngine& engine;
-        uint32_t texture;
-    public:
-        MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture)
-            : engine(engine), texture(texture) {
-        }
-        virtual bool handler() {
-            engine.deleteTextures(1, &texture);
-            return true;
-        }
-    };
-    postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
-}
-
-class DispSyncSource : public VSyncSource, private DispSync::Callback {
-public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
-        const char* name) :
-            mName(name),
-            mValue(0),
-            mTraceVsync(traceVsync),
-            mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
-            mVsyncEventLabel(String8::format("VSYNC-%s", name)),
-            mDispSync(dispSync),
-            mCallbackMutex(),
-            mCallback(),
-            mVsyncMutex(),
-            mPhaseOffset(phaseOffset),
-            mEnabled(false) {}
-
-    virtual ~DispSyncSource() {}
-
-    virtual void setVSyncEnabled(bool enable) {
-        Mutex::Autolock lock(mVsyncMutex);
-        if (enable) {
-            status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
-                    static_cast<DispSync::Callback*>(this));
-            if (err != NO_ERROR) {
-                ALOGE("error registering vsync callback: %s (%d)",
-                        strerror(-err), err);
-            }
-            //ATRACE_INT(mVsyncOnLabel.string(), 1);
-        } else {
-            status_t err = mDispSync->removeEventListener(
-                    static_cast<DispSync::Callback*>(this));
-            if (err != NO_ERROR) {
-                ALOGE("error unregistering vsync callback: %s (%d)",
-                        strerror(-err), err);
-            }
-            //ATRACE_INT(mVsyncOnLabel.string(), 0);
-        }
-        mEnabled = enable;
-    }
-
-    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
-        Mutex::Autolock lock(mCallbackMutex);
-        mCallback = callback;
-    }
-
-    virtual void setPhaseOffset(nsecs_t phaseOffset) {
-        Mutex::Autolock lock(mVsyncMutex);
-
-        // Normalize phaseOffset to [0, period)
-        auto period = mDispSync->getPeriod();
-        phaseOffset %= period;
-        if (phaseOffset < 0) {
-            // If we're here, then phaseOffset is in (-period, 0). After this
-            // operation, it will be in (0, period)
-            phaseOffset += period;
-        }
-        mPhaseOffset = phaseOffset;
-
-        // If we're not enabled, we don't need to mess with the listeners
-        if (!mEnabled) {
-            return;
-        }
-
-        // Remove the listener with the old offset
-        status_t err = mDispSync->removeEventListener(
-                static_cast<DispSync::Callback*>(this));
-        if (err != NO_ERROR) {
-            ALOGE("error unregistering vsync callback: %s (%d)",
-                    strerror(-err), err);
-        }
-
-        // Add a listener with the new offset
-        err = mDispSync->addEventListener(mName, mPhaseOffset,
-                static_cast<DispSync::Callback*>(this));
-        if (err != NO_ERROR) {
-            ALOGE("error registering vsync callback: %s (%d)",
-                    strerror(-err), err);
-        }
-    }
-
-private:
-    virtual void onDispSyncEvent(nsecs_t when) {
-        sp<VSyncSource::Callback> callback;
-        {
-            Mutex::Autolock lock(mCallbackMutex);
-            callback = mCallback;
-
-            if (mTraceVsync) {
-                mValue = (mValue + 1) % 2;
-                ATRACE_INT(mVsyncEventLabel.string(), mValue);
-            }
-        }
-
-        if (callback != NULL) {
-            callback->onVSyncEvent(when);
-        }
-    }
-
-    const char* const mName;
-
-    int mValue;
-
-    const bool mTraceVsync;
-    const String8 mVsyncOnLabel;
-    const String8 mVsyncEventLabel;
-
-    DispSync* mDispSync;
-
-    Mutex mCallbackMutex; // Protects the following
-    sp<VSyncSource::Callback> mCallback;
-
-    Mutex mVsyncMutex; // Protects the following
-    nsecs_t mPhaseOffset;
-    bool mEnabled;
-};
-
-class InjectVSyncSource : public VSyncSource {
-public:
-    InjectVSyncSource() {}
-
-    virtual ~InjectVSyncSource() {}
-
-    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
-        std::lock_guard<std::mutex> lock(mCallbackMutex);
-        mCallback = callback;
-    }
-
-    virtual void onInjectSyncEvent(nsecs_t when) {
-        std::lock_guard<std::mutex> lock(mCallbackMutex);
-        mCallback->onVSyncEvent(when);
-    }
-
-    virtual void setVSyncEnabled(bool) {}
-    virtual void setPhaseOffset(nsecs_t) {}
-
-private:
-    std::mutex mCallbackMutex; // Protects the following
-    sp<VSyncSource::Callback> mCallback;
-};
-
-// Do not call property_set on main thread which will be blocked by init
-// Use StartPropertySetThread instead.
-void SurfaceFlinger::init() {
-    ALOGI(  "SurfaceFlinger's main thread ready to run. "
-            "Initializing graphics H/W...");
-
-    Mutex::Autolock _l(mStateLock);
-
-    // initialize EGL for the default display
-    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglInitialize(mEGLDisplay, NULL, NULL);
-
-    // start the EventThread
-    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            vsyncPhaseOffsetNs, true, "app");
-    mEventThread = new EventThread(vsyncSrc, *this, false);
-    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            sfVsyncPhaseOffsetNs, true, "sf");
-    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
-    mEventQueue.setEventThread(mSFEventThread);
-
-    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
-    struct sched_param param = {0};
-    param.sched_priority = 2;
-    if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
-    }
-    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO for EventThread");
-    }
-
-    // Initialize the H/W composer object.  There may or may not be an
-    // actual hardware composer underneath.
-    mHwc.reset(new HWComposer(this,
-            *static_cast<HWComposer::EventHandler *>(this)));
-
-    // get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay,
-            mHwc->getVisualID(), 0);
-
-    // retrieve the EGL context that was selected/created
-    mEGLContext = mRenderEngine->getEGLContext();
-
-    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
-            "couldn't create EGLContext");
-
-    // initialize our non-virtual displays
-    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
-        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
-        // set-up the displays that are already connected
-        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
-            // All non-virtual displays are currently considered secure.
-            bool isSecure = true;
-            createBuiltinDisplayLocked(type);
-            wp<IBinder> token = mBuiltinDisplays[i];
-
-            sp<IGraphicBufferProducer> producer;
-            sp<IGraphicBufferConsumer> consumer;
-            BufferQueue::createBufferQueue(&producer, &consumer);
-
-            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
-                    consumer);
-            int32_t hwcId = allocateHwcDisplayId(type);
-            sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
-                    fbs, producer,
-                    mRenderEngine->getEGLConfig(), false);
-            if (i > DisplayDevice::DISPLAY_PRIMARY) {
-                // FIXME: currently we don't get blank/unblank requests
-                // for displays other than the main display, so we always
-                // assume a connected display is unblanked.
-                ALOGD("marking display %zu as acquired/unblanked", i);
-                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
-            }
-            mDisplays.add(token, hw);
-        }
-    }
-
-    // make the GLContext current so that we can create textures when creating Layers
-    // (which may happens before we render something)
-    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
-
-    mEventControlThread = new EventControlThread(this);
-    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
-
-    // set a fake vsync period if there is no HWComposer
-    if (mHwc->initCheck() != NO_ERROR) {
-        mPrimaryDispSync.setPeriod(16666667);
-    }
-
-    // initialize our drawing state
-    mDrawingState = mCurrentState;
-
-    // set initial conditions (e.g. unblank default device)
-    initializeDisplays();
-
-    mRenderEngine->primeCache();
-
-    // Inform native graphics APIs that the present timestamp is NOT supported:
-    mStartPropertySetThread = new StartPropertySetThread(false);
-    if (mStartPropertySetThread->Start() != NO_ERROR) {
-        ALOGE("Run StartPropertySetThread failed!");
-    }
-
-    ALOGV("Done initializing");
-}
-
-int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
-    return (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) ?
-            type : mHwc->allocateDisplayId();
-}
-
-void SurfaceFlinger::startBootAnim() {
-    // Start boot animation service by setting a property mailbox
-    // if property setting thread is already running, Start() will be just a NOP
-    mStartPropertySetThread->Start();
-    // Wait until property was set
-    if (mStartPropertySetThread->join() != NO_ERROR) {
-        ALOGE("Join StartPropertySetThread failed!");
-    }
-}
-
-size_t SurfaceFlinger::getMaxTextureSize() const {
-    return mRenderEngine->getMaxTextureSize();
-}
-
-size_t SurfaceFlinger::getMaxViewportDims() const {
-    return mRenderEngine->getMaxViewportDims();
-}
-
-// ----------------------------------------------------------------------------
-
-bool SurfaceFlinger::authenticateSurfaceTexture(
-        const sp<IGraphicBufferProducer>& bufferProducer) const {
-    Mutex::Autolock _l(mStateLock);
-    return authenticateSurfaceTextureLocked(bufferProducer);
-}
-
-bool SurfaceFlinger::authenticateSurfaceTextureLocked(
-        const sp<IGraphicBufferProducer>& bufferProducer) const {
-    sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
-    return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
-}
-
-status_t SurfaceFlinger::getSupportedFrameTimestamps(
-        std::vector<FrameEvent>* outSupported) const {
-    *outSupported = {
-        FrameEvent::REQUESTED_PRESENT,
-        FrameEvent::ACQUIRE,
-        FrameEvent::LATCH,
-        FrameEvent::FIRST_REFRESH_START,
-        FrameEvent::LAST_REFRESH_START,
-        FrameEvent::GPU_COMPOSITION_DONE,
-        FrameEvent::DEQUEUE_READY,
-        FrameEvent::RELEASE,
-    };
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
-        Vector<DisplayInfo>* configs) {
-    if ((configs == NULL) || (display.get() == NULL)) {
-        return BAD_VALUE;
-    }
-
-    int32_t type = getDisplayType(display);
-    if (type < 0) return type;
-
-    // TODO: Not sure if display density should handled by SF any longer
-    class Density {
-        static int getDensityFromProperty(char const* propName) {
-            char property[PROPERTY_VALUE_MAX];
-            int density = 0;
-            if (property_get(propName, property, NULL) > 0) {
-                density = atoi(property);
-            }
-            return density;
-        }
-    public:
-        static int getEmuDensity() {
-            return getDensityFromProperty("qemu.sf.lcd_density"); }
-        static int getBuildDensity()  {
-            return getDensityFromProperty("ro.sf.lcd_density"); }
-    };
-
-    configs->clear();
-
-    const Vector<HWComposer::DisplayConfig>& hwConfigs =
-            getHwComposer().getConfigs(type);
-    for (size_t c = 0; c < hwConfigs.size(); ++c) {
-        const HWComposer::DisplayConfig& hwConfig = hwConfigs[c];
-        DisplayInfo info = DisplayInfo();
-
-        float xdpi = hwConfig.xdpi;
-        float ydpi = hwConfig.ydpi;
-
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
-            // The density of the device is provided by a build property
-            float density = Density::getBuildDensity() / 160.0f;
-            if (density == 0) {
-                // the build doesn't provide a density -- this is wrong!
-                // use xdpi instead
-                ALOGE("ro.sf.lcd_density must be defined as a build property");
-                density = xdpi / 160.0f;
-            }
-            if (Density::getEmuDensity()) {
-                // if "qemu.sf.lcd_density" is specified, it overrides everything
-                xdpi = ydpi = density = Density::getEmuDensity();
-                density /= 160.0f;
-            }
-            info.density = density;
-
-            // TODO: this needs to go away (currently needed only by webkit)
-            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-            info.orientation = hw->getOrientation();
-        } else {
-            // TODO: where should this value come from?
-            static const int TV_DENSITY = 213;
-            info.density = TV_DENSITY / 160.0f;
-            info.orientation = 0;
-        }
-
-        info.w = hwConfig.width;
-        info.h = hwConfig.height;
-        info.xdpi = xdpi;
-        info.ydpi = ydpi;
-        info.fps = float(1e9 / hwConfig.refresh);
-        info.appVsyncOffset = vsyncPhaseOffsetNs;
-
-        // This is how far in advance a buffer must be queued for
-        // presentation at a given time.  If you want a buffer to appear
-        // on the screen at time N, you must submit the buffer before
-        // (N - presentationDeadline).
-        //
-        // Normally it's one full refresh period (to give SF a chance to
-        // latch the buffer), but this can be reduced by configuring a
-        // DispSync offset.  Any additional delays introduced by the hardware
-        // composer or panel must be accounted for here.
-        //
-        // We add an additional 1ms to allow for processing time and
-        // differences between the ideal and actual refresh rate.
-        info.presentationDeadline =
-                hwConfig.refresh - sfVsyncPhaseOffsetNs + 1000000;
-
-        // All non-virtual displays are currently considered secure.
-        info.secure = true;
-
-        configs->push_back(info);
-    }
-
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */,
-        DisplayStatInfo* stats) {
-    if (stats == NULL) {
-        return BAD_VALUE;
-    }
-
-    // FIXME for now we always return stats for the primary display
-    memset(stats, 0, sizeof(*stats));
-    stats->vsyncTime   = mPrimaryDispSync.computeNextRefresh(0);
-    stats->vsyncPeriod = mPrimaryDispSync.getPeriod();
-    return NO_ERROR;
-}
-
-int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
-    sp<const DisplayDevice> device(getDisplayDevice(display));
-    if (device != NULL) {
-        return device->getActiveConfig();
-    }
-    return BAD_VALUE;
-}
-
-void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) {
-    ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
-          this);
-    int32_t type = hw->getDisplayType();
-    int currentMode = hw->getActiveConfig();
-
-    if (mode == currentMode) {
-        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
-        return;
-    }
-
-    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        ALOGW("Trying to set config for virtual display");
-        return;
-    }
-
-    hw->setActiveConfig(mode);
-    getHwComposer().setActiveConfig(type, mode);
-}
-
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
-    class MessageSetActiveConfig: public MessageBase {
-        SurfaceFlinger& mFlinger;
-        sp<IBinder> mDisplay;
-        int mMode;
-    public:
-        MessageSetActiveConfig(SurfaceFlinger& flinger, const sp<IBinder>& disp,
-                               int mode) :
-            mFlinger(flinger), mDisplay(disp) { mMode = mode; }
-        virtual bool handler() {
-            Vector<DisplayInfo> configs;
-            mFlinger.getDisplayConfigs(mDisplay, &configs);
-            if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
-                ALOGE("Attempt to set active config = %d for display with %zu configs",
-                        mMode, configs.size());
-            }
-            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
-            if (hw == NULL) {
-                ALOGE("Attempt to set active config = %d for null display %p",
-                        mMode, mDisplay.get());
-            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to set active config = %d for virtual display",
-                        mMode);
-            } else {
-                mFlinger.setActiveConfigInternal(hw, mMode);
-            }
-            return true;
-        }
-    };
-    sp<MessageBase> msg = new MessageSetActiveConfig(*this, display, mode);
-    postMessageSync(msg);
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
-        Vector<android_color_mode_t>* outColorModes) {
-    if (outColorModes == nullptr || display.get() == nullptr) {
-        return BAD_VALUE;
-    }
-
-    int32_t type = getDisplayType(display);
-    if (type < 0) return type;
-
-    std::set<android_color_mode_t> colorModes;
-    for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) {
-        colorModes.insert(hwConfig.colorMode);
-    }
-
-    outColorModes->clear();
-    std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes));
-
-    return NO_ERROR;
-}
-
-android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
-    if (display.get() == nullptr) return static_cast<android_color_mode_t>(BAD_VALUE);
-
-    int32_t type = getDisplayType(display);
-    if (type < 0) return static_cast<android_color_mode_t>(type);
-
-    return getHwComposer().getColorMode(type);
-}
-
-status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
-        android_color_mode_t colorMode) {
-    if (display.get() == nullptr || colorMode < 0) {
-        return BAD_VALUE;
-    }
-
-    int32_t type = getDisplayType(display);
-    if (type < 0) return type;
-    const Vector<HWComposer::DisplayConfig>& hwConfigs = getHwComposer().getConfigs(type);
-    HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)];
-    desiredConfig.colorMode = colorMode;
-    for (size_t c = 0; c < hwConfigs.size(); ++c) {
-        const HWComposer::DisplayConfig config = hwConfigs[c];
-        if (config == desiredConfig) {
-            return setActiveConfig(display, c);
-        }
-    }
-    return BAD_VALUE;
-}
-
-status_t SurfaceFlinger::clearAnimationFrameStats() {
-    Mutex::Autolock _l(mStateLock);
-    mAnimFrameTracker.clearStats();
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const {
-    Mutex::Autolock _l(mStateLock);
-    mAnimFrameTracker.getStats(outStats);
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& /*display*/,
-        HdrCapabilities* outCapabilities) const {
-    // HWC1 does not provide HDR capabilities
-    *outCapabilities = HdrCapabilities();
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
-    if (enable == mInjectVSyncs) {
-        return NO_ERROR;
-    }
-
-    if (enable) {
-        mInjectVSyncs = enable;
-        ALOGV("VSync Injections enabled");
-        if (mVSyncInjector.get() == nullptr) {
-            mVSyncInjector = new InjectVSyncSource();
-            mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
-        }
-        mEventQueue.setEventThread(mInjectorEventThread);
-    } else {
-        mInjectVSyncs = enable;
-        ALOGV("VSync Injections disabled");
-        mEventQueue.setEventThread(mSFEventThread);
-        mVSyncInjector.clear();
-    }
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::injectVSync(nsecs_t when) {
-    if (!mInjectVSyncs) {
-        ALOGE("VSync Injections not enabled");
-        return BAD_VALUE;
-    }
-    if (mInjectVSyncs && mInjectorEventThread.get() != nullptr) {
-        ALOGV("Injecting VSync inside SurfaceFlinger");
-        mVSyncInjector->onInjectSyncEvent(when);
-    }
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    const int uid = ipc->getCallingUid();
-    if ((uid != AID_SHELL) &&
-            !PermissionCache::checkPermission(sDump, pid, uid)) {
-        ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
-        return PERMISSION_DENIED;
-    }
-
-    // Try to acquire a lock for 1s, fail gracefully
-    status_t err = mStateLock.timedLock(s2ns(1));
-    bool locked = (err == NO_ERROR);
-    if (!locked) {
-        ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err);
-        return TIMED_OUT;
-    }
-
-    outLayers->clear();
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-            outLayers->push_back(layer->getLayerDebugInfo());
-        });
-
-    mStateLock.unlock();
-
-    return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
-        ISurfaceComposer::VsyncSource vsyncSource) {
-    if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-        return mSFEventThread->createEventConnection();
-    } else {
-        return mEventThread->createEventConnection();
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-void SurfaceFlinger::waitForEvent() {
-    mEventQueue.waitMessage();
-}
-
-void SurfaceFlinger::signalTransaction() {
-    mEventQueue.invalidate();
-}
-
-void SurfaceFlinger::signalLayerUpdate() {
-    mEventQueue.invalidate();
-}
-
-void SurfaceFlinger::signalRefresh() {
-    mEventQueue.refresh();
-}
-
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
-        nsecs_t reltime, uint32_t /* flags */) {
-    return mEventQueue.postMessage(msg, reltime);
-}
-
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
-        nsecs_t reltime, uint32_t /* flags */) {
-    status_t res = mEventQueue.postMessage(msg, reltime);
-    if (res == NO_ERROR) {
-        msg->wait();
-    }
-    return res;
-}
-
-void SurfaceFlinger::run() {
-    do {
-        waitForEvent();
-    } while (true);
-}
-
-void SurfaceFlinger::enableHardwareVsync() {
-    Mutex::Autolock _l(mHWVsyncLock);
-    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
-        mPrimaryDispSync.beginResync();
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
-        mEventControlThread->setVsyncEnabled(true);
-        mPrimaryHWVsyncEnabled = true;
-    }
-}
-
-void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
-    Mutex::Autolock _l(mHWVsyncLock);
-
-    if (makeAvailable) {
-        mHWVsyncAvailable = true;
-    } else if (!mHWVsyncAvailable) {
-        // Hardware vsync is not currently available, so abort the resync
-        // attempt for now
-        return;
-    }
-
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-
-    mPrimaryDispSync.reset();
-    mPrimaryDispSync.setPeriod(period);
-
-    if (!mPrimaryHWVsyncEnabled) {
-        mPrimaryDispSync.beginResync();
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
-        mEventControlThread->setVsyncEnabled(true);
-        mPrimaryHWVsyncEnabled = true;
-    }
-}
-
-void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
-    Mutex::Autolock _l(mHWVsyncLock);
-    if (mPrimaryHWVsyncEnabled) {
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
-        mEventControlThread->setVsyncEnabled(false);
-        mPrimaryDispSync.endResync();
-        mPrimaryHWVsyncEnabled = false;
-    }
-    if (makeUnavailable) {
-        mHWVsyncAvailable = false;
-    }
-}
-
-void SurfaceFlinger::resyncWithRateLimit() {
-    static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
-    if (systemTime() - mLastSwapTime > kIgnoreDelay) {
-        resyncToHardwareVsync(false);
-    }
-}
-
-void SurfaceFlinger::onVSyncReceived(HWComposer* /*composer*/, int type,
-                                     nsecs_t timestamp) {
-    bool needsHwVsync = false;
-
-    { // Scope for the lock
-        Mutex::Autolock _l(mHWVsyncLock);
-        if (type == 0 && mPrimaryHWVsyncEnabled) {
-            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
-        }
-    }
-
-    if (needsHwVsync) {
-        enableHardwareVsync();
-    } else {
-        disableHardwareVsync(false);
-    }
-}
-
-void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
-    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
-    *compositorTiming = mCompositorTiming;
-}
-
-void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
-    if (mEventThread == NULL) {
-        // This is a temporary workaround for b/7145521.  A non-null pointer
-        // does not mean EventThread has finished initializing, so this
-        // is not a correct fix.
-        ALOGW("WARNING: EventThread not started, ignoring hotplug");
-        return;
-    }
-
-    if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        Mutex::Autolock _l(mStateLock);
-        if (connected) {
-            createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
-        } else {
-            mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
-            mBuiltinDisplays[type].clear();
-        }
-        setTransactionFlags(eDisplayTransactionNeeded);
-
-        // Defer EventThread notification until SF has updated mDisplays.
-    }
-}
-
-void SurfaceFlinger::onInvalidateReceived(HWComposer* /*composer*/) {
-    repaintEverything();
-}
-
-void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
-    ATRACE_CALL();
-    getHwComposer().eventControl(disp, event, enabled);
-}
-
-void SurfaceFlinger::onMessageReceived(int32_t what) {
-    ATRACE_CALL();
-    switch (what) {
-        case MessageQueue::INVALIDATE: {
-            bool refreshNeeded = handleMessageTransaction();
-            refreshNeeded |= handleMessageInvalidate();
-            refreshNeeded |= mRepaintEverything;
-            if (refreshNeeded) {
-                // Signal a refresh if a transaction modified the window state,
-                // a new buffer was latched, or if HWC has requested a full
-                // repaint
-                signalRefresh();
-            }
-            break;
-        }
-        case MessageQueue::REFRESH: {
-            handleMessageRefresh();
-            break;
-        }
-    }
-}
-
-bool SurfaceFlinger::handleMessageTransaction() {
-    uint32_t transactionFlags = peekTransactionFlags();
-    if (transactionFlags) {
-        handleTransaction(transactionFlags);
-        return true;
-    }
-    return false;
-}
-
-bool SurfaceFlinger::handleMessageInvalidate() {
-    ATRACE_CALL();
-    return handlePageFlip();
-}
-
-void SurfaceFlinger::handleMessageRefresh() {
-    ATRACE_CALL();
-
-    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    preComposition(refreshStartTime);
-    rebuildLayerStacks();
-    setUpHWComposer();
-    doDebugFlashRegions();
-    doComposition();
-    postComposition(refreshStartTime);
-}
-
-void SurfaceFlinger::doDebugFlashRegions()
-{
-    // is debugging enabled
-    if (CC_LIKELY(!mDebugRegion))
-        return;
-
-    const bool repaintEverything = mRepaintEverything;
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->isDisplayOn()) {
-            // transform the dirty region into this screen's coordinate space
-            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
-            if (!dirtyRegion.isEmpty()) {
-                // redraw the whole screen
-                doComposeSurfaces(hw, Region(hw->bounds()));
-
-                // and draw the dirty region
-                const int32_t height = hw->getHeight();
-                RenderEngine& engine(getRenderEngine());
-                engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
-
-                hw->compositionComplete();
-                hw->swapBuffers(getHwComposer());
-            }
-        }
-    }
-
-    postFramebuffer();
-
-    if (mDebugRegion > 1) {
-        usleep(mDebugRegion * 1000);
-    }
-
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        status_t err = hwc.prepare();
-        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-    }
-}
-
-void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
-{
-    bool needExtraInvalidate = false;
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
-        if (layer->onPreComposition(refreshStartTime)) {
-            needExtraInvalidate = true;
-        }
-    });
-
-    if (needExtraInvalidate) {
-        signalLayerUpdate();
-    }
-}
-
-void SurfaceFlinger::updateCompositorTiming(
-        nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
-        std::shared_ptr<FenceTime>& presentFenceTime) {
-    // Update queue of past composite+present times and determine the
-    // most recently known composite to present latency.
-    mCompositePresentTimes.push({compositeTime, presentFenceTime});
-    nsecs_t compositeToPresentLatency = -1;
-    while (!mCompositePresentTimes.empty()) {
-        CompositePresentTime& cpt = mCompositePresentTimes.front();
-        // Cached values should have been updated before calling this method,
-        // which helps avoid duplicate syscalls.
-        nsecs_t displayTime = cpt.display->getCachedSignalTime();
-        if (displayTime == Fence::SIGNAL_TIME_PENDING) {
-            break;
-        }
-        compositeToPresentLatency = displayTime - cpt.composite;
-        mCompositePresentTimes.pop();
-    }
-
-    // Don't let mCompositePresentTimes grow unbounded, just in case.
-    while (mCompositePresentTimes.size() > 16) {
-        mCompositePresentTimes.pop();
-    }
-
-    setCompositorTimingSnapped(
-            vsyncPhase, vsyncInterval, compositeToPresentLatency);
-}
-
-void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
-        nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
-    // Integer division and modulo round toward 0 not -inf, so we need to
-    // treat negative and positive offsets differently.
-    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
-            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
-            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
-
-    // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
-    if (idealLatency <= 0) {
-        idealLatency = vsyncInterval;
-    }
-
-    // Snap the latency to a value that removes scheduling jitter from the
-    // composition and present times, which often have >1ms of jitter.
-    // Reducing jitter is important if an app attempts to extrapolate
-    // something (such as user input) to an accurate diasplay time.
-    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
-    // with (presentLatency % interval).
-    nsecs_t bias = vsyncInterval / 2;
-    int64_t extraVsyncs =
-            (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
-    nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
-            idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
-
-    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
-    mCompositorTiming.deadline = vsyncPhase - idealLatency;
-    mCompositorTiming.interval = vsyncInterval;
-    mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
-}
-
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
-{
-    const HWComposer& hwc = getHwComposer();
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-
-    mGlCompositionDoneTimeline.updateSignalTimes();
-    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
-    if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
-        glCompositionDoneFenceTime =
-                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
-        mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
-    } else {
-        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
-    }
-
-    mDisplayTimeline.updateSignalTimes();
-    sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
-    auto retireFenceTime = std::make_shared<FenceTime>(retireFence);
-    mDisplayTimeline.push(retireFenceTime);
-
-    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
-    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
-
-    // We use the refreshStartTime which might be sampled a little later than
-    // when we started doing work for this frame, but that should be okay
-    // since updateCompositorTiming has snapping logic.
-    updateCompositorTiming(
-        vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
-    CompositorTiming compositorTiming;
-    {
-        std::lock_guard<std::mutex> lock(mCompositorTimingLock);
-        compositorTiming = mCompositorTiming;
-    }
-
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
-        // TODO(brianderson): The retire fence is incorrectly passed in as the
-        // present fence. Fix this if this file lives on.
-        bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
-                retireFenceTime, compositorTiming);
-        if (frameLatched) {
-            recordBufferingStats(layer->getName().string(),
-                    layer->getOccupancyHistory(false));
-        }
-    });
-
-    if (retireFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(retireFenceTime)) {
-            enableHardwareVsync();
-        } else {
-            disableHardwareVsync(false);
-        }
-    }
-
-    if (!hasSyncFramework) {
-        if (hw->isDisplayOn()) {
-            enableHardwareVsync();
-        }
-    }
-
-    if (mAnimCompositionPending) {
-        mAnimCompositionPending = false;
-
-        if (retireFenceTime->isValid()) {
-            mAnimFrameTracker.setActualPresentFence(std::move(retireFenceTime));
-        } else {
-            // The HWC doesn't support present fences, so use the refresh
-            // timestamp instead.
-            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
-            mAnimFrameTracker.setActualPresentTime(presentTime);
-        }
-        mAnimFrameTracker.advanceFrame();
-    }
-
-    if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
-        return;
-    }
-
-    nsecs_t currentTime = systemTime();
-    if (mHasPoweredOff) {
-        mHasPoweredOff = false;
-    } else {
-        nsecs_t period = mPrimaryDispSync.getPeriod();
-        nsecs_t elapsedTime = currentTime - mLastSwapTime;
-        size_t numPeriods = static_cast<size_t>(elapsedTime / period);
-        if (numPeriods < NUM_BUCKETS - 1) {
-            mFrameBuckets[numPeriods] += elapsedTime;
-        } else {
-            mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
-        }
-        mTotalTime += elapsedTime;
-    }
-    mLastSwapTime = currentTime;
-}
-
-void SurfaceFlinger::rebuildLayerStacks() {
-    // rebuild the visible layer list per screen
-    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
-        ATRACE_CALL();
-        mVisibleRegionsDirty = false;
-        invalidateHwcGeometry();
-
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            Region opaqueRegion;
-            Region dirtyRegion;
-            Vector< sp<Layer> > layersSortedByZ;
-            const sp<DisplayDevice>& hw(mDisplays[dpy]);
-            const Transform& tr(hw->getTransform());
-            const Rect bounds(hw->getBounds());
-            if (hw->isDisplayOn()) {
-                computeVisibleRegions(hw, dirtyRegion, opaqueRegion);
-
-                mDrawingState.traverseInZOrder([&](Layer* layer) {
-                    if (layer->getLayerStack() == hw->getLayerStack()) {
-                        Region drawRegion(tr.transform(
-                                layer->visibleNonTransparentRegion));
-                        drawRegion.andSelf(bounds);
-                        if (!drawRegion.isEmpty()) {
-                            layersSortedByZ.add(layer);
-                        }
-                    }
-                });
-            }
-            hw->setVisibleLayersSortedByZ(layersSortedByZ);
-            hw->undefinedRegion.set(bounds);
-            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
-            hw->dirtyRegion.orSelf(dirtyRegion);
-        }
-    }
-}
-
-void SurfaceFlinger::setUpHWComposer() {
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
-        bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
-        bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
-
-        // If nothing has changed (!dirty), don't recompose.
-        // If something changed, but we don't currently have any visible layers,
-        //   and didn't when we last did a composition, then skip it this time.
-        // The second rule does two things:
-        // - When all layers are removed from a display, we'll emit one black
-        //   frame, then nothing more until we get new layers.
-        // - When a display is created with a private layer stack, we won't
-        //   emit any black frames until a layer is added to the layer stack.
-        bool mustRecompose = dirty && !(empty && wasEmpty);
-
-        ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
-                "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
-                mustRecompose ? "doing" : "skipping",
-                dirty ? "+" : "-",
-                empty ? "+" : "-",
-                wasEmpty ? "+" : "-");
-
-        mDisplays[dpy]->beginFrame(mustRecompose);
-
-        if (mustRecompose) {
-            mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
-        }
-    }
-
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        // build the h/w work list
-        if (CC_UNLIKELY(mHwWorkListDirty)) {
-            mHwWorkListDirty = false;
-            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-                sp<const DisplayDevice> hw(mDisplays[dpy]);
-                const int32_t id = hw->getHwcDisplayId();
-                if (id >= 0) {
-                    const Vector< sp<Layer> >& currentLayers(
-                        hw->getVisibleLayersSortedByZ());
-                    const size_t count = currentLayers.size();
-                    if (hwc.createWorkList(id, count) == NO_ERROR) {
-                        HWComposer::LayerListIterator cur = hwc.begin(id);
-                        const HWComposer::LayerListIterator end = hwc.end(id);
-                        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                            const sp<Layer>& layer(currentLayers[i]);
-                            layer->setGeometry(hw, *cur);
-                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
-                                cur->setSkip(true);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // set the per-frame data
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            const int32_t id = hw->getHwcDisplayId();
-            if (id >= 0) {
-                const Vector< sp<Layer> >& currentLayers(
-                    hw->getVisibleLayersSortedByZ());
-                const size_t count = currentLayers.size();
-                HWComposer::LayerListIterator cur = hwc.begin(id);
-                const HWComposer::LayerListIterator end = hwc.end(id);
-                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                    /*
-                     * update the per-frame h/w composer data for each layer
-                     * and build the transparent region of the FB
-                     */
-                    const sp<Layer>& layer(currentLayers[i]);
-                    layer->setPerFrameData(hw, *cur);
-                }
-            }
-        }
-
-        // If possible, attempt to use the cursor overlay on each display.
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            const int32_t id = hw->getHwcDisplayId();
-            if (id >= 0) {
-                const Vector< sp<Layer> >& currentLayers(
-                    hw->getVisibleLayersSortedByZ());
-                const size_t count = currentLayers.size();
-                HWComposer::LayerListIterator cur = hwc.begin(id);
-                const HWComposer::LayerListIterator end = hwc.end(id);
-                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                    const sp<Layer>& layer(currentLayers[i]);
-                    if (layer->isPotentialCursor()) {
-                        cur->setIsCursorLayerHint();
-                        break;
-                    }
-                }
-            }
-        }
-
-        status_t err = hwc.prepare();
-        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            hw->prepareFrame(hwc);
-        }
-    }
-}
-
-void SurfaceFlinger::doComposition() {
-    ATRACE_CALL();
-    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->isDisplayOn()) {
-            // transform the dirty region into this screen's coordinate space
-            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
-
-            // repaint the framebuffer (if needed)
-            doDisplayComposition(hw, dirtyRegion);
-
-            hw->dirtyRegion.clear();
-            hw->flip(hw->swapRegion);
-            hw->swapRegion.clear();
-        }
-        // inform the h/w that we're done compositing
-        hw->compositionComplete();
-    }
-    postFramebuffer();
-}
-
-void SurfaceFlinger::postFramebuffer()
-{
-    ATRACE_CALL();
-
-    const nsecs_t now = systemTime();
-    mDebugInSwapBuffers = now;
-
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        if (!hwc.supportsFramebufferTarget()) {
-            // EGL spec says:
-            //   "surface must be bound to the calling thread's current context,
-            //    for the current rendering API."
-            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
-        }
-        hwc.commit();
-    }
-
-    // make the default display current because the VirtualDisplayDevice code cannot
-    // deal with dequeueBuffer() being called outside of the composition loop; however
-    // the code below can call glFlush() which is allowed (and does in some case) call
-    // dequeueBuffer().
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
-
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        sp<const DisplayDevice> hw(mDisplays[dpy]);
-        const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
-        hw->onSwapBuffersCompleted(hwc);
-        const size_t count = currentLayers.size();
-        int32_t id = hw->getHwcDisplayId();
-        if (id >=0 && hwc.initCheck() == NO_ERROR) {
-            HWComposer::LayerListIterator cur = hwc.begin(id);
-            const HWComposer::LayerListIterator end = hwc.end(id);
-            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
-                currentLayers[i]->onLayerDisplayed(hw, &*cur);
-            }
-        } else {
-            for (size_t i = 0; i < count; i++) {
-                currentLayers[i]->onLayerDisplayed(hw, NULL);
-            }
-        }
-    }
-
-    mLastSwapBufferTime = systemTime() - now;
-    mDebugInSwapBuffers = 0;
-
-    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
-    if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
-        logFrameStats();
-    }
-}
-
-void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
-{
-    ATRACE_CALL();
-
-    // here we keep a copy of the drawing state (that is the state that's
-    // going to be overwritten by handleTransactionLocked()) outside of
-    // mStateLock so that the side-effects of the State assignment
-    // don't happen with mStateLock held (which can cause deadlocks).
-    State drawingState(mDrawingState);
-
-    Mutex::Autolock _l(mStateLock);
-    const nsecs_t now = systemTime();
-    mDebugInTransaction = now;
-
-    // Here we're guaranteed that some transaction flags are set
-    // so we can call handleTransactionLocked() unconditionally.
-    // We call getTransactionFlags(), which will also clear the flags,
-    // with mStateLock held to guarantee that mCurrentState won't change
-    // until the transaction is committed.
-
-    transactionFlags = getTransactionFlags(eTransactionMask);
-    handleTransactionLocked(transactionFlags);
-
-    mLastTransactionTime = systemTime() - now;
-    mDebugInTransaction = 0;
-    invalidateHwcGeometry();
-    // here the transaction has been committed
-}
-
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
-{
-    // Notify all layers of available frames
-    mCurrentState.traverseInZOrder([](Layer* layer) {
-        layer->notifyAvailableFrames();
-    });
-
-    /*
-     * Traversal of the children
-     * (perform the transaction for each of them if needed)
-     */
-
-    if (transactionFlags & eTraversalNeeded) {
-        mCurrentState.traverseInZOrder([&](Layer* layer) {
-            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
-            if (!trFlags) return;
-
-            const uint32_t flags = layer->doTransaction(0);
-            if (flags & Layer::eVisibleRegion)
-                mVisibleRegionsDirty = true;
-        });
-    }
-
-    /*
-     * Perform display own transactions if needed
-     */
-
-    if (transactionFlags & eDisplayTransactionNeeded) {
-        // here we take advantage of Vector's copy-on-write semantics to
-        // improve performance by skipping the transaction entirely when
-        // know that the lists are identical
-        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
-        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
-        if (!curr.isIdenticalTo(draw)) {
-            mVisibleRegionsDirty = true;
-            const size_t cc = curr.size();
-                  size_t dc = draw.size();
-
-            // find the displays that were removed
-            // (ie: in drawing state but not in current state)
-            // also handle displays that changed
-            // (ie: displays that are in both lists)
-            for (size_t i=0 ; i<dc ; i++) {
-                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
-                if (j < 0) {
-                    // in drawing state but not in current state
-                    if (!draw[i].isMainDisplay()) {
-                        // Call makeCurrent() on the primary display so we can
-                        // be sure that nothing associated with this display
-                        // is current.
-                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
-                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
-                        sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
-                        if (hw != NULL)
-                            hw->disconnect(getHwComposer());
-                        if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
-                            mEventThread->onHotplugReceived(draw[i].type, false);
-                        mDisplays.removeItem(draw.keyAt(i));
-                    } else {
-                        ALOGW("trying to remove the main display");
-                    }
-                } else {
-                    // this display is in both lists. see if something changed.
-                    const DisplayDeviceState& state(curr[j]);
-                    const wp<IBinder>& display(curr.keyAt(j));
-                    const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
-                    const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
-                    if (state_binder != draw_binder) {
-                        // changing the surface is like destroying and
-                        // recreating the DisplayDevice, so we just remove it
-                        // from the drawing state, so that it get re-added
-                        // below.
-                        sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
-                        if (hw != NULL)
-                            hw->disconnect(getHwComposer());
-                        mDisplays.removeItem(display);
-                        mDrawingState.displays.removeItemsAt(i);
-                        dc--; i--;
-                        // at this point we must loop to the next item
-                        continue;
-                    }
-
-                    const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
-                    if (disp != NULL) {
-                        if (state.layerStack != draw[i].layerStack) {
-                            disp->setLayerStack(state.layerStack);
-                        }
-                        if ((state.orientation != draw[i].orientation)
-                                || (state.viewport != draw[i].viewport)
-                                || (state.frame != draw[i].frame))
-                        {
-                            disp->setProjection(state.orientation,
-                                    state.viewport, state.frame);
-                        }
-                        if (state.width != draw[i].width || state.height != draw[i].height) {
-                            disp->setDisplaySize(state.width, state.height);
-                        }
-                    }
-                }
-            }
-
-            // find displays that were added
-            // (ie: in current state but not in drawing state)
-            for (size_t i=0 ; i<cc ; i++) {
-                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
-                    const DisplayDeviceState& state(curr[i]);
-
-                    sp<DisplaySurface> dispSurface;
-                    sp<IGraphicBufferProducer> producer;
-                    sp<IGraphicBufferProducer> bqProducer;
-                    sp<IGraphicBufferConsumer> bqConsumer;
-                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
-
-                    int32_t hwcDisplayId = -1;
-                    if (state.isVirtualDisplay()) {
-                        // Virtual displays without a surface are dormant:
-                        // they have external state (layer stack, projection,
-                        // etc.) but no internal state (i.e. a DisplayDevice).
-                        if (state.surface != NULL) {
-
-                            int width = 0;
-                            int status = state.surface->query(
-                                    NATIVE_WINDOW_WIDTH, &width);
-                            ALOGE_IF(status != NO_ERROR,
-                                    "Unable to query width (%d)", status);
-                            int height = 0;
-                            status = state.surface->query(
-                                    NATIVE_WINDOW_HEIGHT, &height);
-                            ALOGE_IF(status != NO_ERROR,
-                                    "Unable to query height (%d)", status);
-                            if (mUseHwcVirtualDisplays &&
-                                    (SurfaceFlinger::maxVirtualDisplaySize == 0 ||
-                                    (width <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize) &&
-                                     height <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize)))) {
-                                hwcDisplayId = allocateHwcDisplayId(state.type);
-                            }
-
-                            sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
-                                    *mHwc, hwcDisplayId, state.surface,
-                                    bqProducer, bqConsumer, state.displayName);
-
-                            dispSurface = vds;
-                            producer = vds;
-                        }
-                    } else {
-                        ALOGE_IF(state.surface!=NULL,
-                                "adding a supported display, but rendering "
-                                "surface is provided (%p), ignoring it",
-                                state.surface.get());
-                        hwcDisplayId = allocateHwcDisplayId(state.type);
-                        // for supported (by hwc) displays we provide our
-                        // own rendering surface
-                        dispSurface = new FramebufferSurface(*mHwc, state.type,
-                                bqConsumer);
-                        producer = bqProducer;
-                    }
-
-                    const wp<IBinder>& display(curr.keyAt(i));
-                    if (dispSurface != NULL) {
-                        sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, hwcDisplayId,
-                                mHwc->getFormat(hwcDisplayId), state.isSecure,
-                                display, dispSurface, producer,
-                                mRenderEngine->getEGLConfig(), false);
-                        hw->setLayerStack(state.layerStack);
-                        hw->setProjection(state.orientation,
-                                state.viewport, state.frame);
-                        hw->setDisplayName(state.displayName);
-                        mDisplays.add(display, hw);
-                        if (state.isVirtualDisplay()) {
-                            if (hwcDisplayId >= 0) {
-                                mHwc->setVirtualDisplayProperties(hwcDisplayId,
-                                        hw->getWidth(), hw->getHeight(),
-                                        hw->getFormat());
-                            }
-                        } else {
-                            mEventThread->onHotplugReceived(state.type, true);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
-        // The transform hint might have changed for some layers
-        // (either because a display has changed, or because a layer
-        // as changed).
-        //
-        // Walk through all the layers in currentLayers,
-        // and update their transform hint.
-        //
-        // If a layer is visible only on a single display, then that
-        // display is used to calculate the hint, otherwise we use the
-        // default display.
-        //
-        // NOTE: we do this here, rather than in rebuildLayerStacks() so that
-        // the hint is set before we acquire a buffer from the surface texture.
-        //
-        // NOTE: layer transactions have taken place already, so we use their
-        // drawing state. However, SurfaceFlinger's own transaction has not
-        // happened yet, so we must use the current state layer list
-        // (soon to become the drawing state list).
-        //
-        sp<const DisplayDevice> disp;
-        uint32_t currentlayerStack = 0;
-        bool first = true;
-        mCurrentState.traverseInZOrder([&](Layer* layer) {
-            // NOTE: we rely on the fact that layers are sorted by
-            // layerStack first (so we don't have to traverse the list
-            // of displays for every layer).
-            uint32_t layerStack = layer->getLayerStack();
-            if (first || currentlayerStack != layerStack) {
-                currentlayerStack = layerStack;
-                // figure out if this layerstack is mirrored
-                // (more than one display) if so, pick the default display,
-                // if not, pick the only display it's on.
-                disp.clear();
-                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-                    sp<const DisplayDevice> hw(mDisplays[dpy]);
-                    if (hw->getLayerStack() == currentlayerStack) {
-                        if (disp == NULL) {
-                            disp = hw;
-                        } else {
-                            disp = NULL;
-                            break;
-                        }
-                    }
-                }
-            }
-            if (disp == NULL) {
-                // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
-                // redraw after transform hint changes. See bug 8508397.
-
-                // could be null when this layer is using a layerStack
-                // that is not visible on any display. Also can occur at
-                // screen off/on times.
-                disp = getDefaultDisplayDeviceLocked();
-            }
-            layer->updateTransformHint(disp);
-
-            first = false;
-        });
-    }
-
-
-    /*
-     * Perform our own transaction if needed
-     */
-
-    if (mLayersAdded) {
-        mLayersAdded = false;
-        // Layers have been added.
-        mVisibleRegionsDirty = true;
-    }
-
-    // some layers might have been removed, so
-    // we need to update the regions they're exposing.
-    if (mLayersRemoved) {
-        mLayersRemoved = false;
-        mVisibleRegionsDirty = true;
-        mDrawingState.traverseInZOrder([&](Layer* layer) {
-            if (mLayersPendingRemoval.indexOf(layer) >= 0) {
-                // this layer is not visible anymore
-                // TODO: we could traverse the tree from front to back and
-                //       compute the actual visible region
-                // TODO: we could cache the transformed region
-                Region visibleReg;
-                visibleReg.set(layer->computeScreenBounds());
-                invalidateLayerStack(layer, visibleReg);
-            }
-        });
-    }
-
-    commitTransaction();
-
-    updateCursorAsync();
-}
-
-void SurfaceFlinger::updateCursorAsync()
-{
-    HWComposer& hwc(getHwComposer());
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        sp<const DisplayDevice> hw(mDisplays[dpy]);
-        const int32_t id = hw->getHwcDisplayId();
-        if (id < 0) {
-            continue;
-        }
-        const Vector< sp<Layer> >& currentLayers(
-            hw->getVisibleLayersSortedByZ());
-        const size_t count = currentLayers.size();
-        HWComposer::LayerListIterator cur = hwc.begin(id);
-        const HWComposer::LayerListIterator end = hwc.end(id);
-        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
-                continue;
-            }
-            const sp<Layer>& layer(currentLayers[i]);
-            Rect cursorPos = layer->getPosition(hw);
-            hwc.setCursorPositionAsync(id, cursorPos);
-            break;
-        }
-    }
-}
-
-void SurfaceFlinger::commitTransaction()
-{
-    if (!mLayersPendingRemoval.isEmpty()) {
-        // Notify removed layers now that they can't be drawn from
-        for (const auto& l : mLayersPendingRemoval) {
-            recordBufferingStats(l->getName().string(),
-                    l->getOccupancyHistory(true));
-            l->onRemoved();
-        }
-        mLayersPendingRemoval.clear();
-    }
-
-    // If this transaction is part of a window animation then the next frame
-    // we composite should be considered an animation as well.
-    mAnimCompositionPending = mAnimTransactionPending;
-
-    mDrawingState = mCurrentState;
-    mDrawingState.traverseInZOrder([](Layer* layer) {
-        layer->commitChildList();
-    });
-    mTransactionPending = false;
-    mAnimTransactionPending = false;
-    mTransactionCV.broadcast();
-}
-
-void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
-        Region& outDirtyRegion, Region& outOpaqueRegion)
-{
-    ATRACE_CALL();
-
-    Region aboveOpaqueLayers;
-    Region aboveCoveredLayers;
-    Region dirty;
-
-    outDirtyRegion.clear();
-
-    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
-        // start with the whole surface at its current location
-        const Layer::State& s(layer->getDrawingState());
-
-        // only consider the layers on the given layer stack
-        if (layer->getLayerStack() != displayDevice->getLayerStack())
-            return;
-
-        /*
-         * opaqueRegion: area of a surface that is fully opaque.
-         */
-        Region opaqueRegion;
-
-        /*
-         * visibleRegion: area of a surface that is visible on screen
-         * and not fully transparent. This is essentially the layer's
-         * footprint minus the opaque regions above it.
-         * Areas covered by a translucent surface are considered visible.
-         */
-        Region visibleRegion;
-
-        /*
-         * coveredRegion: area of a surface that is covered by all
-         * visible regions above it (which includes the translucent areas).
-         */
-        Region coveredRegion;
-
-        /*
-         * transparentRegion: area of a surface that is hinted to be completely
-         * transparent. This is only used to tell when the layer has no visible
-         * non-transparent regions and can be removed from the layer list. It
-         * does not affect the visibleRegion of this layer or any layers
-         * beneath it. The hint may not be correct if apps don't respect the
-         * SurfaceView restrictions (which, sadly, some don't).
-         */
-        Region transparentRegion;
-
-
-        // handle hidden surfaces by setting the visible region to empty
-        if (CC_LIKELY(layer->isVisible())) {
-            const bool translucent = !layer->isOpaque(s);
-            Rect bounds(layer->computeScreenBounds());
-            visibleRegion.set(bounds);
-            Transform tr = layer->getTransform();
-            if (!visibleRegion.isEmpty()) {
-                // Remove the transparent area from the visible region
-                if (translucent) {
-                    if (tr.preserveRects()) {
-                        // transform the transparent region
-                        transparentRegion = tr.transform(s.activeTransparentRegion);
-                    } else {
-                        // transformation too complex, can't do the
-                        // transparent region optimization.
-                        transparentRegion.clear();
-                    }
-                }
-
-                // compute the opaque region
-                const int32_t layerOrientation = tr.getOrientation();
-                if (s.alpha==255 && !translucent &&
-                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
-                    // the opaque region is the layer's footprint
-                    opaqueRegion = visibleRegion;
-                }
-            }
-        }
-
-        // Clip the covered region to the visible region
-        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
-
-        // Update aboveCoveredLayers for next (lower) layer
-        aboveCoveredLayers.orSelf(visibleRegion);
-
-        // subtract the opaque region covered by the layers above us
-        visibleRegion.subtractSelf(aboveOpaqueLayers);
-
-        // compute this layer's dirty region
-        if (layer->contentDirty) {
-            // we need to invalidate the whole region
-            dirty = visibleRegion;
-            // as well, as the old visible region
-            dirty.orSelf(layer->visibleRegion);
-            layer->contentDirty = false;
-        } else {
-            /* compute the exposed region:
-             *   the exposed region consists of two components:
-             *   1) what's VISIBLE now and was COVERED before
-             *   2) what's EXPOSED now less what was EXPOSED before
-             *
-             * note that (1) is conservative, we start with the whole
-             * visible region but only keep what used to be covered by
-             * something -- which mean it may have been exposed.
-             *
-             * (2) handles areas that were not covered by anything but got
-             * exposed because of a resize.
-             */
-            const Region newExposed = visibleRegion - coveredRegion;
-            const Region oldVisibleRegion = layer->visibleRegion;
-            const Region oldCoveredRegion = layer->coveredRegion;
-            const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
-            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
-        }
-        dirty.subtractSelf(aboveOpaqueLayers);
-
-        // accumulate to the screen dirty region
-        outDirtyRegion.orSelf(dirty);
-
-        // Update aboveOpaqueLayers for next (lower) layer
-        aboveOpaqueLayers.orSelf(opaqueRegion);
-
-        // Store the visible region in screen space
-        layer->setVisibleRegion(visibleRegion);
-        layer->setCoveredRegion(coveredRegion);
-        layer->setVisibleNonTransparentRegion(
-                visibleRegion.subtract(transparentRegion));
-    });
-
-    outOpaqueRegion = aboveOpaqueLayers;
-}
-
-void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
-    uint32_t layerStack = layer->getLayerStack();
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->getLayerStack() == layerStack) {
-            hw->dirtyRegion.orSelf(dirty);
-        }
-    }
-}
-
-bool SurfaceFlinger::handlePageFlip()
-{
-    nsecs_t latchTime = systemTime();
-    Region dirtyRegion;
-
-    bool visibleRegions = false;
-    bool frameQueued = false;
-
-    // Store the set of layers that need updates. This set must not change as
-    // buffers are being latched, as this could result in a deadlock.
-    // Example: Two producers share the same command stream and:
-    // 1.) Layer 0 is latched
-    // 2.) Layer 0 gets a new frame
-    // 2.) Layer 1 gets a new frame
-    // 3.) Layer 1 is latched.
-    // Display is now waiting on Layer 1's frame, which is behind layer 0's
-    // second frame. But layer 0's second frame could be waiting on display.
-    Vector<Layer*> layersWithQueuedFrames;
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
-        if (layer->hasQueuedFrame()) {
-            frameQueued = true;
-            if (layer->shouldPresentNow(mPrimaryDispSync)) {
-                layersWithQueuedFrames.push_back(layer);
-            } else {
-                layer->useEmptyDamage();
-            }
-        } else {
-            layer->useEmptyDamage();
-        }
-    });
-    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
-        Layer* layer = layersWithQueuedFrames[i];
-        const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
-        layer->useSurfaceDamage();
-        invalidateLayerStack(layer, dirty);
-    }
-
-    mVisibleRegionsDirty |= visibleRegions;
-
-    // If we will need to wake up at some time in the future to deal with a
-    // queued frame that shouldn't be displayed during this vsync period, wake
-    // up during the next vsync period to check again.
-    if (frameQueued && layersWithQueuedFrames.empty()) {
-        signalLayerUpdate();
-    }
-
-    // Only continue with the refresh if there is actually new work to do
-    return !layersWithQueuedFrames.empty();
-}
-
-void SurfaceFlinger::invalidateHwcGeometry()
-{
-    mHwWorkListDirty = true;
-}
-
-
-void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
-        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
-    //    keep its virtual display state machine in sync, or
-    // 2) There is work to be done (the dirty region isn't empty)
-    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
-    if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
-        return;
-    }
-
-    Region dirtyRegion(inDirtyRegion);
-
-    // compute the invalid region
-    hw->swapRegion.orSelf(dirtyRegion);
-
-    uint32_t flags = hw->getFlags();
-    if (flags & DisplayDevice::SWAP_RECTANGLE) {
-        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
-        // takes a rectangle, we must make sure to update that whole
-        // rectangle in that case
-        dirtyRegion.set(hw->swapRegion.bounds());
-    } else {
-        if (flags & DisplayDevice::PARTIAL_UPDATES) {
-            // We need to redraw the rectangle that will be updated
-            // (pushed to the framebuffer).
-            // This is needed because PARTIAL_UPDATES only takes one
-            // rectangle instead of a region (see DisplayDevice::flip())
-            dirtyRegion.set(hw->swapRegion.bounds());
-        } else {
-            // we need to redraw everything (the whole screen)
-            dirtyRegion.set(hw->bounds());
-            hw->swapRegion = dirtyRegion;
-        }
-    }
-
-    if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
-        if (!doComposeSurfaces(hw, dirtyRegion)) return;
-    } else {
-        RenderEngine& engine(getRenderEngine());
-        mat4 colorMatrix = mColorMatrix;
-        if (mDaltonize) {
-            colorMatrix = colorMatrix * mDaltonizer();
-        }
-        mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
-        doComposeSurfaces(hw, dirtyRegion);
-        engine.setupColorTransform(oldMatrix);
-    }
-
-    // update the swap region and clear the dirty region
-    hw->swapRegion.orSelf(dirtyRegion);
-
-    // swap buffers (presentation)
-    hw->swapBuffers(getHwComposer());
-}
-
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
-{
-    RenderEngine& engine(getRenderEngine());
-    const int32_t id = hw->getHwcDisplayId();
-    HWComposer& hwc(getHwComposer());
-    HWComposer::LayerListIterator cur = hwc.begin(id);
-    const HWComposer::LayerListIterator end = hwc.end(id);
-
-    bool hasGlesComposition = hwc.hasGlesComposition(id);
-    if (hasGlesComposition) {
-        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
-            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
-                  hw->getDisplayName().string());
-            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
-              ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
-            }
-            return false;
-        }
-
-        // Never touch the framebuffer if we don't have any framebuffer layers
-        const bool hasHwcComposition = hwc.hasHwcComposition(id);
-        if (hasHwcComposition) {
-            // when using overlays, we assume a fully transparent framebuffer
-            // NOTE: we could reduce how much we need to clear, for instance
-            // remove where there are opaque FB layers. however, on some
-            // GPUs doing a "clean slate" clear might be more efficient.
-            // We'll revisit later if needed.
-            engine.clearWithColor(0, 0, 0, 0);
-        } else {
-            // we start with the whole screen area
-            const Region bounds(hw->getBounds());
-
-            // we remove the scissor part
-            // we're left with the letterbox region
-            // (common case is that letterbox ends-up being empty)
-            const Region letterbox(bounds.subtract(hw->getScissor()));
-
-            // compute the area to clear
-            Region region(hw->undefinedRegion.merge(letterbox));
-
-            // but limit it to the dirty region
-            region.andSelf(dirty);
-
-            // screen is already cleared here
-            if (!region.isEmpty()) {
-                // can happen with SurfaceView
-                drawWormhole(hw, region);
-            }
-        }
-
-        if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
-            // just to be on the safe side, we don't set the
-            // scissor on the main display. It should never be needed
-            // anyways (though in theory it could since the API allows it).
-            const Rect& bounds(hw->getBounds());
-            const Rect& scissor(hw->getScissor());
-            if (scissor != bounds) {
-                // scissor doesn't match the screen's dimensions, so we
-                // need to clear everything outside of it and enable
-                // the GL scissor so we don't draw anything where we shouldn't
-
-                // enable scissor for this frame
-                const uint32_t height = hw->getHeight();
-                engine.setScissor(scissor.left, height - scissor.bottom,
-                        scissor.getWidth(), scissor.getHeight());
-            }
-        }
-    }
-
-    /*
-     * and then, render the layers targeted at the framebuffer
-     */
-
-    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
-    const size_t count = layers.size();
-    const Transform& tr = hw->getTransform();
-    if (cur != end) {
-        // we're using h/w composer
-        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
-            const sp<Layer>& layer(layers[i]);
-            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
-            if (!clip.isEmpty()) {
-                switch (cur->getCompositionType()) {
-                    case HWC_CURSOR_OVERLAY:
-                    case HWC_OVERLAY: {
-                        const Layer::State& state(layer->getDrawingState());
-                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
-                                && i
-                                && layer->isOpaque(state) && (state.alpha == 0xFF)
-                                && hasGlesComposition) {
-                            // never clear the very first layer since we're
-                            // guaranteed the FB is already cleared
-                            layer->clearWithOpenGL(hw);
-                        }
-                        break;
-                    }
-                    case HWC_FRAMEBUFFER: {
-                        layer->draw(hw, clip);
-                        break;
-                    }
-                    case HWC_FRAMEBUFFER_TARGET: {
-                        // this should not happen as the iterator shouldn't
-                        // let us get there.
-                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
-                        break;
-                    }
-                }
-            }
-            layer->setAcquireFence(hw, *cur);
-        }
-    } else {
-        // we're not using h/w composer
-        for (size_t i=0 ; i<count ; ++i) {
-            const sp<Layer>& layer(layers[i]);
-            const Region clip(dirty.intersect(
-                    tr.transform(layer->visibleRegion)));
-            if (!clip.isEmpty()) {
-                layer->draw(hw, clip);
-            }
-        }
-    }
-
-    // disable scissor at the end of the frame
-    engine.disableScissor();
-    return true;
-}
-
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const {
-    const int32_t height = hw->getHeight();
-    RenderEngine& engine(getRenderEngine());
-    engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
-}
-
-status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
-        const sp<IBinder>& handle,
-        const sp<IGraphicBufferProducer>& gbc,
-        const sp<Layer>& lbc,
-        const sp<Layer>& parent)
-{
-    // add this layer to the current state list
-    {
-        Mutex::Autolock _l(mStateLock);
-        if (mNumLayers >= MAX_LAYERS) {
-            return NO_MEMORY;
-        }
-        if (parent == nullptr) {
-            mCurrentState.layersSortedByZ.add(lbc);
-        } else {
-            if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
-                ALOGE("addClientLayer called with a removed parent");
-                return NAME_NOT_FOUND;
-            }
-            parent->addChild(lbc);
-        }
-
-        mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
-        mLayersAdded = true;
-        mNumLayers++;
-    }
-
-    // attach this layer to the client
-    client->attachLayer(handle, lbc);
-
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
-    Mutex::Autolock _l(mStateLock);
-
-    const auto& p = layer->getParent();
-    ssize_t index;
-    if (p != nullptr) {
-        if (topLevelOnly) {
-            return NO_ERROR;
-        }
-
-        sp<Layer> ancestor = p;
-        while (ancestor->getParent() != nullptr) {
-            ancestor = ancestor->getParent();
-        }
-        if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
-            ALOGE("removeLayer called with a layer whose parent has been removed");
-            return NAME_NOT_FOUND;
-        }
-
-        index = p->removeChild(layer);
-    } else {
-        index = mCurrentState.layersSortedByZ.remove(layer);
-    }
-
-    // As a matter of normal operation, the LayerCleaner will produce a second
-    // attempt to remove the surface. The Layer will be kept alive in mDrawingState
-    // so we will succeed in promoting it, but it's already been removed
-    // from mCurrentState. As long as we can find it in mDrawingState we have no problem
-    // otherwise something has gone wrong and we are leaking the layer.
-    if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
-        ALOGE("Failed to find layer (%s) in layer parent (%s).",
-                layer->getName().string(),
-                (p != nullptr) ? p->getName().string() : "no-parent");
-        return BAD_VALUE;
-    } else if (index < 0) {
-        return NO_ERROR;
-    }
-
-    layer->onRemovedFromCurrentState();
-    mLayersPendingRemoval.add(layer);
-    mLayersRemoved = true;
-    mNumLayers -= 1 + layer->getChildrenCount();
-    setTransactionFlags(eTransactionNeeded);
-    return NO_ERROR;
-}
-
-uint32_t SurfaceFlinger::peekTransactionFlags() {
-    return android_atomic_release_load(&mTransactionFlags);
-}
-
-uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) {
-    return android_atomic_and(~flags, &mTransactionFlags) & flags;
-}
-
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
-    uint32_t old = android_atomic_or(flags, &mTransactionFlags);
-    if ((old & flags)==0) { // wake the server up
-        signalTransaction();
-    }
-    return old;
-}
-
-void SurfaceFlinger::setTransactionState(
-        const Vector<ComposerState>& state,
-        const Vector<DisplayState>& displays,
-        uint32_t flags)
-{
-    ATRACE_CALL();
-    Mutex::Autolock _l(mStateLock);
-    uint32_t transactionFlags = 0;
-
-    if (flags & eAnimation) {
-        // For window updates that are part of an animation we must wait for
-        // previous animation "frames" to be handled.
-        while (mAnimTransactionPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // caller after a few seconds.
-                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
-                        "waiting for previous animation frame");
-                mAnimTransactionPending = false;
-                break;
-            }
-        }
-    }
-
-    size_t count = displays.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const DisplayState& s(displays[i]);
-        transactionFlags |= setDisplayStateLocked(s);
-    }
-
-    count = state.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const ComposerState& s(state[i]);
-        // Here we need to check that the interface we're given is indeed
-        // one of our own. A malicious client could give us a NULL
-        // IInterface, or one of its own or even one of our own but a
-        // different type. All these situations would cause us to crash.
-        //
-        // NOTE: it would be better to use RTTI as we could directly check
-        // that we have a Client*. however, RTTI is disabled in Android.
-        if (s.client != NULL) {
-            sp<IBinder> binder = IInterface::asBinder(s.client);
-            if (binder != NULL) {
-                if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
-                    sp<Client> client( static_cast<Client *>(s.client.get()) );
-                    transactionFlags |= setClientStateLocked(client, s.state);
-                }
-            }
-        }
-    }
-
-    // If a synchronous transaction is explicitly requested without any changes,
-    // force a transaction anyway. This can be used as a flush mechanism for
-    // previous async transactions.
-    if (transactionFlags == 0 && (flags & eSynchronous)) {
-        transactionFlags = eTransactionNeeded;
-    }
-
-    if (transactionFlags) {
-        if (mInterceptor.isEnabled()) {
-            mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
-        }
-
-        // this triggers the transaction
-        setTransactionFlags(transactionFlags);
-
-        // if this is a synchronous transaction, wait for it to take effect
-        // before returning.
-        if (flags & eSynchronous) {
-            mTransactionPending = true;
-        }
-        if (flags & eAnimation) {
-            mAnimTransactionPending = true;
-        }
-        while (mTransactionPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // called after a few seconds.
-                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
-                mTransactionPending = false;
-                break;
-            }
-        }
-    }
-}
-
-uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
-{
-    ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
-    if (dpyIdx < 0)
-        return 0;
-
-    uint32_t flags = 0;
-    DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
-    if (disp.isValid()) {
-        const uint32_t what = s.what;
-        if (what & DisplayState::eSurfaceChanged) {
-            if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
-                disp.surface = s.surface;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eLayerStackChanged) {
-            if (disp.layerStack != s.layerStack) {
-                disp.layerStack = s.layerStack;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eDisplayProjectionChanged) {
-            if (disp.orientation != s.orientation) {
-                disp.orientation = s.orientation;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.frame != s.frame) {
-                disp.frame = s.frame;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.viewport != s.viewport) {
-                disp.viewport = s.viewport;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eDisplaySizeChanged) {
-            if (disp.width != s.width) {
-                disp.width = s.width;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.height != s.height) {
-                disp.height = s.height;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-    }
-    return flags;
-}
-
-uint32_t SurfaceFlinger::setClientStateLocked(
-        const sp<Client>& client,
-        const layer_state_t& s)
-{
-    uint32_t flags = 0;
-    sp<Layer> layer(client->getLayerUser(s.surface));
-    if (layer != 0) {
-        const uint32_t what = s.what;
-        bool geometryAppliesWithResize =
-                what & layer_state_t::eGeometryAppliesWithResize;
-        if (what & layer_state_t::ePositionChanged) {
-            if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
-                flags |= eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eLayerChanged) {
-            // NOTE: index needs to be calculated before we update the state
-            const auto& p = layer->getParent();
-            if (p == nullptr) {
-                ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-                if (layer->setLayer(s.z) && idx >= 0) {
-                    mCurrentState.layersSortedByZ.removeAt(idx);
-                    mCurrentState.layersSortedByZ.add(layer);
-                    // we need traversal (state changed)
-                    // AND transaction (list changed)
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            } else {
-                if (p->setChildLayer(layer, s.z)) {
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            }
-        }
-        if (what & layer_state_t::eRelativeLayerChanged) {
-            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
-                mCurrentState.layersSortedByZ.removeAt(idx);
-                mCurrentState.layersSortedByZ.add(layer);
-                flags |= eTransactionNeeded|eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eSizeChanged) {
-            if (layer->setSize(s.w, s.h)) {
-                flags |= eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eAlphaChanged) {
-            if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eMatrixChanged) {
-            if (layer->setMatrix(s.matrix))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eTransparentRegionChanged) {
-            if (layer->setTransparentRegionHint(s.transparentRegion))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eFlagsChanged) {
-            if (layer->setFlags(s.flags, s.mask))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eCropChanged) {
-            if (layer->setCrop(s.crop, !geometryAppliesWithResize))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eFinalCropChanged) {
-            if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
-                flags |= eTraversalNeeded;
-        }
-        if (what & layer_state_t::eLayerStackChanged) {
-            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            // We only allow setting layer stacks for top level layers,
-            // everything else inherits layer stack from its parent.
-            if (layer->hasParent()) {
-                ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
-                        layer->getName().string());
-            } else if (idx < 0) {
-                ALOGE("Attempt to set layer stack on layer without parent (%s) that "
-                        "that also does not appear in the top level layer list. Something"
-                        " has gone wrong.", layer->getName().string());
-            } else if (layer->setLayerStack(s.layerStack)) {
-                mCurrentState.layersSortedByZ.removeAt(idx);
-                mCurrentState.layersSortedByZ.add(layer);
-                // we need traversal (state changed)
-                // AND transaction (list changed)
-                flags |= eTransactionNeeded|eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eDeferTransaction) {
-            if (s.barrierHandle != nullptr) {
-                layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
-            } else if (s.barrierGbp != nullptr) {
-                const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
-                if (authenticateSurfaceTextureLocked(gbp)) {
-                    const auto& otherLayer =
-                        (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
-                    layer->deferTransactionUntil(otherLayer, s.frameNumber);
-                } else {
-                    ALOGE("Attempt to defer transaction to to an"
-                            " unrecognized GraphicBufferProducer");
-                }
-            }
-            // We don't trigger a traversal here because if no other state is
-            // changed, we don't want this to cause any more work
-        }
-        if (what & layer_state_t::eReparentChildren) {
-            if (layer->reparentChildren(s.reparentHandle)) {
-                flags |= eTransactionNeeded|eTraversalNeeded;
-            }
-        }
-        if (what & layer_state_t::eDetachChildren) {
-            layer->detachChildren();
-        }
-        if (what & layer_state_t::eOverrideScalingModeChanged) {
-            layer->setOverrideScalingMode(s.overrideScalingMode);
-            // We don't trigger a traversal here because if no other state is
-            // changed, we don't want this to cause any more work
-        }
-    }
-    return flags;
-}
-
-status_t SurfaceFlinger::createLayer(
-        const String8& name,
-        const sp<Client>& client,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-        uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
-        sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
-{
-    if (int32_t(w|h) < 0) {
-        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
-                int(w), int(h));
-        return BAD_VALUE;
-    }
-
-    status_t result = NO_ERROR;
-
-    sp<Layer> layer;
-
-    String8 uniqueName = getUniqueLayerName(name);
-
-    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
-        case ISurfaceComposerClient::eFXSurfaceNormal:
-            result = createNormalLayer(client,
-                    uniqueName, w, h, flags, format,
-                    handle, gbp, &layer);
-            break;
-        case ISurfaceComposerClient::eFXSurfaceDim:
-            result = createDimLayer(client,
-                    uniqueName, w, h, flags,
-                    handle, gbp, &layer);
-            break;
-        default:
-            result = BAD_VALUE;
-            break;
-    }
-
-    if (result != NO_ERROR) {
-        return result;
-    }
-
-    layer->setInfo(windowType, ownerUid);
-
-    result = addClientLayer(client, *handle, *gbp, layer, *parent);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    mInterceptor.saveSurfaceCreation(layer);
-
-    setTransactionFlags(eTransactionNeeded);
-    return result;
-}
-
-String8 SurfaceFlinger::getUniqueLayerName(const String8& name)
-{
-    bool matchFound = true;
-    uint32_t dupeCounter = 0;
-
-    // Tack on our counter whether there is a hit or not, so everyone gets a tag
-    String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
-
-    // Loop over layers until we're sure there is no matching name
-    while (matchFound) {
-        matchFound = false;
-        mDrawingState.traverseInZOrder([&](Layer* layer) {
-            if (layer->getName() == uniqueName) {
-                matchFound = true;
-                uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
-            }
-        });
-    }
-
-    ALOGD_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), uniqueName.c_str());
-
-    return uniqueName;
-}
-
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
-        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
-        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
-{
-    // initialize the surfaces
-    switch (format) {
-    case PIXEL_FORMAT_TRANSPARENT:
-    case PIXEL_FORMAT_TRANSLUCENT:
-        format = PIXEL_FORMAT_RGBA_8888;
-        break;
-    case PIXEL_FORMAT_OPAQUE:
-        format = PIXEL_FORMAT_RGBX_8888;
-        break;
-    }
-
-    *outLayer = new Layer(this, client, name, w, h, flags);
-    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
-    if (err == NO_ERROR) {
-        *handle = (*outLayer)->getHandle();
-        *gbp = (*outLayer)->getProducer();
-    }
-
-    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
-    return err;
-}
-
-status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
-        const String8& name, uint32_t w, uint32_t h, uint32_t flags,
-        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
-{
-    *outLayer = new LayerDim(this, client, name, w, h, flags);
-    *handle = (*outLayer)->getHandle();
-    *gbp = (*outLayer)->getProducer();
-    return NO_ERROR;
-}
-
-status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
-{
-    // called by a client when it wants to remove a Layer
-    status_t err = NO_ERROR;
-    sp<Layer> l(client->getLayerUser(handle));
-    if (l != NULL) {
-        mInterceptor.saveSurfaceDeletion(l);
-        err = removeLayer(l);
-        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
-                "error removing layer=%p (%s)", l.get(), strerror(-err));
-    }
-    return err;
-}
-
-status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
-{
-    // called by ~LayerCleaner() when all references to the IBinder (handle)
-    // are gone
-    sp<Layer> l = layer.promote();
-    if (l == nullptr) {
-        // The layer has already been removed, carry on
-        return NO_ERROR;
-    }
-    // If we have a parent, then we can continue to live as long as it does.
-    return removeLayer(l, true);
-}
-
-// ---------------------------------------------------------------------------
-
-void SurfaceFlinger::onInitializeDisplays() {
-    // reset screen orientation and use primary layer stack
-    Vector<ComposerState> state;
-    Vector<DisplayState> displays;
-    DisplayState d;
-    d.what = DisplayState::eDisplayProjectionChanged |
-             DisplayState::eLayerStackChanged;
-    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
-    d.layerStack = 0;
-    d.orientation = DisplayState::eOrientationDefault;
-    d.frame.makeInvalid();
-    d.viewport.makeInvalid();
-    d.width = 0;
-    d.height = 0;
-    displays.add(d);
-    setTransactionState(state, displays, 0);
-    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
-
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-    mAnimFrameTracker.setDisplayRefreshPeriod(period);
-
-    // Use phase of 0 since phase is not known.
-    // Use latency of 0, which will snap to the ideal latency.
-    setCompositorTimingSnapped(0, period, 0);
-}
-
-void SurfaceFlinger::initializeDisplays() {
-    class MessageScreenInitialized : public MessageBase {
-        SurfaceFlinger* flinger;
-    public:
-        explicit MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
-        virtual bool handler() {
-            flinger->onInitializeDisplays();
-            return true;
-        }
-    };
-    sp<MessageBase> msg = new MessageScreenInitialized(this);
-    postMessageAsync(msg);  // we may be called from main thread, use async message
-}
-
-void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
-        int mode) {
-    ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
-            this);
-    int32_t type = hw->getDisplayType();
-    int currentMode = hw->getPowerMode();
-
-    if (mode == currentMode) {
-        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
-        return;
-    }
-
-    hw->setPowerMode(mode);
-    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        ALOGW("Trying to set power mode for virtual display");
-        return;
-    }
-
-    if (mInterceptor.isEnabled()) {
-        Mutex::Autolock _l(mStateLock);
-        ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
-        if (idx < 0) {
-            ALOGW("Surface Interceptor SavePowerMode: invalid display token");
-            return;
-        }
-        mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
-    }
-
-    if (currentMode == HWC_POWER_MODE_OFF) {
-        // Turn on the display
-        getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY &&
-            mode != HWC_POWER_MODE_DOZE_SUSPEND) {
-            // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenAcquired();
-            resyncToHardwareVsync(true);
-        }
-
-        mVisibleRegionsDirty = true;
-        mHasPoweredOff = true;
-        repaintEverything();
-
-        struct sched_param param = {0};
-        param.sched_priority = 1;
-        if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
-            ALOGW("Couldn't set SCHED_FIFO on display on");
-        }
-    } else if (mode == HWC_POWER_MODE_OFF) {
-        // Turn off the display
-        struct sched_param param = {0};
-        if (sched_setscheduler(0, SCHED_OTHER, &param) != 0) {
-            ALOGW("Couldn't set SCHED_OTHER on display off");
-        }
-
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
-            disableHardwareVsync(true); // also cancels any in-progress resync
-
-            // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenReleased();
-        }
-
-        getHwComposer().setPowerMode(type, mode);
-        mVisibleRegionsDirty = true;
-        // from this point on, SF will stop drawing on this display
-    } else if (mode == HWC_POWER_MODE_DOZE ||
-               mode == HWC_POWER_MODE_NORMAL) {
-        // Update display while dozing
-        getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
-            // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenAcquired();
-            resyncToHardwareVsync(true);
-        }
-    } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
-        // Leave display going to doze
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
-            disableHardwareVsync(true); // also cancels any in-progress resync
-            // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenReleased();
-        }
-        getHwComposer().setPowerMode(type, mode);
-    } else {
-        ALOGE("Attempting to set unknown power mode: %d\n", mode);
-        getHwComposer().setPowerMode(type, mode);
-    }
-}
-
-void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
-    class MessageSetPowerMode: public MessageBase {
-        SurfaceFlinger& mFlinger;
-        sp<IBinder> mDisplay;
-        int mMode;
-    public:
-        MessageSetPowerMode(SurfaceFlinger& flinger,
-                const sp<IBinder>& disp, int mode) : mFlinger(flinger),
-                    mDisplay(disp) { mMode = mode; }
-        virtual bool handler() {
-            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
-            if (hw == NULL) {
-                ALOGE("Attempt to set power mode = %d for null display %p",
-                        mMode, mDisplay.get());
-            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to set power mode = %d for virtual display",
-                        mMode);
-            } else {
-                mFlinger.setPowerModeInternal(hw, mMode);
-            }
-            return true;
-        }
-    };
-    sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
-    postMessageSync(msg);
-}
-
-// ---------------------------------------------------------------------------
-
-status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
-{
-    String8 result;
-
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    const int uid = ipc->getCallingUid();
-    if ((uid != AID_SHELL) &&
-            !PermissionCache::checkPermission(sDump, pid, uid)) {
-        result.appendFormat("Permission Denial: "
-                "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
-    } else {
-        // Try to get the main lock, but give up after one second
-        // (this would indicate SF is stuck, but we want to be able to
-        // print something in dumpsys).
-        status_t err = mStateLock.timedLock(s2ns(1));
-        bool locked = (err == NO_ERROR);
-        if (!locked) {
-            result.appendFormat(
-                    "SurfaceFlinger appears to be unresponsive (%s [%d]), "
-                    "dumping anyways (no locks held)\n", strerror(-err), err);
-        }
-
-        bool dumpAll = true;
-        size_t index = 0;
-        size_t numArgs = args.size();
-        if (numArgs) {
-            if ((index < numArgs) &&
-                    (args[index] == String16("--list"))) {
-                index++;
-                listLayersLocked(args, index, result);
-                dumpAll = false;
-            }
-
-            if ((index < numArgs) &&
-                    (args[index] == String16("--latency"))) {
-                index++;
-                dumpStatsLocked(args, index, result);
-                dumpAll = false;
-            }
-
-            if ((index < numArgs) &&
-                    (args[index] == String16("--latency-clear"))) {
-                index++;
-                clearStatsLocked(args, index, result);
-                dumpAll = false;
-            }
-
-            if ((index < numArgs) &&
-                    (args[index] == String16("--dispsync"))) {
-                index++;
-                mPrimaryDispSync.dump(result);
-                dumpAll = false;
-            }
-
-            if ((index < numArgs) &&
-                    (args[index] == String16("--static-screen"))) {
-                index++;
-                dumpStaticScreenStats(result);
-                dumpAll = false;
-            }
-
-            if ((index < numArgs) &&
-                    (args[index] == String16("--frame-events"))) {
-                index++;
-                dumpFrameEventsLocked(result);
-                dumpAll = false;
-            }
-        }
-
-        if (dumpAll) {
-            dumpAllLocked(args, index, result);
-        }
-
-        if (locked) {
-            mStateLock.unlock();
-        }
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */,
-        size_t& /* index */, String8& result) const
-{
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        result.appendFormat("%s\n", layer->getName().string());
-    });
-}
-
-void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result) const
-{
-    String8 name;
-    if (index < args.size()) {
-        name = String8(args[index]);
-        index++;
-    }
-
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-    result.appendFormat("%" PRId64 "\n", period);
-
-    if (name.isEmpty()) {
-        mAnimFrameTracker.dumpStats(result);
-    } else {
-        mCurrentState.traverseInZOrder([&](Layer* layer) {
-            if (name == layer->getName()) {
-                layer->dumpFrameStats(result);
-            }
-        });
-    }
-}
-
-void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& /* result */)
-{
-    String8 name;
-    if (index < args.size()) {
-        name = String8(args[index]);
-        index++;
-    }
-
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        if (name.isEmpty() || (name == layer->getName())) {
-            layer->clearFrameStats();
-        }
-    });
-
-    mAnimFrameTracker.clearStats();
-}
-
-// This should only be called from the main thread.  Otherwise it would need
-// the lock and should use mCurrentState rather than mDrawingState.
-void SurfaceFlinger::logFrameStats() {
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
-        layer->logFrameStats();
-    });
-
-    mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
-}
-
-void SurfaceFlinger::appendSfConfigString(String8& result) const
-{
-    result.append(" [sf");
-    result.appendFormat(" HAS_CONTEXT_PRIORITY=%d", useContextPriority);
-
-    if (isLayerTripleBufferingDisabled())
-        result.append(" DISABLE_TRIPLE_BUFFERING");
-
-    result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
-    result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
-    result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
-    result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
-    result.appendFormat(" NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
-                        maxFrameBufferAcquiredBuffers);
-    result.append("]");
-}
-
-void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
-{
-    result.appendFormat("Static screen stats:\n");
-    for (size_t b = 0; b < NUM_BUCKETS - 1; ++b) {
-        float bucketTimeSec = mFrameBuckets[b] / 1e9;
-        float percent = 100.0f *
-                static_cast<float>(mFrameBuckets[b]) / mTotalTime;
-        result.appendFormat("  < %zd frames: %.3f s (%.1f%%)\n",
-                b + 1, bucketTimeSec, percent);
-    }
-    float bucketTimeSec = mFrameBuckets[NUM_BUCKETS - 1] / 1e9;
-    float percent = 100.0f *
-            static_cast<float>(mFrameBuckets[NUM_BUCKETS - 1]) / mTotalTime;
-    result.appendFormat("  %zd+ frames: %.3f s (%.1f%%)\n",
-            NUM_BUCKETS - 1, bucketTimeSec, percent);
-}
-
-void SurfaceFlinger::dumpFrameEventsLocked(String8& result) {
-    result.appendFormat("Layer frame timestamps:\n");
-
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
-    const size_t count = currentLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        currentLayers[i]->dumpFrameEvents(result);
-    }
-}
-
-void SurfaceFlinger::recordBufferingStats(const char* layerName,
-        std::vector<OccupancyTracker::Segment>&& history) {
-    Mutex::Autolock lock(mBufferingStatsMutex);
-    auto& stats = mBufferingStats[layerName];
-    for (const auto& segment : history) {
-        if (!segment.usedThirdBuffer) {
-            stats.twoBufferTime += segment.totalTime;
-        }
-        if (segment.occupancyAverage < 1.0f) {
-            stats.doubleBufferedTime += segment.totalTime;
-        } else if (segment.occupancyAverage < 2.0f) {
-            stats.tripleBufferedTime += segment.totalTime;
-        }
-        ++stats.numSegments;
-        stats.totalTime += segment.totalTime;
-    }
-}
-
-void SurfaceFlinger::dumpBufferingStats(String8& result) const {
-    result.append("Buffering stats:\n");
-    result.append("  [Layer name] <Active time> <Two buffer> "
-            "<Double buffered> <Triple buffered>\n");
-    Mutex::Autolock lock(mBufferingStatsMutex);
-    typedef std::tuple<std::string, float, float, float> BufferTuple;
-    std::map<float, BufferTuple, std::greater<float>> sorted;
-    for (const auto& statsPair : mBufferingStats) {
-        const char* name = statsPair.first.c_str();
-        const BufferingStats& stats = statsPair.second;
-        if (stats.numSegments == 0) {
-            continue;
-        }
-        float activeTime = ns2ms(stats.totalTime) / 1000.0f;
-        float twoBufferRatio = static_cast<float>(stats.twoBufferTime) /
-                stats.totalTime;
-        float doubleBufferRatio = static_cast<float>(
-                stats.doubleBufferedTime) / stats.totalTime;
-        float tripleBufferRatio = static_cast<float>(
-                stats.tripleBufferedTime) / stats.totalTime;
-        sorted.insert({activeTime, {name, twoBufferRatio,
-                doubleBufferRatio, tripleBufferRatio}});
-    }
-    for (const auto& sortedPair : sorted) {
-        float activeTime = sortedPair.first;
-        const BufferTuple& values = sortedPair.second;
-        result.appendFormat("  [%s] %.2f %.3f %.3f %.3f\n",
-                std::get<0>(values).c_str(), activeTime,
-                std::get<1>(values), std::get<2>(values),
-                std::get<3>(values));
-    }
-    result.append("\n");
-}
-
-void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
-        String8& result) const
-{
-    bool colorize = false;
-    if (index < args.size()
-            && (args[index] == String16("--color"))) {
-        colorize = true;
-        index++;
-    }
-
-    Colorizer colorizer(colorize);
-
-    // figure out if we're stuck somewhere
-    const nsecs_t now = systemTime();
-    const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
-    const nsecs_t inTransaction(mDebugInTransaction);
-    nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
-    nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
-
-    /*
-     * Dump library configuration.
-     */
-
-    colorizer.bold(result);
-    result.append("Build configuration:");
-    colorizer.reset(result);
-    appendSfConfigString(result);
-    appendUiConfigString(result);
-    appendGuiConfigString(result);
-    result.append("\n");
-
-    colorizer.bold(result);
-    result.append("Sync configuration: ");
-    colorizer.reset(result);
-    result.append(SyncFeatures::getInstance().toString());
-    result.append("\n");
-
-    colorizer.bold(result);
-    result.append("DispSync configuration: ");
-    colorizer.reset(result);
-    result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
-            "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
-        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, dispSyncPresentTimeOffset,
-        mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
-    result.append("\n");
-
-    // Dump static screen stats
-    result.append("\n");
-    dumpStaticScreenStats(result);
-    result.append("\n");
-
-    dumpBufferingStats(result);
-
-    /*
-     * Dump the visible layer list
-     */
-    colorizer.bold(result);
-    result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
-    colorizer.reset(result);
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        result.append(to_string(layer->getLayerDebugInfo()).c_str());
-    });
-
-    /*
-     * Dump Display state
-     */
-
-    colorizer.bold(result);
-    result.appendFormat("Displays (%zu entries)\n", mDisplays.size());
-    colorizer.reset(result);
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        const sp<const DisplayDevice>& hw(mDisplays[dpy]);
-        hw->dump(result);
-    }
-
-    /*
-     * Dump SurfaceFlinger global state
-     */
-
-    colorizer.bold(result);
-    result.append("SurfaceFlinger global state:\n");
-    colorizer.reset(result);
-
-    HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
-
-    colorizer.bold(result);
-    result.appendFormat("EGL implementation : %s\n",
-            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
-    colorizer.reset(result);
-    result.appendFormat("%s\n",
-            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-
-    mRenderEngine->dump(result);
-
-    hw->undefinedRegion.dump(result, "undefinedRegion");
-    result.appendFormat("  orientation=%d, isDisplayOn=%d\n",
-            hw->getOrientation(), hw->isDisplayOn());
-    result.appendFormat(
-            "  last eglSwapBuffers() time: %f us\n"
-            "  last transaction time     : %f us\n"
-            "  transaction-flags         : %08x\n"
-            "  refresh-rate              : %f fps\n"
-            "  x-dpi                     : %f\n"
-            "  y-dpi                     : %f\n"
-            "  gpu_to_cpu_unsupported    : %d\n"
-            ,
-            mLastSwapBufferTime/1000.0,
-            mLastTransactionTime/1000.0,
-            mTransactionFlags,
-            1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
-            hwc.getDpiX(HWC_DISPLAY_PRIMARY),
-            hwc.getDpiY(HWC_DISPLAY_PRIMARY),
-            !mGpuToCpuSupported);
-
-    result.appendFormat("  eglSwapBuffers time: %f us\n",
-            inSwapBuffersDuration/1000.0);
-
-    result.appendFormat("  transaction time: %f us\n",
-            inTransactionDuration/1000.0);
-
-    /*
-     * VSYNC state
-     */
-    mEventThread->dump(result);
-
-    /*
-     * Dump HWComposer state
-     */
-    colorizer.bold(result);
-    result.append("h/w composer state:\n");
-    colorizer.reset(result);
-    result.appendFormat("  h/w composer %s and %s\n",
-            hwc.initCheck()==NO_ERROR ? "present" : "not present",
-                    (mDebugDisableHWC || mDebugRegion || mDaltonize
-                            || mHasColorMatrix) ? "disabled" : "enabled");
-    hwc.dump(result);
-
-    /*
-     * Dump gralloc state
-     */
-    const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
-    alloc.dump(result);
-}
-
-const Vector< sp<Layer> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
-    // Note: mStateLock is held here
-    wp<IBinder> dpy;
-    for (size_t i=0 ; i<mDisplays.size() ; i++) {
-        if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
-            dpy = mDisplays.keyAt(i);
-            break;
-        }
-    }
-    if (dpy == NULL) {
-        ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
-        // Just use the primary display so we have something to return
-        dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
-    }
-    return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ();
-}
-
-bool SurfaceFlinger::startDdmConnection()
-{
-    void* libddmconnection_dso =
-            dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
-    if (!libddmconnection_dso) {
-        return false;
-    }
-    void (*DdmConnection_start)(const char* name);
-    DdmConnection_start =
-            (decltype(DdmConnection_start))dlsym(libddmconnection_dso, "DdmConnection_start");
-    if (!DdmConnection_start) {
-        dlclose(libddmconnection_dso);
-        return false;
-    }
-    (*DdmConnection_start)(getServiceName());
-    return true;
-}
-
-status_t SurfaceFlinger::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case CREATE_CONNECTION:
-        case CREATE_DISPLAY:
-        case BOOT_FINISHED:
-        case CLEAR_ANIMATION_FRAME_STATS:
-        case GET_ANIMATION_FRAME_STATS:
-        case SET_POWER_MODE:
-        case GET_HDR_CAPABILITIES:
-        {
-            // codes that require permission check
-            IPCThreadState* ipc = IPCThreadState::self();
-            const int pid = ipc->getCallingPid();
-            const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
-                    !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
-                ALOGE("Permission Denial: "
-                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
-                return PERMISSION_DENIED;
-            }
-            break;
-        }
-        /*
-         * Calling setTransactionState is safe, because you need to have been
-         * granted a reference to Client* and Handle* to do anything with it.
-         *
-         * Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
-         */
-        case SET_TRANSACTION_STATE:
-        case CREATE_SCOPED_CONNECTION:
-        {
-            break;
-        }
-        case CAPTURE_SCREEN:
-        {
-            // codes that require permission check
-            IPCThreadState* ipc = IPCThreadState::self();
-            const int pid = ipc->getCallingPid();
-            const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) &&
-                    !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
-                ALOGE("Permission Denial: "
-                        "can't read framebuffer pid=%d, uid=%d", pid, uid);
-                return PERMISSION_DENIED;
-            }
-            break;
-        }
-    }
-
-    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
-    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
-        CHECK_INTERFACE(ISurfaceComposer, data, reply);
-        if (CC_UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
-            IPCThreadState* ipc = IPCThreadState::self();
-            const int pid = ipc->getCallingPid();
-            const int uid = ipc->getCallingUid();
-            ALOGE("Permission Denial: "
-                    "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
-            return PERMISSION_DENIED;
-        }
-        int n;
-        switch (code) {
-            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
-            case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
-                return NO_ERROR;
-            case 1002:  // SHOW_UPDATES
-                n = data.readInt32();
-                mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
-                invalidateHwcGeometry();
-                repaintEverything();
-                return NO_ERROR;
-            case 1004:{ // repaint everything
-                repaintEverything();
-                return NO_ERROR;
-            }
-            case 1005:{ // force transaction
-                setTransactionFlags(
-                        eTransactionNeeded|
-                        eDisplayTransactionNeeded|
-                        eTraversalNeeded);
-                return NO_ERROR;
-            }
-            case 1006:{ // send empty update
-                signalRefresh();
-                return NO_ERROR;
-            }
-            case 1008:  // toggle use of hw composer
-                n = data.readInt32();
-                mDebugDisableHWC = n ? 1 : 0;
-                invalidateHwcGeometry();
-                repaintEverything();
-                return NO_ERROR;
-            case 1009:  // toggle use of transform hint
-                n = data.readInt32();
-                mDebugDisableTransformHint = n ? 1 : 0;
-                invalidateHwcGeometry();
-                repaintEverything();
-                return NO_ERROR;
-            case 1010:  // interrogate.
-                reply->writeInt32(0);
-                reply->writeInt32(0);
-                reply->writeInt32(mDebugRegion);
-                reply->writeInt32(0);
-                reply->writeInt32(mDebugDisableHWC);
-                return NO_ERROR;
-            case 1013: {
-                Mutex::Autolock _l(mStateLock);
-                sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-                reply->writeInt32(hw->getPageFlipCount());
-                return NO_ERROR;
-            }
-            case 1014: {
-                // daltonize
-                n = data.readInt32();
-                switch (n % 10) {
-                    case 1:
-                        mDaltonizer.setType(ColorBlindnessType::Protanomaly);
-                        break;
-                    case 2:
-                        mDaltonizer.setType(ColorBlindnessType::Deuteranomaly);
-                        break;
-                    case 3:
-                        mDaltonizer.setType(ColorBlindnessType::Tritanomaly);
-                        break;
-                }
-                if (n >= 10) {
-                    mDaltonizer.setMode(ColorBlindnessMode::Correction);
-                } else {
-                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
-                }
-                mDaltonize = n > 0;
-                invalidateHwcGeometry();
-                repaintEverything();
-                return NO_ERROR;
-            }
-            case 1015: {
-                // apply a color matrix
-                n = data.readInt32();
-                mHasColorMatrix = n ? 1 : 0;
-                if (n) {
-                    // color matrix is sent as mat3 matrix followed by vec3
-                    // offset, then packed into a mat4 where the last row is
-                    // the offset and extra values are 0
-                    for (size_t i = 0 ; i < 4; i++) {
-                      for (size_t j = 0; j < 4; j++) {
-                          mColorMatrix[i][j] = data.readFloat();
-                      }
-                    }
-                } else {
-                    mColorMatrix = mat4();
-                }
-                invalidateHwcGeometry();
-                repaintEverything();
-                return NO_ERROR;
-            }
-            // This is an experimental interface
-            // Needs to be shifted to proper binder interface when we productize
-            case 1016: {
-                n = data.readInt32();
-                mPrimaryDispSync.setRefreshSkipCount(n);
-                return NO_ERROR;
-            }
-            case 1017: {
-                n = data.readInt32();
-                mForceFullDamage = static_cast<bool>(n);
-                return NO_ERROR;
-            }
-            case 1018: { // Modify Choreographer's phase offset
-                n = data.readInt32();
-                mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
-                return NO_ERROR;
-            }
-            case 1019: { // Modify SurfaceFlinger's phase offset
-                n = data.readInt32();
-                mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
-                return NO_ERROR;
-            }
-            case 1020: { // Layer updates interceptor
-                n = data.readInt32();
-                if (n) {
-                    ALOGV("Interceptor enabled");
-                    mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
-                }
-                else{
-                    ALOGV("Interceptor disabled");
-                    mInterceptor.disable();
-                }
-                return NO_ERROR;
-            }
-            case 1021: { // Disable HWC virtual displays
-                n = data.readInt32();
-                mUseHwcVirtualDisplays = !n;
-                return NO_ERROR;
-            }
-        }
-    }
-    return err;
-}
-
-void SurfaceFlinger::repaintEverything() {
-    android_atomic_or(1, &mRepaintEverything);
-    signalTransaction();
-}
-
-// ---------------------------------------------------------------------------
-// Capture screen into an IGraphiBufferProducer
-// ---------------------------------------------------------------------------
-
-/* The code below is here to handle b/8734824
- *
- * We create a IGraphicBufferProducer wrapper that forwards all calls
- * from the surfaceflinger thread to the calling binder thread, where they
- * are executed. This allows the calling thread in the calling process to be
- * reused and not depend on having "enough" binder threads to handle the
- * requests.
- */
-class GraphicProducerWrapper : public BBinder, public MessageHandler {
-    /* Parts of GraphicProducerWrapper are run on two different threads,
-     * communicating by sending messages via Looper but also by shared member
-     * data. Coherence maintenance is subtle and in places implicit (ugh).
-     *
-     * Don't rely on Looper's sendMessage/handleMessage providing
-     * release/acquire semantics for any data not actually in the Message.
-     * Data going from surfaceflinger to binder threads needs to be
-     * synchronized explicitly.
-     *
-     * Barrier open/wait do provide release/acquire semantics. This provides
-     * implicit synchronization for data coming back from binder to
-     * surfaceflinger threads.
-     */
-
-    sp<IGraphicBufferProducer> impl;
-    sp<Looper> looper;
-    status_t result;
-    bool exitPending;
-    bool exitRequested;
-    Barrier barrier;
-    uint32_t code;
-    Parcel const* data;
-    Parcel* reply;
-
-    enum {
-        MSG_API_CALL,
-        MSG_EXIT
-    };
-
-    /*
-     * Called on surfaceflinger thread. This is called by our "fake"
-     * BpGraphicBufferProducer. We package the data and reply Parcel and
-     * forward them to the binder thread.
-     */
-    virtual status_t transact(uint32_t code,
-            const Parcel& data, Parcel* reply, uint32_t /* flags */) {
-        this->code = code;
-        this->data = &data;
-        this->reply = reply;
-        if (exitPending) {
-            // if we've exited, we run the message synchronously right here.
-            // note (JH): as far as I can tell from looking at the code, this
-            // never actually happens. if it does, i'm not sure if it happens
-            // on the surfaceflinger or binder thread.
-            handleMessage(Message(MSG_API_CALL));
-        } else {
-            barrier.close();
-            // Prevent stores to this->{code, data, reply} from being
-            // reordered later than the construction of Message.
-            atomic_thread_fence(memory_order_release);
-            looper->sendMessage(this, Message(MSG_API_CALL));
-            barrier.wait();
-        }
-        return result;
-    }
-
-    /*
-     * here we run on the binder thread. All we've got to do is
-     * call the real BpGraphicBufferProducer.
-     */
-    virtual void handleMessage(const Message& message) {
-        int what = message.what;
-        // Prevent reads below from happening before the read from Message
-        atomic_thread_fence(memory_order_acquire);
-        if (what == MSG_API_CALL) {
-            result = IInterface::asBinder(impl)->transact(code, data[0], reply);
-            barrier.open();
-        } else if (what == MSG_EXIT) {
-            exitRequested = true;
-        }
-    }
-
-public:
-    explicit GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
-    :   impl(impl),
-        looper(new Looper(true)),
-        result(NO_ERROR),
-        exitPending(false),
-        exitRequested(false),
-        code(0),
-        data(NULL),
-        reply(NULL)
-    {}
-
-    // Binder thread
-    status_t waitForResponse() {
-        do {
-            looper->pollOnce(-1);
-        } while (!exitRequested);
-        return result;
-    }
-
-    // Client thread
-    void exit(status_t result) {
-        this->result = result;
-        exitPending = true;
-        // Ensure this->result is visible to the binder thread before it
-        // handles the message.
-        atomic_thread_fence(memory_order_release);
-        looper->sendMessage(this, Message(MSG_EXIT));
-    }
-};
-
-
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
-        const sp<IGraphicBufferProducer>& producer,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
-
-    if (CC_UNLIKELY(display == 0))
-        return BAD_VALUE;
-
-    if (CC_UNLIKELY(producer == 0))
-        return BAD_VALUE;
-
-    // if we have secure windows on this display, never allow the screen capture
-    // unless the producer interface is local (i.e.: we can take a screenshot for
-    // ourselves).
-    bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
-
-    // Convert to surfaceflinger's internal rotation type.
-    Transform::orientation_flags rotationFlags;
-    switch (rotation) {
-        case ISurfaceComposer::eRotateNone:
-            rotationFlags = Transform::ROT_0;
-            break;
-        case ISurfaceComposer::eRotate90:
-            rotationFlags = Transform::ROT_90;
-            break;
-        case ISurfaceComposer::eRotate180:
-            rotationFlags = Transform::ROT_180;
-            break;
-        case ISurfaceComposer::eRotate270:
-            rotationFlags = Transform::ROT_270;
-            break;
-        default:
-            rotationFlags = Transform::ROT_0;
-            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
-            break;
-    }
-
-    class MessageCaptureScreen : public MessageBase {
-        SurfaceFlinger* flinger;
-        sp<IBinder> display;
-        sp<IGraphicBufferProducer> producer;
-        Rect sourceCrop;
-        uint32_t reqWidth, reqHeight;
-        int32_t minLayerZ,maxLayerZ;
-        bool useIdentityTransform;
-        Transform::orientation_flags rotation;
-        status_t result;
-        bool isLocalScreenshot;
-    public:
-        MessageCaptureScreen(SurfaceFlinger* flinger,
-                const sp<IBinder>& display,
-                const sp<IGraphicBufferProducer>& producer,
-                Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-                int32_t minLayerZ, int32_t maxLayerZ,
-                bool useIdentityTransform,
-                Transform::orientation_flags rotation,
-                bool isLocalScreenshot)
-            : flinger(flinger), display(display), producer(producer),
-              sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
-              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
-              useIdentityTransform(useIdentityTransform),
-              rotation(rotation), result(PERMISSION_DENIED),
-              isLocalScreenshot(isLocalScreenshot)
-        {
-        }
-        status_t getResult() const {
-            return result;
-        }
-        virtual bool handler() {
-            Mutex::Autolock _l(flinger->mStateLock);
-            sp<const DisplayDevice> hw(flinger->getDisplayDeviceLocked(display));
-            result = flinger->captureScreenImplLocked(hw, producer,
-                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform, rotation, isLocalScreenshot);
-            static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
-            return true;
-        }
-    };
-
-    // this creates a "fake" BBinder which will serve as a "fake" remote
-    // binder to receive the marshaled calls and forward them to the
-    // real remote (a BpGraphicBufferProducer)
-    sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
-
-    // the asInterface() call below creates our "fake" BpGraphicBufferProducer
-    // which does the marshaling work forwards to our "fake remote" above.
-    sp<MessageBase> msg = new MessageCaptureScreen(this,
-            display, IGraphicBufferProducer::asInterface( wrapper ),
-            sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-            useIdentityTransform, rotationFlags, isLocalScreenshot);
-
-    status_t res = postMessageAsync(msg);
-    if (res == NO_ERROR) {
-        res = wrapper->waitForResponse();
-    }
-    return res;
-}
-
-
-void SurfaceFlinger::renderScreenImplLocked(
-        const sp<const DisplayDevice>& hw,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
-{
-    ATRACE_CALL();
-    RenderEngine& engine(getRenderEngine());
-
-    // get screen geometry
-    const int32_t hw_w = hw->getWidth();
-    const int32_t hw_h = hw->getHeight();
-    const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
-                           static_cast<int32_t>(reqHeight) != hw_h;
-
-    // if a default or invalid sourceCrop is passed in, set reasonable values
-    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
-            !sourceCrop.isValid()) {
-        sourceCrop.setLeftTop(Point(0, 0));
-        sourceCrop.setRightBottom(Point(hw_w, hw_h));
-    }
-
-    // ensure that sourceCrop is inside screen
-    if (sourceCrop.left < 0) {
-        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
-    }
-    if (sourceCrop.right > hw_w) {
-        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
-    }
-    if (sourceCrop.top < 0) {
-        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
-    }
-    if (sourceCrop.bottom > hw_h) {
-        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
-    }
-
-    // make sure to clear all GL error flags
-    engine.checkErrors();
-
-    // set-up our viewport
-    engine.setViewportAndProjection(
-        reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
-    engine.disableTexturing();
-
-    // redraw the screen entirely...
-    engine.clearWithColor(0, 0, 0, 1);
-
-    // We loop through the first level of layers without traversing,
-    // as we need to interpret min/max layer Z in the top level Z space.
-    for (const auto& layer : mDrawingState.layersSortedByZ) {
-        if (layer->getLayerStack() != hw->getLayerStack()) {
-            continue;
-        }
-        const Layer::State& state(layer->getDrawingState());
-        if (state.z < minLayerZ || state.z > maxLayerZ) {
-            continue;
-        }
-        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
-            if (!layer->isVisible()) {
-                return;
-            }
-            if (filtering) layer->setFiltering(true);
-            layer->draw(hw, useIdentityTransform);
-            if (filtering) layer->setFiltering(false);
-        });
-    }
-
-    // compositionComplete is needed for older driver
-    hw->compositionComplete();
-    hw->setViewportAndProjection();
-}
-
-
-status_t SurfaceFlinger::captureScreenImplLocked(
-        const sp<const DisplayDevice>& hw,
-        const sp<IGraphicBufferProducer>& producer,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform, Transform::orientation_flags rotation,
-        bool isLocalScreenshot)
-{
-    ATRACE_CALL();
-
-    // get screen geometry
-    uint32_t hw_w = hw->getWidth();
-    uint32_t hw_h = hw->getHeight();
-
-    if (rotation & Transform::ROT_90) {
-        std::swap(hw_w, hw_h);
-    }
-
-    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)",
-                reqWidth, reqHeight, hw_w, hw_h);
-        return BAD_VALUE;
-    }
-
-    reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
-    reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
-    bool secureLayerIsVisible = false;
-    for (const auto& layer : mDrawingState.layersSortedByZ) {
-        const Layer::State& state(layer->getDrawingState());
-        if ((layer->getLayerStack() != hw->getLayerStack()) ||
-                (state.z < minLayerZ || state.z > maxLayerZ)) {
-            continue;
-        }
-        layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
-            secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
-                    layer->isSecure());
-        });
-    }
-
-    if (!isLocalScreenshot && secureLayerIsVisible) {
-        ALOGW("FB is protected: PERMISSION_DENIED");
-        return PERMISSION_DENIED;
-    }
-
-    // create a surface (because we're a producer, and we need to
-    // dequeue/queue a buffer)
-    sp<Surface> sur = new Surface(producer, false);
-    ANativeWindow* window = sur.get();
-
-    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
-    if (result == NO_ERROR) {
-        uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
-                        GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
-        int err = 0;
-        err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
-        err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-        err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
-        err |= native_window_set_usage(window, usage);
-
-        if (err == NO_ERROR) {
-            ANativeWindowBuffer* buffer;
-            /* TODO: Once we have the sync framework everywhere this can use
-             * server-side waits on the fence that dequeueBuffer returns.
-             */
-            result = native_window_dequeue_buffer_and_wait(window,  &buffer);
-            if (result == NO_ERROR) {
-                int syncFd = -1;
-                // create an EGLImage from the buffer so we can later
-                // turn it into a texture
-                EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
-                        EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
-                if (image != EGL_NO_IMAGE_KHR) {
-                    // this binds the given EGLImage as a framebuffer for the
-                    // duration of this scope.
-                    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
-                    if (imageBond.getStatus() == NO_ERROR) {
-                        // this will in fact render into our dequeued buffer
-                        // via an FBO, which means we didn't have to create
-                        // an EGLSurface and therefore we're not
-                        // dependent on the context's EGLConfig.
-                        renderScreenImplLocked(
-                            hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
-                            useIdentityTransform, rotation);
-
-                        // Attempt to create a sync khr object that can produce a sync point. If that
-                        // isn't available, create a non-dupable sync object in the fallback path and
-                        // wait on it directly.
-                        EGLSyncKHR sync;
-                        if (!DEBUG_SCREENSHOTS) {
-                           sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
-                           // native fence fd will not be populated until flush() is done.
-                           getRenderEngine().flush();
-                        } else {
-                            sync = EGL_NO_SYNC_KHR;
-                        }
-                        if (sync != EGL_NO_SYNC_KHR) {
-                            // get the sync fd
-                            syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
-                            if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-                                ALOGW("captureScreen: failed to dup sync khr object");
-                                syncFd = -1;
-                            }
-                            eglDestroySyncKHR(mEGLDisplay, sync);
-                        } else {
-                            // fallback path
-                            sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
-                            if (sync != EGL_NO_SYNC_KHR) {
-                                EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
-                                    EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
-                                EGLint eglErr = eglGetError();
-                                if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-                                    ALOGW("captureScreen: fence wait timed out");
-                                } else {
-                                    ALOGW_IF(eglErr != EGL_SUCCESS,
-                                            "captureScreen: error waiting on EGL fence: %#x", eglErr);
-                                }
-                                eglDestroySyncKHR(mEGLDisplay, sync);
-                            } else {
-                                ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
-                            }
-                        }
-                        if (DEBUG_SCREENSHOTS) {
-                            uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
-                            getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
-                            checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
-                                    hw, minLayerZ, maxLayerZ);
-                            delete [] pixels;
-                        }
-
-                    } else {
-                        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
-                        result = INVALID_OPERATION;
-                        window->cancelBuffer(window, buffer, syncFd);
-                        buffer = NULL;
-                    }
-                    // destroy our image
-                    eglDestroyImageKHR(mEGLDisplay, image);
-                } else {
-                    result = BAD_VALUE;
-                }
-                if (buffer) {
-                    // queueBuffer takes ownership of syncFd
-                    result = window->queueBuffer(window, buffer, syncFd);
-                }
-            }
-        } else {
-            result = BAD_VALUE;
-        }
-        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
-    }
-
-    return result;
-}
-
-void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
-        const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) {
-    if (DEBUG_SCREENSHOTS) {
-        for (size_t y=0 ; y<h ; y++) {
-            uint32_t const * p = (uint32_t const *)vaddr + y*s;
-            for (size_t x=0 ; x<w ; x++) {
-                if (p[x] != 0xFF000000) return;
-            }
-        }
-        ALOGE("*** we just took a black screenshot ***\n"
-                "requested minz=%d, maxz=%d, layerStack=%d",
-                minLayerZ, maxLayerZ, hw->getLayerStack());
-        size_t i = 0;
-        for (const auto& layer : mDrawingState.layersSortedByZ) {
-            const Layer::State& state(layer->getDrawingState());
-            if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
-                    state.z <= maxLayerZ) {
-                layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
-                    ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x",
-                            layer->isVisible() ? '+' : '-',
-                            i, layer->getName().string(), layer->getLayerStack(), state.z,
-                            layer->isVisible(), state.flags, state.alpha);
-                    i++;
-                });
-            }
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
-    layersSortedByZ.traverseInZOrder(stateSet, visitor);
-}
-
-void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& visitor) const {
-    layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
-}
-
-}; // namespace android
-
-
-#if defined(__gl_h_)
-#error "don't include gl/gl.h in this file"
-#endif
-
-#if defined(__gl2_h_)
-#error "don't include gl2/gl2.h in this file"
-#endif
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index db489b2..eeb4929 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -98,7 +98,7 @@
     addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(),
             layer->mCurrentState.active.transform.ty());
     addDepthLocked(transaction, layerId, layer->mCurrentState.z);
-    addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha);
+    addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a);
     addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion);
     addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
     addCropLocked(transaction, layerId, layer->mCurrentState.crop);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
new file mode 100644
index 0000000..f8c466e
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef LOG_TAG
+#define LOG_TAG "SurfaceTracing"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "SurfaceTracing.h"
+
+#include <android-base/file.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+namespace android {
+
+void SurfaceTracing::enable() {
+    if (mEnabled) {
+        return;
+    }
+    ATRACE_CALL();
+    mEnabled = true;
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
+    mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
+                            LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+}
+
+status_t SurfaceTracing::disable() {
+    if (!mEnabled) {
+        return NO_ERROR;
+    }
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    mEnabled = false;
+    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.Clear();
+    return err;
+}
+
+bool SurfaceTracing::isEnabled() {
+    return mEnabled;
+}
+
+void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
+    LayersTraceProto* entry = mTrace.add_entry();
+    entry->set_elapsed_realtime_nanos(elapsedRealtimeNano());
+    entry->set_where(where);
+    entry->mutable_layers()->Swap(&layers);
+}
+
+status_t SurfaceTracing::writeProtoFileLocked() {
+    ATRACE_CALL();
+
+    if (!mTrace.IsInitialized()) {
+        return NOT_ENOUGH_DATA;
+    }
+    std::string output;
+    if (!mTrace.SerializeToString(&output)) {
+        return PERMISSION_DENIED;
+    }
+    if (!android::base::WriteStringToFile(output, mOutputFileName, true)) {
+        return PERMISSION_DENIED;
+    }
+
+    return NO_ERROR;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
new file mode 100644
index 0000000..590ab96
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <layerproto/LayerProtoHeader.h>
+#include <utils/Errors.h>
+
+#include <mutex>
+
+using namespace android::surfaceflinger;
+
+namespace android {
+
+/*
+ * SurfaceTracing records layer states during surface flinging.
+ */
+class SurfaceTracing {
+public:
+    void enable();
+    status_t disable();
+    bool isEnabled();
+
+    void traceLayers(const char* where, LayersProto);
+
+private:
+    static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb";
+
+    status_t writeProtoFileLocked();
+
+    bool mEnabled = false;
+    std::string mOutputFileName = DEFAULT_FILENAME;
+    std::mutex mTraceMutex;
+    LayersTraceFileProto mTrace;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 6be9ae2..37925a1 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -20,8 +20,8 @@
 #include <utils/String8.h>
 #include <ui/Region.h>
 
-#include "clz.h"
 #include "Transform.h"
+#include "clz.h"
 
 // ---------------------------------------------------------------------------
 
@@ -388,6 +388,23 @@
     ALOGD("%.4f  %.4f  %.4f", m[0][2], m[1][2], m[2][2]);
 }
 
+Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) {
+    // Convert to surfaceflinger's internal rotation type.
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            return Transform::ROT_0;
+        case ISurfaceComposer::eRotate90:
+            return Transform::ROT_90;
+        case ISurfaceComposer::eRotate180:
+            return Transform::ROT_180;
+        case ISurfaceComposer::eRotate270:
+            return Transform::ROT_270;
+        default:
+            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+            return Transform::ROT_0;
+    }
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 6640a13..bfc66ec 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -25,6 +25,8 @@
 #include <math/vec2.h>
 #include <math/vec3.h>
 
+#include <gui/ISurfaceComposer.h>
+
 #include <hardware/hardware.h>
 
 namespace android {
@@ -51,6 +53,8 @@
                 ROT_INVALID = 0x80
             };
 
+            static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation);
+
             enum type_mask {
                 IDENTITY            = 0,
                 TRANSLATE           = 0x1,
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
new file mode 100644
index 0000000..8eb218c
--- /dev/null
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -0,0 +1,36 @@
+cc_library_shared {
+    name: "liblayers_proto",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+
+    srcs: [
+        "LayerProtoParser.cpp",
+        "layers.proto",
+        "layerstrace.proto",
+    ],
+
+    shared_libs: [
+        "libui",
+        "libprotobuf-cpp-lite",
+        "libbase",
+    ],
+
+    proto: {
+        export_proto_headers: true,
+    },
+
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-format",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-float-conversion",
+        "-Wno-disabled-macro-expansion",
+        "-Wno-float-equal",
+        "-Wno-sign-conversion",
+        "-Wno-padded",
+        "-Wno-old-style-cast",
+        "-Wno-undef",
+    ],
+
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
new file mode 100644
index 0000000..bf37e1e
--- /dev/null
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/stringprintf.h>
+#include <layerproto/LayerProtoParser.h>
+#include <ui/DebugUtils.h>
+
+using android::base::StringAppendF;
+using android::base::StringPrintf;
+
+namespace android {
+namespace surfaceflinger {
+
+bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+    uint32_t ls = lhs->layerStack;
+    uint32_t rs = rhs->layerStack;
+    if (ls != rs) return ls < rs;
+
+    int32_t lz = lhs->z;
+    int32_t rz = rhs->z;
+    if (lz != rz) {
+        return (lz > rz) ? 1 : -1;
+    }
+
+    return lhs->id < rhs->id;
+}
+
+std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+        const LayersProto& layersProto) {
+    auto layerMap = generateMap(layersProto);
+
+    std::vector<const Layer*> layers;
+    std::for_each(layerMap.begin(), layerMap.end(),
+                  [&](const std::pair<const int32_t, Layer*>& ref) {
+                      if (ref.second->parent == nullptr) {
+                          // only save top level layers
+                          layers.push_back(ref.second);
+                      }
+                  });
+
+    std::sort(layers.begin(), layers.end(), sortLayers);
+    return layers;
+}
+
+std::unordered_map<int32_t, LayerProtoParser::Layer*> LayerProtoParser::generateMap(
+        const LayersProto& layersProto) {
+    std::unordered_map<int32_t, Layer*> layerMap;
+
+    for (int i = 0; i < layersProto.layers_size(); i++) {
+        const LayerProto& layerProto = layersProto.layers(i);
+        layerMap[layerProto.id()] = generateLayer(layerProto);
+    }
+
+    for (int i = 0; i < layersProto.layers_size(); i++) {
+        const LayerProto& layerProto = layersProto.layers(i);
+        updateChildrenAndRelative(layerProto, layerMap);
+    }
+
+    return layerMap;
+}
+
+LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) {
+    Layer* layer = new Layer();
+    layer->id = layerProto.id();
+    layer->name = layerProto.name();
+    layer->type = layerProto.type();
+    layer->transparentRegion = generateRegion(layerProto.transparent_region());
+    layer->visibleRegion = generateRegion(layerProto.visible_region());
+    layer->damageRegion = generateRegion(layerProto.damage_region());
+    layer->layerStack = layerProto.layer_stack();
+    layer->z = layerProto.z();
+    layer->position = {layerProto.position().x(), layerProto.position().y()};
+    layer->requestedPosition = {layerProto.requested_position().x(),
+                                layerProto.requested_position().y()};
+    layer->size = {layerProto.size().w(), layerProto.size().h()};
+    layer->crop = generateRect(layerProto.crop());
+    layer->finalCrop = generateRect(layerProto.final_crop());
+    layer->isOpaque = layerProto.is_opaque();
+    layer->invalidate = layerProto.invalidate();
+    layer->dataspace = layerProto.dataspace();
+    layer->pixelFormat = layerProto.pixel_format();
+    layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(),
+                    layerProto.color().a()};
+    layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(),
+                             layerProto.requested_color().b(), layerProto.requested_color().a()};
+    layer->flags = layerProto.flags();
+    layer->transform = generateTransform(layerProto.transform());
+    layer->requestedTransform = generateTransform(layerProto.requested_transform());
+    layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
+    layer->queuedFrames = layerProto.queued_frames();
+    layer->refreshPending = layerProto.refresh_pending();
+
+    return layer;
+}
+
+LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) {
+    LayerProtoParser::Region region;
+    region.id = regionProto.id();
+    for (int i = 0; i < regionProto.rect_size(); i++) {
+        const RectProto& rectProto = regionProto.rect(i);
+        region.rects.push_back(generateRect(rectProto));
+    }
+
+    return region;
+}
+
+LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) {
+    LayerProtoParser::Rect rect;
+    rect.left = rectProto.left();
+    rect.top = rectProto.top();
+    rect.right = rectProto.right();
+    rect.bottom = rectProto.bottom();
+
+    return rect;
+}
+
+LayerProtoParser::Transform LayerProtoParser::generateTransform(
+        const TransformProto& transformProto) {
+    LayerProtoParser::Transform transform;
+    transform.dsdx = transformProto.dsdx();
+    transform.dtdx = transformProto.dtdx();
+    transform.dsdy = transformProto.dsdy();
+    transform.dtdy = transformProto.dtdy();
+
+    return transform;
+}
+
+LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer(
+        const ActiveBufferProto& activeBufferProto) {
+    LayerProtoParser::ActiveBuffer activeBuffer;
+    activeBuffer.width = activeBufferProto.width();
+    activeBuffer.height = activeBufferProto.height();
+    activeBuffer.stride = activeBufferProto.stride();
+    activeBuffer.format = activeBufferProto.format();
+
+    return activeBuffer;
+}
+
+void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto,
+                                                 std::unordered_map<int32_t, Layer*>& layerMap) {
+    auto currLayer = layerMap[layerProto.id()];
+
+    for (int i = 0; i < layerProto.children_size(); i++) {
+        if (layerMap.count(layerProto.children(i)) > 0) {
+            auto childLayer = layerMap[layerProto.children(i)];
+            currLayer->children.push_back(childLayer);
+        }
+    }
+
+    for (int i = 0; i < layerProto.relatives_size(); i++) {
+        if (layerMap.count(layerProto.relatives(i)) > 0) {
+            auto relativeLayer = layerMap[layerProto.relatives(i)];
+            currLayer->relatives.push_back(relativeLayer);
+        }
+    }
+
+    if (layerProto.has_parent()) {
+        if (layerMap.count(layerProto.parent()) > 0) {
+            auto parentLayer = layerMap[layerProto.parent()];
+            currLayer->parent = parentLayer;
+        }
+    }
+
+    if (layerProto.has_z_order_relative_of()) {
+        if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
+            auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
+            currLayer->zOrderRelativeOf = relativeLayer;
+        }
+    }
+}
+
+std::string LayerProtoParser::layersToString(
+        const std::vector<const LayerProtoParser::Layer*> layers) {
+    std::string result;
+    for (const LayerProtoParser::Layer* layer : layers) {
+        if (layer->zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        result.append(layerToString(layer).c_str());
+    }
+
+    return result;
+}
+
+std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+    std::string result;
+
+    std::vector<const Layer*> traverse(layer->relatives);
+    for (const LayerProtoParser::Layer* child : layer->children) {
+        if (child->zOrderRelativeOf != nullptr) {
+            continue;
+        }
+
+        traverse.push_back(child);
+    }
+
+    std::sort(traverse.begin(), traverse.end(), sortLayers);
+
+    size_t i = 0;
+    for (; i < traverse.size(); i++) {
+        const auto& relative = traverse[i];
+        if (relative->z >= 0) {
+            break;
+        }
+        result.append(layerToString(relative).c_str());
+    }
+    result.append(layer->to_string().c_str());
+    result.append("\n");
+    for (; i < traverse.size(); i++) {
+        const auto& relative = traverse[i];
+        result.append(layerToString(relative).c_str());
+    }
+
+    return result;
+}
+
+std::string LayerProtoParser::ActiveBuffer::to_string() const {
+    return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride,
+                        decodePixelFormat(format).c_str());
+}
+
+std::string LayerProtoParser::Transform::to_string() const {
+    return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(dsdx),
+                        static_cast<double>(dtdx), static_cast<double>(dsdy),
+                        static_cast<double>(dtdy));
+}
+
+std::string LayerProtoParser::Rect::to_string() const {
+    return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
+}
+
+std::string LayerProtoParser::Region::to_string(const char* what) const {
+    std::string result =
+            StringPrintf("  Region %s (this=%lx count=%d)\n", what, static_cast<unsigned long>(id),
+                         static_cast<int>(rects.size()));
+
+    for (auto& rect : rects) {
+        StringAppendF(&result, "    %s\n", rect.to_string().c_str());
+    }
+
+    return result;
+}
+
+std::string LayerProtoParser::Layer::to_string() const {
+    std::string result;
+    StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str());
+    result.append(transparentRegion.to_string("TransparentRegion").c_str());
+    result.append(visibleRegion.to_string("VisibleRegion").c_str());
+    result.append(damageRegion.to_string("SurfaceDamageRegion").c_str());
+
+    StringAppendF(&result, "      layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", layerStack,
+                  z, static_cast<double>(position.x), static_cast<double>(position.y), size.x,
+                  size.y);
+
+    StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
+                  finalCrop.to_string().c_str());
+    StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
+    StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
+    StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+    StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+                  static_cast<double>(color.r), static_cast<double>(color.g),
+                  static_cast<double>(color.b), static_cast<double>(color.a), flags);
+    StringAppendF(&result, "tr=%s", transform.to_string().c_str());
+    result.append("\n");
+    StringAppendF(&result, "      parent=%s\n", parent == nullptr ? "none" : parent->name.c_str());
+    StringAppendF(&result, "      zOrderRelativeOf=%s\n",
+                  zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
+    StringAppendF(&result, "      activeBuffer=%s,", activeBuffer.to_string().c_str());
+    StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending);
+
+    return result;
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
new file mode 100644
index 0000000..f560562
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Projectlayerproto/LayerProtoHeader.h
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// pragma is used here to disable the warnings emitted from the protobuf
+// headers. By adding #pragma before including layer.pb.h, it supresses
+// protobuf warnings, but allows the rest of the files to continuing using
+// the current flags.
+// This file should be included instead of directly including layer.b.h
+#pragma GCC system_header
+#include <layers.pb.h>
+#include <layerstrace.pb.h>
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
new file mode 100644
index 0000000..78c6cd1
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <math/vec4.h>
+
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace surfaceflinger {
+
+class LayerProtoParser {
+public:
+    class ActiveBuffer {
+    public:
+        uint32_t width;
+        uint32_t height;
+        uint32_t stride;
+        int32_t format;
+
+        std::string to_string() const;
+    };
+
+    class Transform {
+    public:
+        float dsdx;
+        float dtdx;
+        float dsdy;
+        float dtdy;
+
+        std::string to_string() const;
+    };
+
+    class Rect {
+    public:
+        int32_t left;
+        int32_t top;
+        int32_t right;
+        int32_t bottom;
+
+        std::string to_string() const;
+    };
+
+    class Region {
+    public:
+        uint64_t id;
+        std::vector<Rect> rects;
+
+        std::string to_string(const char* what) const;
+    };
+
+    class Layer {
+    public:
+        int32_t id;
+        std::string name;
+        std::vector<const Layer*> children;
+        std::vector<const Layer*> relatives;
+        std::string type;
+        LayerProtoParser::Region transparentRegion;
+        LayerProtoParser::Region visibleRegion;
+        LayerProtoParser::Region damageRegion;
+        uint32_t layerStack;
+        int32_t z;
+        float2 position;
+        float2 requestedPosition;
+        int2 size;
+        LayerProtoParser::Rect crop;
+        LayerProtoParser::Rect finalCrop;
+        bool isOpaque;
+        bool invalidate;
+        std::string dataspace;
+        std::string pixelFormat;
+        half4 color;
+        half4 requestedColor;
+        uint32_t flags;
+        Transform transform;
+        Transform requestedTransform;
+        Layer* parent = 0;
+        Layer* zOrderRelativeOf = 0;
+        LayerProtoParser::ActiveBuffer activeBuffer;
+        int32_t queuedFrames;
+        bool refreshPending;
+
+        std::string to_string() const;
+    };
+
+    static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
+    static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+
+private:
+    static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
+    static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto);
+    static LayerProtoParser::Region generateRegion(const RegionProto& regionProto);
+    static LayerProtoParser::Rect generateRect(const RectProto& rectProto);
+    static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto);
+    static LayerProtoParser::ActiveBuffer generateActiveBuffer(
+            const ActiveBufferProto& activeBufferProto);
+    static void updateChildrenAndRelative(const LayerProto& layerProto,
+                                          std::unordered_map<int32_t, Layer*>& layerMap);
+
+    static std::string layerToString(const LayerProtoParser::Layer* layer);
+};
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
new file mode 100644
index 0000000..d27dc9b
--- /dev/null
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -0,0 +1,110 @@
+// Definitions for SurfaceFlinger layers.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+package android.surfaceflinger;
+
+// Contains a list of all layers.
+message LayersProto {
+  repeated LayerProto layers = 1;
+}
+
+// Information about each layer.
+message LayerProto {
+  // unique id per layer.
+  optional int32 id = 1;
+  // unique name per layer.
+  optional string name = 2;
+  // list of children this layer may have. May be empty.
+  repeated int32 children = 3;
+  // list of layers that are z order relative to this layer.
+  repeated int32 relatives = 4;
+  // The type of layer, ex Color, Layer
+  optional string type = 5;
+  optional RegionProto transparent_region = 6;
+  optional RegionProto visible_region = 7;
+  optional RegionProto damage_region = 8;
+  optional uint32 layer_stack = 9;
+  // The layer's z order. Can be z order in layer stack, relative to parent,
+  // or relative to another layer specified in zOrderRelative.
+  optional int32 z = 10;
+  // The layer's position on the display.
+  optional PositionProto position = 11;
+  // The layer's requested position.
+  optional PositionProto requested_position = 12;
+  // The layer's size.
+  optional SizeProto size = 13;
+  // The layer's crop in it's own bounds.
+  optional RectProto crop = 14;
+  // The layer's crop in it's parent's bounds.
+  optional RectProto final_crop = 15;
+  optional bool is_opaque = 16;
+  optional bool invalidate = 17;
+  optional string dataspace = 18;
+  optional string pixel_format = 19;
+  // The layer's actual color.
+  optional ColorProto color = 20;
+  // The layer's requested color.
+  optional ColorProto requested_color = 21;
+  // Can be any combination of
+  //    hidden = 0x01
+  //    opaque = 0x02,
+  //    secure = 0x80,
+  optional uint32 flags = 22;
+  // The layer's actual transform
+  optional TransformProto transform = 23;
+  // The layer's requested transform.
+  optional TransformProto requested_transform = 24;
+  // The parent layer. This value can be null if there is no parent.
+  optional int32 parent = 25 [default = -1];
+  // The layer that this layer has a z order relative to. This value can be null.
+  optional int32 z_order_relative_of = 26 [default = -1];
+  // This value can be null if there's nothing to draw.
+  optional ActiveBufferProto active_buffer = 27;
+  // The number of frames available.
+  optional int32 queued_frames = 28;
+  optional bool refresh_pending = 29;
+}
+
+message PositionProto {
+  optional float x = 1;
+  optional float y = 2;
+}
+
+message SizeProto {
+  optional int32 w = 1;
+  optional int32 h = 2;
+}
+
+message TransformProto {
+  optional float dsdx = 1;
+  optional float dtdx = 2;
+  optional float dsdy = 3;
+  optional float dtdy = 4;
+}
+
+message RegionProto {
+  optional uint64 id = 1;
+  repeated RectProto rect = 2;
+}
+
+message RectProto {
+  optional int32 left   = 1;
+  optional int32 top    = 2;
+  optional int32 right  = 3;
+  optional int32 bottom = 4;
+}
+
+message ActiveBufferProto {
+  optional uint32 width = 1;
+  optional uint32 height = 2;
+  optional uint32 stride = 3;
+  optional int32 format = 4;
+}
+
+message ColorProto {
+  optional float r = 1;
+  optional float g = 2;
+  optional float b = 3;
+  optional float a = 4;
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
new file mode 100644
index 0000000..bee17d2
--- /dev/null
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+import "frameworks/native/services/surfaceflinger/layerproto/layers.proto";
+
+package android.surfaceflinger;
+
+/* represents a file full of surface flinger trace entries.
+   Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such
+   that they can be easily identified. */
+message LayersTraceFileProto {
+
+    /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+       (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+        constants into .proto files. */
+    enum MagicNumber {
+        INVALID = 0;
+        MAGIC_NUMBER_L = 0x5452594c;  /* LYRT (little-endian ASCII) */
+        MAGIC_NUMBER_H = 0x45434152;  /* RACE (little-endian ASCII) */
+    }
+
+    optional fixed64 magic_number = 1;  /* Must be the first field, set to value in MagicNumber */
+    repeated LayersTraceProto entry = 2;
+}
+
+/* one window manager trace entry. */
+message LayersTraceProto {
+    /* required: elapsed realtime in nanos since boot of when this entry was logged */
+    optional fixed64 elapsed_realtime_nanos = 1;
+
+    /* where the trace originated */
+    optional string where = 2;
+
+    optional LayersProto layers = 3;
+}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index e50f3ce..2a924ae 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -105,7 +105,8 @@
 
     // publish surface flinger
     sp<IServiceManager> sm(defaultServiceManager());
-    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
+    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
+                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
 
     // publish GpuService
     sp<GpuService> gpuservice = new GpuService();
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 6be708a..be4127c 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*"
+            "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*"
         }
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 0cc763c..ed806b8 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -22,10 +22,11 @@
 #include <android/native_window.h>
 
 #include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
+
 #include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
 #include <ui/DisplayInfo.h>
 
 #include <fstream>
@@ -34,6 +35,8 @@
 
 namespace android {
 
+using Transaction = SurfaceComposerClient::Transaction;
+
 constexpr int32_t SCALING_UPDATE = 1;
 constexpr uint32_t BUFFER_UPDATES = 18;
 constexpr uint32_t LAYER_UPDATE = INT_MAX - 2;
@@ -149,11 +152,11 @@
         ASSERT_TRUE(mBGSurfaceControl->isValid());
         mBGLayerId = getSurfaceId("BG Interceptor Test Surface");
 
-        SurfaceComposerClient::openGlobalTransaction();
-        mComposerClient->setDisplayLayerStack(display, 0);
-        ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-3));
-        ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
-        SurfaceComposerClient::closeGlobalTransaction(true);
+        Transaction t;
+        t.setDisplayLayerStack(display, 0);
+        ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
+                .show(mBGSurfaceControl)
+                .apply());
     }
 
     virtual void TearDown() {
@@ -169,13 +172,14 @@
     int32_t mTargetId;
 
 public:
-    void captureTest(void (SurfaceInterceptorTest::* action)(void),
+    void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
             bool (SurfaceInterceptorTest::* verification)(Trace *));
-    void captureTest(void (SurfaceInterceptorTest::* action)(void),
+    void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
             SurfaceChange::SurfaceChangeCase changeCase);
-    void captureTest(void (SurfaceInterceptorTest::* action)(void),
+    void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
             Increment::IncrementCase incrementCase);
-    void runInTransaction(void (SurfaceInterceptorTest::* action)(void), bool intercepted = false);
+    void runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
+            bool intercepted = false);
 
     // Verification of changes to a surface
     bool positionUpdateFound(const SurfaceChange& change, bool foundPosition);
@@ -206,28 +210,29 @@
     bool bufferUpdatesFound(Trace* trace);
 
     // Perform each of the possible changes to a surface
-    void positionUpdate();
-    void sizeUpdate();
-    void alphaUpdate();
-    void layerUpdate();
-    void cropUpdate();
-    void finalCropUpdate();
-    void matrixUpdate();
-    void overrideScalingModeUpdate();
-    void transparentRegionHintUpdate();
-    void layerStackUpdate();
-    void hiddenFlagUpdate();
-    void opaqueFlagUpdate();
-    void secureFlagUpdate();
-    void deferredTransactionUpdate();
-    void runAllUpdates();
-    void surfaceCreation();
+    void positionUpdate(Transaction&);
+    void sizeUpdate(Transaction&);
+    void alphaUpdate(Transaction&);
+    void layerUpdate(Transaction&);
+    void cropUpdate(Transaction&);
+    void finalCropUpdate(Transaction&);
+    void matrixUpdate(Transaction&);
+    void overrideScalingModeUpdate(Transaction&);
+    void transparentRegionHintUpdate(Transaction&);
+    void layerStackUpdate(Transaction&);
+    void hiddenFlagUpdate(Transaction&);
+    void opaqueFlagUpdate(Transaction&);
+    void secureFlagUpdate(Transaction&);
+    void deferredTransactionUpdate(Transaction&);
+    void surfaceCreation(Transaction&);
+    void displayCreation(Transaction&);
+    void displayDeletion(Transaction&);
+
     void nBufferUpdates();
-    void displayCreation();
-    void displayDeletion();
+    void runAllUpdates();
 };
 
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
         bool (SurfaceInterceptorTest::* verification)(Trace *))
 {
     runInTransaction(action, true);
@@ -236,7 +241,7 @@
     ASSERT_TRUE((this->*verification)(&capturedTrace));
 }
 
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
         Increment::IncrementCase incrementCase)
 {
     runInTransaction(action, true);
@@ -245,7 +250,7 @@
     ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase));
 }
 
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
         SurfaceChange::SurfaceChangeCase changeCase)
 {
     runInTransaction(action, true);
@@ -254,83 +259,84 @@
     ASSERT_TRUE(surfaceUpdateFound(&capturedTrace, changeCase));
 }
 
-void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
         bool intercepted)
 {
     if (intercepted) {
         enableInterceptor();
     }
-    SurfaceComposerClient::openGlobalTransaction();
-    (this->*action)();
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    Transaction t;
+    (this->*action)(t);
+    t.apply(true);
+
     if (intercepted) {
         disableInterceptor();
     }
 }
 
-void SurfaceInterceptorTest::positionUpdate() {
-    mBGSurfaceControl->setPosition(POSITION_UPDATE, POSITION_UPDATE);
+void SurfaceInterceptorTest::positionUpdate(Transaction& t) {
+    t.setPosition(mBGSurfaceControl, POSITION_UPDATE, POSITION_UPDATE);
 }
 
-void SurfaceInterceptorTest::sizeUpdate() {
-    mBGSurfaceControl->setSize(SIZE_UPDATE, SIZE_UPDATE);
+void SurfaceInterceptorTest::sizeUpdate(Transaction& t) {
+    t.setSize(mBGSurfaceControl, SIZE_UPDATE, SIZE_UPDATE);
 }
 
-void SurfaceInterceptorTest::alphaUpdate() {
-    mBGSurfaceControl->setAlpha(ALPHA_UPDATE);
+void SurfaceInterceptorTest::alphaUpdate(Transaction& t) {
+    t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE);
 }
 
-void SurfaceInterceptorTest::layerUpdate() {
-    mBGSurfaceControl->setLayer(LAYER_UPDATE);
+void SurfaceInterceptorTest::layerUpdate(Transaction& t) {
+    t.setLayer(mBGSurfaceControl, LAYER_UPDATE);
 }
 
-void SurfaceInterceptorTest::cropUpdate() {
-    mBGSurfaceControl->setCrop(CROP_UPDATE);
+void SurfaceInterceptorTest::cropUpdate(Transaction& t) {
+    t.setCrop(mBGSurfaceControl, CROP_UPDATE);
 }
 
-void SurfaceInterceptorTest::finalCropUpdate() {
-    mBGSurfaceControl->setFinalCrop(CROP_UPDATE);
+void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) {
+    t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE);
 }
 
-void SurfaceInterceptorTest::matrixUpdate() {
-    mBGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2);
+void SurfaceInterceptorTest::matrixUpdate(Transaction& t) {
+    t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2);
 }
 
-void SurfaceInterceptorTest::overrideScalingModeUpdate() {
-    mBGSurfaceControl->setOverrideScalingMode(SCALING_UPDATE);
+void SurfaceInterceptorTest::overrideScalingModeUpdate(Transaction& t) {
+    t.setOverrideScalingMode(mBGSurfaceControl, SCALING_UPDATE);
 }
 
-void SurfaceInterceptorTest::transparentRegionHintUpdate() {
+void SurfaceInterceptorTest::transparentRegionHintUpdate(Transaction& t) {
     Region region(CROP_UPDATE);
-    mBGSurfaceControl->setTransparentRegionHint(region);
+    t.setTransparentRegionHint(mBGSurfaceControl, region);
 }
 
-void SurfaceInterceptorTest::layerStackUpdate() {
-    mBGSurfaceControl->setLayerStack(STACK_UPDATE);
+void SurfaceInterceptorTest::layerStackUpdate(Transaction& t) {
+    t.setLayerStack(mBGSurfaceControl, STACK_UPDATE);
 }
 
-void SurfaceInterceptorTest::hiddenFlagUpdate() {
-    mBGSurfaceControl->setFlags(layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+void SurfaceInterceptorTest::hiddenFlagUpdate(Transaction& t) {
+    t.setFlags(mBGSurfaceControl, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
 }
 
-void SurfaceInterceptorTest::opaqueFlagUpdate() {
-    mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+void SurfaceInterceptorTest::opaqueFlagUpdate(Transaction& t) {
+    t.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
 }
 
-void SurfaceInterceptorTest::secureFlagUpdate() {
-    mBGSurfaceControl->setFlags(layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
+void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) {
+    t.setFlags(mBGSurfaceControl, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
 }
 
-void SurfaceInterceptorTest::deferredTransactionUpdate() {
-    mBGSurfaceControl->deferTransactionUntil(mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
+void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) {
+    t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
 }
 
-void SurfaceInterceptorTest::displayCreation() {
+void SurfaceInterceptorTest::displayCreation(Transaction&) {
     sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
     SurfaceComposerClient::destroyDisplay(testDisplay);
 }
 
-void SurfaceInterceptorTest::displayDeletion() {
+void SurfaceInterceptorTest::displayDeletion(Transaction&) {
     sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
     mTargetId = getDisplayId(DISPLAY_NAME.string());
     SurfaceComposerClient::destroyDisplay(testDisplay);
@@ -353,7 +359,7 @@
     runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
 }
 
-void SurfaceInterceptorTest::surfaceCreation() {
+void SurfaceInterceptorTest::surfaceCreation(Transaction&) {
     mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE,
             PIXEL_FORMAT_RGBA_8888, 0);
 }
@@ -825,8 +831,10 @@
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::nBufferUpdates,
-            &SurfaceInterceptorTest::bufferUpdatesFound);
+    nBufferUpdates();
+    Trace capturedTrace;
+    ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+    ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
 }
 
 // If the interceptor is enabled while buffer updates are being pushed, the interceptor should
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4ce14f8..ff81dc9 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -14,26 +14,138 @@
  * limitations under the License.
  */
 
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <ostream>
+
 #include <gtest/gtest.h>
 
 #include <android/native_window.h>
 
 #include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
+
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
 
-#include <utils/String8.h>
 #include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+#include <utils/String8.h>
 
 #include <math.h>
+#include <math/vec3.h>
 
 namespace android {
 
+namespace {
+
+struct Color {
+    uint8_t r;
+    uint8_t g;
+    uint8_t b;
+    uint8_t a;
+
+    static const Color RED;
+    static const Color GREEN;
+    static const Color BLUE;
+    static const Color WHITE;
+    static const Color BLACK;
+    static const Color TRANSPARENT;
+};
+
+const Color Color::RED{255, 0, 0, 255};
+const Color Color::GREEN{0, 255, 0, 255};
+const Color Color::BLUE{0, 0, 255, 255};
+const Color Color::WHITE{255, 255, 255, 255};
+const Color Color::BLACK{0, 0, 0, 255};
+const Color Color::TRANSPARENT{0, 0, 0, 0};
+
+std::ostream& operator<<(std::ostream& os, const Color& color) {
+    os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a);
+    return os;
+}
+
+// Fill a region with the specified color.
+void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) {
+    int32_t x = rect.left;
+    int32_t y = rect.top;
+    int32_t width = rect.right - rect.left;
+    int32_t height = rect.bottom - rect.top;
+
+    if (x < 0) {
+        width += x;
+        x = 0;
+    }
+    if (y < 0) {
+        height += y;
+        y = 0;
+    }
+    if (x + width > buffer.width) {
+        x = std::min(x, buffer.width);
+        width = buffer.width - x;
+    }
+    if (y + height > buffer.height) {
+        y = std::min(y, buffer.height);
+        height = buffer.height - y;
+    }
+
+    for (int32_t j = 0; j < height; j++) {
+        uint8_t* dst = static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (y + j) + x) * 4;
+        for (int32_t i = 0; i < width; i++) {
+            dst[0] = color.r;
+            dst[1] = color.g;
+            dst[2] = color.b;
+            dst[3] = color.a;
+            dst += 4;
+        }
+    }
+}
+
+// Check if a region has the specified color.
+void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels, const Rect& rect,
+                       const Color& color, uint8_t tolerance) {
+    int32_t x = rect.left;
+    int32_t y = rect.top;
+    int32_t width = rect.right - rect.left;
+    int32_t height = rect.bottom - rect.top;
+
+    int32_t bufferWidth = int32_t(outBuffer->getWidth());
+    int32_t bufferHeight = int32_t(outBuffer->getHeight());
+    if (x + width > bufferWidth) {
+        x = std::min(x, bufferWidth);
+        width = bufferWidth - x;
+    }
+    if (y + height > bufferHeight) {
+        y = std::min(y, bufferHeight);
+        height = bufferHeight - y;
+    }
+
+    auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
+        uint8_t tmp = a >= b ? a - b : b - a;
+        return tmp <= tolerance;
+    };
+    for (int32_t j = 0; j < height; j++) {
+        const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
+        for (int32_t i = 0; i < width; i++) {
+            const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
+            EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
+                    << "pixel @ (" << x + i << ", " << y + j << "): "
+                    << "expected (" << color << "), "
+                    << "got (" << Color{src[0], src[1], src[2], src[3]} << ")";
+            src += 4;
+        }
+    }
+}
+
+} // anonymous namespace
+
+using Transaction = SurfaceComposerClient::Transaction;
+
 // Fill an RGBA_8888 formatted surface with a single color.
-static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
-        uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
+static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b,
+                             bool unlock = true) {
     ANativeWindow_Buffer outBuffer;
     sp<Surface> s = sc->getSurface();
     ASSERT_TRUE(s != NULL);
@@ -41,7 +153,7 @@
     uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
     for (int y = 0; y < outBuffer.height; y++) {
         for (int x = 0; x < outBuffer.width; x++) {
-            uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
+            uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
             pixel[0] = r;
             pixel[1] = g;
             pixel[2] = b;
@@ -57,67 +169,1310 @@
 // individual pixel values for testing purposes.
 class ScreenCapture : public RefBase {
 public:
-    static void captureScreen(sp<ScreenCapture>* sc) {
-        sp<IGraphicBufferProducer> producer;
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&producer, &consumer);
-        sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+    static void captureScreen(sp<ScreenCapture>* sc, int32_t minLayerZ = 0,
+                              int32_t maxLayerZ = std::numeric_limits<int32_t>::max()) {
         sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        sp<IBinder> display(sf->getBuiltInDisplay(
-                ISurfaceComposer::eDisplayIdMain));
-        SurfaceComposerClient::openGlobalTransaction();
-        SurfaceComposerClient::closeGlobalTransaction(true);
-        ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0,
-                0, INT_MAX, false));
-        *sc = new ScreenCapture(cpuConsumer);
+        sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        SurfaceComposerClient::Transaction().apply(true);
+
+        sp<GraphicBuffer> outBuffer;
+        ASSERT_EQ(NO_ERROR,
+                  sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ,
+                                    false));
+        *sc = new ScreenCapture(outBuffer);
+    }
+
+    static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
+                              Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
+        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+        SurfaceComposerClient::Transaction().apply(true);
+
+        sp<GraphicBuffer> outBuffer;
+        ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale));
+        *sc = std::make_unique<ScreenCapture>(outBuffer);
+    }
+
+    void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+        ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+        expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
+    }
+
+    void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+        ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+        const bool leftBorder = rect.left > 0;
+        const bool topBorder = rect.top > 0;
+        const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth());
+        const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight());
+
+        if (topBorder) {
+            Rect top(rect.left, rect.top - 1, rect.right, rect.top);
+            if (leftBorder) {
+                top.left -= 1;
+            }
+            if (rightBorder) {
+                top.right += 1;
+            }
+            expectColor(top, color, tolerance);
+        }
+        if (leftBorder) {
+            Rect left(rect.left - 1, rect.top, rect.left, rect.bottom);
+            expectColor(left, color, tolerance);
+        }
+        if (rightBorder) {
+            Rect right(rect.right, rect.top, rect.right + 1, rect.bottom);
+            expectColor(right, color, tolerance);
+        }
+        if (bottomBorder) {
+            Rect bottom(rect.left, rect.bottom, rect.right, rect.bottom + 1);
+            if (leftBorder) {
+                bottom.left -= 1;
+            }
+            if (rightBorder) {
+                bottom.right += 1;
+            }
+            expectColor(bottom, color, tolerance);
+        }
+    }
+
+    void expectQuadrant(const Rect& rect, const Color& topLeft, const Color& topRight,
+                        const Color& bottomLeft, const Color& bottomRight, bool filtered = false,
+                        uint8_t tolerance = 0) {
+        ASSERT_TRUE((rect.right - rect.left) % 2 == 0 && (rect.bottom - rect.top) % 2 == 0);
+
+        const int32_t centerX = rect.left + (rect.right - rect.left) / 2;
+        const int32_t centerY = rect.top + (rect.bottom - rect.top) / 2;
+        // avoid checking borders due to unspecified filtering behavior
+        const int32_t offsetX = filtered ? 2 : 0;
+        const int32_t offsetY = filtered ? 2 : 0;
+        expectColor(Rect(rect.left, rect.top, centerX - offsetX, centerY - offsetY), topLeft,
+                    tolerance);
+        expectColor(Rect(centerX + offsetX, rect.top, rect.right, centerY - offsetY), topRight,
+                    tolerance);
+        expectColor(Rect(rect.left, centerY + offsetY, centerX - offsetX, rect.bottom), bottomLeft,
+                    tolerance);
+        expectColor(Rect(centerX + offsetX, centerY + offsetY, rect.right, rect.bottom),
+                    bottomRight, tolerance);
     }
 
     void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
-        ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
-        const uint8_t* img = static_cast<const uint8_t*>(mBuf.data);
-        const uint8_t* pixel = img + (4 * (y * mBuf.stride + x));
+        ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+        const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
         if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
             String8 err(String8::format("pixel @ (%3d, %3d): "
-                    "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
-                    x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
+                                        "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
+                                        x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
             EXPECT_EQ(String8(), err) << err.string();
         }
     }
 
-    void expectFGColor(uint32_t x, uint32_t y) {
-        checkPixel(x, y, 195, 63, 63);
+    void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); }
+
+    void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); }
+
+    void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
+
+    ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+        mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
     }
 
-    void expectBGColor(uint32_t x, uint32_t y) {
-        checkPixel(x, y, 63, 63, 195);
-    }
-
-    void expectChildColor(uint32_t x, uint32_t y) {
-        checkPixel(x, y, 200, 200, 200);
-    }
+    ~ScreenCapture() { mOutBuffer->unlock(); }
 
 private:
-    ScreenCapture(const sp<CpuConsumer>& cc) :
-        mCC(cc) {
-        EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf));
-    }
-
-    ~ScreenCapture() {
-        mCC->unlockBuffer(mBuf);
-    }
-
-    sp<CpuConsumer> mCC;
-    CpuConsumer::LockedBuffer mBuf;
+    sp<GraphicBuffer> mOutBuffer;
+    uint8_t* mPixels = NULL;
 };
 
-class LayerUpdateTest : public ::testing::Test {
+class LayerTransactionTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        mClient = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient";
+
+        ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
+    }
+
+    sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+                                   uint32_t flags = 0) {
+        auto layer =
+                mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags);
+        EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
+
+        status_t error = Transaction()
+                                 .setLayerStack(layer, mDisplayLayerStack)
+                                 .setLayer(layer, mLayerZBase)
+                                 .apply();
+        if (error != NO_ERROR) {
+            ADD_FAILURE() << "failed to initialize SurfaceControl";
+            layer.clear();
+        }
+
+        return layer;
+    }
+
+    ANativeWindow_Buffer getLayerBuffer(const sp<SurfaceControl>& layer) {
+        // wait for previous transactions (such as setSize) to complete
+        Transaction().apply(true);
+
+        ANativeWindow_Buffer buffer = {};
+        EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
+
+        return buffer;
+    }
+
+    void postLayerBuffer(const sp<SurfaceControl>& layer) {
+        ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
+
+        // wait for the newly posted buffer to be latched
+        waitForLayerBuffers();
+    }
+
+    void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color) {
+        ANativeWindow_Buffer buffer;
+        ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+        fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color);
+        postLayerBuffer(layer);
+    }
+
+    void fillLayerQuadrant(const sp<SurfaceControl>& layer, const Color& topLeft,
+                           const Color& topRight, const Color& bottomLeft,
+                           const Color& bottomRight) {
+        ANativeWindow_Buffer buffer;
+        ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+        ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0);
+
+        const int32_t halfW = buffer.width / 2;
+        const int32_t halfH = buffer.height / 2;
+        fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+        fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight);
+        fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft);
+        fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight);
+
+        postLayerBuffer(layer);
+    }
+
+    sp<ScreenCapture> screenshot() {
+        sp<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot, mLayerZBase);
+        return screenshot;
+    }
+
+    sp<SurfaceComposerClient> mClient;
+
+    sp<IBinder> mDisplay;
+    uint32_t mDisplayWidth;
+    uint32_t mDisplayHeight;
+    uint32_t mDisplayLayerStack;
+
+    // leave room for ~256 layers
+    const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
+
+private:
+    void SetUpDisplay() {
+        mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+        ASSERT_NE(nullptr, mDisplay.get()) << "failed to get built-in display";
+
+        // get display width/height
+        DisplayInfo info;
+        SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+        mDisplayWidth = info.w;
+        mDisplayHeight = info.h;
+
+        // After a new buffer is queued, SurfaceFlinger is notified and will
+        // latch the new buffer on next vsync.  Let's heuristically wait for 3
+        // vsyncs.
+        mBufferPostDelay = int32_t(1e6 / info.fps) * 3;
+
+        mDisplayLayerStack = 0;
+        // set layer stack (b/68888219)
+        Transaction t;
+        t.setDisplayLayerStack(mDisplay, mDisplayLayerStack);
+        t.apply();
+    }
+
+    void waitForLayerBuffers() { usleep(mBufferPostDelay); }
+
+    int32_t mBufferPostDelay;
+};
+
+TEST_F(LayerTransactionTest, SetPositionBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    {
+        SCOPED_TRACE("default position");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    Transaction().setPosition(layer, 5, 10).apply();
+    {
+        SCOPED_TRACE("new position");
+        auto shot = screenshot();
+        shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
+        shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionRounding) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // GLES requires only 4 bits of subpixel precision during rasterization
+    // XXX GLES composition does not match HWC composition due to precision
+    // loss (b/69315223)
+    const float epsilon = 1.0f / 16.0f;
+    Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply();
+    {
+        SCOPED_TRACE("rounding down");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply();
+    {
+        SCOPED_TRACE("rounding up");
+        screenshot()->expectColor(Rect(1, 1, 33, 33), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionOutOfBounds) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    Transaction().setPosition(layer, -32, -32).apply();
+    {
+        SCOPED_TRACE("negative coordinates");
+        screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    }
+
+    Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply();
+    {
+        SCOPED_TRACE("positive coordinates");
+        screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // partially out of bounds
+    Transaction().setPosition(layer, -30, -30).apply();
+    {
+        SCOPED_TRACE("negative coordinates");
+        screenshot()->expectColor(Rect(0, 0, 2, 2), Color::RED);
+    }
+
+    Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply();
+    {
+        SCOPED_TRACE("positive coordinates");
+        screenshot()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth,
+                                       mDisplayHeight),
+                                  Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setPosition is applied immediately by default, with or without resize
+    // pending
+    Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
+        shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("resize applied");
+        screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithNextResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // request setPosition to be applied with the next resize
+    Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply();
+    {
+        SCOPED_TRACE("new position pending");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setPosition(layer, 15, 20).apply();
+    {
+        SCOPED_TRACE("pending new position modified");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setSize(layer, 64, 64).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    // finally resize and latch the buffer
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("new position applied");
+        screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setPosition is not immediate even with SCALE_TO_WINDOW override
+    Transaction()
+            .setPosition(layer, 5, 10)
+            .setSize(layer, 64, 64)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .setGeometryAppliesWithResize(layer)
+            .apply();
+    {
+        SCOPED_TRACE("new position pending");
+        screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("new position applied");
+        screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetSizeBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    Transaction().setSize(layer, 64, 64).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("resize applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
+        shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetSizeInvalid) {
+    // cannot test robustness against invalid sizes (zero or really huge)
+}
+
+TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
+    Transaction()
+            .setSize(layer, 64, 64)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .apply();
+    screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetZBasic) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+    Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+    {
+        SCOPED_TRACE("layerR");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setLayer(layerG, mLayerZBase + 2).apply();
+    {
+        SCOPED_TRACE("layerG");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetZNegative) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+    Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply();
+    {
+        SCOPED_TRACE("layerR");
+        sp<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot, -2, -1);
+        screenshot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setLayer(layerR, -3).apply();
+    {
+        SCOPED_TRACE("layerG");
+        sp<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot, -3, -1);
+        screenshot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZBasic) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+    Transaction()
+            .setPosition(layerG, 16, 16)
+            .setRelativeLayer(layerG, layerR->getHandle(), 1)
+            .apply();
+    {
+        SCOPED_TRACE("layerG above");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+        shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN);
+    }
+
+    Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply();
+    {
+        SCOPED_TRACE("layerG below");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZNegative) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    sp<SurfaceControl> layerB;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+    ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+
+    // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2
+    Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply();
+
+    sp<ScreenCapture> screenshot;
+    // only layerB is in this range
+    ScreenCapture::captureScreen(&screenshot, -2, -1);
+    screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZGroup) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    sp<SurfaceControl> layerB;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+    ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+
+    // layerR = 0, layerG = layerR + 3, layerB = 2
+    Transaction()
+            .setPosition(layerG, 8, 8)
+            .setRelativeLayer(layerG, layerR->getHandle(), 3)
+            .setPosition(layerB, 16, 16)
+            .setLayer(layerB, mLayerZBase + 2)
+            .apply();
+    {
+        SCOPED_TRACE("(layerR < layerG) < layerB");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+        shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN);
+        shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+    }
+
+    // layerR = 4, layerG = layerR + 3, layerB = 2
+    Transaction().setLayer(layerR, mLayerZBase + 4).apply();
+    {
+        SCOPED_TRACE("layerB < (layerR < layerG)");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+        shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN);
+        shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+    }
+
+    // layerR = 4, layerG = layerR - 3, layerB = 2
+    Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply();
+    {
+        SCOPED_TRACE("layerB < (layerG < layerR)");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN);
+        shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+    }
+
+    // restore to absolute z
+    // layerR = 4, layerG = 0, layerB = 2
+    Transaction().setLayer(layerG, mLayerZBase).apply();
+    {
+        SCOPED_TRACE("layerG < layerB < layerR");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE);
+    }
+
+    // layerR should not affect layerG anymore
+    // layerR = 1, layerG = 0, layerB = 2
+    Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+    {
+        SCOPED_TRACE("layerG < layerR < layerB");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+        shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZBug64572777) {
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+    Transaction()
+            .setPosition(layerG, 16, 16)
+            .setRelativeLayer(layerG, layerR->getHandle(), 1)
+            .apply();
+
+    mClient->destroySurface(layerG->getHandle());
+    // layerG should have been removed
+    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetFlagsHidden) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
+    {
+        SCOPED_TRACE("layer hidden");
+        screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    }
+
+    Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply();
+    {
+        SCOPED_TRACE("layer shown");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFlagsOpaque) {
+    const Color translucentRed = {100, 0, 0, 100};
+    sp<SurfaceControl> layerR;
+    sp<SurfaceControl> layerG;
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed));
+    ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+    Transaction()
+            .setLayer(layerR, mLayerZBase + 1)
+            .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque)
+            .apply();
+    {
+        SCOPED_TRACE("layerR opaque");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255});
+    }
+
+    Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply();
+    {
+        SCOPED_TRACE("layerR translucent");
+        const uint8_t g = uint8_t(255 - translucentRed.a);
+        screenshot()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255});
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFlagsSecure) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<GraphicBuffer> outBuffer;
+    Transaction()
+            .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
+            .apply(true);
+    ASSERT_EQ(PERMISSION_DENIED,
+              composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+                                      false));
+
+    Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
+    ASSERT_EQ(NO_ERROR,
+              composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+                                      false));
+}
+
+TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) {
+    const Rect top(0, 0, 32, 16);
+    const Rect bottom(0, 16, 32, 32);
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+
+    ANativeWindow_Buffer buffer;
+    ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+    ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED));
+    // setTransparentRegionHint always applies to the following buffer
+    Transaction().setTransparentRegionHint(layer, Region(top)).apply();
+    ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+    {
+        SCOPED_TRACE("top transparent");
+        auto shot = screenshot();
+        shot->expectColor(top, Color::BLACK);
+        shot->expectColor(bottom, Color::RED);
+    }
+
+    Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
+    {
+        SCOPED_TRACE("transparent region hint pending");
+        auto shot = screenshot();
+        shot->expectColor(top, Color::BLACK);
+        shot->expectColor(bottom, Color::RED);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+    ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+    {
+        SCOPED_TRACE("bottom transparent");
+        auto shot = screenshot();
+        shot->expectColor(top, Color::RED);
+        shot->expectColor(bottom, Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) {
+    sp<SurfaceControl> layerTransparent;
+    sp<SurfaceControl> layerR;
+    ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+
+    // check that transparent region hint is bound by the layer size
+    Transaction()
+            .setTransparentRegionHint(layerTransparent,
+                                      Region(Rect(0, 0, mDisplayWidth, mDisplayHeight)))
+            .setPosition(layerR, 16, 16)
+            .setLayer(layerR, mLayerZBase + 1)
+            .apply();
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+    screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetAlphaBasic) {
+    sp<SurfaceControl> layer1;
+    sp<SurfaceControl> layer2;
+    ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}));
+
+    Transaction()
+            .setAlpha(layer1, 0.25f)
+            .setAlpha(layer2, 0.75f)
+            .setPosition(layer2, 16, 0)
+            .setLayer(layer2, mLayerZBase + 1)
+            .apply();
+    {
+        auto shot = screenshot();
+        uint8_t r = 16; // 64 * 0.25f
+        uint8_t g = 48; // 64 * 0.75f
+        shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255});
+        shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255});
+
+        r /= 4; // r * (1.0f - 0.75f)
+        shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255});
+    }
+}
+
+TEST_F(LayerTransactionTest, SetAlphaClamped) {
+    const Color color = {64, 0, 0, 255};
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color));
+
+    Transaction().setAlpha(layer, 2.0f).apply();
+    {
+        SCOPED_TRACE("clamped to 1.0f");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), color);
+    }
+
+    Transaction().setAlpha(layer, -1.0f).apply();
+    {
+        SCOPED_TRACE("clamped to 0.0f");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetColorBasic) {
+    sp<SurfaceControl> bufferLayer;
+    sp<SurfaceControl> colorLayer;
+    ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+    Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+    {
+        SCOPED_TRACE("default color");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+    const Color expected = {15, 51, 85, 255};
+    // this is handwavy, but the precison loss scaled by 255 (8-bit per
+    // channel) should be less than one
+    const uint8_t tolerance = 1;
+    Transaction().setColor(colorLayer, color).apply();
+    {
+        SCOPED_TRACE("new color");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetColorClamped) {
+    sp<SurfaceControl> colorLayer;
+    ASSERT_NO_FATAL_FAILURE(
+            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+    Transaction().setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)).apply();
+    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetColorWithAlpha) {
+    sp<SurfaceControl> bufferLayer;
+    sp<SurfaceControl> colorLayer;
+    ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(
+            colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+    const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+    const float alpha = 0.25f;
+    const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
+    // this is handwavy, but the precison loss scaled by 255 (8-bit per
+    // channel) should be less than one
+    const uint8_t tolerance = 1;
+    Transaction()
+            .setColor(colorLayer, color)
+            .setAlpha(colorLayer, alpha)
+            .setLayer(colorLayer, mLayerZBase + 1)
+            .apply();
+    screenshot()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
+                              tolerance);
+}
+
+TEST_F(LayerTransactionTest, SetColorWithBuffer) {
+    sp<SurfaceControl> bufferLayer;
+    ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+
+    // color is ignored
+    Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply();
+    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetLayerStackBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
+    {
+        SCOPED_TRACE("non-existing layer stack");
+        screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+    }
+
+    Transaction().setLayerStack(layer, mDisplayLayerStack).apply();
+    {
+        SCOPED_TRACE("original layer stack");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(
+            fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+    Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
+    {
+        SCOPED_TRACE("IDENTITY");
+        screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+                                     Color::WHITE);
+    }
+
+    Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply();
+    {
+        SCOPED_TRACE("FLIP_H");
+        screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
+                                     Color::BLUE);
+    }
+
+    Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply();
+    {
+        SCOPED_TRACE("FLIP_V");
+        screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
+                                     Color::GREEN);
+    }
+
+    Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply();
+    {
+        SCOPED_TRACE("ROT_90");
+        screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
+                                     Color::GREEN);
+    }
+
+    Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply();
+    {
+        SCOPED_TRACE("SCALE");
+        screenshot()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN, Color::BLUE,
+                                     Color::WHITE, true /* filtered */);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixRot45) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(
+            fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+    const float rot = M_SQRT1_2; // 45 degrees
+    const float trans = M_SQRT2 * 16.0f;
+    Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply();
+
+    auto shot = screenshot();
+    // check a 8x8 region inside each color
+    auto get8x8Rect = [](int32_t centerX, int32_t centerY) {
+        const int32_t halfL = 4;
+        return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL);
+    };
+    const int32_t unit = int32_t(trans / 2);
+    shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED);
+    shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN);
+    shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE);
+    shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
+}
+
+TEST_F(LayerTransactionTest, SetMatrixWithResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setMatrix is applied after any pending resize, unlike setPosition
+    Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("resize applied");
+        screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
+    Transaction()
+            .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+            .setSize(layer, 64, 64)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .apply();
+    screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(
+            fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+    // XXX SCALE_CROP is not respected; calling setSize and
+    // setOverrideScalingMode in separate transactions does not work
+    // (b/69315456)
+    Transaction()
+            .setSize(layer, 64, 16)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .apply();
+    {
+        SCOPED_TRACE("SCALE_TO_WINDOW");
+        screenshot()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN, Color::BLUE,
+                                     Color::WHITE, true /* filtered */);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetCropBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    const Rect crop(8, 8, 24, 24);
+
+    Transaction().setCrop(layer, crop).apply();
+    auto shot = screenshot();
+    shot->expectColor(crop, Color::RED);
+    shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropEmpty) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    {
+        SCOPED_TRACE("empty rect");
+        Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    {
+        SCOPED_TRACE("negative rect");
+        Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetCropOutOfBounds) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply();
+    auto shot = screenshot();
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithTranslation) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    const Point position(32, 32);
+    const Rect crop(8, 8, 24, 24);
+    Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply();
+    auto shot = screenshot();
+    shot->expectColor(crop + position, Color::RED);
+    shot->expectBorder(crop + position, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithScale) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // crop is affected by matrix
+    Transaction()
+            .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+            .setCrop(layer, Rect(8, 8, 24, 24))
+            .apply();
+    auto shot = screenshot();
+    shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+    shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setCrop is applied immediately by default, with or without resize pending
+    Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+        shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("resize applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+        shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // request setCrop to be applied with the next resize
+    Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply();
+    {
+        SCOPED_TRACE("waiting for next resize");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply();
+    {
+        SCOPED_TRACE("pending crop modified");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setSize(layer, 16, 16).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    // finally resize
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("new crop applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // setCrop is not immediate even with SCALE_TO_WINDOW override
+    Transaction()
+            .setCrop(layer, Rect(4, 4, 12, 12))
+            .setSize(layer, 16, 16)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .setGeometryAppliesWithResize(layer)
+            .apply();
+    {
+        SCOPED_TRACE("new crop pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+        shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
+    }
+
+    // XXX crop is never latched without other geometry change (b/69315677)
+    Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    Transaction().setPosition(layer, 0, 0).apply();
+    {
+        SCOPED_TRACE("new crop applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropBasic) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    const Rect crop(8, 8, 24, 24);
+
+    // same as in SetCropBasic
+    Transaction().setFinalCrop(layer, crop).apply();
+    auto shot = screenshot();
+    shot->expectColor(crop, Color::RED);
+    shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropEmpty) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // same as in SetCropEmpty
+    {
+        SCOPED_TRACE("empty rect");
+        Transaction().setFinalCrop(layer, Rect(8, 8, 8, 8)).apply();
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    {
+        SCOPED_TRACE("negative rect");
+        Transaction().setFinalCrop(layer, Rect(8, 8, 0, 0)).apply();
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // same as in SetCropOutOfBounds
+    Transaction().setFinalCrop(layer, Rect(-128, -64, 128, 64)).apply();
+    auto shot = screenshot();
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // final crop is applied post-translation
+    Transaction().setPosition(layer, 16, 16).setFinalCrop(layer, Rect(8, 8, 24, 24)).apply();
+    auto shot = screenshot();
+    shot->expectColor(Rect(16, 16, 24, 24), Color::RED);
+    shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithScale) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // final crop is not affected by matrix
+    Transaction()
+            .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+            .setFinalCrop(layer, Rect(8, 8, 24, 24))
+            .apply();
+    auto shot = screenshot();
+    shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+    shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // same as in SetCropWithResize
+    Transaction().setFinalCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+        shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("resize applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+        shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // same as in SetCropWithNextResize
+    Transaction()
+            .setFinalCrop(layer, Rect(8, 8, 24, 24))
+            .setGeometryAppliesWithResize(layer)
+            .apply();
+    {
+        SCOPED_TRACE("waiting for next resize");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setFinalCrop(layer, Rect(4, 4, 12, 12)).apply();
+    {
+        SCOPED_TRACE("pending final crop modified");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    Transaction().setSize(layer, 16, 16).apply();
+    {
+        SCOPED_TRACE("resize pending");
+        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    }
+
+    // finally resize
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    {
+        SCOPED_TRACE("new final crop applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+    }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+    // same as in SetCropWithNextResizeScaleToWindow
+    Transaction()
+            .setFinalCrop(layer, Rect(4, 4, 12, 12))
+            .setSize(layer, 16, 16)
+            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+            .setGeometryAppliesWithResize(layer)
+            .apply();
+    {
+        SCOPED_TRACE("new final crop pending");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+        shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
+    }
+
+    // XXX final crop is never latched without other geometry change (b/69315677)
+    Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+    Transaction().setPosition(layer, 0, 0).apply();
+    {
+        SCOPED_TRACE("new final crop applied");
+        auto shot = screenshot();
+        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+    }
+}
+
+class LayerUpdateTest : public LayerTransactionTest {
 protected:
     virtual void SetUp() {
         mComposerClient = new SurfaceComposerClient;
         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
 
-        sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
-                ISurfaceComposer::eDisplayIdMain));
+        sp<IBinder> display(
+                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
         DisplayInfo info;
         SurfaceComposerClient::getDisplayInfo(display, &info);
 
@@ -125,46 +1480,42 @@
         ssize_t displayHeight = info.h;
 
         // Background surface
-        mBGSurfaceControl = mComposerClient->createSurface(
-                String8("BG Test Surface"), displayWidth, displayHeight,
-                PIXEL_FORMAT_RGBA_8888, 0);
+        mBGSurfaceControl =
+                mComposerClient->createSurface(String8("BG Test Surface"), displayWidth,
+                                               displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
         ASSERT_TRUE(mBGSurfaceControl != NULL);
         ASSERT_TRUE(mBGSurfaceControl->isValid());
         fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
 
         // Foreground surface
-        mFGSurfaceControl = mComposerClient->createSurface(
-                String8("FG Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+        mFGSurfaceControl = mComposerClient->createSurface(String8("FG Test Surface"), 64, 64,
+                                                           PIXEL_FORMAT_RGBA_8888, 0);
         ASSERT_TRUE(mFGSurfaceControl != NULL);
         ASSERT_TRUE(mFGSurfaceControl->isValid());
 
         fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
 
         // Synchronization surface
-        mSyncSurfaceControl = mComposerClient->createSurface(
-                String8("Sync Test Surface"), 1, 1, PIXEL_FORMAT_RGBA_8888, 0);
+        mSyncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1,
+                                                             PIXEL_FORMAT_RGBA_8888, 0);
         ASSERT_TRUE(mSyncSurfaceControl != NULL);
         ASSERT_TRUE(mSyncSurfaceControl->isValid());
 
         fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
 
-        SurfaceComposerClient::openGlobalTransaction();
+        asTransaction([&](Transaction& t) {
+            t.setDisplayLayerStack(display, 0);
 
-        mComposerClient->setDisplayLayerStack(display, 0);
+            t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
 
-        ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX-2));
-        ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
+            t.setLayer(mFGSurfaceControl, INT32_MAX - 1)
+                    .setPosition(mFGSurfaceControl, 64, 64)
+                    .show(mFGSurfaceControl);
 
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX-1));
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
-
-        ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT32_MAX-1));
-        ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2,
-                displayHeight-2));
-        ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show());
-
-        SurfaceComposerClient::closeGlobalTransaction(true);
+            t.setLayer(mSyncSurfaceControl, INT32_MAX - 1)
+                    .setPosition(mSyncSurfaceControl, displayWidth - 2, displayHeight - 2)
+                    .show(mSyncSurfaceControl);
+        });
     }
 
     virtual void TearDown() {
@@ -185,6 +1536,12 @@
         fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
     }
 
+    void asTransaction(const std::function<void(Transaction&)>& exec) {
+        Transaction t;
+        exec(t);
+        t.apply(true);
+    }
+
     sp<SurfaceComposerClient> mComposerClient;
     sp<SurfaceControl> mBGSurfaceControl;
     sp<SurfaceControl> mFGSurfaceControl;
@@ -194,287 +1551,45 @@
     sp<SurfaceControl> mSyncSurfaceControl;
 };
 
-TEST_F(LayerUpdateTest, LayerMoveWorks) {
+TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
     sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before move");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(0, 12);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should reflect the new position, but not the new color.
-        SCOPED_TRACE("after move, before redraw");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectFGColor(145, 145);
-    }
-
-    fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
+    sp<SurfaceControl> relative = mComposerClient->createSurface(String8("relativeTestSurface"), 10,
+                                                                 10, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(relative, 10, 10, 10);
     waitForPostedBuffers();
-    {
-        // This should reflect the new position and the new color.
-        SCOPED_TRACE("after redraw");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->checkPixel(145, 145, 63, 195, 63);
-    }
-}
 
-TEST_F(LayerUpdateTest, LayerResizeWorks) {
-    sp<ScreenCapture> sc;
+    Transaction{}
+            .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
+            .setPosition(relative, 64, 64)
+            .apply();
+
     {
-        SCOPED_TRACE("before resize");
+        // The relative should be on top of the FG control.
         ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(0, 12);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
+        sc->checkPixel(64, 64, 10, 10, 10);
+    }
+    Transaction{}.detachChildren(mFGSurfaceControl).apply();
+
+    {
+        // Nothing should change at this point.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(64, 64, 10, 10, 10);
     }
 
-    ALOGD("resizing");
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    ALOGD("resized");
-    {
-        // This should not reflect the new size or color because SurfaceFlinger
-        // has not yet received a buffer of the correct size.
-        SCOPED_TRACE("after resize, before redraw");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(0, 12);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
+    Transaction{}.hide(relative).apply();
 
-    ALOGD("drawing");
-    fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
-    waitForPostedBuffers();
-    ALOGD("drawn");
     {
-        // This should reflect the new size and the new color.
-        SCOPED_TRACE("after redraw");
+        // Ensure that the relative was actually hidden, rather than
+        // being left in the detached but visible state.
         ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->checkPixel(75, 75, 63, 195, 63);
-        sc->checkPixel(145, 145, 63, 195, 63);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerCropWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before crop");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    Rect cropRect(16, 16, 32, 32);
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should crop the foreground surface.
-        SCOPED_TRACE("after crop");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectFGColor(95, 80);
-        sc->expectFGColor(80, 95);
-        sc->expectBGColor(96, 96);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerFinalCropWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before crop");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-    SurfaceComposerClient::openGlobalTransaction();
-    Rect cropRect(16, 16, 32, 32);
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should crop the foreground surface.
-        SCOPED_TRACE("after crop");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectBGColor(95, 80);
-        sc->expectBGColor(80, 95);
-        sc->expectBGColor(96, 96);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before setLayer");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should hide the foreground surface beneath the background.
-        SCOPED_TRACE("after setLayer");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerShowHideWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before hide");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should hide the foreground surface.
-        SCOPED_TRACE("after hide, before show");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should show the foreground surface.
-        SCOPED_TRACE("after show");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerSetAlphaWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before setAlpha");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should set foreground to be 75% opaque.
-        SCOPED_TRACE("after setAlpha");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->checkPixel(75, 75, 162, 63, 96);
-        sc->expectBGColor(145, 145);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before setLayerStack");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should hide the foreground surface since it goes to a different
-        // layer stack.
-        SCOPED_TRACE("after setLayerStack");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerSetFlagsWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before setFlags");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
-            layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        // This should hide the foreground surface
-        SCOPED_TRACE("after setFlags");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectBGColor(75, 75);
-        sc->expectBGColor(145, 145);
-    }
-}
-
-TEST_F(LayerUpdateTest, LayerSetMatrixWorks) {
-    sp<ScreenCapture> sc;
-    {
-        SCOPED_TRACE("before setMatrix");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(91, 96);
-        sc->expectFGColor(96, 101);
-        sc->expectBGColor(145, 145);
-    }
-
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2,
-            -M_SQRT1_2, M_SQRT1_2));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-    {
-        SCOPED_TRACE("after setMatrix");
-        ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
-        sc->expectFGColor(91, 96);
-        sc->expectBGColor(96, 91);
-        sc->expectBGColor(145, 145);
+        sc->expectFGColor(64, 64);
     }
 }
 
 class GeometryLatchingTest : public LayerUpdateTest {
 protected:
-    void EXPECT_INITIAL_STATE(const char * trace) {
+    void EXPECT_INITIAL_STATE(const char* trace) {
         SCOPED_TRACE(trace);
         ScreenCapture::captureScreen(&sc);
         // We find the leading edge of the FG surface.
@@ -482,9 +1597,7 @@
         sc->expectBGColor(128, 128);
     }
 
-    void lockAndFillFGBuffer() {
-        fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
-    }
+    void lockAndFillFGBuffer() { fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false); }
 
     void unlockFGBuffer() {
         sp<Surface> s = mFGSurfaceControl->getSurface();
@@ -497,65 +1610,18 @@
         waitForPostedBuffers();
     }
     void restoreInitialState() {
-        SurfaceComposerClient::openGlobalTransaction();
-        mFGSurfaceControl->setSize(64, 64);
-        mFGSurfaceControl->setPosition(64, 64);
-        mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64));
-        mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
-        SurfaceComposerClient::closeGlobalTransaction(true);
+        asTransaction([&](Transaction& t) {
+            t.setSize(mFGSurfaceControl, 64, 64);
+            t.setPosition(mFGSurfaceControl, 64, 64);
+            t.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64));
+            t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
+        });
 
         EXPECT_INITIAL_STATE("After restoring initial state");
     }
     sp<ScreenCapture> sc;
 };
 
-TEST_F(GeometryLatchingTest, SurfacePositionLatching) {
-    EXPECT_INITIAL_STATE("before anything");
-
-    // By default position can be updated even while
-    // a resize is pending.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(32, 32);
-    mFGSurfaceControl->setPosition(100, 100);
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    {
-        SCOPED_TRACE("After moving surface");
-        ScreenCapture::captureScreen(&sc);
-        // If we moved, the FG Surface should cover up what was previously BG
-        // however if we didn't move the FG wouldn't be large enough now.
-        sc->expectFGColor(163, 163);
-    }
-
-    restoreInitialState();
-
-    // Now we repeat with setGeometryAppliesWithResize
-    // and verify the position DOESN'T latch.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setGeometryAppliesWithResize();
-    mFGSurfaceControl->setSize(32, 32);
-    mFGSurfaceControl->setPosition(100, 100);
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    {
-        SCOPED_TRACE("While resize is pending");
-        ScreenCapture::captureScreen(&sc);
-        // This time we shouldn't have moved, so the BG color
-        // should still be visible.
-        sc->expectBGColor(128, 128);
-    }
-
-    completeFGResize();
-
-    {
-        SCOPED_TRACE("After the resize");
-        ScreenCapture::captureScreen(&sc);
-        // But after the resize completes, we should move
-        // and the FG should be visible here.
-        sc->expectFGColor(128, 128);
-    }
-}
-
 class CropLatchingTest : public GeometryLatchingTest {
 protected:
     void EXPECT_CROPPED_STATE(const char* trace) {
@@ -577,65 +1643,15 @@
     }
 };
 
-TEST_F(CropLatchingTest, CropLatching) {
-    EXPECT_INITIAL_STATE("before anything");
-    // Normally the crop applies immediately even while a resize is pending.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
-
-    restoreInitialState();
-
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setGeometryAppliesWithResize();
-    mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
-
-    completeFGResize();
-
-    EXPECT_CROPPED_STATE("after the resize finishes");
-}
-
-TEST_F(CropLatchingTest, FinalCropLatching) {
-    EXPECT_INITIAL_STATE("before anything");
-    // Normally the crop applies immediately even while a resize is pending.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
-
-    restoreInitialState();
-
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setGeometryAppliesWithResize();
-    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
-
-    completeFGResize();
-
-    EXPECT_CROPPED_STATE("after the resize finishes");
-}
-
 // In this test we ensure that setGeometryAppliesWithResize actually demands
 // a buffer of the new size, and not just any size.
 TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
     EXPECT_INITIAL_STATE("before anything");
     // Normally the crop applies immediately even while a resize is pending.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.setSize(mFGSurfaceControl, 128, 128);
+        t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+    });
 
     EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
 
@@ -645,11 +1661,11 @@
     // initiating the resize.
     lockAndFillFGBuffer();
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setGeometryAppliesWithResize();
-    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.setSize(mFGSurfaceControl, 128, 128);
+        t.setGeometryAppliesWithResize(mFGSurfaceControl);
+        t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+    });
 
     EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
 
@@ -664,30 +1680,6 @@
     EXPECT_CROPPED_STATE("after the resize finishes");
 }
 
-TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
-    EXPECT_INITIAL_STATE("before anything");
-    // In this scenario, we attempt to set the final crop a second time while the resize
-    // is still pending, and ensure we are successful. Success meaning the second crop
-    // is the one which eventually latches and not the first.
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setSize(128, 128);
-    mFGSurfaceControl->setGeometryAppliesWithResize();
-    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
-
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
-    EXPECT_INITIAL_STATE("after setting another crop");
-
-    completeFGResize();
-
-    EXPECT_RESIZE_STATE("after the resize finishes");
-}
-
 TEST_F(LayerUpdateTest, DeferredTransactionTest) {
     sp<ScreenCapture> sc;
     {
@@ -699,17 +1691,17 @@
     }
 
     // set up two deferred transactions on different frames
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
-    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
-            mSyncSurfaceControl->getSurface()->getNextFrameNumber());
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.setAlpha(mFGSurfaceControl, 0.75);
+        t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+                                mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+    });
 
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
-    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
-            mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.setPosition(mFGSurfaceControl, 128, 128);
+        t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+                                mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+    });
 
     {
         SCOPED_TRACE("before any trigger");
@@ -730,9 +1722,7 @@
     }
 
     // should show up immediately since it's not deferred
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); });
 
     // trigger the second deferred transaction
     fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
@@ -745,46 +1735,55 @@
     }
 }
 
-TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) {
+    sp<ScreenCapture> sc;
+
+    sp<SurfaceControl> childNoBuffer =
+            mComposerClient->createSurface(String8("Bufferless child"), 10, 10,
+                                           PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    sp<SurfaceControl> childBuffer =
+            mComposerClient->createSurface(String8("Buffered child"), 20, 20,
+                                           PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
+    fillSurfaceRGBA8(childBuffer, 200, 200, 200);
+
+    SurfaceComposerClient::Transaction{}.show(childNoBuffer).show(childBuffer).apply(true);
+
+    {
+        ScreenCapture::captureScreen(&sc);
+        sc->expectChildColor(73, 73);
+        sc->expectFGColor(74, 74);
+    }
+
+    SurfaceComposerClient::Transaction{}.setSize(childNoBuffer, 20, 20).apply(true);
+
+    {
+        ScreenCapture::captureScreen(&sc);
+        sc->expectChildColor(73, 73);
+        sc->expectChildColor(74, 74);
+    }
+}
+
+TEST_F(LayerUpdateTest, MergingTransactions) {
     sp<ScreenCapture> sc;
     {
-        SCOPED_TRACE("before adding relative surface");
+        SCOPED_TRACE("before move");
         ScreenCapture::captureScreen(&sc);
-        sc->expectBGColor(24, 24);
+        sc->expectBGColor(0, 12);
         sc->expectFGColor(75, 75);
         sc->expectBGColor(145, 145);
     }
 
-    auto relativeSurfaceControl = mComposerClient->createSurface(
-            String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
-    fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
-    waitForPostedBuffers();
-
-    // Now we stack the surface above the foreground surface and make sure it is visible.
-    SurfaceComposerClient::openGlobalTransaction();
-    relativeSurfaceControl->setPosition(64, 64);
-    relativeSurfaceControl->show();
-    relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
-    SurfaceComposerClient::closeGlobalTransaction(true);
-
+    Transaction t1, t2;
+    t1.setPosition(mFGSurfaceControl, 128, 128);
+    t2.setPosition(mFGSurfaceControl, 0, 0);
+    // We expect that the position update from t2 now
+    // overwrites the position update from t1.
+    t1.merge(std::move(t2));
+    t1.apply();
 
     {
-        SCOPED_TRACE("after adding relative surface");
         ScreenCapture::captureScreen(&sc);
-        // our relative surface should be visible now.
-        sc->checkPixel(75, 75, 255, 177, 177);
-    }
-
-    // A call to setLayer will override a call to setRelativeLayer
-    SurfaceComposerClient::openGlobalTransaction();
-    relativeSurfaceControl->setLayer(0);
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    {
-        SCOPED_TRACE("after set layer");
-        ScreenCapture::captureScreen(&sc);
-        // now the FG surface should be visible again.
-        sc->expectFGColor(75, 75);
+        sc->expectFGColor(1, 1);
     }
 }
 
@@ -792,10 +1791,8 @@
 protected:
     void SetUp() override {
         LayerUpdateTest::SetUp();
-        mChild = mComposerClient->createSurface(
-                String8("Child surface"),
-                10, 10, PIXEL_FORMAT_RGBA_8888,
-                0, mFGSurfaceControl.get());
+        mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10,
+                                                PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
         fillSurfaceRGBA8(mChild, 200, 200, 200);
 
         {
@@ -814,11 +1811,11 @@
 };
 
 TEST_F(ChildLayerTest, ChildLayerPositioning) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(10, 10);
-    mFGSurfaceControl->setPosition(64, 64);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -830,9 +1827,7 @@
         mCapture->expectFGColor(84, 84);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -846,12 +1841,12 @@
 }
 
 TEST_F(ChildLayerTest, ChildLayerCropping) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(0, 0);
-    mFGSurfaceControl->setPosition(0, 0);
-    mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 0, 0);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+        t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -862,12 +1857,12 @@
 }
 
 TEST_F(ChildLayerTest, ChildLayerFinalCropping) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(0, 0);
-    mFGSurfaceControl->setPosition(0, 0);
-    mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 0, 0);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+        t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -878,11 +1873,11 @@
 }
 
 TEST_F(ChildLayerTest, ChildLayerConstraints) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mFGSurfaceControl->setPosition(0, 0);
-    mChild->setPosition(63, 63);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+        t.setPosition(mChild, 63, 63);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -896,9 +1891,7 @@
 }
 
 TEST_F(ChildLayerTest, ChildLayerScaling) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setPosition(0, 0);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); });
 
     // Find the boundary between the parent and child
     {
@@ -907,9 +1900,7 @@
         mCapture->expectFGColor(10, 10);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); });
 
     // The boundary should be twice as far from the origin now.
     // The pixels from the last test should all be child now
@@ -928,11 +1919,11 @@
     fillSurfaceRGBA8(mChild, 0, 254, 0);
     waitForPostedBuffers();
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(0, 0);
-    mFGSurfaceControl->setPosition(0, 0);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 0, 0);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -940,9 +1931,7 @@
         mCapture->checkPixel(0, 0, 0, 254, 0);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -950,9 +1939,7 @@
         mCapture->checkPixel(0, 0, 127, 127, 0);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5));
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -962,11 +1949,11 @@
 }
 
 TEST_F(ChildLayerTest, ReparentChildren) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(10, 10);
-    mFGSurfaceControl->setPosition(64, 64);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -977,7 +1964,11 @@
         // And 10 more pixels we should be back to the foreground surface
         mCapture->expectFGColor(84, 84);
     }
-    mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle());
+
+    asTransaction([&](Transaction& t) {
+        t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
+    });
+
     {
         ScreenCapture::captureScreen(&mCapture);
         mCapture->expectFGColor(64, 64);
@@ -990,12 +1981,12 @@
     }
 }
 
-TEST_F(ChildLayerTest, DetachChildren) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(10, 10);
-    mFGSurfaceControl->setPosition(64, 64);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+TEST_F(ChildLayerTest, DetachChildrenSameClient) {
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -1007,13 +1998,51 @@
         mCapture->expectFGColor(84, 84);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->detachChildren();
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->hide();
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) { t.hide(mChild); });
+
+    // Since the child has the same client as the parent, it will not get
+    // detached and will be hidden.
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectFGColor(64, 64);
+        mCapture->expectFGColor(74, 74);
+        mCapture->expectFGColor(84, 84);
+    }
+}
+
+TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
+    sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
+    sp<SurfaceControl> mChildNewClient =
+            mNewComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+    ASSERT_TRUE(mChildNewClient != NULL);
+    ASSERT_TRUE(mChildNewClient->isValid());
+
+    fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
+
+    asTransaction([&](Transaction& t) {
+        t.hide(mChild);
+        t.show(mChildNewClient);
+        t.setPosition(mChildNewClient, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // But 10 pixels in we should see the child surface
+        mCapture->expectChildColor(74, 74);
+        // And 10 more pixels we should be back to the foreground surface
+        mCapture->expectFGColor(84, 84);
+    }
+
+    asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
+
+    asTransaction([&](Transaction& t) { t.hide(mChildNewClient); });
 
     // Nothing should have changed.
     {
@@ -1025,11 +2054,11 @@
 }
 
 TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(0, 0);
-    mFGSurfaceControl->setPosition(0, 0);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 0, 0);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -1039,11 +2068,11 @@
         mCapture->expectFGColor(10, 10);
     }
 
-    SurfaceComposerClient::openGlobalTransaction();
-    mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-    // We cause scaling by 2.
-    mFGSurfaceControl->setSize(128, 128);
-    SurfaceComposerClient::closeGlobalTransaction();
+    asTransaction([&](Transaction& t) {
+        t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        // We cause scaling by 2.
+        t.setSize(mFGSurfaceControl, 128, 128);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -1058,11 +2087,11 @@
 
 // Regression test for b/37673612
 TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->show();
-    mChild->setPosition(0, 0);
-    mFGSurfaceControl->setPosition(0, 0);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 0, 0);
+        t.setPosition(mFGSurfaceControl, 0, 0);
+    });
 
     {
         ScreenCapture::captureScreen(&mCapture);
@@ -1071,11 +2100,9 @@
         // But it's only 10x10.
         mCapture->expectFGColor(10, 10);
     }
-
-
     // We set things up as in b/37673612 so that there is a mismatch between the buffer size and
     // the WM specified state size.
-    mFGSurfaceControl->setSize(128, 64);
+    asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); });
     sp<Surface> s = mFGSurfaceControl->getSurface();
     auto anw = static_cast<ANativeWindow*>(s.get());
     native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
@@ -1102,11 +2129,11 @@
                                             mFGSurfaceControl.get());
 
     // Show the child layer in a deferred transaction
-    SurfaceComposerClient::openGlobalTransaction();
-    mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(),
-                                  mFGSurfaceControl->getSurface()->getNextFrameNumber());
-    mChild->show();
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    asTransaction([&](Transaction& t) {
+        t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(),
+                                mFGSurfaceControl->getSurface()->getNextFrameNumber());
+        t.show(mChild);
+    });
 
     // Render the foreground surface a few times
     //
@@ -1123,4 +2150,314 @@
     fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
 }
 
+TEST_F(ChildLayerTest, Reparent) {
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // But 10 pixels in we should see the child surface
+        mCapture->expectChildColor(74, 74);
+        // And 10 more pixels we should be back to the foreground surface
+        mCapture->expectFGColor(84, 84);
+    }
+
+    asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectFGColor(64, 64);
+        // In reparenting we should have exposed the entire foreground surface.
+        mCapture->expectFGColor(74, 74);
+        // And the child layer should now begin at 10, 10 (since the BG
+        // layer is at (0, 0)).
+        mCapture->expectBGColor(9, 9);
+        mCapture->expectChildColor(10, 10);
+    }
 }
+
+TEST_F(ChildLayerTest, ReparentToNoParent) {
+    asTransaction([&](Transaction& t) {
+        t.show(mChild);
+        t.setPosition(mChild, 10, 10);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // But 10 pixels in we should see the child surface
+        mCapture->expectChildColor(74, 74);
+        // And 10 more pixels we should be back to the foreground surface
+        mCapture->expectFGColor(84, 84);
+    }
+    asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); });
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Nothing should have changed.
+        mCapture->expectFGColor(64, 64);
+        mCapture->expectChildColor(74, 74);
+        mCapture->expectFGColor(84, 84);
+    }
+}
+
+TEST_F(ChildLayerTest, ReparentFromNoParent) {
+    sp<SurfaceControl> newSurface = mComposerClient->createSurface(String8("New Surface"), 10, 10,
+                                                                   PIXEL_FORMAT_RGBA_8888, 0);
+    ASSERT_TRUE(newSurface != NULL);
+    ASSERT_TRUE(newSurface->isValid());
+
+    fillSurfaceRGBA8(newSurface, 63, 195, 63);
+    asTransaction([&](Transaction& t) {
+        t.hide(mChild);
+        t.show(newSurface);
+        t.setPosition(newSurface, 10, 10);
+        t.setLayer(newSurface, INT32_MAX - 2);
+        t.setPosition(mFGSurfaceControl, 64, 64);
+    });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Top left of foreground must now be visible
+        mCapture->expectFGColor(64, 64);
+        // At 10, 10 we should see the new surface
+        mCapture->checkPixel(10, 10, 63, 195, 63);
+    }
+
+    asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); });
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from
+        // mFGSurface, putting it at 74, 74.
+        mCapture->expectFGColor(64, 64);
+        mCapture->checkPixel(74, 74, 63, 195, 63);
+        mCapture->expectFGColor(84, 84);
+    }
+}
+
+TEST_F(ChildLayerTest, NestedChildren) {
+    sp<SurfaceControl> grandchild =
+            mComposerClient->createSurface(String8("Grandchild surface"), 10, 10,
+                                           PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer
+        // which begins at 64, 64
+        mCapture->checkPixel(64, 64, 50, 50, 50);
+    }
+}
+
+TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
+    sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 128,
+                                                                 128, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(relative, 255, 255, 255);
+
+    Transaction t;
+    t.setLayer(relative, INT32_MAX)
+            .setRelativeLayer(mChild, relative->getHandle(), 1)
+            .setPosition(mFGSurfaceControl, 0, 0)
+            .apply(true);
+
+    // We expect that the child should have been elevated above our
+    // INT_MAX layer even though it's not a child of it.
+    {
+        ScreenCapture::captureScreen(&mCapture);
+        mCapture->expectChildColor(0, 0);
+        mCapture->expectChildColor(9, 9);
+        mCapture->checkPixel(10, 10, 255, 255, 255);
+    }
+}
+
+class ScreenCaptureTest : public LayerUpdateTest {
+protected:
+    std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
+    auto bgHandle = mBGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, bgHandle);
+    mCapture->expectBGColor(0, 0);
+    // Doesn't capture FG layer which is at 64, 64
+    mCapture->expectBGColor(64, 64);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+
+    SurfaceComposerClient::Transaction().show(child).apply(true);
+
+    // Captures mFGSurfaceControl layer and its child.
+    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    mCapture->expectFGColor(10, 10);
+    mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+
+    sp<SurfaceControl> grandchild =
+            mComposerClient->createSurface(String8("Grandchild surface"), 5, 5,
+                                           PIXEL_FORMAT_RGBA_8888, 0, child.get());
+
+    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            .setPosition(grandchild, 5, 5)
+            .show(grandchild)
+            .apply(true);
+
+    // Captures mFGSurfaceControl, its child, and the grandchild.
+    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    mCapture->expectFGColor(10, 10);
+    mCapture->expectChildColor(0, 0);
+    mCapture->checkPixel(5, 5, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureChildOnly) {
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    auto childHandle = child->getHandle();
+
+    SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
+
+    // Captures only the child layer, and not the parent.
+    ScreenCapture::captureLayers(&mCapture, childHandle);
+    mCapture->expectChildColor(0, 0);
+    mCapture->expectChildColor(9, 9);
+}
+
+TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
+    sp<SurfaceControl> child =
+            mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+                                           0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    auto childHandle = child->getHandle();
+
+    sp<SurfaceControl> grandchild =
+            mComposerClient->createSurface(String8("Grandchild surface"), 5, 5,
+                                           PIXEL_FORMAT_RGBA_8888, 0, child.get());
+    fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            .setPosition(grandchild, 5, 5)
+            .show(grandchild)
+            .apply(true);
+
+    auto grandchildHandle = grandchild->getHandle();
+
+    // Captures only the grandchild.
+    ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+    mCapture->checkPixel(0, 0, 50, 50, 50);
+    mCapture->checkPixel(4, 4, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureCrop) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+                                                                 PIXEL_FORMAT_RGBA_8888, 0);
+    sp<SurfaceControl> blueLayer =
+            mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
+                                           0, redLayer.get());
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+
+    SurfaceComposerClient::Transaction()
+            .setLayer(redLayer, INT32_MAX - 1)
+            .show(redLayer)
+            .show(blueLayer)
+            .apply(true);
+
+    auto redLayerHandle = redLayer->getHandle();
+
+    // Capturing full screen should have both red and blue are visible.
+    ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+    mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+    // red area below the blue area
+    mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+    // red area to the right of the blue area
+    mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+    Rect crop = Rect(0, 0, 30, 30);
+    ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+    // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
+    // area visible.
+    mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+    mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureSize) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+                                                                 PIXEL_FORMAT_RGBA_8888, 0);
+    sp<SurfaceControl> blueLayer =
+            mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
+                                           0, redLayer.get());
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+
+    SurfaceComposerClient::Transaction()
+            .setLayer(redLayer, INT32_MAX - 1)
+            .show(redLayer)
+            .show(blueLayer)
+            .apply(true);
+
+    auto redLayerHandle = redLayer->getHandle();
+
+    // Capturing full screen should have both red and blue are visible.
+    ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+    mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+    // red area below the blue area
+    mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+    // red area to the right of the blue area
+    mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+    ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+    // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
+    mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
+    // red area below the blue area
+    mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
+    // red area to the right of the blue area
+    mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
+    mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+                                                                 PIXEL_FORMAT_RGBA_8888, 0);
+
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+
+    auto redLayerHandle = redLayer->getHandle();
+    mComposerClient->destroySurface(redLayerHandle);
+    SurfaceComposerClient::Transaction().apply(true);
+
+    sp<GraphicBuffer> outBuffer;
+
+    // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 94f3f25..47c4f4a 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -22,7 +22,8 @@
         "libsync",
         "libfmq",
         "libbase",
-        "libhidltransport"
+        "libhidltransport",
+        "liblayers_proto"
     ],
     static_libs: [
         "libhwcomposer-client",
@@ -30,6 +31,9 @@
         "libtrace_proto",
         "libgmock"
     ],
+    cppflags: [
+        "-std=c++1z",
+    ],
     tags: ["tests"],
     test_suites: ["device-tests"]
 }
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 60916f3..d97ffa3 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -36,7 +36,6 @@
 #include <thread>
 
 constexpr Config NULL_DISPLAY_CONFIG = static_cast<Config>(0);
-constexpr Display DEFAULT_DISPLAY = static_cast<Display>(1);
 
 using namespace sftest;
 
@@ -168,7 +167,7 @@
     ALOGV("enableCallback");
     mCallbacksOn = enable;
     if (mCallbacksOn) {
-        mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
+        mClient->onHotplug(PRIMARY_DISPLAY, IComposerCallback::Connection::CONNECTED);
     }
 }
 
@@ -507,7 +506,7 @@
         if (mSurfaceComposer != nullptr) {
             mSurfaceComposer->injectVSync(timestamp);
         } else {
-            mClient->onVsync(DEFAULT_DISPLAY, timestamp);
+            mClient->onVsync(PRIMARY_DISPLAY, timestamp);
         }
     }
 }
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
index 294abb2..b944182 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
@@ -16,9 +16,16 @@
 
 #pragma once
 
+#define HWC2_USE_CPP11
+#define HWC2_INCLUDE_STRINGIFICATION
 #include "ComposerClient.h"
+#undef HWC2_USE_CPP11
+#undef HWC2_INCLUDE_STRINGIFICATION
 #include "RenderState.h"
 
+// Needed for display type/ID enums
+#include <hardware/hwcomposer_defs.h>
+
 #include <utils/Condition.h>
 
 #include <chrono>
@@ -40,6 +47,13 @@
 
 namespace sftest {
 
+// NOTE: The ID's need to be exactly these. VR composer and parts of
+// the SurfaceFlinger assume the display IDs to have these values
+// despite the enum being documented as a display type.
+// TODO: Reference to actual documentation
+constexpr Display PRIMARY_DISPLAY = static_cast<Display>(HWC_DISPLAY_PRIMARY);
+constexpr Display EXTERNAL_DISPLAY = static_cast<Display>(HWC_DISPLAY_EXTERNAL);
+
 class FakeComposerClient : public ComposerBase {
 public:
     FakeComposerClient();
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 74dc0e5..1258a97 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -87,7 +87,7 @@
 
 /*
  * All surface state changes are supposed to happen inside a global
- * transaction. GlobalTransactionScope object at the beginning of
+ * transaction. TransactionScope object at the beginning of
  * scope automates the process. The resulting scope gives a visual cue
  * on the span of the transaction as well.
  *
@@ -96,23 +96,26 @@
  * is built to explicitly request vsyncs one at the time. A delayed
  * request must be made before closing the transaction or the test
  * thread stalls until SurfaceFlinger does an emergency vsync by
- * itself. GlobalTransactionScope encapsulates this vsync magic.
+ * itself. TransactionScope encapsulates this vsync magic.
  */
-class GlobalTransactionScope {
+class TransactionScope : public android::SurfaceComposerClient::Transaction {
 public:
-    GlobalTransactionScope(FakeComposerClient& composer) : mComposer(composer) {
-        android::SurfaceComposerClient::openGlobalTransaction();
+    TransactionScope(FakeComposerClient& composer) :
+            Transaction(),
+            mComposer(composer) {
     }
-    ~GlobalTransactionScope() {
+
+    ~TransactionScope() {
         int frameCount = mComposer.getFrameCount();
         mComposer.runVSyncAfter(1ms);
-        android::SurfaceComposerClient::closeGlobalTransaction(true);
+        LOG_ALWAYS_FATAL_IF(android::NO_ERROR != apply());
         // Make sure that exactly one frame has been rendered.
         mComposer.waitUntilFrame(frameCount + 1);
         LOG_ALWAYS_FATAL_IF(frameCount + 1 != mComposer.getFrameCount(),
                             "Unexpected frame advance. Delta: %d",
                             mComposer.getFrameCount() - frameCount);
     }
+
     FakeComposerClient& mComposer;
 };
 
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 8902ede..7f4c58a 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -24,11 +24,11 @@
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerDebugInfo.h>
+#include <gui/LayerState.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
 #include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
 
 #include <ui/DisplayInfo.h>
 
@@ -62,6 +62,8 @@
 using ::testing::SetArgPointee;
 using ::testing::_;
 
+using Transaction = SurfaceComposerClient::Transaction;
+
 ///////////////////////////////////////////////
 
 struct TestColor {
@@ -168,17 +170,15 @@
     android::hardware::ProcessState::self()->startThreadPool();
     android::ProcessState::self()->startThreadPool();
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(1, _))
+    EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _))
             .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                             Return(Error::NONE)));
-    // Seems to be doubled right now, once for display ID 1 and once for 0. This sounds fishy
-    // but encoding that here exactly.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(1, 1, _, _))
-            .Times(5)
-            .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
-    // TODO: Find out what code is generating the ID 0.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(0, 1, _, _))
-            .Times(5)
+    // Primary display will be queried twice for all 5 attributes. One
+    // set of queries comes from the SurfaceFlinger proper an the
+    // other set from the VR composer.
+    // TODO: Is VR composer always present? Change to atLeast(5)?
+    EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _))
+            .Times(2 * 5)
             .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
 
     startSurfaceFlinger();
@@ -207,31 +207,32 @@
 TEST_F(DisplayTest, Hotplug) {
     ALOGD("DisplayTest::Hotplug");
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(2, _))
+    EXPECT_CALL(*mMockComposer, getDisplayType(EXTERNAL_DISPLAY, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                                   Return(Error::NONE)));
     // The attribute queries will get done twice. This is for defaults
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, _, _))
+    EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _))
             .Times(2 * 3)
             .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
     // ... and then special handling for dimensions. Specifying this
     // rules later means that gmock will try them first, i.e.,
     // ordering of width/height vs. the default implementation for
     // other queries is significant.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::WIDTH, _))
+    EXPECT_CALL(*mMockComposer,
+                getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::WIDTH, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<3>(400), Return(Error::NONE)));
 
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::HEIGHT, _))
+    EXPECT_CALL(*mMockComposer,
+                getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::HEIGHT, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<3>(200), Return(Error::NONE)));
 
     // TODO: Width and height queries are not actually called. Display
     // info returns dimensions 0x0 in display info. Why?
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::CONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
 
     {
         sp<android::IBinder> display(
@@ -249,21 +250,19 @@
         fillSurfaceRGBA8(surfaceControl, BLUE);
 
         {
-            GlobalTransactionScope gts(*mMockComposer);
-            mComposerClient->setDisplayLayerStack(display, 0);
+            TransactionScope ts(*mMockComposer);
+            ts.setDisplayLayerStack(display, 0);
 
-            ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2));
-            ASSERT_EQ(NO_ERROR, surfaceControl->show());
+            ts.setLayer(surfaceControl, INT32_MAX - 2)
+                .show(surfaceControl);
         }
     }
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::DISCONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
 
     mMockComposer->clearFrames();
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::CONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
 
     {
         sp<android::IBinder> display(
@@ -281,15 +280,14 @@
         fillSurfaceRGBA8(surfaceControl, BLUE);
 
         {
-            GlobalTransactionScope gts(*mMockComposer);
-            mComposerClient->setDisplayLayerStack(display, 0);
+            TransactionScope ts(*mMockComposer);
+            ts.setDisplayLayerStack(display, 0);
 
-            ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2));
-            ASSERT_EQ(NO_ERROR, surfaceControl->show());
+            ts.setLayer(surfaceControl, INT32_MAX - 2)
+                .show(surfaceControl);
         }
     }
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::DISCONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
 }
 
 ////////////////////////////////////////////////
@@ -374,25 +372,24 @@
 
     fillSurfaceRGBA8(mFGSurfaceControl, RED);
 
-    SurfaceComposerClient::openGlobalTransaction();
+    Transaction t;
+    t.setDisplayLayerStack(display, 0);
 
-    mComposerClient->setDisplayLayerStack(display, 0);
+    t.setLayer(mBGSurfaceControl, INT32_MAX - 2);
+    t.show(mBGSurfaceControl);
 
-    ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX - 2));
-    ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
-
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX - 1));
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
-    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+    t.setLayer(mFGSurfaceControl, INT32_MAX - 1);
+    t.setPosition(mFGSurfaceControl, 64, 64);
+    t.show(mFGSurfaceControl);
 
     // Synchronous transaction will stop this thread, so we set up a
     // delayed, off-thread vsync request before closing the
     // transaction. In the test code this is usually done with
-    // GlobalTransactionScope. Leaving here in the 'vanilla' form for
+    // TransactionScope. Leaving here in the 'vanilla' form for
     // reference.
     ASSERT_EQ(0, sFakeComposer->getFrameCount());
     sFakeComposer->runVSyncAfter(1ms);
-    SurfaceComposerClient::closeGlobalTransaction(true);
+    t.apply();
     sFakeComposer->waitUntilFrame(1);
 
     // Reference data. This is what the HWC should see.
@@ -449,8 +446,8 @@
     // should be available in the latest frame stored by the fake
     // composer.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
+        TransactionScope ts(*sFakeComposer);
+        ts.setPosition(mFGSurfaceControl, 128, 128);
         // NOTE: No changes yet, so vsync will do nothing, HWC does not get any calls.
         // (How to verify that? Throw in vsync and wait a 2x frame time? Separate test?)
         //
@@ -477,8 +474,8 @@
 TEST_F(TransactionTest, LayerResize) {
     ALOGD("TransactionTest::LayerResize");
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
     }
 
     fillSurfaceRGBA8(mFGSurfaceControl, GREEN);
@@ -501,9 +498,9 @@
 TEST_F(TransactionTest, LayerCrop) {
     // TODO: Add scaling to confirm that crop happens in buffer space?
     {
-        GlobalTransactionScope gts(*sFakeComposer);
+        TransactionScope ts(*sFakeComposer);
         Rect cropRect(16, 16, 32, 32);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
+        ts.setCrop(mFGSurfaceControl, cropRect);
     }
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
 
@@ -516,9 +513,9 @@
 TEST_F(TransactionTest, LayerFinalCrop) {
     // TODO: Add scaling to confirm that crop happens in display space?
     {
-        GlobalTransactionScope gts(*sFakeComposer);
+        TransactionScope ts(*sFakeComposer);
         Rect cropRect(32, 32, 32 + 64, 32 + 64);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+        ts.setFinalCrop(mFGSurfaceControl, cropRect);
     }
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
 
@@ -534,9 +531,9 @@
 TEST_F(TransactionTest, LayerFinalCropEmpty) {
     // TODO: Add scaling to confirm that crop happens in display space?
     {
-        GlobalTransactionScope gts(*sFakeComposer);
+        TransactionScope ts(*sFakeComposer);
         Rect cropRect(16, 16, 32, 32);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+        ts.setFinalCrop(mFGSurfaceControl, cropRect);
     }
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
 
@@ -549,8 +546,8 @@
 
 TEST_F(TransactionTest, LayerSetLayer) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
+        TransactionScope ts(*sFakeComposer);
+        ts.setLayer(mFGSurfaceControl, INT_MAX - 3);
     }
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
 
@@ -564,11 +561,10 @@
 
 TEST_F(TransactionTest, LayerSetLayerOpaque) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
-        ASSERT_EQ(NO_ERROR,
-                  mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque,
-                                              layer_state_t::eLayerOpaque));
+        TransactionScope ts(*sFakeComposer);
+        ts.setLayer(mFGSurfaceControl, INT_MAX - 3);
+        ts.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque,
+                layer_state_t::eLayerOpaque);
     }
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
 
@@ -581,8 +577,8 @@
 TEST_F(TransactionTest, SetLayerStack) {
     ALOGD("TransactionTest::SetLayerStack");
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
+        TransactionScope ts(*sFakeComposer);
+        ts.setLayerStack(mFGSurfaceControl, 1);
     }
 
     // Foreground layer should have disappeared.
@@ -595,8 +591,8 @@
 TEST_F(TransactionTest, LayerShowHide) {
     ALOGD("TransactionTest::LayerShowHide");
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
+        TransactionScope ts(*sFakeComposer);
+        ts.hide(mFGSurfaceControl);
     }
 
     // Foreground layer should have disappeared.
@@ -606,8 +602,8 @@
     EXPECT_TRUE(framesAreSame(refFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mFGSurfaceControl);
     }
 
     // Foreground layer should be back
@@ -617,8 +613,8 @@
 
 TEST_F(TransactionTest, LayerSetAlpha) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
+        TransactionScope ts(*sFakeComposer);
+        ts.setAlpha(mFGSurfaceControl, 0.75f);
     }
 
     ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -629,10 +625,9 @@
 
 TEST_F(TransactionTest, LayerSetFlags) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR,
-                  mFGSurfaceControl->setFlags(layer_state_t::eLayerHidden,
-                                              layer_state_t::eLayerHidden));
+        TransactionScope ts(*sFakeComposer);
+        ts.setFlags(mFGSurfaceControl, layer_state_t::eLayerHidden,
+                layer_state_t::eLayerHidden);
     }
 
     // Foreground layer should have disappeared.
@@ -664,17 +659,16 @@
              {{0.f, 1.f, 1.f, 0.f},     HWC_TRANSFORM_FLIP_H_ROT_90,    {64, 64, 128, 128}},
              {{0.f, 1.f, 1.f, 0.f},     HWC_TRANSFORM_FLIP_V_ROT_90,    {64, 64, 128, 128}}};
     // clang-format on
-    constexpr int TEST_COUNT = sizeof(MATRIX_TESTS)/sizeof(matrixTestData);
+    constexpr int TEST_COUNT = sizeof(MATRIX_TESTS) / sizeof(matrixTestData);
 
     for (int i = 0; i < TEST_COUNT; i++) {
         // TODO: How to leverage the HWC2 stringifiers?
         const matrixTestData& xform = MATRIX_TESTS[i];
         SCOPED_TRACE(i);
         {
-            GlobalTransactionScope gts(*sFakeComposer);
-            ASSERT_EQ(NO_ERROR,
-                      mFGSurfaceControl->setMatrix(xform.matrix[0], xform.matrix[1],
-                                                   xform.matrix[2], xform.matrix[3]));
+            TransactionScope ts(*sFakeComposer);
+            ts.setMatrix(mFGSurfaceControl, xform.matrix[0], xform.matrix[1],
+                    xform.matrix[2], xform.matrix[3]);
         }
 
         auto referenceFrame = mBaseFrame;
@@ -688,10 +682,10 @@
 #if 0
 TEST_F(TransactionTest, LayerSetMatrix2) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
+        TransactionScope ts(*sFakeComposer);
         // TODO: PLEASE SPEC THE FUNCTION!
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(0.11f, 0.123f,
-                                                         -2.33f, 0.22f));
+        ts.setMatrix(mFGSurfaceControl, 0.11f, 0.123f,
+                -2.33f, 0.22f);
     }
     auto referenceFrame = mBaseFrame;
     // TODO: Is this correct for sure?
@@ -712,10 +706,10 @@
     fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY);
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, syncSurfaceControl->setLayer(INT32_MAX - 1));
-        ASSERT_EQ(NO_ERROR, syncSurfaceControl->setPosition(mDisplayWidth - 2, mDisplayHeight - 2));
-        ASSERT_EQ(NO_ERROR, syncSurfaceControl->show());
+        TransactionScope ts(*sFakeComposer);
+        ts.setLayer(syncSurfaceControl, INT32_MAX - 1);
+        ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2);
+        ts.show(syncSurfaceControl);
     }
     auto referenceFrame = mBaseFrame;
     referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2,
@@ -727,20 +721,20 @@
     // set up two deferred transactions on different frames - these should not yield composited
     // frames
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
-        mFGSurfaceControl
-                ->deferTransactionUntil(syncSurfaceControl->getHandle(),
-                                        syncSurfaceControl->getSurface()->getNextFrameNumber());
+        TransactionScope ts(*sFakeComposer);
+        ts.setAlpha(mFGSurfaceControl, 0.75);
+        ts.deferTransactionUntil(mFGSurfaceControl, 
+                syncSurfaceControl->getHandle(),
+                syncSurfaceControl->getSurface()->getNextFrameNumber());
     }
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
-        mFGSurfaceControl
-                ->deferTransactionUntil(syncSurfaceControl->getHandle(),
-                                        syncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+        TransactionScope ts(*sFakeComposer);
+        ts.setPosition(mFGSurfaceControl, 128, 128);
+        ts.deferTransactionUntil(mFGSurfaceControl,
+                syncSurfaceControl->getHandle(),
+                syncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
     }
     EXPECT_EQ(4, sFakeComposer->getFrameCount());
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
@@ -756,8 +750,8 @@
 
     // should show up immediately since it's not deferred
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+        TransactionScope ts(*sFakeComposer);
+        ts.setAlpha(mFGSurfaceControl, 1.0);
     }
     referenceFrame[FG_LAYER].mPlaneAlpha = 1.f;
     EXPECT_EQ(6, sFakeComposer->getFrameCount());
@@ -781,10 +775,10 @@
 
     // Now we stack the surface above the foreground surface and make sure it is visible.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        relativeSurfaceControl->setPosition(64, 64);
-        relativeSurfaceControl->show();
-        relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+        TransactionScope ts(*sFakeComposer);
+        ts.setPosition(relativeSurfaceControl, 64, 64);
+        ts.show(relativeSurfaceControl);
+        ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1);
     }
     auto referenceFrame = mBaseFrame;
     // NOTE: All three layers will be visible as the surfaces are
@@ -795,8 +789,8 @@
 
     // A call to setLayer will override a call to setRelativeLayer
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        relativeSurfaceControl->setLayer(0);
+        TransactionScope ts(*sFakeComposer);
+        ts.setLayer(relativeSurfaceControl, 0);
     }
 
     // Previous top layer will now appear at the bottom.
@@ -832,11 +826,11 @@
 
 TEST_F(ChildLayerTest, Positioning) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(10, 10);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 10, 10);
         // Move to the same position as in the original setup.
-        mFGSurfaceControl->setPosition(64, 64);
+        ts.setPosition(mFGSurfaceControl, 64, 64);
     }
 
     auto referenceFrame = mBaseFrame;
@@ -846,8 +840,8 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0));
+        TransactionScope ts(*sFakeComposer);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
     }
 
     auto referenceFrame2 = mBaseFrame;
@@ -859,11 +853,11 @@
 
 TEST_F(ChildLayerTest, Cropping) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(0, 0);
-        mFGSurfaceControl->setPosition(0, 0);
-        mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 0, 0);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
+        ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
     }
     // NOTE: The foreground surface would be occluded by the child
     // now, but is included in the stack because the child is
@@ -878,11 +872,11 @@
 
 TEST_F(ChildLayerTest, FinalCropping) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(0, 0);
-        mFGSurfaceControl->setPosition(0, 0);
-        mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 0, 0);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
     }
     auto referenceFrame = mBaseFrame;
     referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5};
@@ -894,10 +888,10 @@
 
 TEST_F(ChildLayerTest, Constraints) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mFGSurfaceControl->setPosition(0, 0);
-        mChild->setPosition(63, 63);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
+        ts.setPosition(mChild, 63, 63);
     }
     auto referenceFrame = mBaseFrame;
     referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64};
@@ -908,8 +902,8 @@
 
 TEST_F(ChildLayerTest, Scaling) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setPosition(0, 0);
+        TransactionScope ts(*sFakeComposer);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
     }
     auto referenceFrame = mBaseFrame;
     referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64};
@@ -917,8 +911,8 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0);
+        TransactionScope ts(*sFakeComposer);
+        ts.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0);
     }
 
     auto referenceFrame2 = mBaseFrame;
@@ -929,11 +923,11 @@
 
 TEST_F(ChildLayerTest, LayerAlpha) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(0, 0);
-        mFGSurfaceControl->setPosition(0, 0);
-        ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5));
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 0, 0);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
+        ts.setAlpha(mChild, 0.5);
     }
 
     auto referenceFrame = mBaseFrame;
@@ -943,8 +937,8 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5));
+        TransactionScope ts(*sFakeComposer);
+        ts.setAlpha(mFGSurfaceControl, 0.5);
     }
 
     auto referenceFrame2 = referenceFrame;
@@ -955,10 +949,10 @@
 
 TEST_F(ChildLayerTest, ReparentChildren) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(10, 10);
-        mFGSurfaceControl->setPosition(64, 64);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 10, 10);
+        ts.setPosition(mFGSurfaceControl, 64, 64);
     }
     auto referenceFrame = mBaseFrame;
     referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
@@ -967,8 +961,8 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle());
+        TransactionScope ts(*sFakeComposer);
+        ts.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
     }
 
     auto referenceFrame2 = referenceFrame;
@@ -979,10 +973,10 @@
 
 TEST_F(ChildLayerTest, DetachChildren) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(10, 10);
-        mFGSurfaceControl->setPosition(64, 64);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 10, 10);
+        ts.setPosition(mFGSurfaceControl, 64, 64);
     }
 
     auto referenceFrame = mBaseFrame;
@@ -992,13 +986,13 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->detachChildren();
+        TransactionScope ts(*sFakeComposer);
+        ts.detachChildren(mFGSurfaceControl);
     }
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->hide();
+        TransactionScope ts(*sFakeComposer);
+        ts.hide(mChild);
     }
 
     // Nothing should have changed. The child control becomes a no-op
@@ -1009,17 +1003,17 @@
 
 TEST_F(ChildLayerTest, InheritNonTransformScalingFromParent) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(0, 0);
-        mFGSurfaceControl->setPosition(0, 0);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 0, 0);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
     }
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        TransactionScope ts(*sFakeComposer);
+        ts.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
         // We cause scaling by 2.
-        mFGSurfaceControl->setSize(128, 128);
+        ts.setSize(mFGSurfaceControl, 128, 128);
     }
 
     auto referenceFrame = mBaseFrame;
@@ -1033,17 +1027,17 @@
 // Regression test for b/37673612
 TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->show();
-        mChild->setPosition(0, 0);
-        mFGSurfaceControl->setPosition(0, 0);
+        TransactionScope ts(*sFakeComposer);
+        ts.show(mChild);
+        ts.setPosition(mChild, 0, 0);
+        ts.setPosition(mFGSurfaceControl, 0, 0);
     }
 
     // We set things up as in b/37673612 so that there is a mismatch between the buffer size and
     // the WM specified state size.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 64);
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 64);
     }
 
     sp<Surface> s = mFGSurfaceControl->getSurface();
@@ -1074,10 +1068,10 @@
 
     // Show the child layer in a deferred transaction
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(),
+        TransactionScope ts(*sFakeComposer);
+        ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(), 
                                       mFGSurfaceControl->getSurface()->getNextFrameNumber());
-        mChild->show();
+        ts.show(mChild);
     }
 
     // Render the foreground surface a few times
@@ -1114,11 +1108,11 @@
         sFakeComposer->runVSyncAndWait();
     }
     void restoreInitialState() {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(64, 64);
-        mFGSurfaceControl->setPosition(64, 64);
-        mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64));
-        mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 64, 64);
+        ts.setPosition(mFGSurfaceControl, 64, 64);
+        ts.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64));
+        ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
     }
 };
 
@@ -1126,9 +1120,9 @@
     // By default position can be updated even while
     // a resize is pending.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(32, 32);
-        mFGSurfaceControl->setPosition(100, 100);
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 32, 32);
+        ts.setPosition(mFGSurfaceControl, 100, 100);
     }
 
     // The size should not have updated as we have not provided a new buffer.
@@ -1141,10 +1135,10 @@
     // Now we repeat with setGeometryAppliesWithResize
     // and verify the position DOESN'T latch.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setGeometryAppliesWithResize();
-        mFGSurfaceControl->setSize(32, 32);
-        mFGSurfaceControl->setPosition(100, 100);
+        TransactionScope ts(*sFakeComposer);
+        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+        ts.setSize(mFGSurfaceControl, 32, 32);
+        ts.setPosition(mFGSurfaceControl, 100, 100);
     }
     EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
 
@@ -1160,9 +1154,9 @@
 TEST_F(LatchingTest, CropLatching) {
     // Normally the crop applies immediately even while a resize is pending.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
     }
 
     auto referenceFrame1 = mBaseFrame;
@@ -1173,10 +1167,10 @@
     restoreInitialState();
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setGeometryAppliesWithResize();
-        mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+        ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
     }
     EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
 
@@ -1192,9 +1186,9 @@
 TEST_F(LatchingTest, FinalCropLatching) {
     // Normally the crop applies immediately even while a resize is pending.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
     }
 
     auto referenceFrame1 = mBaseFrame;
@@ -1206,10 +1200,10 @@
     restoreInitialState();
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setGeometryAppliesWithResize();
-        mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
     }
     EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
 
@@ -1228,9 +1222,9 @@
 TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) {
     // Normally the crop applies immediately even while a resize is pending.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
     }
 
     auto referenceFrame1 = mBaseFrame;
@@ -1246,10 +1240,10 @@
     lockAndFillFGBuffer();
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setGeometryAppliesWithResize();
-        mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
     }
     EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
 
@@ -1275,15 +1269,15 @@
     // is still pending, and ensure we are successful. Success meaning the second crop
     // is the one which eventually latches and not the first.
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setSize(128, 128);
-        mFGSurfaceControl->setGeometryAppliesWithResize();
-        mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+        TransactionScope ts(*sFakeComposer);
+        ts.setSize(mFGSurfaceControl, 128, 128);
+        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
     }
 
     {
-        GlobalTransactionScope gts(*sFakeComposer);
-        mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+        TransactionScope ts(*sFakeComposer);
+        ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
     }
     EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
 
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
index 203ced5..010ac9c 100644
--- a/services/surfaceflinger/tests/hwc2/Android.mk
+++ b/services/surfaceflinger/tests/hwc2/Android.mk
@@ -36,7 +36,9 @@
     libui \
     libgui \
     liblog \
-    libsync
+    libsync \
+    libhwui \
+    android.hardware.graphics.common@1.0
 LOCAL_STATIC_LIBRARIES := \
     libbase \
     libadf \
@@ -49,6 +51,7 @@
     Hwc2TestLayers.cpp \
     Hwc2TestBuffer.cpp \
     Hwc2TestClientTarget.cpp \
-    Hwc2TestVirtualDisplay.cpp
+    Hwc2TestVirtualDisplay.cpp \
+    Hwc2TestPixelComparator.cpp
 
 include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 4055527..4878c14 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -1775,6 +1775,145 @@
         }
     }
 
+    void createAndPresentVirtualDisplay(size_t layerCnt,
+            Hwc2TestCoverage coverage,
+            const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
+            coverageExceptions)
+    {
+        Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
+        hwc2_display_t display;
+        android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+        do {
+            // Items dependent on the display dimensions
+            hwc2_error_t err = HWC2_ERROR_NONE;
+            const UnsignedArea& dimension =
+                    testVirtualDisplay.getDisplayDimension();
+            ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+                    dimension.height, &desiredFormat, &display, &err));
+            ASSERT_TRUE(err == HWC2_ERROR_NONE)
+                    << "Cannot allocate virtual display";
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+            ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+            std::vector<hwc2_config_t> configs;
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+                Area displayArea;
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+
+                std::vector<hwc2_layer_t> layers;
+                ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers,
+                        layerCnt));
+                Hwc2TestLayers testLayers(layers, coverage, displayArea,
+                        coverageExceptions);
+
+                /*
+                 * Layouts that do not cover an entire virtual display will
+                 * cause undefined behavior.
+                 * Enable optimizeLayouts to avoid this.
+                 */
+                testLayers.optimizeLayouts();
+                do {
+                    // Items dependent on the testLayers properties
+                    std::set<hwc2_layer_t> clientLayers;
+                    std::set<hwc2_layer_t> clearLayers;
+                    uint32_t numTypes, numRequests;
+                    bool hasChanges, skip;
+                    bool flipClientTarget;
+                    int32_t presentFence;
+                    Hwc2TestClientTarget testClientTarget;
+                    buffer_handle_t outputBufferHandle;
+                    android::base::unique_fd outputBufferReleaseFence;
+
+                    ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+                            &testLayers, &skip));
+
+                    if (skip)
+                        continue;
+
+                    ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+                            &numRequests, &hasChanges));
+
+                    if (hasChanges)
+                        EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+                                << "wrong number of requests";
+
+                    ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+                            testLayers, layers, numTypes, &clientLayers));
+
+                    ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+                            numRequests, &clearLayers, &flipClientTarget));
+                    ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
+                            &testClientTarget, testLayers, clientLayers,
+                            clearLayers, flipClientTarget, displayArea));
+                    ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
+
+                    ASSERT_EQ(testVirtualDisplay.getOutputBuffer(
+                            &outputBufferHandle, &outputBufferReleaseFence), 0);
+                    ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display,
+                            outputBufferHandle, outputBufferReleaseFence));
+
+                    EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
+                            &presentFence));
+                    ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
+
+                    ASSERT_EQ(testVirtualDisplay.verifyOutputBuffer(&testLayers,
+                            &layers, &clearLayers), 0);
+
+                    /*
+                     * Upscaling the image causes minor pixel differences.
+                     * Work around this by using some threshold.
+                     *
+                     * Fail test if we are off by more than 1% of our
+                     * pixels.
+                     */
+                    ComparatorResult& comparatorResult = ComparatorResult::get();
+                    int threshold = (dimension.width * dimension.height) / 100;
+                    double diffPercent = (comparatorResult.getDifferentPixelCount() * 100.0) /
+                            (dimension.width * dimension.height);
+
+                    if (comparatorResult.getDifferentPixelCount() != 0)
+                        EXPECT_TRUE(false)
+                                << comparatorResult.getDifferentPixelCount() << " pixels ("
+                                << diffPercent << "%) are different.";
+
+                    if (comparatorResult.getDifferentPixelCount() > threshold) {
+                        EXPECT_TRUE(false)
+                                << "Mismatched pixel count exceeds threshold. "
+                                << "Writing buffers to file.";
+
+                        const ::testing::TestInfo* const test_info =
+                                ::testing::UnitTest::GetInstance()
+                                ->current_test_info();
+
+                        EXPECT_EQ(testVirtualDisplay.writeBuffersToFile(
+                                test_info->name()), 0)
+                                << "Failed to write buffers.";
+                    }
+
+                    ASSERT_LE(comparatorResult.getDifferentPixelCount(), threshold)
+                            << comparatorResult.getDifferentPixelCount() << " pixels ("
+                            << diffPercent << "%) are different. "
+                            << "Exceeds 1% threshold, terminating test. "
+                            << "Test case: " << testLayers.dump();
+
+                } while (testLayers.advance());
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+                        std::move(layers)));
+            }
+            ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+            ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+        } while (testVirtualDisplay.advance());
+    }
+
     hwc2_device_t* mHwc2Device = nullptr;
 
     enum class Hwc2TestHotplugStatus {
@@ -4479,7 +4618,7 @@
                 buffer_handle_t handle;
                 android::base::unique_fd acquireFence;
 
-                if (testVirtualDisplay->getBuffer(&handle, &acquireFence) >= 0)
+                if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) >= 0)
                     EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
                             handle, acquireFence));
             }));
@@ -4499,7 +4638,7 @@
 
                 ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
 
-                if (testVirtualDisplay->getBuffer(&handle, &acquireFence) < 0)
+                if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) < 0)
                     return;
 
                 ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
@@ -4539,7 +4678,7 @@
             android::base::unique_fd acquireFence;
             hwc2_error_t err = HWC2_ERROR_NONE;
 
-            if (testVirtualDisplay.getBuffer(&handle, &acquireFence) < 0)
+            if (testVirtualDisplay.getOutputBuffer(&handle, &acquireFence) < 0)
                 continue;
 
             ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
@@ -4557,3 +4696,74 @@
 
     ASSERT_NO_FATAL_FAILURE(dump(&buffer));
 }
+
+/*
+ * TODO(b/64724708): Hwc2TestPropertyName::BufferArea MUST be default for all
+ * virtual display tests as we don't handle this case correctly.
+ *
+ * Only default dataspace is supported in our drawing code.
+ */
+const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>
+        virtualDisplayExceptions =
+        {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Default},
+        {Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Default}};
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_1)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    const size_t layerCnt = 1;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with basic coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_basic_1)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
+    const size_t layerCnt = 1;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_2)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    const size_t layerCnt = 2;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_3)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    const size_t layerCnt = 3;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_4)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    const size_t layerCnt = 4;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 5 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5)
+{
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    const size_t layerCnt = 5;
+    ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+            virtualDisplayExceptions));
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
index 1d3a1d3..6484562 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
@@ -23,14 +23,17 @@
 #include <gui/BufferItemConsumer.h>
 
 #include <ui/GraphicBuffer.h>
+#include <android/hardware/graphics/common/1.0/types.h>
 #include <math/vec4.h>
 
 #include <GLES3/gl3.h>
-
+#include <SkImageEncoder.h>
+#include <SkStream.h>
 #include "Hwc2TestBuffer.h"
 #include "Hwc2TestLayers.h"
 
 using namespace android;
+using android::hardware::graphics::common::V1_0::BufferUsage;
 
 /* Returns a fence from egl */
 typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
@@ -396,8 +399,9 @@
 {
     /* Create new graphic buffer with correct dimensions */
     mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
-            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
-            "hwc2_test_buffer");
+            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+            BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
+
     int ret = mGraphicBuffer->initCheck();
     if (ret) {
         return ret;
@@ -408,7 +412,8 @@
 
     /* Locks the buffer for writing */
     uint8_t* img;
-    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+            (void**)(&img));
 
     uint32_t stride = mGraphicBuffer->getStride();
 
@@ -458,31 +463,22 @@
 
 Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
 
-/* Generates a client target buffer using the layers assigned for client
- * composition. Takes into account the individual layer properties such as
+/* Generates a buffer from layersToDraw.
+ * Takes into account the individual layer properties such as
  * transform, blend mode, source crop, etc. */
-int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
-        int32_t* outFence, const Area& bufferArea,
+static void compositeBufferFromLayers(
+        const android::sp<android::GraphicBuffer>& graphicBuffer,
+        android_pixel_format_t format, const Area& bufferArea,
         const Hwc2TestLayers* testLayers,
-        const std::set<hwc2_layer_t>* clientLayers,
+        const std::set<hwc2_layer_t>* layersToDraw,
         const std::set<hwc2_layer_t>* clearLayers)
 {
-    /* Create new graphic buffer with correct dimensions */
-    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
-            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
-            "hwc2_test_buffer");
-    int ret = mGraphicBuffer->initCheck();
-    if (ret) {
-        return ret;
-    }
-    if (!mGraphicBuffer->handle) {
-        return -EINVAL;
-    }
-
+    /* Locks the buffer for writing */
     uint8_t* img;
-    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    graphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+            (void**)(&img));
 
-    uint32_t stride = mGraphicBuffer->getStride();
+    uint32_t stride = graphicBuffer->getStride();
 
     float bWDiv3 = bufferArea.width / 3;
     float bW2Div3 = bufferArea.width * 2 / 3;
@@ -497,10 +493,10 @@
             uint8_t r = 0, g = 0, b = 0;
             float a = 0.0f;
 
-            /* Cycle through each client layer from back to front and
+            /* Cycle through each layer from back to front and
              * update the pixel color. */
-            for (auto layer = clientLayers->rbegin();
-                    layer != clientLayers->rend(); ++layer) {
+            for (auto layer = layersToDraw->rbegin();
+                    layer != layersToDraw->rend(); ++layer) {
 
                 const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
 
@@ -570,8 +566,8 @@
                      * (100x50) at the end of the transformation. */
                     if (transform & HWC_TRANSFORM_ROT_90) {
                         float tmp = xPos;
-                        xPos = -yPos * dfW / dfH;
-                        yPos = tmp * dfH / dfW;
+                        xPos = yPos * dfW / dfH;
+                        yPos = -tmp * dfH / dfW;
                     }
 
                     /* Change origin back to the top left corner of the
@@ -682,14 +678,114 @@
             }
 
             /* Set the pixel color */
-            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
+            setColor(x, y, format, stride, img, r, g, b, a * 255);
         }
     }
 
-    mGraphicBuffer->unlock();
+    graphicBuffer->unlock();
+}
+
+/* Generates a client target buffer using the layers assigned for client
+ * composition. Takes into account the individual layer properties such as
+ * transform, blend mode, source crop, etc. */
+int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
+        int32_t* outFence, const Area& bufferArea,
+        const Hwc2TestLayers* testLayers,
+        const std::set<hwc2_layer_t>* clientLayers,
+        const std::set<hwc2_layer_t>* clearLayers)
+{
+    /* Create new graphic buffer with correct dimensions */
+    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
+            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+            BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
+
+    int ret = mGraphicBuffer->initCheck();
+    if (ret)
+        return ret;
+
+    if (!mGraphicBuffer->handle)
+        return -EINVAL;
+
+    compositeBufferFromLayers(mGraphicBuffer, mFormat, bufferArea, testLayers,
+            clientLayers, clearLayers);
 
     *outFence = mFenceGenerator->get();
     *outHandle = mGraphicBuffer->handle;
 
     return 0;
 }
+
+void Hwc2TestVirtualBuffer::updateBufferArea(const Area& bufferArea)
+{
+    mBufferArea.width = bufferArea.width;
+    mBufferArea.height = bufferArea.height;
+}
+
+bool Hwc2TestVirtualBuffer::writeBufferToFile(std::string path)
+{
+    SkFILEWStream file(path.c_str());
+    const SkImageInfo info = SkImageInfo::Make(mBufferArea.width,
+            mBufferArea.height, SkColorType::kRGBA_8888_SkColorType,
+            SkAlphaType::kPremul_SkAlphaType);
+
+    uint8_t* img;
+    mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+            (void**)(&img));
+
+    SkPixmap pixmap(info, img, mGraphicBuffer->getStride());
+    bool result = file.isValid() && SkEncodeImage(&file, pixmap,
+            SkEncodedImageFormat::kPNG, 100);
+
+    mGraphicBuffer->unlock();
+    return result;
+}
+
+/* Generates a buffer that holds the expected result of compositing all of our
+ * layers */
+int Hwc2TestExpectedBuffer::generateExpectedBuffer(
+        const Hwc2TestLayers* testLayers,
+        const std::vector<hwc2_layer_t>* allLayers,
+        const std::set<hwc2_layer_t>* clearLayers)
+{
+    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
+            mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
+            "hwc2_test_buffer");
+
+    int ret = mGraphicBuffer->initCheck();
+    if (ret)
+        return ret;
+
+    if (!mGraphicBuffer->handle)
+        return -EINVAL;
+
+    const std::set<hwc2_layer_t> allLayerSet(allLayers->begin(),
+            allLayers->end());
+
+    compositeBufferFromLayers(mGraphicBuffer, mFormat, mBufferArea, testLayers,
+            &allLayerSet, clearLayers);
+
+    return 0;
+}
+
+int Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle,
+        int32_t* outFence)
+{
+    if (mBufferArea.width == -1 || mBufferArea.height == -1)
+        return -EINVAL;
+
+    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
+            mFormat, BufferUsage::CPU_READ_OFTEN |
+            BufferUsage::GPU_RENDER_TARGET, "hwc2_test_buffer");
+
+    int ret = mGraphicBuffer->initCheck();
+    if (ret)
+        return ret;
+
+    if (!mGraphicBuffer->handle)
+        return -EINVAL;
+
+    *outFence = -1;
+    *outHandle = mGraphicBuffer->handle;
+
+    return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
index b2b3a66..fd54fef 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
@@ -71,4 +71,38 @@
     const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 };
 
+
+class Hwc2TestVirtualBuffer {
+public:
+    void updateBufferArea(const Area& bufferArea);
+
+    bool writeBufferToFile(std::string path);
+
+    android::sp<android::GraphicBuffer>& graphicBuffer()
+    {
+        return mGraphicBuffer;
+    }
+
+protected:
+    android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+    Area mBufferArea = {-1, -1};
+
+    const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+};
+
+
+class Hwc2TestExpectedBuffer : public Hwc2TestVirtualBuffer {
+public:
+    int generateExpectedBuffer(const Hwc2TestLayers* testLayers,
+            const std::vector<hwc2_layer_t>* allLayers,
+            const std::set<hwc2_layer_t>* clearLayers);
+};
+
+
+class Hwc2TestOutputBuffer : public Hwc2TestVirtualBuffer {
+public:
+    int getOutputBuffer(buffer_handle_t* outHandle, int32_t* outFence);
+};
+
 #endif /* ifndef _HWC2_TEST_BUFFER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
new file mode 100644
index 0000000..904b927
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <android/hardware/graphics/common/1.0/types.h>
+
+#include "Hwc2TestPixelComparator.h"
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
+uint32_t ComparatorResult::getPixel(int32_t x, int32_t y, uint32_t stride,
+        uint8_t* img) const
+{
+    uint32_t r = img[(y * stride + x) * 4 + 0];
+    uint32_t g = img[(y * stride + x) * 4 + 1];
+    uint32_t b = img[(y * stride + x) * 4 + 2];
+    uint32_t a = img[(y * stride + x) * 4 + 3];
+
+    uint32_t pixel = 0;
+    pixel |= r;
+    pixel |= g << 8;
+    pixel |= b << 16;
+    pixel |= a << 24;
+    return pixel;
+}
+
+void ComparatorResult::CompareBuffers(
+        android::sp<android::GraphicBuffer>& resultBuffer,
+        android::sp<android::GraphicBuffer>& expectedBuffer)
+{
+    uint8_t* resultBufferImg;
+    uint8_t* expectedBufferImg;
+    resultBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
+            (void**)(&resultBufferImg));
+
+    expectedBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
+            (void**)(&expectedBufferImg));
+    mComparisons.clear();
+    int32_t mDifferentPixelCount = 0;
+    int32_t mBlankPixelCount = 0;
+
+    for (uint32_t y = 0; y < resultBuffer->getHeight(); y++) {
+        for (uint32_t x = 0; x < resultBuffer->getWidth(); x++) {
+            uint32_t result = getPixel(x, y, resultBuffer->getStride(),
+                    resultBufferImg);
+            uint32_t expected = getPixel(x, y, expectedBuffer->getStride(),
+                    expectedBufferImg);
+
+            if (result == 0)
+                mBlankPixelCount++;
+
+            if (result != expected)
+                mDifferentPixelCount++;
+
+            mComparisons.emplace_back(std::make_tuple(x, y, result, expected));
+        }
+    }
+    resultBuffer->unlock();
+    expectedBuffer->unlock();
+}
+
+std::string ComparatorResult::pixelDiff(uint32_t x, uint32_t y,
+        uint32_t resultPixel, uint32_t expectedPixel) const
+{
+    uint32_t resultAlpha = (resultPixel >> 24) & 0xFF;
+    uint32_t resultBlue = (resultPixel >> 16) & 0xFF;
+    uint32_t resultGreen = (resultPixel >> 8) & 0xFF;
+    uint32_t resultRed = resultPixel & 0xFF;
+
+    uint32_t expectedAlpha = (expectedPixel >> 24) & 0xFF;
+    uint32_t expectedBlue = (expectedPixel >> 16) & 0xFF;
+    uint32_t expectedGreen = (expectedPixel >> 8) & 0xFF;
+    uint32_t expectedRed = expectedPixel & 0xFF;
+
+    std::ostringstream stream;
+
+    stream << "x: " << x << " y: " << y << std::endl;
+    stream << std::hex;
+    stream << "Result pixel:   " << resultRed << "|" << resultGreen << "|"
+           << resultBlue << "|" << resultAlpha << std::endl;
+
+    stream << "Expected pixel: " << expectedRed << "|" << expectedGreen << "|"
+           << expectedBlue << "|" << expectedAlpha << std::endl;
+
+    return stream.str();
+}
+
+std::string ComparatorResult::dumpComparison() const
+{
+    std::ostringstream stream;
+    stream << "Number of different pixels: " << mDifferentPixelCount;
+
+    for (const auto& comparison : mComparisons) {
+        if (std::get<2>(comparison) != std::get<3>(comparison))
+            stream << pixelDiff(std::get<0>(comparison),
+                    std::get<1>(comparison), std::get<2>(comparison),
+                    std::get<3>(comparison));
+    }
+    return stream.str();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
new file mode 100644
index 0000000..55fa936
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HWC2_TEST_PIXEL_COMPARATOR_H
+#define _HWC2_TEST_PIXEL_COMPARATOR_H
+
+#include <ui/GraphicBuffer.h>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+class ComparatorResult {
+public:
+    static ComparatorResult& get()
+    {
+        static ComparatorResult instance;
+        return instance;
+    }
+
+    void CompareBuffers(android::sp<android::GraphicBuffer>& resultBuffer,
+            android::sp<android::GraphicBuffer>& expectedBuffer);
+
+    std::string dumpComparison() const;
+
+    ComparatorResult(const ComparatorResult&) = delete;
+    ComparatorResult(ComparatorResult&&) = delete;
+    ComparatorResult& operator=(ComparatorResult const&) = delete;
+    ComparatorResult& operator=(ComparatorResult&&) = delete;
+
+    int32_t getDifferentPixelCount() const { return mDifferentPixelCount; }
+    int32_t getBlankPixelCount() const { return mBlankPixelCount; }
+
+private:
+    ComparatorResult() = default;
+    uint32_t getPixel(int32_t x, int32_t y, uint32_t stride, uint8_t* img) const;
+    std::string pixelDiff(uint32_t x, uint32_t y, uint32_t resultPixel,
+            uint32_t expectedPixel) const;
+
+    int32_t mDifferentPixelCount;
+    int32_t mBlankPixelCount;
+    /* std::tuple<X coordinate, Y coordinate, resultPixel, expectedPixel> */
+    std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>>
+            mComparisons;
+};
+
+#endif /* ifndef _HWC2_TEST_PIXEL_COMPARATOR_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
index b5522de..5b3bbeb 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -335,9 +335,9 @@
     return dmp.str();
 }
 
-void Hwc2TestDisplayDimension::setDependent(Hwc2TestBuffer* buffer)
+void Hwc2TestDisplayDimension::setDependent(Hwc2TestVirtualBuffer* buffer)
 {
-    mBuffer = buffer;
+    mBuffers.insert(buffer);
     updateDependents();
 }
 
@@ -345,8 +345,8 @@
 {
     const UnsignedArea& curr = get();
 
-    if (mBuffer)
-        mBuffer->updateBufferArea({static_cast<int32_t>(curr.width),
+    for (Hwc2TestVirtualBuffer* buffer : mBuffers)
+        buffer->updateBufferArea({static_cast<int32_t>(curr.width),
                 static_cast<int32_t>(curr.height)});
 }
 
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index c2029ab..cb811e0 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -243,6 +243,7 @@
     static const std::array<bool, 6> mCompositionSupport;
 };
 
+class Hwc2TestVirtualBuffer;
 
 class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
 public:
@@ -250,12 +251,12 @@
 
     std::string dump() const;
 
-    void setDependent(Hwc2TestBuffer* buffer);
+    void setDependent(Hwc2TestVirtualBuffer* buffer);
 
 private:
     void updateDependents();
 
-    Hwc2TestBuffer* mBuffer;
+    std::set<Hwc2TestVirtualBuffer*> mBuffers;
 
     static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
     static const std::vector<UnsignedArea> mBasicDisplayDimensions;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
index d0fbc0b..e6cceb8 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
@@ -15,14 +15,18 @@
  */
 
 #include <sstream>
+#include <sys/stat.h>
 
 #include "Hwc2TestVirtualDisplay.h"
 
+#define DIR_NAME "images"
+
 Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay(
         Hwc2TestCoverage coverage)
     : mDisplayDimension(coverage)
 {
-    mDisplayDimension.setDependent(&mBuffer);
+    mDisplayDimension.setDependent(&mOutputBuffer);
+    mDisplayDimension.setDependent(&mExpectedBuffer);
 }
 
 std::string Hwc2TestVirtualDisplay::dump() const
@@ -36,11 +40,11 @@
     return dmp.str();
 }
 
-int Hwc2TestVirtualDisplay::getBuffer(buffer_handle_t* outHandle,
+int Hwc2TestVirtualDisplay::getOutputBuffer(buffer_handle_t* outHandle,
         android::base::unique_fd* outAcquireFence)
 {
     int32_t acquireFence;
-    int ret = mBuffer.get(outHandle, &acquireFence);
+    int ret = mOutputBuffer.getOutputBuffer(outHandle, &acquireFence);
     outAcquireFence->reset(acquireFence);
     return ret;
 }
@@ -59,3 +63,36 @@
 {
     return mDisplayDimension.get();
 }
+
+int Hwc2TestVirtualDisplay::verifyOutputBuffer(const Hwc2TestLayers* testLayers,
+        const std::vector<hwc2_layer_t>* allLayers,
+        const std::set<hwc2_layer_t>* clearLayers)
+{
+    int ret = mExpectedBuffer.generateExpectedBuffer(testLayers, allLayers,
+            clearLayers);
+    if (ret)
+        return ret;
+
+    ComparatorResult::get().CompareBuffers(mOutputBuffer.graphicBuffer(),
+        mExpectedBuffer.graphicBuffer());
+
+    return 0;
+}
+
+int Hwc2TestVirtualDisplay::writeBuffersToFile(std::string name)
+{
+    std::ostringstream expectedPath;
+    std::ostringstream resultPath;
+    int ret = mkdir(DIR_NAME, DEFFILEMODE);
+    if (ret && errno != EEXIST)
+        return ret;
+
+    expectedPath << DIR_NAME << "/expected-" << name << ".png";
+    resultPath << DIR_NAME << "/result-" << name << ".png";
+
+    if (!mExpectedBuffer.writeBufferToFile(expectedPath.str()) ||
+            !mOutputBuffer.writeBufferToFile(resultPath.str()))
+        return -1;
+
+    return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
index 09420ef..10c8ef0 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -18,6 +18,7 @@
 #define _HWC2_TEST_VIRTUAL_DISPLAY_H
 
 #include "Hwc2TestBuffer.h"
+#include "Hwc2TestPixelComparator.h"
 #include "Hwc2TestProperties.h"
 
 #define HWC2_INCLUDE_STRINGIFICATION
@@ -32,17 +33,22 @@
 
     std::string dump() const;
 
-    int getBuffer(buffer_handle_t* outHandle,
+    int getOutputBuffer(buffer_handle_t* outHandle,
             android::base::unique_fd* outAcquireFence);
 
+    int verifyOutputBuffer(const Hwc2TestLayers* testLayers,
+            const std::vector<hwc2_layer_t>* allLayers,
+            const std::set<hwc2_layer_t>* clearLayers);
+
+    int writeBuffersToFile(std::string name);
     void reset();
     bool advance();
 
     UnsignedArea getDisplayDimension() const;
 
 private:
-    Hwc2TestBuffer mBuffer;
-
+    Hwc2TestOutputBuffer mOutputBuffer;
+    Hwc2TestExpectedBuffer mExpectedBuffer;
     Hwc2TestDisplayDimension mDisplayDimension;
 };
 
diff --git a/services/thermalservice/thermalservice.rc b/services/thermalservice/thermalservice.rc
index b9836ce..94c2c78 100644
--- a/services/thermalservice/thermalservice.rc
+++ b/services/thermalservice/thermalservice.rc
@@ -1,2 +1,4 @@
 service thermalservice /system/bin/thermalserviced
     class core
+    user system
+    group system
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
new file mode 100644
index 0000000..6132956
--- /dev/null
+++ b/services/utils/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// Static library used in testing and executables
+//
+cc_library_static {
+    name: "libserviceutils",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    srcs: [
+        "PriorityDumper.cpp",
+    ],
+
+    clang: true,
+    export_include_dirs: ["include"],
+}
+
+subdirs = ["tests"]
diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp
new file mode 100644
index 0000000..967dee5
--- /dev/null
+++ b/services/utils/PriorityDumper.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/serviceutils/PriorityDumper.h"
+
+namespace android {
+
+const char16_t PriorityDumper::PROTO_ARG[] = u"--proto";
+const char16_t PriorityDumper::PRIORITY_ARG[] = u"--dump-priority";
+const char16_t PriorityDumper::PRIORITY_ARG_CRITICAL[] = u"CRITICAL";
+const char16_t PriorityDumper::PRIORITY_ARG_HIGH[] = u"HIGH";
+const char16_t PriorityDumper::PRIORITY_ARG_NORMAL[] = u"NORMAL";
+
+enum class PriorityType { INVALID, CRITICAL, HIGH, NORMAL };
+
+static PriorityType getPriorityType(const String16& arg) {
+    if (arg == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+        return PriorityType::CRITICAL;
+    } else if (arg == PriorityDumper::PRIORITY_ARG_HIGH) {
+        return PriorityType::HIGH;
+    } else if (arg == PriorityDumper::PRIORITY_ARG_NORMAL) {
+        return PriorityType::NORMAL;
+    }
+    return PriorityType::INVALID;
+}
+
+status_t PriorityDumper::dumpAll(int fd, const Vector<String16>& args, bool asProto) {
+    status_t status;
+    status = dumpCritical(fd, args, asProto);
+    if (status != OK) return status;
+    status = dumpHigh(fd, args, asProto);
+    if (status != OK) return status;
+    status = dumpNormal(fd, args, asProto);
+    if (status != OK) return status;
+    return status;
+}
+
+status_t PriorityDumper::priorityDump(int fd, const Vector<String16>& args) {
+    status_t status;
+    bool asProto = false;
+    PriorityType priority = PriorityType::INVALID;
+
+    Vector<String16> strippedArgs;
+    for (uint32_t argIndex = 0; argIndex < args.size(); argIndex++) {
+        if (args[argIndex] == PROTO_ARG) {
+            asProto = true;
+        } else if (args[argIndex] == PRIORITY_ARG) {
+            if (argIndex + 1 < args.size()) {
+                argIndex++;
+                priority = getPriorityType(args[argIndex]);
+            }
+        } else {
+            strippedArgs.add(args[argIndex]);
+        }
+    }
+
+    switch (priority) {
+        case PriorityType::CRITICAL:
+            status = dumpCritical(fd, strippedArgs, asProto);
+            break;
+        case PriorityType::HIGH:
+            status = dumpHigh(fd, strippedArgs, asProto);
+            break;
+        case PriorityType::NORMAL:
+            status = dumpNormal(fd, strippedArgs, asProto);
+            break;
+        default:
+            status = dumpAll(fd, strippedArgs, asProto);
+            break;
+    }
+    return status;
+}
+} // namespace android
diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h
new file mode 100644
index 0000000..d01a102
--- /dev/null
+++ b/services/utils/include/serviceutils/PriorityDumper.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_PRIORITYDUMPER_H
+#define ANDROID_UTILS_PRIORITYDUMPER_H
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+// Helper class to parse common arguments responsible for splitting dumps into
+// various priority buckets and changing the output format of the dump.
+class PriorityDumper {
+public:
+    static const char16_t PRIORITY_ARG[];
+    static const char16_t PRIORITY_ARG_CRITICAL[];
+    static const char16_t PRIORITY_ARG_HIGH[];
+    static const char16_t PRIORITY_ARG_NORMAL[];
+    static const char16_t PROTO_ARG[];
+
+    // Parses the argument list searching for --dump_priority with a priority type
+    // (HIGH, CRITICAL or NORMAL) and --proto. Matching arguments are stripped.
+    // If a valid priority type is found, the associated PriorityDumper
+    // method is called otherwise all supported sections are dumped.
+    // If --proto is found, the dumpAsProto flag is set to dump sections in proto
+    // format.
+    status_t priorityDump(int fd, const Vector<String16>& args);
+
+    // Dumps CRITICAL priority sections.
+    virtual status_t dumpCritical(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+        return OK;
+    }
+
+    // Dumps HIGH priority sections.
+    virtual status_t dumpHigh(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+        return OK;
+    }
+
+    // Dumps normal priority sections.
+    virtual status_t dumpNormal(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+        return OK;
+    }
+
+    // Dumps all sections.
+    // This method is called when priorityDump is called without priority
+    // arguments. By default, it calls all three dump methods.
+    virtual status_t dumpAll(int fd, const Vector<String16>& args, bool asProto);
+    virtual ~PriorityDumper() = default;
+};
+
+} // namespace android
+
+#endif // ANDROID_UTILS_PRIORITYDUMPER_H
diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp
new file mode 100644
index 0000000..15829fa
--- /dev/null
+++ b/services/utils/tests/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Build unit tests.
+
+cc_test {
+    name: "prioritydumper_test",
+    test_suites: ["device-tests"],
+    srcs: [ "PriorityDumper_test.cpp"],
+    shared_libs: [
+        "libutils",
+    ],
+    static_libs = [
+        "libgmock",
+        "libserviceutils"
+    ],
+    clang: true,
+}
\ No newline at end of file
diff --git a/services/utils/tests/AndroidTest.xml b/services/utils/tests/AndroidTest.xml
new file mode 100644
index 0000000..83c890d
--- /dev/null
+++ b/services/utils/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for prioritydumper_test">
+  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+    <option name="cleanup" value="true" />
+    <option name="push" value="prioritydumper_test->/data/local/tmp/prioritydumper_test" />
+  </target_preparer>
+  <option name="test-suite-tag" value="apct" />
+  <test class="com.android.tradefed.testtype.GTest" >
+    <option name="native-test-device-path" value="/data/local/tmp" />
+    <option name="module-name" value="prioritydumper_test" />
+  </test>
+</configuration>
\ No newline at end of file
diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp
new file mode 100644
index 0000000..90cc6de
--- /dev/null
+++ b/services/utils/tests/PriorityDumper_test.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "serviceutils/PriorityDumper.h"
+
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+using ::testing::ElementsAreArray;
+using ::testing::Mock;
+using ::testing::Test;
+
+class PriorityDumperMock : public PriorityDumper {
+public:
+    MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+    MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+    MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
+    MOCK_METHOD3(dumpAll, status_t(int, const Vector<String16>&, bool));
+};
+
+class DumpAllMock : public PriorityDumper {
+public:
+    MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+    MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+    MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
+};
+
+class PriorityDumperTest : public Test {
+public:
+    PriorityDumperTest() : dumper_(), dumpAlldumper_(), fd(1) {}
+    PriorityDumperMock dumper_;
+    DumpAllMock dumpAlldumper_;
+    int fd;
+};
+
+static void addAll(Vector<String16>& av, const std::vector<std::string>& v) {
+    for (auto element : v) {
+        av.add(String16(element.c_str()));
+    }
+}
+
+TEST_F(PriorityDumperTest, noArgsPassed) {
+    Vector<String16> args;
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, noPriorityArgsPassed) {
+    Vector<String16> args;
+    addAll(args, {"bunch", "of", "args"});
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgsOnly) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "CRITICAL"});
+    Vector<String16> strippedArgs;
+    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpCritical) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "CRITICAL", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpCriticalInMiddle) {
+    Vector<String16> args;
+    addAll(args, {"args", "left", "--dump-priority", "CRITICAL", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpHigh) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "HIGH", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpHighInEnd) {
+    Vector<String16> args;
+    addAll(args, {"args", "left", "behind", "--dump-priority", "HIGH"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpNormal) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "NORMAL", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpAll) {
+    Vector<String16> args;
+    addAll(args, {"args", "left", "behind"});
+
+    EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args), /*asProto=*/false));
+    EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args), /*asProto=*/false));
+    EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args), /*asProto=*/false));
+
+    dumpAlldumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority"});
+    Vector<String16> strippedArgs;
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "REALLY_HIGH"});
+    Vector<String16> strippedArgs;
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArg) {
+    Vector<String16> args;
+    addAll(args, {"--proto"});
+    Vector<String16> strippedArgs;
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgs) {
+    Vector<String16> args;
+    addAll(args, {"--proto", "args", "--dump-priority", "NORMAL", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgsInReverseOrder) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "NORMAL", "--proto", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgInMiddle) {
+    Vector<String16> args;
+    addAll(args, {"--unknown", "args", "--proto", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgAtEnd) {
+    Vector<String16> args;
+    addAll(args, {"--unknown", "args", "args", "left", "behind", "--proto"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithInvalidPriorityType) {
+    Vector<String16> args;
+    addAll(args, {"--dump-priority", "NOT_SO_HIGH", "--proto", "args", "left", "behind"});
+    Vector<String16> strippedArgs;
+    addAll(strippedArgs, {"args", "left", "behind"});
+    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+    dumper_.priorityDump(fd, args);
+}
\ No newline at end of file
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index 28cf53d..e1997d7 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -32,6 +32,7 @@
 
 sharedLibraries := \
 	libbase \
+	libbinder \
 	libcutils \
 	liblog \
 	libsync \
diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index 46fe5f9..c470de5 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -2,5 +2,4 @@
   class core
   user system
   group system
-  writepid /dev/cpuset/tasks
   socket pdx/system/buffer_hub/client stream 0660 system system u:object_r:pdx_bufferhub_client_endpoint_socket:s0
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index e92b8d8..76ec42d 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -20,6 +20,7 @@
     "android.hardware.graphics.composer@2.1",
     "android.hardware.graphics.mapper@2.0",
     "libbase",
+    "libbinder",
     "libcutils",
     "libfmq",
     "libhardware",
diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 2605a47..af9760e 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -2,5 +2,4 @@
   class core
   user root
   group system readproc
-  writepid /dev/cpuset/tasks
   socket pdx/system/performance/client stream 0666 system system u:object_r:pdx_performance_client_endpoint_socket:s0
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 2981a95..2bbe5e6 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -27,7 +27,7 @@
 
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
-define VERSION_MINOR 0
+define VERSION_MINOR 1
 define VERSION_PATCH 61
 
 // API limits
@@ -37,11 +37,10 @@
 define VK_MAX_DESCRIPTION_SIZE          256
 define VK_MAX_MEMORY_TYPES              32
 define VK_MAX_MEMORY_HEAPS              16    /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
-define VK_MAX_DEVICE_GROUP_SIZE_KHX     32
-//@extension("VK_KHR_external_memory_capabilities")
-define VK_LUID_SIZE_KHR                 8
-//@extension("VK_KHR_external_memory")
-define VK_QUEUE_FAMILY_EXTERNAL_KHR     -2
+@vulkan1_1
+define VK_MAX_DEVICE_GROUP_SIZE         32
+define VK_LUID_SIZE                     8
+define VK_QUEUE_FAMILY_EXTERNAL         -2
 
 // API keywords
 define VK_TRUE        1
@@ -55,7 +54,7 @@
 @extension("VK_KHR_surface") define VK_KHR_SURFACE_EXTENSION_NAME               "VK_KHR_surface"
 
 // 2
-@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION             68
+@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION             70
 @extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_EXTENSION_NAME           "VK_KHR_swapchain"
 
 // 3
@@ -95,7 +94,7 @@
 @extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME             "VK_ANDROID_native_buffer"
 
 // 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       8
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       9
 @extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
 
 // 13
@@ -163,8 +162,8 @@
 @extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
 
 // 54
-@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_SPEC_VERSION 1
-@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
+@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_SPEC_VERSION 1
+@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
 
 // 56
 @extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
@@ -187,8 +186,8 @@
 @extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
 
 // 61
-@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_SPEC_VERSION 2
-@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
+@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_SPEC_VERSION 3
+@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
 
 // 62
 @extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
@@ -215,8 +214,8 @@
 @extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
 
 // 71
-@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
-@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
+@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
 
 // 72
 @extension("VK_KHR_external_memory_capabilities") define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
@@ -255,7 +254,7 @@
 @extension("VK_KHR_external_semaphore_fd") define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
 
 // 81
-@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
 @extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
 
 // 84
@@ -450,6 +449,10 @@
 @extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
 @extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
 
+// 169
+@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
+@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+
 /////////////
 //  Types  //
 /////////////
@@ -488,6 +491,10 @@
 @nonDispatchHandle type u64 VkRenderPass
 @nonDispatchHandle type u64 VkPipelineCache
 
+@vulkan1_1
+@nonDispatchHandle type u64 VkSamplerYcbcrConversion
+@nonDispatchHandle type u64 VkDescriptorUpdateTemplate
+
 // 1
 @extension("VK_KHR_surface")    @nonDispatchHandle type u64 VkSurfaceKHR
 
@@ -529,6 +536,10 @@
     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL                    = 0x00000007,   /// Optimal layout when image is used only as destination of transfer operations
     VK_IMAGE_LAYOUT_PREINITIALIZED                          = 0x00000008,   /// Initial layout used when the data is populated by the CPU
 
+    //@vulkan1_1
+    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
+    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
+
     //@extension("VK_KHR_swapchain") // 2
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
 
@@ -1012,6 +1023,42 @@
     VK_FORMAT_ASTC_12x12_UNORM_BLOCK                        = 183,
     VK_FORMAT_ASTC_12x12_SRGB_BLOCK                         = 184,
 
+    //@vulkan1_1
+    VK_FORMAT_G8B8G8R8_422_UNORM                            = 1000156000,
+    VK_FORMAT_B8G8R8G8_422_UNORM                            = 1000156001,
+    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM                     = 1000156002,
+    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM                      = 1000156003,
+    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM                     = 1000156004,
+    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM                      = 1000156005,
+    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM                     = 1000156006,
+    VK_FORMAT_R10X6_UNORM_PACK16                            = 1000156007,
+    VK_FORMAT_R10X6G10X6_UNORM_2PACK16                      = 1000156008,
+    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16            = 1000156009,
+    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16        = 1000156010,
+    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16        = 1000156011,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16    = 1000156012,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16     = 1000156013,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16    = 1000156014,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16     = 1000156015,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16    = 1000156016,
+    VK_FORMAT_R12X4_UNORM_PACK16                            = 1000156017,
+    VK_FORMAT_R12X4G12X4_UNORM_2PACK16                      = 1000156018,
+    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16            = 1000156019,
+    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16        = 1000156020,
+    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16        = 1000156021,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16    = 1000156022,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16     = 1000156023,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16    = 1000156024,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16     = 1000156025,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16    = 1000156026,
+    VK_FORMAT_G16B16G16R16_422_UNORM                        = 1000156027,
+    VK_FORMAT_B16G16R16G16_422_UNORM                        = 1000156028,
+    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM                  = 1000156029,
+    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM                   = 1000156030,
+    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM                  = 1000156031,
+    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM                   = 1000156032,
+    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM                  = 1000156033,
+
     //@extension("VK_IMG_format_pvrtc") // 28
     VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG                   = 1000054000,
     VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG                   = 1000054001,
@@ -1111,9 +1158,83 @@
     VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO               = 47,
     VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO                 = 48,
 
+    //@vulkan1_1
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES       = 1000094000,
+    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO                   = 1000157000,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO                    = 1000157001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES    = 1000083000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS             = 1000127000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO            = 1000127001,
+    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO                = 1000060000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO       = 1000060003,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO    = 1000060004,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO                  = 1000060005,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO             = 1000060006,
+    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO      = 1000060013,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO       = 1000060014,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES          = 1000070000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO           = 1000070001,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2         = 1000146000,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2          = 1000146001,
+    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2   = 1000146002,
+    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2                     = 1000146003,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2        = 1000146004,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2                = 1000059000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2              = 1000059001,
+    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2                       = 1000059002,
+    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2                 = 1000059003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2       = 1000059004,
+    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2                 = 1000059005,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2       = 1000059006,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2          = 1000059007,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2            = 1000059008,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES             = 1000117000,
+    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO       = 1000117001,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO                          = 1000117002,
+    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO                 = 1000053000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES                = 1000053001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES              = 1000053002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES         = 1000120000,
+    VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO                             = 1000145000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES         = 1000145001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES       = 1000145002,
+    VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2                               = 1000145003,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO              = 1000156000,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO                     = 1000156001,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO                      = 1000156002,
+    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO              = 1000156003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES  = 1000156005,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO            = 1000085000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO        = 1000071000,
+    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES                  = 1000071001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO              = 1000071002,
+    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES                        = 1000071003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES                     = 1000071004,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO                = 1000072000,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO                 = 1000072001,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO                       = 1000072002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO               = 1000112000,
+    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES                         = 1000112001,
+    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO                          = 1000113000,
+    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO                      = 1000077000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO           = 1000076000,
+    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES                     = 1000076001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES          = 1000168000,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT                     = 1000168001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES    = 1000063000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR             = 1000060007,
+
     //@extension("VK_KHR_swapchain") // 2
     VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR                 = 1000001000,
     VK_STRUCTURE_TYPE_PRESENT_INFO_KHR                          = 1000001001,
+    // added as interaction from VK_KHR_device_group / VK 1.1
+    VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR           = 1000060008,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR      = 1000060009,
+    VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR               = 1000060010,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR             = 1000060011,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR    = 1000060012,
 
     //@extension("VK_KHR_display") // 3
     VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR              = 1000002000,
@@ -1164,10 +1285,10 @@
     //@extension("VK_AMD_texture_gather_bias_lod") // 42
     VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD  = 1000041000,
 
-    //@extension("VK_KHX_multiview") // 54
-    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX     = 1000053000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX    = 1000053001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX  = 1000053002,
+    //@extension("VK_KHR_multiview") // 54
+    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR     = 1000053000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR    = 1000053001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR  = 1000053002,
 
     //@extension("VK_NV_external_memory") // 57
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV      = 1000056000,
@@ -1191,20 +1312,16 @@
     VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR      = 1000059007,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
 
-    //@extension("VK_KHX_device_group") // 61
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX            = 1000060000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX   = 1000060003,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX              = 1000060005,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX         = 1000060006,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX     = 1000060007,
-    VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX           = 1000060008,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX      = 1000060009,
-    VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX               = 1000060010,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX             = 1000060011,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX    = 1000060012,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHX  = 1000060013,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHX   = 1000060014,
+    //@extension("VK_KHR_device_group") // 61
+    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR            = 1000060000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR   = 1000060003,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = 1000060004,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR              = 1000060005,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR         = 1000060006,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR     = 1000060007,
+    // tokens 08-12 are listed with VK_KHR_swapchain
+    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR  = 1000060013,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR   = 1000060014,
 
     //@extension("VK_EXT_validation_flags") // 62
     VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT                      = 1000061000,
@@ -1212,9 +1329,9 @@
     //@extension("VK_NN_vi_surface") // 63
     VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN                 = 1000062000,
 
-    //@extension("VK_KHX_device_group_creation") // 71
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX      = 1000070000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX       = 1000070001,
+    //@extension("VK_KHR_device_group_creation") // 71
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR      = 1000070000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR       = 1000070001,
 
     //@extension("VK_KHR_external_memory_capabilities") // 72
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR    = 1000071000,
@@ -1394,6 +1511,10 @@
     //@extension("VK_EXT_validation_cache") // 161
     VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT                  = 1000160000,
     VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT    = 1000160001,
+
+    //@extension("VK_KHR_maintenance3") // 169
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR      = 1000168000,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR                 = 1000168001,
 }
 
 enum VkSubpassContents {
@@ -1433,6 +1554,10 @@
     VK_ERROR_FORMAT_NOT_SUPPORTED                           = 0xFFFFFFF5, // -11
     VK_ERROR_FRAGMENTED_POOL                                = 0xFFFFFFF4, // -12
 
+    //@vulkan1_1
+    VK_ERROR_OUT_OF_POOL_MEMORY                             = 0xC4642878, // -1000069000
+    VK_ERROR_INVALID_EXTERNAL_HANDLE                        = 0xC4641CBD, // -1000072003
+
     //@extension("VK_KHR_surface") // 1
     VK_ERROR_SURFACE_LOST_KHR                               = 0xC4653600, // -1000000000
     VK_ERROR_NATIVE_WINDOW_IN_USE_KHR                       = 0xC46535FF, // -1000000001
@@ -1505,6 +1630,10 @@
     VK_OBJECT_TYPE_FRAMEBUFFER                              = 24,
     VK_OBJECT_TYPE_COMMAND_POOL                             = 25,
 
+    //@vulkan1_1
+    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION                 = 1000156000,
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE               = 1000085000,
+
     //@extension("VK_KHR_surface") // 1
     VK_OBJECT_TYPE_SURFACE_KHR                              = 1000000000,
 
@@ -1532,6 +1661,42 @@
     VK_OBJECT_TYPE_VALIDATION_CACHE_EXT                     = 1000160000,
 }
 
+
+//@vulkan1_1 enums
+
+enum VkPointClippingBehavior {
+    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES              = 0,
+    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY        = 1,
+}
+
+enum VkTessellationDomainOrigin {
+    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT                = 0,
+    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT                = 1,
+}
+
+enum VkSamplerYcbcrModelConversion {
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY          = 0,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY        = 1,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709             = 2,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601             = 3,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020            = 4,
+}
+
+enum VkSamplerYcbcrRange {
+    VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
+    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+}
+
+enum VkChromaLocation {
+    VK_CHROMA_LOCATION_COSITED_EVEN = 0,
+    VK_CHROMA_LOCATION_MIDPOINT = 1,
+}
+
+enum VkDescriptorUpdateTemplateType {
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+}
+
 @extension("VK_KHR_surface") // 1
 enum VkPresentModeKHR {
     VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
@@ -1546,7 +1711,7 @@
 
 @extension("VK_KHR_surface") // 1
 enum VkColorSpaceKHR {
-    VK_COLORSPACE_SRGB_NONLINEAR_KHR                        = 0x00000000,
+    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR                       = 0x00000000,
 
     //@extension("VK_EXT_swapchain_colorspace") // 105
     VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT                 = 1000104001,
@@ -1756,6 +1921,9 @@
     VK_QUEUE_COMPUTE_BIT                                    = 0x00000002,    /// Queue supports compute operations
     VK_QUEUE_TRANSFER_BIT                                   = 0x00000004,    /// Queue supports transfer operations
     VK_QUEUE_SPARSE_BINDING_BIT                             = 0x00000008,    /// Queue supports sparse resource memory management operations
+
+    //@vulkan1_1
+    VK_QUEUE_PROTECTED_BIT                                  = 0x00000010,
 }
 
 /// Memory properties passed into vkAllocMemory().
@@ -1766,6 +1934,9 @@
     VK_MEMORY_PROPERTY_HOST_COHERENT_BIT                    = 0x00000004,
     VK_MEMORY_PROPERTY_HOST_CACHED_BIT                      = 0x00000008,
     VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT                 = 0x00000010,
+
+    //@vulkan1_1
+    VK_MEMORY_PROPERTY_PROTECTED_BIT                        = 0x00000020,
 }
 
 /// Memory heap flags
@@ -1773,8 +1944,11 @@
 bitfield VkMemoryHeapFlagBits {
     VK_MEMORY_HEAP_DEVICE_LOCAL_BIT                         = 0x00000001,
 
-    //@extension("VK_KHX_device_group_creation") // 71
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX                   = 0x00000002,
+    //@vulkan1_1
+    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT                       = 0x00000002,
+
+    //@extension("VK_KHR_device_group_creation") // 71
+    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR                   = 0x00000002,
 }
 
 /// Access flags
@@ -1826,6 +2000,9 @@
     VK_BUFFER_CREATE_SPARSE_BINDING_BIT                     = 0x00000001,    /// Buffer should support sparse backing
     VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT                   = 0x00000002,    /// Buffer should support sparse backing with partial residency
     VK_BUFFER_CREATE_SPARSE_ALIASED_BIT                     = 0x00000004,    /// Buffer should support constent data access to physical memory blocks mapped into multiple locations of sparse buffers
+
+    //@vulkan1_1
+    VK_BUFFER_CREATE_PROTECTED_BIT                          = 0x00000008,
 }
 
 /// Shader stage flags
@@ -1875,14 +2052,20 @@
     VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT                      = 0x00000008,    /// Allows image views to have different format than the base image
     VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT                     = 0x00000010,    /// Allows creating image views with cube type from the created image
 
+    //@vulkan1_1
+    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT                 = 0x00000020,
+    VK_IMAGE_CREATE_BIND_SFR_BIT                            = 0x00000040,
+    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT         = 0x00000080,
+    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT                      = 0x00000100,
+    VK_IMAGE_CREATE_DISJOINT_BIT                            = 0x00000200,
+    VK_IMAGE_CREATE_ALIAS_BIT                               = 0x00000400,
+    VK_IMAGE_CREATE_PROTECTED_BIT                           = 0x00000800,
+
     //@extension("VK_KHR_maintenance1") // 70
     VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR             = 0x00000020,
 
-    //@extension("VK_KHX_device_group") // 61
-    VK_IMAGE_CREATE_BIND_SFR_BIT_KHX                        = 0x00000040,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
+    //@extension("VK_KHR_device_group") // 61
+    VK_IMAGE_CREATE_BIND_SFR_BIT_KHR                        = 0x00000040,
 
     //@extension("VK_KHR_maintenance2") // 118
     VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR     = 0x00000080,
@@ -1893,6 +2076,9 @@
 
     //@extension("VK_KHR_bind_memory2") // 158
     VK_IMAGE_CREATE_ALIAS_BIT_KHR                           = 0x00000400,
+
+    //@extension("VK_EXT_sample_locations") // 144
+    VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
 }
 
 /// Image view creation flags
@@ -1907,9 +2093,13 @@
     VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT                = 0x00000002,
     VK_PIPELINE_CREATE_DERIVATIVE_BIT                       = 0x00000004,
 
-    //@extension("VK_KHX_device_group") // 61
-    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
-    VK_PIPELINE_CREATE_DISPATCH_BASE_KHX                    = 0x00000010,
+    //@vulkan1_1
+    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT     = 0x00000008,
+    VK_PIPELINE_CREATE_DISPATCH_BASE                        = 0x00000010,
+
+    //@extension("VK_KHR_device_group") // 61
+    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
+    VK_PIPELINE_CREATE_DISPATCH_BASE_KHR                    = 0x00000010,
 }
 
 /// Color component flags
@@ -1949,6 +2139,17 @@
     VK_FORMAT_FEATURE_BLIT_DST_BIT                          = 0x00000800,    /// Format can be used as the destination image of blits with vkCommandBlitImage
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT       = 0x00001000,
 
+    //@vulkan1_1
+    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT                      = 0x00004000,
+    VK_FORMAT_FEATURE_TRANSFER_DST_BIT                      = 0x00008000,
+    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT                                                   = 0x00020000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT                              = 0x00040000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT             = 0x00080000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT             = 0x00100000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT   = 0x00200000,
+    VK_FORMAT_FEATURE_DISJOINT_BIT                                                                  = 0x00400000,
+    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT                                                    = 0x00800000,
+
     //@extension("VK_IMG_filter_cubic") // 16
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG    = 0x00002000,
 
@@ -2031,6 +2232,11 @@
     VK_IMAGE_ASPECT_STENCIL_BIT                             = 0x00000004,
     VK_IMAGE_ASPECT_METADATA_BIT                            = 0x00000008,
 
+    //@vulkan1_1
+    VK_IMAGE_ASPECT_PLANE_0_BIT                             = 0x00000010,
+    VK_IMAGE_ASPECT_PLANE_1_BIT                             = 0x00000020,
+    VK_IMAGE_ASPECT_PLANE_2_BIT                             = 0x00000040,
+
     //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
     VK_IMAGE_ASPECT_PLANE_0_BIT_KHR                         = 0x00000010,
     VK_IMAGE_ASPECT_PLANE_1_BIT_KHR                         = 0x00000020,
@@ -2096,6 +2302,9 @@
 bitfield VkCommandPoolCreateFlagBits {
     VK_COMMAND_POOL_CREATE_TRANSIENT_BIT                    = 0x00000001,  /// Command buffers have a short lifetime
     VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT         = 0x00000002,  /// Command buffers may release their memory individually
+
+    //@vulkan1_1
+    VK_COMMAND_POOL_CREATE_PROTECTED_BIT                    = 0x00000004,
 }
 
 /// Command pool reset flags
@@ -2139,8 +2348,10 @@
 
 /// Device queue creation flags
 type VkFlags VkDeviceQueueCreateFlags
-//bitfield VkDeviceQueueCreateFlagBits {
-//}
+@vulkan1_1
+bitfield VkDeviceQueueCreateFlagBits {
+    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT                    = 0x00000001,
+}
 
 /// Query pool creation flags
 type VkFlags VkQueryPoolCreateFlags
@@ -2239,11 +2450,15 @@
 bitfield VkDependencyFlagBits {
     VK_DEPENDENCY_BY_REGION_BIT                             = 0x00000001,
 
-    //@extension("VK_KHX_multiview") // 54
-    VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX                        = 0x00000002,
+    //@vulkan1_1
+    VK_DEPENDENCY_DEVICE_GROUP_BIT                          = 0x00000004,
+    VK_DEPENDENCY_VIEW_LOCAL_BIT                            = 0x00000002,
 
-    //@extension("VK_KHX_device_group") // 61
-    VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX                      = 0x00000004,
+    //@extension("VK_KHR_multiview") // 54
+    VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR                        = 0x00000002,
+
+    //@extension("VK_KHR_device_group") // 61
+    VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR                      = 0x00000004,
 }
 
 /// Cull mode flags
@@ -2255,6 +2470,109 @@
     VK_CULL_MODE_FRONT_AND_BACK                             = 0x00000003,
 }
 
+//@vulkan1_1 flags
+
+/// Subgroup feature flags
+type VkFlags VkSubgroupFeatureFlags
+bitfield VkSubgroupFeatureFlagBits {
+    VK_SUBGROUP_FEATURE_BASIC_BIT                           = 0x00000001,
+    VK_SUBGROUP_FEATURE_VOTE_BIT                            = 0x00000002,
+    VK_SUBGROUP_FEATURE_ARITHMETIC_BIT                      = 0x00000004,
+    VK_SUBGROUP_FEATURE_BALLOT_BIT                          = 0x00000008,
+    VK_SUBGROUP_FEATURE_SHUFFLE_BIT                         = 0x00000010,
+    VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT                = 0x00000020,
+    VK_SUBGROUP_FEATURE_CLUSTERED_BIT                       = 0x00000040,
+    VK_SUBGROUP_FEATURE_QUAD_BIT                            = 0x00000080,
+}
+
+/// Peer memory feature flags
+type VkFlags VkPeerMemoryFeatureFlags
+bitfield VkPeerMemoryFeatureFlagBits {
+    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT                     = 0x00000001,
+    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT                     = 0x00000002,
+    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT                  = 0x00000004,
+    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT                  = 0x00000008,
+}
+
+/// Memory allocation flags
+type VkFlags VkMemoryAllocateFlags
+bitfield VkMemoryAllocateFlagBits {
+    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT                      = 0x00000001,
+}
+
+type VkFlags VkCommandPoolTrimFlags
+//bitfield VkCommandPoolTrimFlagBits {
+//}
+
+type VkFlags VkDescriptorUpdateTemplateCreateFlags
+//bitfield VkDescriptorUpdateTemplateCreateFlagBits {
+//}
+
+/// External memory handle type flags
+type VkFlags VkExternalMemoryHandleTypeFlags
+bitfield VkExternalMemoryHandleTypeFlagBits {
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT            = 0x00000001,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT         = 0x00000002,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT     = 0x00000004,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT        = 0x00000008,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT    = 0x00000010,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT           = 0x00000020,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT       = 0x00000040,
+}
+
+/// External memory feature flags
+type VkFlags VkExternalMemoryFeatureFlags
+bitfield VkExternalMemoryFeatureFlagBits {
+    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT           = 0x00000001,
+    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT               = 0x00000002,
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT               = 0x00000004,
+}
+
+/// External fence handle type flags
+type VkFlags VkExternalFenceHandleTypeFlags
+bitfield VkExternalFenceHandleTypeFlagBits {
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT             = 0x00000001,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT          = 0x00000002,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT      = 0x00000004,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT               = 0x00000008,
+}
+
+/// External fence feature flags
+type VkFlags VkExternalFenceFeatureFlags
+bitfield VkExternalFenceFeatureFlagBits {
+    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT                = 0x00000001,
+    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT                = 0x00000002,
+}
+
+/// Fence import flags
+type VkFlags VkFenceImportFlags
+bitfield VkFenceImportFlagBits {
+    VK_FENCE_IMPORT_TEMPORARY_BIT                           = 0x00000001,
+}
+
+/// Semaphore import flags
+type VkFlags VkSemaphoreImportFlags
+bitfield VkSemaphoreImportFlagBits {
+    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT                       = 0x00000001,
+}
+
+/// External semaphore handle type flags
+type VkFlags VkExternalSemaphoreHandleTypeFlags
+bitfield VkExternalSemaphoreHandleTypeFlagBits {
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT         = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT      = 0x00000002,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT  = 0x00000004,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT       = 0x00000008,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT           = 0x00000010,
+}
+
+/// External semaphore feature flags
+type VkFlags VkExternalSemaphoreFeatureFlags
+bitfield VkExternalSemaphoreFeatureFlagBits {
+    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT            = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT            = 0x00000002,
+}
+
 @extension("VK_KHR_surface") // 1
 type VkFlags VkSurfaceTransformFlagsKHR
 @extension("VK_KHR_surface") // 1
@@ -2284,8 +2602,21 @@
 type VkFlags VkSwapchainCreateFlagsKHR
 @extension("VK_KHR_swapchain") // 2
 bitfield VkSwapchainCreateFlagBitsKHR {
-    //@extension("VK_KHX_device_group") // 61
-    VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX                    = 0x00000001,
+    //@vulkan1_1
+    VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHR                    = 0x00000001,
+    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR                   = 0x00000002,
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+type VkFlags VkDeviceGroupPresentModeFlagsKHR
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+bitfield VkDeviceGroupPresentModeFlagBitsKHR {
+    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR              = 0x00000001,
+    VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR             = 0x00000002,
+    VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR                = 0x00000004,
+    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
 }
 
 @extension("VK_KHR_display") // 3
@@ -2383,31 +2714,21 @@
     VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV            = 0x00000004,
 }
 
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkPeerMemoryFeatureFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkPeerMemoryFeatureFlagBitsKHX {
-    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX                 = 0x00000001,
-    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX                 = 0x00000002,
-    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX              = 0x00000004,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX              = 0x00000008,
+@extension("VK_KHR_device_group") // 61
+type VkFlags VkPeerMemoryFeatureFlagsKHR
+@extension("VK_KHR_device_group") // 61
+bitfield VkPeerMemoryFeatureFlagBitsKHR {
+    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR                 = 0x00000001,
+    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR                 = 0x00000002,
+    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR              = 0x00000004,
+    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR              = 0x00000008,
 }
 
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkMemoryAllocateFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkMemoryAllocateFlagBitsKHX {
-    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX                  = 0x00000001,
-}
-
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkDeviceGroupPresentModeFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkDeviceGroupPresentModeFlagBitsKHX {
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX              = 0x00000001,
-    VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX             = 0x00000002,
-    VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX                = 0x00000004,
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
+@extension("VK_KHR_device_group") // 61
+type VkFlags VkMemoryAllocateFlagsKHR
+@extension("VK_KHR_device_group") // 61
+bitfield VkMemoryAllocateFlagBitsKHR {
+    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR                  = 0x00000001,
 }
 
 @extension("VK_NN_vi_surface") // 63
@@ -3672,6 +3993,493 @@
     u32                                         z
 }
 
+//@vulkan1_1 structures
+
+class VkPhysicalDeviceSubgroupProperties {
+    VkStructureType                             sType
+    void*                                       pNext
+    u32                                         subgroupSize
+    VkShaderStageFlags                          supportedStages
+    VkSubgroupFeatureFlags                      supportedOperations
+    VkBool32                                    quadOperationsInAllStages
+}
+
+class VkBindBufferMemoryInfo {
+    VkStructureType    sType
+    const void*        pNext
+    VkBuffer           buffer
+    VkDeviceMemory     memory
+    VkDeviceSize       memoryOffset
+}
+
+class VkBindImageMemoryInfo {
+    VkStructureType    sType
+    const void*        pNext
+    VkImage            image
+    VkDeviceMemory     memory
+    VkDeviceSize       memoryOffset
+}
+
+class VkPhysicalDevice16BitStorageFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           storageBuffer16BitAccess
+    VkBool32           uniformAndStorageBuffer16BitAccess
+    VkBool32           storagePushConstant16
+    VkBool32           storageInputOutput16
+}
+
+class VkMemoryDedicatedRequirements {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           prefersDedicatedAllocation
+    VkBool32           requiresDedicatedAllocation
+}
+
+class VkMemoryDedicatedAllocateInfo {
+    VkStructureType    sType
+    const void*        pNext
+    VkImage            image
+    VkBuffer           buffer
+}
+
+class VkMemoryAllocateFlagsInfo {
+    VkStructureType          sType
+    const void*              pNext
+    VkMemoryAllocateFlags    flags
+    u32                      deviceMask
+}
+
+class VkDeviceGroupRenderPassBeginInfo {
+    VkStructureType    sType
+    const void*        pNext
+    u32                deviceMask
+    u32                deviceRenderAreaCount
+    const VkRect2D*    pDeviceRenderAreas
+}
+
+class VkDeviceGroupCommandBufferBeginInfo {
+    VkStructureType    sType
+    const void*        pNext
+    u32                deviceMask
+}
+
+class VkDeviceGroupSubmitInfo {
+    VkStructureType             sType
+    const void*                 pNext
+    u32                         waitSemaphoreCount
+    const u32*                  pWaitSemaphoreDeviceIndices
+    u32                         commandBufferCount
+    const u32*                  pCommandBufferDeviceMasks
+    u32                         signalSemaphoreCount
+    const u32*                  pSignalSemaphoreDeviceIndices
+}
+
+class VkDeviceGroupBindSparseInfo {
+    VkStructureType    sType
+    const void*        pNext
+    u32                resourceDeviceIndex
+    u32                memoryDeviceIndex
+}
+
+class VkBindBufferMemoryDeviceGroupInfo {
+    VkStructureType                     sType
+    const void*                         pNext
+    u32                                 deviceIndexCount
+    const u32*                          pDeviceIndices
+}
+
+class VkBindImageMemoryDeviceGroupInfo {
+    VkStructureType                     sType
+    const void*                         pNext
+    u32                                 deviceIndexCount
+    const u32*                          pDeviceIndices
+    u32                                 SFRRectCount
+    const VkRect2D*                     pSFRRects
+}
+
+class VkPhysicalDeviceGroupProperties {
+    VkStructureType                             sType
+    void*                                       pNext
+    u32                                         physicalDeviceCount
+    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE]  physicalDevices
+    VkBool32                                    subsetAllocation
+}
+
+class VkDeviceGroupDeviceCreateInfo {
+    VkStructureType            sType
+    const void*                pNext
+    u32                        physicalDeviceCount
+    const VkPhysicalDevice*    pPhysicalDevices
+}
+
+class VkBufferMemoryRequirementsInfo2 {
+    VkStructureType    sType
+    const void*        pNext
+    VkBuffer           buffer
+}
+
+class VkImageMemoryRequirementsInfo2 {
+    VkStructureType    sType
+    const void*        pNext
+    VkImage            image
+}
+
+class VkImageSparseMemoryRequirementsInfo2 {
+    VkStructureType    sType
+    const void*        pNext
+    VkImage            image
+}
+
+class VkMemoryRequirements2 {
+    VkStructureType         sType
+    void*                   pNext
+    VkMemoryRequirements    memoryRequirements
+}
+
+class VkSparseImageMemoryRequirements2 {
+    VkStructureType                    sType
+    void*                              pNext
+    VkSparseImageMemoryRequirements    memoryRequirements
+}
+
+class VkPhysicalDeviceFeatures2 {
+    VkStructureType             sType
+    void*                       pNext
+    VkPhysicalDeviceFeatures    features
+}
+
+class VkPhysicalDeviceProperties2 {
+    VkStructureType               sType
+    void*                         pNext
+    VkPhysicalDeviceProperties    properties
+}
+
+class VkFormatProperties2 {
+    VkStructureType       sType
+    void*                 pNext
+    VkFormatProperties    formatProperties
+}
+
+class VkImageFormatProperties2 {
+    VkStructureType            sType
+    void*                      pNext
+    VkImageFormatProperties    imageFormatProperties
+}
+
+class VkPhysicalDeviceImageFormatInfo2 {
+    VkStructureType       sType
+    const void*           pNext
+    VkFormat              format
+    VkImageType           type
+    VkImageTiling         tiling
+    VkImageUsageFlags     usage
+    VkImageCreateFlags    flags
+}
+
+class VkQueueFamilyProperties2 {
+    VkStructureType            sType
+    void*                      pNext
+    VkQueueFamilyProperties    queueFamilyProperties
+}
+
+class VkPhysicalDeviceMemoryProperties2 {
+    VkStructureType                     sType
+    void*                               pNext
+    VkPhysicalDeviceMemoryProperties    memoryProperties
+}
+
+class VkSparseImageFormatProperties2 {
+    VkStructureType                  sType
+    void*                            pNext
+    VkSparseImageFormatProperties    properties
+}
+
+class VkPhysicalDeviceSparseImageFormatInfo2 {
+    VkStructureType          sType
+    const void*              pNext
+    VkFormat                 format
+    VkImageType              type
+    VkSampleCountFlagBits    samples
+    VkImageUsageFlags        usage
+    VkImageTiling            tiling
+}
+
+class VkPhysicalDevicePointClippingProperties {
+    VkStructureType            sType
+    void*                      pNext
+    VkPointClippingBehavior    pointClippingBehavior
+}
+
+class VkInputAttachmentAspectReference {
+    u32                   subpass
+    u32                   inputAttachmentIndex
+    VkImageAspectFlags    aspectMask
+}
+
+class VkRenderPassInputAttachmentAspectCreateInfo {
+    VkStructureType                            sType
+    const void*                                pNext
+    u32                                        aspectReferenceCount
+    const VkInputAttachmentAspectReference*    pAspectReferences
+}
+
+class VkImageViewUsageCreateInfo {
+    VkStructureType      sType
+    const void*          pNext
+    VkImageUsageFlags    usage
+}
+
+class VkPipelineTessellationDomainOriginStateCreateInfo {
+    VkStructureType               sType
+    const void*                   pNext
+    VkTessellationDomainOrigin    domainOrigin
+}
+
+class VkRenderPassMultiviewCreateInfo {
+    VkStructureType    sType
+    const void*        pNext
+    u32                subpassCount
+    const u32*         pViewMasks
+    u32                dependencyCount
+    const s32*         pViewOffsets
+    u32                correlationMaskCount
+    const u32*         pCorrelationMasks
+}
+
+class VkPhysicalDeviceMultiviewFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           multiview
+    VkBool32           multiviewGeometryShader
+    VkBool32           multiviewTessellationShader
+}
+
+class VkPhysicalDeviceMultiviewProperties {
+    VkStructureType    sType
+    void*              pNext
+    u32                maxMultiviewViewCount
+    u32                maxMultiviewInstanceIndex
+}
+
+class VkPhysicalDeviceVariablePointerFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           variablePointersStorageBuffer
+    VkBool32           variablePointers
+}
+
+class VkPhysicalDeviceProtectedMemoryFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           protectedMemory
+}
+
+class VkPhysicalDeviceProtectedMemoryProperties {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           protectedNoFault
+}
+
+class VkDeviceQueueInfo2 {
+    VkStructureType             sType
+    const void*                 pNext
+    VkDeviceQueueCreateFlags    flags
+    u32                         queueFamilyIndex
+    u32                         queueIndex
+}
+
+class VkProtectedSubmitInfo {
+    VkStructureType    sType
+    const void*        pNext
+    VkBool32           protectedSubmit
+}
+
+class VkSamplerYcbcrConversionCreateInfo {
+    VkStructureType                  sType
+    const void*                      pNext
+    VkFormat                         format
+    VkSamplerYcbcrModelConversion    ycbcrModel
+    VkSamplerYcbcrRange              ycbcrRange
+    VkComponentMapping               components
+    VkChromaLocation                 xChromaOffset
+    VkChromaLocation                 yChromaOffset
+    VkFilter                         chromaFilter
+    VkBool32                         forceExplicitReconstruction
+}
+
+class VkSamplerYcbcrConversionInfo {
+    VkStructureType             sType
+    const void*                 pNext
+    VkSamplerYcbcrConversion    conversion
+}
+
+class VkBindImagePlaneMemoryInfo {
+    VkStructureType          sType
+    const void*              pNext
+    VkImageAspectFlagBits    planeAspect
+}
+
+class VkImagePlaneMemoryRequirementsInfo {
+    VkStructureType          sType
+    const void*              pNext
+    VkImageAspectFlagBits    planeAspect
+}
+
+class VkPhysicalDeviceSamplerYcbcrConversionFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           samplerYcbcrConversion
+}
+
+class VkSamplerYcbcrConversionImageFormatProperties {
+    VkStructureType    sType
+    void*              pNext
+    u32                combinedImageSamplerDescriptorCount
+}
+
+class VkDescriptorUpdateTemplateEntry {
+    u32                                 dstBinding
+    u32                                 dstArrayElement
+    u32                                 descriptorCount
+    VkDescriptorType                    descriptorType
+    platform.size_t                     offset
+    platform.size_t                     stride
+}
+
+class VkDescriptorUpdateTemplateCreateInfo {
+    VkStructureType                           sType
+    void*                                     pNext
+    VkDescriptorUpdateTemplateCreateFlags     flags
+    u32                                       descriptorUpdateEntryCount
+    const VkDescriptorUpdateTemplateEntry*    pDescriptorUpdateEntries
+    VkDescriptorUpdateTemplateType            templateType
+    VkDescriptorSetLayout                     descriptorSetLayout
+    VkPipelineBindPoint                       pipelineBindPoint
+    VkPipelineLayout                          pipelineLayout
+    u32                                       set
+}
+
+class VkExternalMemoryProperties {
+    VkExternalMemoryFeatureFlags       externalMemoryFeatures
+    VkExternalMemoryHandleTypeFlags    exportFromImportedHandleTypes
+    VkExternalMemoryHandleTypeFlags    compatibleHandleTypes
+}
+
+class VkPhysicalDeviceExternalImageFormatInfo {
+    VkStructureType                       sType
+    const void*                           pNext
+    VkExternalMemoryHandleTypeFlagBits    handleType
+}
+
+class VkExternalImageFormatProperties {
+    VkStructureType               sType
+    void*                         pNext
+    VkExternalMemoryProperties    externalMemoryProperties
+}
+
+class VkPhysicalDeviceExternalBufferInfo {
+    VkStructureType                       sType
+    const void*                           pNext
+    VkBufferCreateFlags                   flags
+    VkBufferUsageFlags                    usage
+    VkExternalMemoryHandleTypeFlagBits    handleType
+}
+
+class VkExternalBufferProperties {
+    VkStructureType               sType
+    void*                         pNext
+    VkExternalMemoryProperties    externalMemoryProperties
+}
+
+class VkPhysicalDeviceIDProperties {
+    VkStructureType    sType
+    void*              pNext
+    u8[VK_UUID_SIZE]   deviceUUID
+    u8[VK_UUID_SIZE]   driverUUID
+    u8[VK_LUID_SIZE]   deviceLUID
+    u32                deviceNodeMask
+    VkBool32           deviceLUIDValid
+}
+
+class VkExternalMemoryImageCreateInfo {
+    VkStructureType                    sType
+    const void*                        pNext
+    VkExternalMemoryHandleTypeFlags    handleTypes
+}
+
+class VkExternalMemoryBufferCreateInfo {
+    VkStructureType                    sType
+    const void*                        pNext
+    VkExternalMemoryHandleTypeFlags    handleTypes
+}
+
+class VkExportMemoryAllocateInfo {
+    VkStructureType                    sType
+    const void*                        pNext
+    VkExternalMemoryHandleTypeFlags    handleTypes
+}
+
+class VkPhysicalDeviceExternalFenceInfo {
+    VkStructureType                      sType
+    const void*                          pNext
+    VkExternalFenceHandleTypeFlagBits    handleType
+}
+
+class VkExternalFenceProperties {
+    VkStructureType                   sType
+    void*                             pNext
+    VkExternalFenceHandleTypeFlags    exportFromImportedHandleTypes
+    VkExternalFenceHandleTypeFlags    compatibleHandleTypes
+    VkExternalFenceFeatureFlags       externalFenceFeatures
+}
+
+class VkExportFenceCreateInfo {
+    VkStructureType                   sType
+    const void*                       pNext
+    VkExternalFenceHandleTypeFlags    handleTypes
+}
+
+class VkExportSemaphoreCreateInfo {
+    VkStructureType                       sType
+    const void*                           pNext
+    VkExternalSemaphoreHandleTypeFlags    handleTypes
+}
+
+class VkPhysicalDeviceExternalSemaphoreInfo {
+    VkStructureType                          sType
+    const void*                              pNext
+    VkExternalSemaphoreHandleTypeFlagBits    handleType
+}
+
+class VkExternalSemaphoreProperties {
+    VkStructureType                       sType
+    void*                                 pNext
+    VkExternalSemaphoreHandleTypeFlags    exportFromImportedHandleTypes
+    VkExternalSemaphoreHandleTypeFlags    compatibleHandleTypes
+    VkExternalSemaphoreFeatureFlags       externalSemaphoreFeatures
+}
+
+class VkPhysicalDeviceMaintenance3Properties {
+    VkStructureType    sType
+    void*              pNext
+    u32                maxPerSetDescriptors
+    VkDeviceSize       maxMemoryAllocationSize
+}
+
+class VkDescriptorSetLayoutSupport {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           supported
+}
+
+class VkPhysicalDeviceShaderDrawParameterFeatures {
+    VkStructureType    sType
+    void*              pNext
+    VkBool32           shaderDrawParameters
+}
+
+
 @extension("VK_KHR_surface") // 1
 class VkSurfaceCapabilitiesKHR {
     u32                                         minImageCount
@@ -3726,6 +4534,62 @@
     VkResult*                                   pResults
 }
 
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkImageSwapchainCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkSwapchainKHR                              swapchain
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkBindImageMemorySwapchainInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkSwapchainKHR                              swapchain
+    u32                                         imageIndex
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkAcquireNextImageInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkSwapchainKHR                              swapchain
+    u64                                         timeout
+    VkSemaphore                                 semaphore
+    VkFence                                     fence
+    u32                                         deviceMask
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupPresentCapabilitiesKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32[VK_MAX_DEVICE_GROUP_SIZE]               presentMask
+    VkDeviceGroupPresentModeFlagsKHR            modes
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupPresentInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         swapchainCount
+    const u32*                                  pDeviceMasks
+    VkDeviceGroupPresentModeFlagBitsKHR         mode
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupSwapchainCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkDeviceGroupPresentModeFlagsKHR            modes
+}
+
 @extension("VK_KHR_display") // 3
 class VkDisplayPropertiesKHR {
     VkDisplayKHR                                display
@@ -3956,8 +4820,8 @@
     VkBool32                                    supportsTextureGatherLODBiasAMD
 }
 
-@extension("VK_KHX_multiview") // 54
-class VkRenderPassMultiviewCreateInfoKHX {
+@extension("VK_KHR_multiview") // 54
+class VkRenderPassMultiviewCreateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         subpassCount
@@ -3968,8 +4832,8 @@
     const u32*                                  pCorrelationMasks
 }
 
-@extension("VK_KHX_multiview") // 54
-class VkPhysicalDeviceMultiviewFeaturesKHX {
+@extension("VK_KHR_multiview") // 54
+class VkPhysicalDeviceMultiviewFeaturesKHR {
     VkStructureType                             sType
     void*                                       pNext
     VkBool32                                    multiview
@@ -3977,8 +4841,8 @@
     VkBool32                                    multiviewTessellationShader
 }
 
-@extension("VK_KHX_multiview") // 54
-class VkPhysicalDeviceMultiviewPropertiesKHX {
+@extension("VK_KHR_multiview") // 54
+class VkPhysicalDeviceMultiviewPropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
     u32                                         maxMultiviewViewCount
@@ -4107,24 +4971,24 @@
     VkImageTiling                               tiling
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkMemoryAllocateFlagsInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkMemoryAllocateFlagsInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkMemoryAllocateFlagsKHX                    flags
+    VkMemoryAllocateFlagsKHR                    flags
     u32                                         deviceMask
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkBindBufferMemoryDeviceGroupInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkBindBufferMemoryDeviceGroupInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         deviceIndexCount
     const u32*                                  pDeviceIndices
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkBindImageMemoryDeviceGroupInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkBindImageMemoryDeviceGroupInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         deviceIndexCount
@@ -4133,8 +4997,8 @@
     const VkRect2D*                             pSFRRects
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupRenderPassBeginInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupRenderPassBeginInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         deviceMask
@@ -4142,15 +5006,15 @@
     const VkRect2D*                             pDeviceRenderAreas
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupCommandBufferBeginInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupCommandBufferBeginInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         deviceMask
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupSubmitInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupSubmitInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         waitSemaphoreCount
@@ -4161,64 +5025,14 @@
     const u32*                                  pSignalSemaphoreDeviceIndices
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupBindSparseInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupBindSparseInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         resourceDeviceIndex
     u32                                         memoryDeviceIndex
 }
 
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupPresentCapabilitiesKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32[VK_MAX_DEVICE_GROUP_SIZE_KHX]           presentMask
-    VkDeviceGroupPresentModeFlagsKHX            modes
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkImageSwapchainCreateInfoKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkBindImageMemorySwapchainInfoKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-    u32                                         imageIndex
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkAcquireNextImageInfoKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-    u64                                         timeout
-    VkSemaphore                                 semaphore
-    VkFence                                     fence
-    u32                                         deviceMask
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupPresentInfoKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         swapchainCount
-    const u32*                                  pDeviceMasks
-    VkDeviceGroupPresentModeFlagBitsKHX         mode
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupSwapchainCreateInfoKHX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDeviceGroupPresentModeFlagsKHX            modes
-}
-
 @extension("VK_EXT_validation_flags") // 62
 class VkValidationFlagsEXT {
     VkStructureType                             sType
@@ -4235,17 +5049,17 @@
     void*                                       window
 }
 
-@extension("VK_KHX_device_group_creation") // 71
-class VkPhysicalDeviceGroupPropertiesKHX {
+@extension("VK_KHR_device_group_creation") // 71
+class VkPhysicalDeviceGroupPropertiesKHR {
     VkStructureType                                 sType
     void*                                           pNext
     u32                                             physicalDeviceCount
-    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX]  physicalDevices
+    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE]      physicalDevices
     VkBool32                                        subsetAllocation
 }
 
-@extension("VK_KHX_device_group_creation") // 71
-class VkDeviceGroupDeviceCreateInfoKHX {
+@extension("VK_KHR_device_group_creation") // 71
+class VkDeviceGroupDeviceCreateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         physicalDeviceCount
@@ -4295,7 +5109,7 @@
     void*                                       pNext
     u8[VK_UUID_SIZE]                            deviceUUID
     u8[VK_UUID_SIZE]                            driverUUID
-    u8[VK_LUID_SIZE_KHR]                        deviceLUID
+    u8[VK_LUID_SIZE]                            deviceLUID
     u32                                         deviceNodeMask
     VkBool32                                    deviceLUIDValid
 }
@@ -5233,6 +6047,22 @@
     VkValidationCacheEXT                            validationCache
 }
 
+@extension("VK_KHR_maintenance3") // 169
+class VkPhysicalDeviceMaintenance3PropertiesKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    u32                                             maxPerSetDescriptors
+    VkDeviceSize                                    maxMemoryAllocationSize
+}
+
+@extension("VK_KHR_maintenance3") // 169
+class VkDescriptorSetLayoutSupportKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        supported
+}
+
+
 ////////////////
 //  Commands  //
 ////////////////
@@ -7428,6 +8258,241 @@
     }
 }
 
+//@vulkan1_1 functions
+
+@vulkan1_1
+cmd VkResult vkEnumerateInstanceVersion(
+        u32*                                            pApiVersion) {
+    return ?
+}
+
+@vulkan1_1
+cmd VkResult vkBindBufferMemory2(
+        VkDevice                                        device,
+        u32                                             bindInfoCount,
+        const VkBindBufferMemoryInfo*                   pBindInfos) {
+    return ?
+}
+
+@vulkan1_1
+cmd VkResult vkBindImageMemory2(
+        VkDevice                                        device,
+        u32                                             bindInfoCount,
+        const VkBindImageMemoryInfo*                    pBindInfos) {
+    return ?
+}
+
+@vulkan1_1
+cmd void vkGetDeviceGroupPeerMemoryFeatures(
+        VkDevice                                    device,
+        u32                                         heapIndex,
+        u32                                         localDeviceIndex,
+        u32                                         remoteDeviceIndex,
+        VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures) {
+}
+
+@vulkan1_1
+cmd void vkCmdSetDeviceMask(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         deviceMask) {
+}
+
+@vulkan1_1
+cmd void vkCmdDispatchBase(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         baseGroupX,
+        u32                                         baseGroupY,
+        u32                                         baseGroupZ,
+        u32                                         groupCountX,
+        u32                                         groupCountY,
+        u32                                         groupCountZ) {
+}
+
+@threadSafety("system")
+@vulkan1_1
+cmd VkResult vkEnumeratePhysicalDeviceGroups(
+        VkInstance                                  instance,
+        u32*                                        pPhysicalDeviceGroupCount,
+        VkPhysicalDeviceGroupProperties*            pPhysicalDeviceGroupProperties) {
+    instanceObject := GetInstance(instance)
+
+    physicalDeviceGroupCount := as!u32(?)
+    pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
+    physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
+
+    for i in (0 .. physicalDeviceGroupCount) {
+        physicalDevice := ?
+        physicalDevices[i] = physicalDevice
+        if !(physicalDevice in State.PhysicalDevices) {
+            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
+        }
+    }
+
+    return ?
+}
+
+@vulkan1_1
+cmd void vkGetImageMemoryRequirements2(
+        VkDevice                                    device,
+        const VkImageMemoryRequirementsInfo2*       pInfo,
+        VkMemoryRequirements2*                      pMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetBufferMemoryRequirements2(
+        VkDevice                                    device,
+        const VkBufferMemoryRequirementsInfo2*      pInfo,
+        VkMemoryRequirements2*                      pMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetImageSparseMemoryRequirements2(
+        VkDevice                                        device,
+        const VkImageSparseMemoryRequirementsInfo2*     pInfo,
+        u32*                                            pSparseMemoryRequirementCount,
+        VkSparseImageMemoryRequirements2*               pSparseMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceFeatures2(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceFeatures2*                  pFeatures) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceProperties2(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceProperties2*                pProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceFormatProperties2(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkFormatProperties2*                        pFormatProperties) {
+}
+
+@vulkan1_1
+cmd VkResult vkGetPhysicalDeviceImageFormatProperties2(
+        VkPhysicalDevice                            physicalDevice,
+        const VkPhysicalDeviceImageFormatInfo2*     pImageFormatInfo,
+        VkImageFormatProperties2*                   pImageFormatProperties) {
+    return ?
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceQueueFamilyProperties2(
+        VkPhysicalDevice                            physicalDevice,
+        u32*                                        pQueueFamilyPropertyCount,
+        VkQueueFamilyProperties2*                   pQueueFamilyProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceMemoryProperties2(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceMemoryProperties2*          pMemoryProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceSparseImageFormatProperties2(
+        VkPhysicalDevice                                    physicalDevice,
+        const VkPhysicalDeviceSparseImageFormatInfo2*       pFormatInfo,
+        u32*                                                pPropertyCount,
+        VkSparseImageFormatProperties2*                     pProperties) {
+}
+
+@vulkan1_1
+cmd void vkTrimCommandPool(
+        VkDevice                                    device,
+        VkCommandPool                               commandPool,
+        VkCommandPoolTrimFlags                      flags) {
+}
+
+
+@vulkan1_1
+cmd void vkGetDeviceQueue2(
+        VkDevice                                    device,
+        const VkDeviceQueueInfo2*                   pQueueInfo,
+        VkQueue*                                    pQueue) {
+    deviceObject := GetDevice(device)
+
+    queue := ?
+    pQueue[0] = queue
+
+    if !(queue in State.Queues) {
+        State.Queues[queue] = new!QueueObject(device: device)
+    }
+}
+
+@vulkan1_1
+cmd VkResult vkCreateSamplerYcbcrConversion(
+        VkDevice                                        device,
+        const VkSamplerYcbcrConversionCreateInfo*       pCreateInfo,
+        const VkAllocationCallbacks*                    pAllocator,
+        VkSamplerYcbcrConversion*                       pYcbcrConversion) {
+    return ?
+}
+
+@vulkan1_1
+cmd void vkDestroySamplerYcbcrConversion(
+        VkDevice                                        device,
+        VkSamplerYcbcrConversion                        ycbcrConversion,
+        const VkAllocationCallbacks*                    pAllocator) {
+}
+
+@vulkan1_1
+cmd VkResult vkCreateDescriptorUpdateTemplate(
+        VkDevice                                    device,
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDescriptorUpdateTemplate*                 pDescriptorUpdateTemplate) {
+    return ?
+}
+
+@vulkan1_1
+cmd void vkDestroyDescriptorUpdateTemplate(
+        VkDevice                                    device,
+        VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@vulkan1_1
+cmd void vkUpdateDescriptorSetWithTemplate(
+        VkDevice                                    device,
+        VkDescriptorSet                             descriptorSet,
+        VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
+        const void*                                 pData) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalBufferProperties(
+        VkPhysicalDevice                                physicalDevice,
+        const VkPhysicalDeviceExternalBufferInfo*       pExternalBufferInfo,
+        VkExternalBufferProperties*                     pExternalBufferProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalFenceProperties(
+        VkPhysicalDevice                            physicalDevice,
+        const VkPhysicalDeviceExternalFenceInfo*    pExternalFenceInfo,
+        VkExternalFenceProperties*                  pExternalFenceProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalSemaphoreProperties(
+        VkPhysicalDevice                                physicalDevice,
+        const VkPhysicalDeviceExternalSemaphoreInfo*    pExternalSemaphoreInfo,
+        VkExternalSemaphoreProperties*                  pExternalSemaphoreProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetDescriptorSetLayoutSupport(
+        VkDevice                                    device,
+        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+        VkDescriptorSetLayoutSupport*               pSupport) {
+}
+
+
 @extension("VK_KHR_surface") // 1
 cmd void vkDestroySurfaceKHR(
         VkInstance                                  instance,
@@ -7582,6 +8647,42 @@
     return ?
 }
 
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHR(
+        VkDevice                                    device,
+        VkDeviceGroupPresentCapabilitiesKHR*        pDeviceGroupPresentCapabilities) {
+    return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetDeviceGroupSurfacePresentModesKHR(
+        VkDevice                                    device,
+        VkSurfaceKHR                                surface,
+        VkDeviceGroupPresentModeFlagsKHR*           pModes) {
+    return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetPhysicalDevicePresentRectanglesKHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkSurfaceKHR                                surface,
+        u32*                                        pRectCount,
+        VkRect2D*                                   pRects) {
+    return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkAcquireNextImage2KHR(
+        VkDevice                                    device,
+        const VkAcquireNextImageInfoKHR*            pAcquireInfo,
+        u32*                                        pImageIndex) {
+    return ?
+}
+
 @extension("VK_KHR_display") // 3
 cmd VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(
         VkPhysicalDevice                        physicalDevice,
@@ -7974,46 +9075,24 @@
         VkSparseImageFormatProperties2KHR*                  pProperties) {
 }
 
-@extension("VK_KHX_device_group") // 61
-cmd void vkGetDeviceGroupPeerMemoryFeaturesKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkGetDeviceGroupPeerMemoryFeaturesKHR(
         VkDevice                                    device,
         u32                                         heapIndex,
         u32                                         localDeviceIndex,
         u32                                         remoteDeviceIndex,
-        VkPeerMemoryFeatureFlagsKHX*                pPeerMemoryFeatures) {
+        VkPeerMemoryFeatureFlagsKHR*                pPeerMemoryFeatures) {
 }
 
-@extension("VK_KHX_device_group") // 61
-cmd void vkCmdSetDeviceMaskKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkCmdSetDeviceMaskKHR(
         VkCommandBuffer                             commandBuffer,
         u32                                         deviceMask) {
 }
 
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHX(
-        VkDevice                                    device,
-        VkDeviceGroupPresentCapabilitiesKHX*        pDeviceGroupPresentCapabilities) {
-    return ?
-}
 
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetDeviceGroupSurfacePresentModesKHX(
-        VkDevice                                    device,
-        VkSurfaceKHR                                surface,
-        VkDeviceGroupPresentModeFlagsKHX*           pModes) {
-    return ?
-}
-
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkAcquireNextImage2KHX(
-        VkDevice                                    device,
-        const VkAcquireNextImageInfoKHX*            pAcquireInfo,
-        u32*                                        pImageIndex) {
-    return ?
-}
-
-@extension("VK_KHX_device_group") // 61
-cmd void vkCmdDispatchBaseKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkCmdDispatchBaseKHR(
         VkCommandBuffer                             commandBuffer,
         u32                                         baseGroupX,
         u32                                         baseGroupY,
@@ -8023,15 +9102,6 @@
         u32                                         groupCountZ) {
 }
 
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetPhysicalDevicePresentRectanglesKHX(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pRectCount,
-        VkRect2D*                                   pRects) {
-    return ?
-}
-
 @extension("VK_NN_vi_surface") // 63
 cmd VkResult vkCreateViSurfaceNN(
         VkInstance                                  instance,
@@ -8048,11 +9118,26 @@
         VkCommandPoolTrimFlagsKHR                   flags) {
 }
 
-@extension("VK_KHX_device_group_creation") // 71
-cmd VkResult vkEnumeratePhysicalDeviceGroupsKHX(
+@extension("VK_KHR_device_group_creation") // 71
+@threadSafety("system")
+cmd VkResult vkEnumeratePhysicalDeviceGroupsKHR(
         VkInstance                                  instance,
         u32*                                        pPhysicalDeviceGroupCount,
-        VkPhysicalDeviceGroupPropertiesKHX*         pPhysicalDeviceGroupProperties) {
+        VkPhysicalDeviceGroupPropertiesKHR*         pPhysicalDeviceGroupProperties) {
+    instanceObject := GetInstance(instance)
+
+    physicalDeviceGroupCount := as!u32(?)
+    pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
+    physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
+
+    for i in (0 .. physicalDeviceGroupCount) {
+        physicalDevice := ?
+        physicalDevices[i] = physicalDevice
+        if !(physicalDevice in State.PhysicalDevices) {
+            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
+        }
+    }
+
     return ?
 }
 
@@ -8543,6 +9628,13 @@
     return ?
 }
 
+@extension("VK_KHR_maintenance3") // 169
+cmd void vkGetDescriptorSetLayoutSupportKHR(
+        VkDevice                                    device,
+        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+        VkDescriptorSetLayoutSupportKHR*            pSupport) {
+}
+
 ////////////////
 // Validation //
 ////////////////
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 7813e4b..f96a9fa 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -138,6 +138,8 @@
     VK_ERROR_TOO_MANY_OBJECTS = -10,
     VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
     VK_ERROR_FRAGMENTED_POOL = -12,
+    VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000,
+    VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003,
     VK_ERROR_SURFACE_LOST_KHR = -1000000000,
     VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
     VK_SUBOPTIMAL_KHR = 1000001003,
@@ -145,8 +147,6 @@
     VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
     VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
     VK_ERROR_INVALID_SHADER_NV = -1000012000,
-    VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = -1000072003,
     VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
     VK_RESULT_END_RANGE = VK_INCOMPLETE,
     VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
@@ -203,8 +203,79 @@
     VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46,
     VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
     VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000,
+    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001,
+    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006,
+    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001,
+    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002,
+    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001,
+    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002,
+    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004,
+    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000,
+    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002,
+    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = 1000120000,
+    VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002,
+    VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002,
+    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
+    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000,
+    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002,
+    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000,
+    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001,
+    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000,
+    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000,
+    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = 1000063000,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
     VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
     VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+    VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008,
+    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009,
+    VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011,
+    VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012,
     VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
     VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
     VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000,
@@ -223,48 +294,13 @@
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
     VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
     VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
     VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
-    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006,
-    VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060013,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060014,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007,
-    VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012,
     VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
     VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = 1000071000,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = 1000071001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = 1000071002,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = 1000071003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = 1000071004,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = 1000072000,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = 1000072001,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = 1000072002,
     VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
     VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
@@ -273,9 +309,6 @@
     VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001,
     VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002,
     VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = 1000076001,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = 1000077000,
     VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000,
     VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001,
     VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002,
@@ -283,9 +316,7 @@
     VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000,
     VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
     VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
     VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
     VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
@@ -305,26 +336,16 @@
     VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
     VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
     VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = 1000112000,
-    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = 1000112001,
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = 1000113000,
     VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000,
     VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001,
     VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002,
     VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000,
     VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = 1000117000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = 1000117001,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = 1000117002,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = 1000117003,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
     VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
     VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
     VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = 1000127000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = 1000127001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
     VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
     VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
@@ -332,25 +353,12 @@
     VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003,
     VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146000,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146001,
-    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146002,
-    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = 1000146003,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = 1000146004,
     VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = 1000147000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001,
     VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002,
     VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
     VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = 1000156000,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = 1000156001,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = 1000156002,
-    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = 1000156003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = 1000156004,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = 1000156005,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = 1000157000,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = 1000157001,
     VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
     VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
     VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@@ -565,6 +573,40 @@
     VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
     VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
     VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+    VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000,
+    VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001,
+    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002,
+    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003,
+    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004,
+    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005,
+    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006,
+    VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007,
+    VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008,
+    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009,
+    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010,
+    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016,
+    VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017,
+    VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018,
+    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019,
+    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020,
+    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026,
+    VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027,
+    VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028,
+    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029,
+    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
+    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
+    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
+    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
     VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
     VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
     VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
@@ -573,40 +615,6 @@
     VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
     VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
     VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
-    VK_FORMAT_G8B8G8R8_422_UNORM_KHR = 1000156000,
-    VK_FORMAT_B8G8R8G8_422_UNORM_KHR = 1000156001,
-    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = 1000156002,
-    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = 1000156003,
-    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = 1000156004,
-    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = 1000156005,
-    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = 1000156006,
-    VK_FORMAT_R10X6_UNORM_PACK16_KHR = 1000156007,
-    VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = 1000156008,
-    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = 1000156009,
-    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = 1000156010,
-    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = 1000156011,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = 1000156012,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = 1000156013,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = 1000156014,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = 1000156015,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = 1000156016,
-    VK_FORMAT_R12X4_UNORM_PACK16_KHR = 1000156017,
-    VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = 1000156018,
-    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = 1000156019,
-    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = 1000156020,
-    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = 1000156021,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = 1000156022,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = 1000156023,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = 1000156024,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = 1000156025,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = 1000156026,
-    VK_FORMAT_G16B16G16R16_422_UNORM_KHR = 1000156027,
-    VK_FORMAT_B16G16R16G16_422_UNORM_KHR = 1000156028,
-    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = 1000156029,
-    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = 1000156030,
-    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = 1000156031,
-    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = 1000156032,
-    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = 1000156033,
     VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
     VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
     VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1),
@@ -673,10 +681,10 @@
     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6,
     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
     VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
+    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
+    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
     VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
-    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = 1000117000,
-    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = 1000117001,
     VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
     VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED,
     VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1),
@@ -1058,15 +1066,15 @@
     VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
     VK_OBJECT_TYPE_FRAMEBUFFER = 24,
     VK_OBJECT_TYPE_COMMAND_POOL = 25,
+    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
     VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
     VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
     VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
     VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
     VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
-    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000,
     VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
     VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
-    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = 1000156000,
     VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
     VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
     VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
@@ -1090,17 +1098,17 @@
     VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
     VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
+    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000,
+    VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000,
+    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000,
+    VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000,
+    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
-    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
-    VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000,
-    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000,
-    VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = 0x00400000,
-    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000,
     VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkFormatFeatureFlagBits;
 typedef VkFlags VkFormatFeatureFlags;
@@ -1124,13 +1132,14 @@
     VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
     VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
     VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
-    VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040,
-    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
-    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080,
-    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = 0x00000100,
+    VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400,
+    VK_IMAGE_CREATE_BIND_SFR_BIT = 0x00000040,
+    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020,
+    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080,
+    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
+    VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
+    VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
     VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
-    VK_IMAGE_CREATE_DISJOINT_BIT_KHR = 0x00000200,
-    VK_IMAGE_CREATE_ALIAS_BIT_KHR = 0x00000400,
     VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageCreateFlagBits;
 typedef VkFlags VkImageCreateFlags;
@@ -1152,6 +1161,7 @@
     VK_QUEUE_COMPUTE_BIT = 0x00000002,
     VK_QUEUE_TRANSFER_BIT = 0x00000004,
     VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
+    VK_QUEUE_PROTECTED_BIT = 0x00000010,
     VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueueFlagBits;
 typedef VkFlags VkQueueFlags;
@@ -1162,17 +1172,23 @@
     VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
     VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
     VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+    VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
     VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkMemoryPropertyFlagBits;
 typedef VkFlags VkMemoryPropertyFlags;
 
 typedef enum VkMemoryHeapFlagBits {
     VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002,
+    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
     VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkMemoryHeapFlagBits;
 typedef VkFlags VkMemoryHeapFlags;
 typedef VkFlags VkDeviceCreateFlags;
+
+typedef enum VkDeviceQueueCreateFlagBits {
+    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001,
+    VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDeviceQueueCreateFlagBits;
 typedef VkFlags VkDeviceQueueCreateFlags;
 
 typedef enum VkPipelineStageFlagBits {
@@ -1204,9 +1220,9 @@
     VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
     VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
     VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
-    VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = 0x00000010,
-    VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = 0x00000020,
-    VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = 0x00000040,
+    VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010,
+    VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020,
+    VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040,
     VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageAspectFlagBits;
 typedef VkFlags VkImageAspectFlags;
@@ -1263,6 +1279,7 @@
     VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
     VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
     VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+    VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008,
     VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkBufferCreateFlagBits;
 typedef VkFlags VkBufferCreateFlags;
@@ -1289,8 +1306,8 @@
     VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
     VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
     VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
-    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
-    VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010,
+    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
+    VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
     VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineCreateFlagBits;
 typedef VkFlags VkPipelineCreateFlags;
@@ -1393,8 +1410,8 @@
 
 typedef enum VkDependencyFlagBits {
     VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002,
-    VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004,
+    VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
+    VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
     VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkDependencyFlagBits;
 typedef VkFlags VkDependencyFlags;
@@ -1402,6 +1419,7 @@
 typedef enum VkCommandPoolCreateFlagBits {
     VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
     VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+    VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
     VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCommandPoolCreateFlagBits;
 typedef VkFlags VkCommandPoolCreateFlags;
@@ -3483,10 +3501,837 @@
     const VkCommandBuffer*                      pCommandBuffers);
 #endif
 
+#define VK_VERSION_1_1 1
+// Vulkan 1.1 version number
+#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0
+
+
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
+
+#define VK_MAX_DEVICE_GROUP_SIZE          32
+#define VK_LUID_SIZE                      8
+#define VK_QUEUE_FAMILY_EXTERNAL          (~0U-1)
+
+
+typedef enum VkPointClippingBehavior {
+    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
+    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
+    VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
+    VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
+    VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1),
+    VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF
+} VkPointClippingBehavior;
+
+typedef enum VkTessellationDomainOrigin {
+    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0,
+    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1,
+    VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
+    VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
+    VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1),
+    VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF
+} VkTessellationDomainOrigin;
+
+typedef enum VkSamplerYcbcrModelConversion {
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1),
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrModelConversion;
+
+typedef enum VkSamplerYcbcrRange {
+    VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
+    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+    VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
+    VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
+    VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1),
+    VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrRange;
+
+typedef enum VkChromaLocation {
+    VK_CHROMA_LOCATION_COSITED_EVEN = 0,
+    VK_CHROMA_LOCATION_MIDPOINT = 1,
+    VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN,
+    VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT,
+    VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1),
+    VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF
+} VkChromaLocation;
+
+typedef enum VkDescriptorUpdateTemplateType {
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1),
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorUpdateTemplateType;
+
+
+typedef enum VkSubgroupFeatureFlagBits {
+    VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001,
+    VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002,
+    VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004,
+    VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008,
+    VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010,
+    VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
+    VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
+    VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+    VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubgroupFeatureFlagBits;
+typedef VkFlags VkSubgroupFeatureFlags;
+
+typedef enum VkPeerMemoryFeatureFlagBits {
+    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
+    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
+    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
+    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
+    VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPeerMemoryFeatureFlagBits;
+typedef VkFlags VkPeerMemoryFeatureFlags;
+
+typedef enum VkMemoryAllocateFlagBits {
+    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
+    VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkMemoryAllocateFlagBits;
+typedef VkFlags VkMemoryAllocateFlags;
+typedef VkFlags VkCommandPoolTrimFlags;
+typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
+
+typedef enum VkExternalMemoryHandleTypeFlagBits {
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBits;
+typedef VkFlags VkExternalMemoryHandleTypeFlags;
+
+typedef enum VkExternalMemoryFeatureFlagBits {
+    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001,
+    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002,
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004,
+    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBits;
+typedef VkFlags VkExternalMemoryFeatureFlags;
+
+typedef enum VkExternalFenceHandleTypeFlagBits {
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceHandleTypeFlagBits;
+typedef VkFlags VkExternalFenceHandleTypeFlags;
+
+typedef enum VkExternalFenceFeatureFlagBits {
+    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+    VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceFeatureFlagBits;
+typedef VkFlags VkExternalFenceFeatureFlags;
+
+typedef enum VkFenceImportFlagBits {
+    VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
+    VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFenceImportFlagBits;
+typedef VkFlags VkFenceImportFlags;
+
+typedef enum VkSemaphoreImportFlagBits {
+    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
+    VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreImportFlagBits;
+typedef VkFlags VkSemaphoreImportFlags;
+
+typedef enum VkExternalSemaphoreHandleTypeFlagBits {
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreHandleTypeFlagBits;
+typedef VkFlags VkExternalSemaphoreHandleTypeFlags;
+
+typedef enum VkExternalSemaphoreFeatureFlagBits {
+    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreFeatureFlagBits;
+typedef VkFlags VkExternalSemaphoreFeatureFlags;
+
+typedef struct VkPhysicalDeviceSubgroupProperties {
+    VkStructureType           sType;
+    void*                     pNext;
+    uint32_t                  subgroupSize;
+    VkShaderStageFlags        supportedStages;
+    VkSubgroupFeatureFlags    supportedOperations;
+    VkBool32                  quadOperationsInAllStages;
+} VkPhysicalDeviceSubgroupProperties;
+
+typedef struct VkBindBufferMemoryInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           buffer;
+    VkDeviceMemory     memory;
+    VkDeviceSize       memoryOffset;
+} VkBindBufferMemoryInfo;
+
+typedef struct VkBindImageMemoryInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+    VkDeviceMemory     memory;
+    VkDeviceSize       memoryOffset;
+} VkBindImageMemoryInfo;
+
+typedef struct VkPhysicalDevice16BitStorageFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           storageBuffer16BitAccess;
+    VkBool32           uniformAndStorageBuffer16BitAccess;
+    VkBool32           storagePushConstant16;
+    VkBool32           storageInputOutput16;
+} VkPhysicalDevice16BitStorageFeatures;
+
+typedef struct VkMemoryDedicatedRequirements {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           prefersDedicatedAllocation;
+    VkBool32           requiresDedicatedAllocation;
+} VkMemoryDedicatedRequirements;
+
+typedef struct VkMemoryDedicatedAllocateInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+    VkBuffer           buffer;
+} VkMemoryDedicatedAllocateInfo;
+
+typedef struct VkMemoryAllocateFlagsInfo {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkMemoryAllocateFlags    flags;
+    uint32_t                 deviceMask;
+} VkMemoryAllocateFlagsInfo;
+
+typedef struct VkDeviceGroupRenderPassBeginInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           deviceMask;
+    uint32_t           deviceRenderAreaCount;
+    const VkRect2D*    pDeviceRenderAreas;
+} VkDeviceGroupRenderPassBeginInfo;
+
+typedef struct VkDeviceGroupCommandBufferBeginInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           deviceMask;
+} VkDeviceGroupCommandBufferBeginInfo;
+
+typedef struct VkDeviceGroupSubmitInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           waitSemaphoreCount;
+    const uint32_t*    pWaitSemaphoreDeviceIndices;
+    uint32_t           commandBufferCount;
+    const uint32_t*    pCommandBufferDeviceMasks;
+    uint32_t           signalSemaphoreCount;
+    const uint32_t*    pSignalSemaphoreDeviceIndices;
+} VkDeviceGroupSubmitInfo;
+
+typedef struct VkDeviceGroupBindSparseInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           resourceDeviceIndex;
+    uint32_t           memoryDeviceIndex;
+} VkDeviceGroupBindSparseInfo;
+
+typedef struct VkBindBufferMemoryDeviceGroupInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           deviceIndexCount;
+    const uint32_t*    pDeviceIndices;
+} VkBindBufferMemoryDeviceGroupInfo;
+
+typedef struct VkBindImageMemoryDeviceGroupInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           deviceIndexCount;
+    const uint32_t*    pDeviceIndices;
+    uint32_t           SFRRectCount;
+    const VkRect2D*    pSFRRects;
+} VkBindImageMemoryDeviceGroupInfo;
+
+typedef struct VkPhysicalDeviceGroupProperties {
+    VkStructureType     sType;
+    void*               pNext;
+    uint32_t            physicalDeviceCount;
+    VkPhysicalDevice    physicalDevices[VK_MAX_DEVICE_GROUP_SIZE];
+    VkBool32            subsetAllocation;
+} VkPhysicalDeviceGroupProperties;
+
+typedef struct VkDeviceGroupDeviceCreateInfo {
+    VkStructureType            sType;
+    const void*                pNext;
+    uint32_t                   physicalDeviceCount;
+    const VkPhysicalDevice*    pPhysicalDevices;
+} VkDeviceGroupDeviceCreateInfo;
+
+typedef struct VkBufferMemoryRequirementsInfo2 {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           buffer;
+} VkBufferMemoryRequirementsInfo2;
+
+typedef struct VkImageMemoryRequirementsInfo2 {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+} VkImageMemoryRequirementsInfo2;
+
+typedef struct VkImageSparseMemoryRequirementsInfo2 {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+} VkImageSparseMemoryRequirementsInfo2;
+
+typedef struct VkMemoryRequirements2 {
+    VkStructureType         sType;
+    void*                   pNext;
+    VkMemoryRequirements    memoryRequirements;
+} VkMemoryRequirements2;
+
+typedef struct VkSparseImageMemoryRequirements2 {
+    VkStructureType                    sType;
+    void*                              pNext;
+    VkSparseImageMemoryRequirements    memoryRequirements;
+} VkSparseImageMemoryRequirements2;
+
+typedef struct VkPhysicalDeviceFeatures2 {
+    VkStructureType             sType;
+    void*                       pNext;
+    VkPhysicalDeviceFeatures    features;
+} VkPhysicalDeviceFeatures2;
+
+typedef struct VkPhysicalDeviceProperties2 {
+    VkStructureType               sType;
+    void*                         pNext;
+    VkPhysicalDeviceProperties    properties;
+} VkPhysicalDeviceProperties2;
+
+typedef struct VkFormatProperties2 {
+    VkStructureType       sType;
+    void*                 pNext;
+    VkFormatProperties    formatProperties;
+} VkFormatProperties2;
+
+typedef struct VkImageFormatProperties2 {
+    VkStructureType            sType;
+    void*                      pNext;
+    VkImageFormatProperties    imageFormatProperties;
+} VkImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceImageFormatInfo2 {
+    VkStructureType       sType;
+    const void*           pNext;
+    VkFormat              format;
+    VkImageType           type;
+    VkImageTiling         tiling;
+    VkImageUsageFlags     usage;
+    VkImageCreateFlags    flags;
+} VkPhysicalDeviceImageFormatInfo2;
+
+typedef struct VkQueueFamilyProperties2 {
+    VkStructureType            sType;
+    void*                      pNext;
+    VkQueueFamilyProperties    queueFamilyProperties;
+} VkQueueFamilyProperties2;
+
+typedef struct VkPhysicalDeviceMemoryProperties2 {
+    VkStructureType                     sType;
+    void*                               pNext;
+    VkPhysicalDeviceMemoryProperties    memoryProperties;
+} VkPhysicalDeviceMemoryProperties2;
+
+typedef struct VkSparseImageFormatProperties2 {
+    VkStructureType                  sType;
+    void*                            pNext;
+    VkSparseImageFormatProperties    properties;
+} VkSparseImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceSparseImageFormatInfo2 {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkFormat                 format;
+    VkImageType              type;
+    VkSampleCountFlagBits    samples;
+    VkImageUsageFlags        usage;
+    VkImageTiling            tiling;
+} VkPhysicalDeviceSparseImageFormatInfo2;
+
+typedef struct VkPhysicalDevicePointClippingProperties {
+    VkStructureType            sType;
+    void*                      pNext;
+    VkPointClippingBehavior    pointClippingBehavior;
+} VkPhysicalDevicePointClippingProperties;
+
+typedef struct VkInputAttachmentAspectReference {
+    uint32_t              subpass;
+    uint32_t              inputAttachmentIndex;
+    VkImageAspectFlags    aspectMask;
+} VkInputAttachmentAspectReference;
+
+typedef struct VkRenderPassInputAttachmentAspectCreateInfo {
+    VkStructureType                            sType;
+    const void*                                pNext;
+    uint32_t                                   aspectReferenceCount;
+    const VkInputAttachmentAspectReference*    pAspectReferences;
+} VkRenderPassInputAttachmentAspectCreateInfo;
+
+typedef struct VkImageViewUsageCreateInfo {
+    VkStructureType      sType;
+    const void*          pNext;
+    VkImageUsageFlags    usage;
+} VkImageViewUsageCreateInfo;
+
+typedef struct VkPipelineTessellationDomainOriginStateCreateInfo {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkTessellationDomainOrigin    domainOrigin;
+} VkPipelineTessellationDomainOriginStateCreateInfo;
+
+typedef struct VkRenderPassMultiviewCreateInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           subpassCount;
+    const uint32_t*    pViewMasks;
+    uint32_t           dependencyCount;
+    const int32_t*     pViewOffsets;
+    uint32_t           correlationMaskCount;
+    const uint32_t*    pCorrelationMasks;
+} VkRenderPassMultiviewCreateInfo;
+
+typedef struct VkPhysicalDeviceMultiviewFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           multiview;
+    VkBool32           multiviewGeometryShader;
+    VkBool32           multiviewTessellationShader;
+} VkPhysicalDeviceMultiviewFeatures;
+
+typedef struct VkPhysicalDeviceMultiviewProperties {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           maxMultiviewViewCount;
+    uint32_t           maxMultiviewInstanceIndex;
+} VkPhysicalDeviceMultiviewProperties;
+
+typedef struct VkPhysicalDeviceVariablePointerFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           variablePointersStorageBuffer;
+    VkBool32           variablePointers;
+} VkPhysicalDeviceVariablePointerFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           protectedMemory;
+} VkPhysicalDeviceProtectedMemoryFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryProperties {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           protectedNoFault;
+} VkPhysicalDeviceProtectedMemoryProperties;
+
+typedef struct VkDeviceQueueInfo2 {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkDeviceQueueCreateFlags    flags;
+    uint32_t                    queueFamilyIndex;
+    uint32_t                    queueIndex;
+} VkDeviceQueueInfo2;
+
+typedef struct VkProtectedSubmitInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBool32           protectedSubmit;
+} VkProtectedSubmitInfo;
+
+typedef struct VkSamplerYcbcrConversionCreateInfo {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkFormat                         format;
+    VkSamplerYcbcrModelConversion    ycbcrModel;
+    VkSamplerYcbcrRange              ycbcrRange;
+    VkComponentMapping               components;
+    VkChromaLocation                 xChromaOffset;
+    VkChromaLocation                 yChromaOffset;
+    VkFilter                         chromaFilter;
+    VkBool32                         forceExplicitReconstruction;
+} VkSamplerYcbcrConversionCreateInfo;
+
+typedef struct VkSamplerYcbcrConversionInfo {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkSamplerYcbcrConversion    conversion;
+} VkSamplerYcbcrConversionInfo;
+
+typedef struct VkBindImagePlaneMemoryInfo {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkImageAspectFlagBits    planeAspect;
+} VkBindImagePlaneMemoryInfo;
+
+typedef struct VkImagePlaneMemoryRequirementsInfo {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkImageAspectFlagBits    planeAspect;
+} VkImagePlaneMemoryRequirementsInfo;
+
+typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           samplerYcbcrConversion;
+} VkPhysicalDeviceSamplerYcbcrConversionFeatures;
+
+typedef struct VkSamplerYcbcrConversionImageFormatProperties {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           combinedImageSamplerDescriptorCount;
+} VkSamplerYcbcrConversionImageFormatProperties;
+
+typedef struct VkDescriptorUpdateTemplateEntry {
+    uint32_t            dstBinding;
+    uint32_t            dstArrayElement;
+    uint32_t            descriptorCount;
+    VkDescriptorType    descriptorType;
+    size_t              offset;
+    size_t              stride;
+} VkDescriptorUpdateTemplateEntry;
+
+typedef struct VkDescriptorUpdateTemplateCreateInfo {
+    VkStructureType                           sType;
+    void*                                     pNext;
+    VkDescriptorUpdateTemplateCreateFlags     flags;
+    uint32_t                                  descriptorUpdateEntryCount;
+    const VkDescriptorUpdateTemplateEntry*    pDescriptorUpdateEntries;
+    VkDescriptorUpdateTemplateType            templateType;
+    VkDescriptorSetLayout                     descriptorSetLayout;
+    VkPipelineBindPoint                       pipelineBindPoint;
+    VkPipelineLayout                          pipelineLayout;
+    uint32_t                                  set;
+} VkDescriptorUpdateTemplateCreateInfo;
+
+typedef struct VkExternalMemoryProperties {
+    VkExternalMemoryFeatureFlags       externalMemoryFeatures;
+    VkExternalMemoryHandleTypeFlags    exportFromImportedHandleTypes;
+    VkExternalMemoryHandleTypeFlags    compatibleHandleTypes;
+} VkExternalMemoryProperties;
+
+typedef struct VkPhysicalDeviceExternalImageFormatInfo {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+} VkPhysicalDeviceExternalImageFormatInfo;
+
+typedef struct VkExternalImageFormatProperties {
+    VkStructureType               sType;
+    void*                         pNext;
+    VkExternalMemoryProperties    externalMemoryProperties;
+} VkExternalImageFormatProperties;
+
+typedef struct VkPhysicalDeviceExternalBufferInfo {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkBufferCreateFlags                   flags;
+    VkBufferUsageFlags                    usage;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+} VkPhysicalDeviceExternalBufferInfo;
+
+typedef struct VkExternalBufferProperties {
+    VkStructureType               sType;
+    void*                         pNext;
+    VkExternalMemoryProperties    externalMemoryProperties;
+} VkExternalBufferProperties;
+
+typedef struct VkPhysicalDeviceIDProperties {
+    VkStructureType    sType;
+    void*              pNext;
+    uint8_t            deviceUUID[VK_UUID_SIZE];
+    uint8_t            driverUUID[VK_UUID_SIZE];
+    uint8_t            deviceLUID[VK_LUID_SIZE];
+    uint32_t           deviceNodeMask;
+    VkBool32           deviceLUIDValid;
+} VkPhysicalDeviceIDProperties;
+
+typedef struct VkExternalMemoryImageCreateInfo {
+    VkStructureType                    sType;
+    const void*                        pNext;
+    VkExternalMemoryHandleTypeFlags    handleTypes;
+} VkExternalMemoryImageCreateInfo;
+
+typedef struct VkExternalMemoryBufferCreateInfo {
+    VkStructureType                    sType;
+    const void*                        pNext;
+    VkExternalMemoryHandleTypeFlags    handleTypes;
+} VkExternalMemoryBufferCreateInfo;
+
+typedef struct VkExportMemoryAllocateInfo {
+    VkStructureType                    sType;
+    const void*                        pNext;
+    VkExternalMemoryHandleTypeFlags    handleTypes;
+} VkExportMemoryAllocateInfo;
+
+typedef struct VkPhysicalDeviceExternalFenceInfo {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkExternalFenceHandleTypeFlagBits    handleType;
+} VkPhysicalDeviceExternalFenceInfo;
+
+typedef struct VkExternalFenceProperties {
+    VkStructureType                   sType;
+    void*                             pNext;
+    VkExternalFenceHandleTypeFlags    exportFromImportedHandleTypes;
+    VkExternalFenceHandleTypeFlags    compatibleHandleTypes;
+    VkExternalFenceFeatureFlags       externalFenceFeatures;
+} VkExternalFenceProperties;
+
+typedef struct VkExportFenceCreateInfo {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkExternalFenceHandleTypeFlags    handleTypes;
+} VkExportFenceCreateInfo;
+
+typedef struct VkExportSemaphoreCreateInfo {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalSemaphoreHandleTypeFlags    handleTypes;
+} VkExportSemaphoreCreateInfo;
+
+typedef struct VkPhysicalDeviceExternalSemaphoreInfo {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+} VkPhysicalDeviceExternalSemaphoreInfo;
+
+typedef struct VkExternalSemaphoreProperties {
+    VkStructureType                       sType;
+    void*                                 pNext;
+    VkExternalSemaphoreHandleTypeFlags    exportFromImportedHandleTypes;
+    VkExternalSemaphoreHandleTypeFlags    compatibleHandleTypes;
+    VkExternalSemaphoreFeatureFlags       externalSemaphoreFeatures;
+} VkExternalSemaphoreProperties;
+
+typedef struct VkPhysicalDeviceMaintenance3Properties {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           maxPerSetDescriptors;
+    VkDeviceSize       maxMemoryAllocationSize;
+} VkPhysicalDeviceMaintenance3Properties;
+
+typedef struct VkDescriptorSetLayoutSupport {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           supported;
+} VkDescriptorSetLayoutSupport;
+
+typedef struct VkPhysicalDeviceShaderDrawParameterFeatures {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           shaderDrawParameters;
+} VkPhysicalDeviceShaderDrawParameterFeatures;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(
+    uint32_t*                                   pApiVersion);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindBufferMemoryInfo*               pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindImageMemoryInfo*                pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures(
+    VkDevice                                    device,
+    uint32_t                                    heapIndex,
+    uint32_t                                    localDeviceIndex,
+    uint32_t                                    remoteDeviceIndex,
+    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    baseGroupX,
+    uint32_t                                    baseGroupY,
+    uint32_t                                    baseGroupZ,
+    uint32_t                                    groupCountX,
+    uint32_t                                    groupCountY,
+    uint32_t                                    groupCountZ);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
+    VkInstance                                  instance,
+    uint32_t*                                   pPhysicalDeviceGroupCount,
+    VkPhysicalDeviceGroupProperties*            pPhysicalDeviceGroupProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2(
+    VkDevice                                    device,
+    const VkImageMemoryRequirementsInfo2*       pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2(
+    VkDevice                                    device,
+    const VkBufferMemoryRequirementsInfo2*      pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2(
+    VkDevice                                    device,
+    const VkImageSparseMemoryRequirementsInfo2* pInfo,
+    uint32_t*                                   pSparseMemoryRequirementCount,
+    VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceFeatures2*                  pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceProperties2*                pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkFormatProperties2*                        pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceImageFormatInfo2*     pImageFormatInfo,
+    VkImageFormatProperties2*                   pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pQueueFamilyPropertyCount,
+    VkQueueFamilyProperties2*                   pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+    uint32_t*                                   pPropertyCount,
+    VkSparseImageFormatProperties2*             pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool(
+    VkDevice                                    device,
+    VkCommandPool                               commandPool,
+    VkCommandPoolTrimFlags                      flags);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2(
+    VkDevice                                    device,
+    const VkDeviceQueueInfo2*                   pQueueInfo,
+    VkQueue*                                    pQueue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(
+    VkDevice                                    device,
+    const VkSamplerYcbcrConversionCreateInfo*   pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSamplerYcbcrConversion*                   pYcbcrConversion);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(
+    VkDevice                                    device,
+    VkSamplerYcbcrConversion                    ycbcrConversion,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate(
+    VkDevice                                    device,
+    const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDescriptorUpdateTemplate*                 pDescriptorUpdateTemplate);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate(
+    VkDevice                                    device,
+    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate(
+    VkDevice                                    device,
+    VkDescriptorSet                             descriptorSet,
+    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
+    const void*                                 pData);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalBufferInfo*   pExternalBufferInfo,
+    VkExternalBufferProperties*                 pExternalBufferProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalFenceInfo*    pExternalFenceInfo,
+    VkExternalFenceProperties*                  pExternalFenceProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+    VkExternalSemaphoreProperties*              pExternalSemaphoreProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(
+    VkDevice                                    device,
+    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+    VkDescriptorSetLayoutSupport*               pSupport);
+#endif
+
 #define VK_KHR_surface 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
 
-#define VK_KHR_SURFACE_SPEC_VERSION       25
+#define VK_KHR_SURFACE_SPEC_VERSION       26
 #define VK_KHR_SURFACE_EXTENSION_NAME     "VK_KHR_surface"
 #define VK_COLORSPACE_SRGB_NONLINEAR_KHR  VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
 
@@ -3550,6 +4395,15 @@
 } VkCompositeAlphaFlagBitsKHR;
 typedef VkFlags VkCompositeAlphaFlagsKHR;
 
+typedef enum VkDeviceGroupPresentModeFlagBitsKHR {
+    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001,
+    VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002,
+    VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004,
+    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
+    VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDeviceGroupPresentModeFlagBitsKHR;
+typedef VkFlags VkDeviceGroupPresentModeFlagsKHR;
+
 typedef struct VkSurfaceCapabilitiesKHR {
     uint32_t                         minImageCount;
     uint32_t                         maxImageCount;
@@ -3608,12 +4462,13 @@
 #define VK_KHR_swapchain 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
 
-#define VK_KHR_SWAPCHAIN_SPEC_VERSION     68
+#define VK_KHR_SWAPCHAIN_SPEC_VERSION     69
 #define VK_KHR_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_swapchain"
 
 
 typedef enum VkSwapchainCreateFlagBitsKHR {
-    VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001,
+    VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHR = 0x00000001,
+    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
     VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkSwapchainCreateFlagBitsKHR;
 typedef VkFlags VkSwapchainCreateFlagsKHR;
@@ -3650,12 +4505,60 @@
     VkResult*                pResults;
 } VkPresentInfoKHR;
 
+typedef struct VkImageSwapchainCreateInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSwapchainKHR     swapchain;
+} VkImageSwapchainCreateInfoKHR;
+
+typedef struct VkBindImageMemorySwapchainInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSwapchainKHR     swapchain;
+    uint32_t           imageIndex;
+} VkBindImageMemorySwapchainInfoKHR;
+
+typedef struct VkAcquireNextImageInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSwapchainKHR     swapchain;
+    uint64_t           timeout;
+    VkSemaphore        semaphore;
+    VkFence            fence;
+    uint32_t           deviceMask;
+} VkAcquireNextImageInfoKHR;
+
+typedef struct VkDeviceGroupPresentCapabilitiesKHR {
+    VkStructureType                     sType;
+    const void*                         pNext;
+    uint32_t                            presentMask[VK_MAX_DEVICE_GROUP_SIZE];
+    VkDeviceGroupPresentModeFlagsKHR    modes;
+} VkDeviceGroupPresentCapabilitiesKHR;
+
+typedef struct VkDeviceGroupPresentInfoKHR {
+    VkStructureType                        sType;
+    const void*                            pNext;
+    uint32_t                               swapchainCount;
+    const uint32_t*                        pDeviceMasks;
+    VkDeviceGroupPresentModeFlagBitsKHR    mode;
+} VkDeviceGroupPresentInfoKHR;
+
+typedef struct VkDeviceGroupSwapchainCreateInfoKHR {
+    VkStructureType                     sType;
+    const void*                         pNext;
+    VkDeviceGroupPresentModeFlagsKHR    modes;
+} VkDeviceGroupSwapchainCreateInfoKHR;
+
 
 typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain);
 typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator);
 typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
 typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
 typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
@@ -3686,6 +4589,26 @@
 VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
     VkQueue                                     queue,
     const VkPresentInfoKHR*                     pPresentInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR(
+    VkDevice                                    device,
+    VkDeviceGroupPresentCapabilitiesKHR*        pDeviceGroupPresentCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR(
+    VkDevice                                    device,
+    VkSurfaceKHR                                surface,
+    VkDeviceGroupPresentModeFlagsKHR*           pModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkSurfaceKHR                                surface,
+    uint32_t*                                   pRectCount,
+    VkRect2D*                                   pRects);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR(
+    VkDevice                                    device,
+    const VkAcquireNextImageInfoKHR*            pAcquireInfo,
+    uint32_t*                                   pImageIndex);
 #endif
 
 #define VK_KHR_display 1
@@ -4048,114 +4971,141 @@
 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
 
 
+#define VK_KHR_multiview 1
+typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR;
+typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR;
+typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR;
+
+#define VK_KHR_MULTIVIEW_SPEC_VERSION     1
+#define VK_KHR_MULTIVIEW_EXTENSION_NAME   "VK_KHR_multiview"
+#define VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR  VK_DEPENDENCY_VIEW_LOCAL_BIT
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES
+#define VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
+
+
 #define VK_KHR_get_physical_device_properties2 1
+typedef VkFormatProperties2 VkFormatProperties2KHR;
+typedef VkImageFormatProperties2 VkImageFormatProperties2KHR;
+typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR;
+typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR;
+typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
+typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR;
+typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR;
+typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR;
+typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR;
+
 #define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
 #define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+#define VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2
+#define VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2
 
-typedef struct VkPhysicalDeviceFeatures2KHR {
-    VkStructureType             sType;
-    void*                       pNext;
-    VkPhysicalDeviceFeatures    features;
-} VkPhysicalDeviceFeatures2KHR;
-
-typedef struct VkPhysicalDeviceProperties2KHR {
-    VkStructureType               sType;
-    void*                         pNext;
-    VkPhysicalDeviceProperties    properties;
-} VkPhysicalDeviceProperties2KHR;
-
-typedef struct VkFormatProperties2KHR {
-    VkStructureType       sType;
-    void*                 pNext;
-    VkFormatProperties    formatProperties;
-} VkFormatProperties2KHR;
-
-typedef struct VkImageFormatProperties2KHR {
-    VkStructureType            sType;
-    void*                      pNext;
-    VkImageFormatProperties    imageFormatProperties;
-} VkImageFormatProperties2KHR;
-
-typedef struct VkPhysicalDeviceImageFormatInfo2KHR {
-    VkStructureType       sType;
-    const void*           pNext;
-    VkFormat              format;
-    VkImageType           type;
-    VkImageTiling         tiling;
-    VkImageUsageFlags     usage;
-    VkImageCreateFlags    flags;
-} VkPhysicalDeviceImageFormatInfo2KHR;
-
-typedef struct VkQueueFamilyProperties2KHR {
-    VkStructureType            sType;
-    void*                      pNext;
-    VkQueueFamilyProperties    queueFamilyProperties;
-} VkQueueFamilyProperties2KHR;
-
-typedef struct VkPhysicalDeviceMemoryProperties2KHR {
-    VkStructureType                     sType;
-    void*                               pNext;
-    VkPhysicalDeviceMemoryProperties    memoryProperties;
-} VkPhysicalDeviceMemoryProperties2KHR;
-
-typedef struct VkSparseImageFormatProperties2KHR {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkSparseImageFormatProperties    properties;
-} VkSparseImageFormatProperties2KHR;
-
-typedef struct VkPhysicalDeviceSparseImageFormatInfo2KHR {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkFormat                 format;
-    VkImageType              type;
-    VkSampleCountFlagBits    samples;
-    VkImageUsageFlags        usage;
-    VkImageTiling            tiling;
-} VkPhysicalDeviceSparseImageFormatInfo2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
     VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceFeatures2KHR*               pFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceProperties2KHR*             pProperties);
+    VkPhysicalDeviceFeatures2*                  pFeatures);
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
     VkFormat                                    format,
-    VkFormatProperties2KHR*                     pFormatProperties);
+    VkFormatProperties2*                        pFormatProperties);
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceImageFormatInfo2KHR*  pImageFormatInfo,
-    VkImageFormatProperties2KHR*                pImageFormatProperties);
+    const VkPhysicalDeviceImageFormatInfo2*     pImageFormatInfo,
+    VkImageFormatProperties2*                   pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceProperties2*                pProperties);
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
     uint32_t*                                   pQueueFamilyPropertyCount,
-    VkQueueFamilyProperties2KHR*                pQueueFamilyProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceMemoryProperties2KHR*       pMemoryProperties);
+    VkQueueFamilyProperties2*                   pQueueFamilyProperties);
 
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
+    const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
     uint32_t*                                   pPropertyCount,
-    VkSparseImageFormatProperties2KHR*          pProperties);
+    VkSparseImageFormatProperties2*             pProperties);
+#endif
+
+#define VK_KHR_device_group 1
+typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR;
+typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR;
+typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR;
+typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR;
+typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
+typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
+typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;
+typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
+typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;
+typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR;
+typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR;
+
+#define VK_KHR_DEVICE_GROUP_SPEC_VERSION  2
+#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
+#define VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR VK_DEPENDENCY_DEVICE_GROUP_BIT
+#define VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT
+#define VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR VK_PEER_MEMORY_FEATURE_COPY_DST_BIT
+#define VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT
+#define VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT
+#define VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT
+#define VK_PIPELINE_CREATE_DISPATCH_BASE_KHR VK_PIPELINE_CREATE_DISPATCH_BASE
+#define VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO
+#define VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO
+#define VK_IMAGE_CREATE_BIND_SFR_BIT_KHR  VK_IMAGE_CREATE_BIND_SFR_BIT
+#define VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO
+
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    baseGroupX,
+    uint32_t                                    baseGroupY,
+    uint32_t                                    baseGroupZ,
+    uint32_t                                    groupCountX,
+    uint32_t                                    groupCountY,
+    uint32_t                                    groupCountZ);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR(
+    VkDevice                                    device,
+    uint32_t                                    heapIndex,
+    uint32_t                                    localDeviceIndex,
+    uint32_t                                    remoteDeviceIndex,
+    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);
 #endif
 
 #define VK_KHR_shader_draw_parameters 1
@@ -4164,121 +5114,96 @@
 
 
 #define VK_KHR_maintenance1 1
+typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
+
 #define VK_KHR_MAINTENANCE1_SPEC_VERSION  1
 #define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
+#define VK_ERROR_OUT_OF_POOL_MEMORY_KHR   VK_ERROR_OUT_OF_POOL_MEMORY
+#define VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR VK_FORMAT_FEATURE_TRANSFER_DST_BIT
+#define VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
+#define VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
 
-typedef VkFlags VkCommandPoolTrimFlagsKHR;
-
-typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR(
     VkDevice                                    device,
     VkCommandPool                               commandPool,
-    VkCommandPoolTrimFlagsKHR                   flags);
+    VkCommandPoolTrimFlags                      flags);
+#endif
+
+#define VK_KHR_device_group_creation 1
+typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR;
+typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR;
+
+#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
+#define VK_MAX_DEVICE_GROUP_SIZE_KHR      VK_MAX_DEVICE_GROUP_SIZE
+#define VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR VK_MEMORY_HEAP_MULTI_INSTANCE_BIT
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR(
+    VkInstance                                  instance,
+    uint32_t*                                   pPhysicalDeviceGroupCount,
+    VkPhysicalDeviceGroupProperties*            pPhysicalDeviceGroupProperties);
 #endif
 
 #define VK_KHR_external_memory_capabilities 1
-#define VK_LUID_SIZE_KHR                  8
+typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR;
+typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR;
+typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR;
+typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR;
+typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR;
+typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR;
+typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR;
+typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR;
+typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR;
+typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR;
+
 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
+#define VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT
+#define VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_LUID_SIZE_KHR                  VK_LUID_SIZE
+#define VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES
+#define VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
 
-
-typedef enum VkExternalMemoryHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = 0x00000010,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = 0x00000020,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = 0x00000040,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalMemoryHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalMemoryHandleTypeFlagsKHR;
-
-typedef enum VkExternalMemoryFeatureFlagBitsKHR {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = 0x00000004,
-    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalMemoryFeatureFlagBitsKHR;
-typedef VkFlags VkExternalMemoryFeatureFlagsKHR;
-
-typedef struct VkExternalMemoryPropertiesKHR {
-    VkExternalMemoryFeatureFlagsKHR       externalMemoryFeatures;
-    VkExternalMemoryHandleTypeFlagsKHR    exportFromImportedHandleTypes;
-    VkExternalMemoryHandleTypeFlagsKHR    compatibleHandleTypes;
-} VkExternalMemoryPropertiesKHR;
-
-typedef struct VkPhysicalDeviceExternalImageFormatInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
-} VkPhysicalDeviceExternalImageFormatInfoKHR;
-
-typedef struct VkExternalImageFormatPropertiesKHR {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkExternalMemoryPropertiesKHR    externalMemoryProperties;
-} VkExternalImageFormatPropertiesKHR;
-
-typedef struct VkPhysicalDeviceExternalBufferInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkBufferCreateFlags                      flags;
-    VkBufferUsageFlags                       usage;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
-} VkPhysicalDeviceExternalBufferInfoKHR;
-
-typedef struct VkExternalBufferPropertiesKHR {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkExternalMemoryPropertiesKHR    externalMemoryProperties;
-} VkExternalBufferPropertiesKHR;
-
-typedef struct VkPhysicalDeviceIDPropertiesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    uint8_t            deviceUUID[VK_UUID_SIZE];
-    uint8_t            driverUUID[VK_UUID_SIZE];
-    uint8_t            deviceLUID[VK_LUID_SIZE_KHR];
-    uint32_t           deviceNodeMask;
-    VkBool32           deviceLUIDValid;
-} VkPhysicalDeviceIDPropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo, VkExternalBufferPropertiesKHR* pExternalBufferProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR(
     VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo,
-    VkExternalBufferPropertiesKHR*              pExternalBufferProperties);
+    const VkPhysicalDeviceExternalBufferInfo*   pExternalBufferInfo,
+    VkExternalBufferProperties*                 pExternalBufferProperties);
 #endif
 
 #define VK_KHR_external_memory 1
+typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
+typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR;
+typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR;
+
 #define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory"
-#define VK_QUEUE_FAMILY_EXTERNAL_KHR      (~0U-1)
-
-typedef struct VkExternalMemoryImageCreateInfoKHR {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
-} VkExternalMemoryImageCreateInfoKHR;
-
-typedef struct VkExternalMemoryBufferCreateInfoKHR {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
-} VkExternalMemoryBufferCreateInfoKHR;
-
-typedef struct VkExportMemoryAllocateInfoKHR {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
-} VkExportMemoryAllocateInfoKHR;
-
+#define VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR VK_ERROR_INVALID_EXTERNAL_HANDLE
+#define VK_QUEUE_FAMILY_EXTERNAL_KHR      VK_QUEUE_FAMILY_EXTERNAL
+#define VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
+#define VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
+#define VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
 
 
 #ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4287,11 +5212,11 @@
 #define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
 
 typedef struct VkImportMemoryWin32HandleInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
-    HANDLE                                   handle;
-    LPCWSTR                                  name;
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+    HANDLE                                handle;
+    LPCWSTR                               name;
 } VkImportMemoryWin32HandleInfoKHR;
 
 typedef struct VkExportMemoryWin32HandleInfoKHR {
@@ -4309,15 +5234,15 @@
 } VkMemoryWin32HandlePropertiesKHR;
 
 typedef struct VkMemoryGetWin32HandleInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkDeviceMemory                           memory;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkDeviceMemory                        memory;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
 } VkMemoryGetWin32HandleInfoKHR;
 
 
 typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
@@ -4327,7 +5252,7 @@
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
     VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
+    VkExternalMemoryHandleTypeFlagBits          handleType,
     HANDLE                                      handle,
     VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties);
 #endif
@@ -4338,10 +5263,10 @@
 #define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
 
 typedef struct VkImportMemoryFdInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
-    int                                      fd;
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+    int                                   fd;
 } VkImportMemoryFdInfoKHR;
 
 typedef struct VkMemoryFdPropertiesKHR {
@@ -4351,15 +5276,15 @@
 } VkMemoryFdPropertiesKHR;
 
 typedef struct VkMemoryGetFdInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkDeviceMemory                           memory;
-    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkDeviceMemory                        memory;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
 } VkMemoryGetFdInfoKHR;
 
 
 typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR(
@@ -4369,7 +5294,7 @@
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(
     VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
+    VkExternalMemoryHandleTypeFlagBits          handleType,
     int                                         fd,
     VkMemoryFdPropertiesKHR*                    pMemoryFdProperties);
 #endif
@@ -4395,68 +5320,43 @@
 #endif /* VK_USE_PLATFORM_WIN32_KHR */
 
 #define VK_KHR_external_semaphore_capabilities 1
+typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR;
+typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR;
+typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR;
+typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR;
+typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR;
+typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR;
+
 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
+#define VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
+#define VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO
 
-
-typedef enum VkExternalSemaphoreHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = 0x00000008,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000010,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalSemaphoreHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHR;
-
-typedef enum VkExternalSemaphoreFeatureFlagBitsKHR {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalSemaphoreFeatureFlagBitsKHR;
-typedef VkFlags VkExternalSemaphoreFeatureFlagsKHR;
-
-typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHR {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
-} VkPhysicalDeviceExternalSemaphoreInfoKHR;
-
-typedef struct VkExternalSemaphorePropertiesKHR {
-    VkStructureType                          sType;
-    void*                                    pNext;
-    VkExternalSemaphoreHandleTypeFlagsKHR    exportFromImportedHandleTypes;
-    VkExternalSemaphoreHandleTypeFlagsKHR    compatibleHandleTypes;
-    VkExternalSemaphoreFeatureFlagsKHR       externalSemaphoreFeatures;
-} VkExternalSemaphorePropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
     VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
-    VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties);
+    const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+    VkExternalSemaphoreProperties*              pExternalSemaphoreProperties);
 #endif
 
 #define VK_KHR_external_semaphore 1
+typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
+typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
+typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
+
 #define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
-
-
-typedef enum VkSemaphoreImportFlagBitsKHR {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
-    VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSemaphoreImportFlagBitsKHR;
-typedef VkFlags VkSemaphoreImportFlagsKHR;
-
-typedef struct VkExportSemaphoreCreateInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalSemaphoreHandleTypeFlagsKHR    handleTypes;
-} VkExportSemaphoreCreateInfoKHR;
-
+#define VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
+#define VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO
 
 
 #ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4465,13 +5365,13 @@
 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
 
 typedef struct VkImportSemaphoreWin32HandleInfoKHR {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkSemaphore                                 semaphore;
-    VkSemaphoreImportFlagsKHR                   flags;
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
-    HANDLE                                      handle;
-    LPCWSTR                                     name;
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkSemaphoreImportFlags                   flags;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+    HANDLE                                   handle;
+    LPCWSTR                                  name;
 } VkImportSemaphoreWin32HandleInfoKHR;
 
 typedef struct VkExportSemaphoreWin32HandleInfoKHR {
@@ -4492,10 +5392,10 @@
 } VkD3D12FenceSubmitInfoKHR;
 
 typedef struct VkSemaphoreGetWin32HandleInfoKHR {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkSemaphore                                 semaphore;
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
 } VkSemaphoreGetWin32HandleInfoKHR;
 
 
@@ -4519,19 +5419,19 @@
 #define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
 
 typedef struct VkImportSemaphoreFdInfoKHR {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkSemaphore                                 semaphore;
-    VkSemaphoreImportFlagsKHR                   flags;
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
-    int                                         fd;
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkSemaphoreImportFlags                   flags;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+    int                                      fd;
 } VkImportSemaphoreFdInfoKHR;
 
 typedef struct VkSemaphoreGetFdInfoKHR {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkSemaphore                                 semaphore;
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
 } VkSemaphoreGetFdInfoKHR;
 
 
@@ -4550,7 +5450,7 @@
 #endif
 
 #define VK_KHR_push_descriptor 1
-#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
 #define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
 
 typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR {
@@ -4561,6 +5461,7 @@
 
 
 typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR(
@@ -4570,21 +5471,21 @@
     uint32_t                                    set,
     uint32_t                                    descriptorWriteCount,
     const VkWriteDescriptorSet*                 pDescriptorWrites);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
+    VkCommandBuffer                             commandBuffer,
+    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
+    VkPipelineLayout                            layout,
+    uint32_t                                    set,
+    const void*                                 pData);
 #endif
 
 #define VK_KHR_16bit_storage 1
+typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR;
+
 #define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
 #define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
-
-typedef struct VkPhysicalDevice16BitStorageFeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           storageBuffer16BitAccess;
-    VkBool32           uniformAndStorageBuffer16BitAccess;
-    VkBool32           storagePushConstant16;
-    VkBool32           storageInputOutput16;
-} VkPhysicalDevice16BitStorageFeaturesKHR;
-
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES
 
 
 #define VK_KHR_incremental_present 1
@@ -4612,74 +5513,39 @@
 
 
 #define VK_KHR_descriptor_update_template 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
+typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
+typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
+typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
+typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR;
+typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
 
 #define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
 #define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
+#define VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
+#define VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE
+#define VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO
+#define VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT
 
-
-typedef enum VkDescriptorUpdateTemplateTypeKHR {
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = 0,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE_KHR = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR + 1),
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkDescriptorUpdateTemplateTypeKHR;
-
-typedef VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
-
-typedef struct VkDescriptorUpdateTemplateEntryKHR {
-    uint32_t            dstBinding;
-    uint32_t            dstArrayElement;
-    uint32_t            descriptorCount;
-    VkDescriptorType    descriptorType;
-    size_t              offset;
-    size_t              stride;
-} VkDescriptorUpdateTemplateEntryKHR;
-
-typedef struct VkDescriptorUpdateTemplateCreateInfoKHR {
-    VkStructureType                              sType;
-    void*                                        pNext;
-    VkDescriptorUpdateTemplateCreateFlagsKHR     flags;
-    uint32_t                                     descriptorUpdateEntryCount;
-    const VkDescriptorUpdateTemplateEntryKHR*    pDescriptorUpdateEntries;
-    VkDescriptorUpdateTemplateTypeKHR            templateType;
-    VkDescriptorSetLayout                        descriptorSetLayout;
-    VkPipelineBindPoint                          pipelineBindPoint;
-    VkPipelineLayout                             pipelineLayout;
-    uint32_t                                     set;
-} VkDescriptorUpdateTemplateCreateInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate);
-typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR(
     VkDevice                                    device,
-    const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
+    const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
     const VkAllocationCallbacks*                pAllocator,
-    VkDescriptorUpdateTemplateKHR*              pDescriptorUpdateTemplate);
+    VkDescriptorUpdateTemplate*                 pDescriptorUpdateTemplate);
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR(
     VkDevice                                    device,
-    VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
+    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
     const VkAllocationCallbacks*                pAllocator);
 
 VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR(
     VkDevice                                    device,
     VkDescriptorSet                             descriptorSet,
-    VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-    const void*                                 pData);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
-    VkCommandBuffer                             commandBuffer,
-    VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-    VkPipelineLayout                            layout,
-    uint32_t                                    set,
+    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
     const void*                                 pData);
 #endif
 
@@ -4703,67 +5569,42 @@
 #endif
 
 #define VK_KHR_external_fence_capabilities 1
+typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR;
+typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR;
+typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR;
+typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR;
+typedef VkExternalFenceProperties VkExternalFencePropertiesKHR;
+typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR;
+
 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
+#define VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
+#define VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO
 
-
-typedef enum VkExternalFenceHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000008,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalFenceHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalFenceHandleTypeFlagsKHR;
-
-typedef enum VkExternalFenceFeatureFlagBitsKHR {
-    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
-    VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalFenceFeatureFlagBitsKHR;
-typedef VkFlags VkExternalFenceFeatureFlagsKHR;
-
-typedef struct VkPhysicalDeviceExternalFenceInfoKHR {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
-} VkPhysicalDeviceExternalFenceInfoKHR;
-
-typedef struct VkExternalFencePropertiesKHR {
-    VkStructureType                      sType;
-    void*                                pNext;
-    VkExternalFenceHandleTypeFlagsKHR    exportFromImportedHandleTypes;
-    VkExternalFenceHandleTypeFlagsKHR    compatibleHandleTypes;
-    VkExternalFenceFeatureFlagsKHR       externalFenceFeatures;
-} VkExternalFencePropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, VkExternalFencePropertiesKHR* pExternalFenceProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR(
     VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
-    VkExternalFencePropertiesKHR*               pExternalFenceProperties);
+    const VkPhysicalDeviceExternalFenceInfo*    pExternalFenceInfo,
+    VkExternalFenceProperties*                  pExternalFenceProperties);
 #endif
 
 #define VK_KHR_external_fence 1
+typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
+typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
+typedef VkFenceImportFlags VkFenceImportFlagsKHR;
+
 #define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
 #define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
-
-
-typedef enum VkFenceImportFlagBitsKHR {
-    VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
-    VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkFenceImportFlagBitsKHR;
-typedef VkFlags VkFenceImportFlagsKHR;
-
-typedef struct VkExportFenceCreateInfoKHR {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkExternalFenceHandleTypeFlagsKHR    handleTypes;
-} VkExportFenceCreateInfoKHR;
-
+#define VK_FENCE_IMPORT_TEMPORARY_BIT_KHR VK_FENCE_IMPORT_TEMPORARY_BIT
+#define VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO
 
 
 #ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4772,13 +5613,13 @@
 #define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
 
 typedef struct VkImportFenceWin32HandleInfoKHR {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkFence                                 fence;
-    VkFenceImportFlagsKHR                   flags;
-    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
-    HANDLE                                  handle;
-    LPCWSTR                                 name;
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkFence                              fence;
+    VkFenceImportFlags                   flags;
+    VkExternalFenceHandleTypeFlagBits    handleType;
+    HANDLE                               handle;
+    LPCWSTR                              name;
 } VkImportFenceWin32HandleInfoKHR;
 
 typedef struct VkExportFenceWin32HandleInfoKHR {
@@ -4790,10 +5631,10 @@
 } VkExportFenceWin32HandleInfoKHR;
 
 typedef struct VkFenceGetWin32HandleInfoKHR {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkFence                                 fence;
-    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkFence                              fence;
+    VkExternalFenceHandleTypeFlagBits    handleType;
 } VkFenceGetWin32HandleInfoKHR;
 
 
@@ -4817,19 +5658,19 @@
 #define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
 
 typedef struct VkImportFenceFdInfoKHR {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkFence                                 fence;
-    VkFenceImportFlagsKHR                   flags;
-    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
-    int                                     fd;
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkFence                              fence;
+    VkFenceImportFlags                   flags;
+    VkExternalFenceHandleTypeFlagBits    handleType;
+    int                                  fd;
 } VkImportFenceFdInfoKHR;
 
 typedef struct VkFenceGetFdInfoKHR {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkFence                                 fence;
-    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkFence                              fence;
+    VkExternalFenceHandleTypeFlagBits    handleType;
 } VkFenceGetFdInfoKHR;
 
 
@@ -4848,59 +5689,28 @@
 #endif
 
 #define VK_KHR_maintenance2 1
+typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR;
+typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR;
+typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR;
+typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR;
+typedef VkPointClippingBehavior VkPointClippingBehaviorKHR;
+typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR;
+typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR;
+
 #define VK_KHR_MAINTENANCE2_SPEC_VERSION  1
 #define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
-
-
-typedef enum VkPointClippingBehaviorKHR {
-    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = 0,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = 1,
-    VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR,
-    VK_POINT_CLIPPING_BEHAVIOR_END_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR,
-    VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE_KHR = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR + 1),
-    VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkPointClippingBehaviorKHR;
-
-typedef enum VkTessellationDomainOriginKHR {
-    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = 0,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = 1,
-    VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR,
-    VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR,
-    VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE_KHR = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR + 1),
-    VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkTessellationDomainOriginKHR;
-
-typedef struct VkPhysicalDevicePointClippingPropertiesKHR {
-    VkStructureType               sType;
-    void*                         pNext;
-    VkPointClippingBehaviorKHR    pointClippingBehavior;
-} VkPhysicalDevicePointClippingPropertiesKHR;
-
-typedef struct VkInputAttachmentAspectReferenceKHR {
-    uint32_t              subpass;
-    uint32_t              inputAttachmentIndex;
-    VkImageAspectFlags    aspectMask;
-} VkInputAttachmentAspectReferenceKHR;
-
-typedef struct VkRenderPassInputAttachmentAspectCreateInfoKHR {
-    VkStructureType                               sType;
-    const void*                                   pNext;
-    uint32_t                                      aspectReferenceCount;
-    const VkInputAttachmentAspectReferenceKHR*    pAspectReferences;
-} VkRenderPassInputAttachmentAspectCreateInfoKHR;
-
-typedef struct VkImageViewUsageCreateInfoKHR {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkImageUsageFlags    usage;
-} VkImageViewUsageCreateInfoKHR;
-
-typedef struct VkPipelineTessellationDomainOriginStateCreateInfoKHR {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkTessellationDomainOriginKHR    domainOrigin;
-} VkPipelineTessellationDomainOriginStateCreateInfoKHR;
-
+#define VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT
+#define VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
+#define VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
+#define VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
+#define VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES
+#define VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY
+#define VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES
+#define VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO
+#define VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT
+#define VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT
 
 
 #define VK_KHR_get_surface_capabilities2 1
@@ -4943,36 +5753,21 @@
 #endif
 
 #define VK_KHR_variable_pointers 1
+typedef VkPhysicalDeviceVariablePointerFeatures VkPhysicalDeviceVariablePointerFeaturesKHR;
+
 #define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
 #define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
-
-typedef struct VkPhysicalDeviceVariablePointerFeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           variablePointersStorageBuffer;
-    VkBool32           variablePointers;
-} VkPhysicalDeviceVariablePointerFeaturesKHR;
-
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES
 
 
 #define VK_KHR_dedicated_allocation 1
+typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
+typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR;
+
 #define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
 #define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
-
-typedef struct VkMemoryDedicatedRequirementsKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           prefersDedicatedAllocation;
-    VkBool32           requiresDedicatedAllocation;
-} VkMemoryDedicatedRequirementsKHR;
-
-typedef struct VkMemoryDedicatedAllocateInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkImage            image;
-    VkBuffer           buffer;
-} VkMemoryDedicatedAllocateInfoKHR;
-
+#define VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
+#define VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS
 
 
 #define VK_KHR_storage_buffer_storage_class 1
@@ -4986,60 +5781,40 @@
 
 
 #define VK_KHR_get_memory_requirements2 1
+typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR;
+typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR;
+typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
+typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
+typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
+
 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1
 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
+#define VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2
+#define VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2
 
-typedef struct VkBufferMemoryRequirementsInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBuffer           buffer;
-} VkBufferMemoryRequirementsInfo2KHR;
-
-typedef struct VkImageMemoryRequirementsInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkImage            image;
-} VkImageMemoryRequirementsInfo2KHR;
-
-typedef struct VkImageSparseMemoryRequirementsInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkImage            image;
-} VkImageSparseMemoryRequirementsInfo2KHR;
-
-typedef struct VkMemoryRequirements2KHR {
-    VkStructureType         sType;
-    void*                   pNext;
-    VkMemoryRequirements    memoryRequirements;
-} VkMemoryRequirements2KHR;
-
-typedef struct VkSparseImageMemoryRequirements2KHR {
-    VkStructureType                    sType;
-    void*                              pNext;
-    VkSparseImageMemoryRequirements    memoryRequirements;
-} VkSparseImageMemoryRequirements2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
 
 #ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
-    VkDevice                                    device,
-    const VkImageMemoryRequirementsInfo2KHR*    pInfo,
-    VkMemoryRequirements2KHR*                   pMemoryRequirements);
-
 VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR(
     VkDevice                                    device,
-    const VkBufferMemoryRequirementsInfo2KHR*   pInfo,
-    VkMemoryRequirements2KHR*                   pMemoryRequirements);
+    const VkBufferMemoryRequirementsInfo2*      pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
+    VkDevice                                    device,
+    const VkImageMemoryRequirementsInfo2*       pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
 
 VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR(
     VkDevice                                    device,
-    const VkImageSparseMemoryRequirementsInfo2KHR* pInfo,
+    const VkImageSparseMemoryRequirementsInfo2* pInfo,
     uint32_t*                                   pSparseMemoryRequirementCount,
-    VkSparseImageMemoryRequirements2KHR*        pSparseMemoryRequirements);
+    VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements);
 #endif
 
 #define VK_KHR_image_format_list 1
@@ -5056,142 +5831,145 @@
 
 
 #define VK_KHR_sampler_ycbcr_conversion 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversionKHR)
+typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR;
+typedef VkChromaLocation VkChromaLocationKHR;
+typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR;
+typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
+typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR;
+typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR;
+typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR;
+typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR;
+typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR;
+typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR;
 
 #define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1
 #define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
+#define VK_CHROMA_LOCATION_COSITED_EVEN_KHR VK_CHROMA_LOCATION_COSITED_EVEN
+#define VK_CHROMA_LOCATION_MIDPOINT_KHR   VK_CHROMA_LOCATION_MIDPOINT
+#define VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT
+#define VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
+#define VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
+#define VK_FORMAT_B16G16R16G16_422_UNORM_KHR VK_FORMAT_B16G16R16G16_422_UNORM
+#define VK_FORMAT_B8G8R8G8_422_UNORM_KHR  VK_FORMAT_B8G8R8G8_422_UNORM
+#define VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT
+#define VK_FORMAT_FEATURE_DISJOINT_BIT_KHR VK_FORMAT_FEATURE_DISJOINT_BIT
+#define VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
+#define VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM
+#define VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM
+#define VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM
+#define VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR VK_FORMAT_G16_B16R16_2PLANE_420_UNORM
+#define VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR VK_FORMAT_G16_B16R16_2PLANE_422_UNORM
+#define VK_FORMAT_G16B16G16R16_422_UNORM_KHR VK_FORMAT_G16B16G16R16_422_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM
+#define VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
+#define VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR VK_FORMAT_G8_B8R8_2PLANE_422_UNORM
+#define VK_FORMAT_G8B8G8R8_422_UNORM_KHR  VK_FORMAT_G8B8G8R8_422_UNORM
+#define VK_FORMAT_R10X6_UNORM_PACK16_KHR  VK_FORMAT_R10X6_UNORM_PACK16
+#define VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR VK_FORMAT_R10X6G10X6_UNORM_2PACK16
+#define VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
+#define VK_FORMAT_R12X4_UNORM_PACK16_KHR  VK_FORMAT_R12X4_UNORM_PACK16
+#define VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR VK_FORMAT_R12X4G12X4_UNORM_2PACK16
+#define VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16
+#define VK_IMAGE_ASPECT_PLANE_0_BIT_KHR   VK_IMAGE_ASPECT_PLANE_0_BIT
+#define VK_IMAGE_ASPECT_PLANE_1_BIT_KHR   VK_IMAGE_ASPECT_PLANE_1_BIT
+#define VK_IMAGE_ASPECT_PLANE_2_BIT_KHR   VK_IMAGE_ASPECT_PLANE_2_BIT
+#define VK_IMAGE_CREATE_DISJOINT_BIT_KHR  VK_IMAGE_CREATE_DISJOINT_BIT
+#define VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
+#define VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR VK_SAMPLER_YCBCR_RANGE_ITU_FULL
+#define VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO
+#define VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO
 
-
-typedef enum VkSamplerYcbcrModelConversionKHR {
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = 0,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = 1,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = 2,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = 3,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = 4,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR + 1),
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSamplerYcbcrModelConversionKHR;
-
-typedef enum VkSamplerYcbcrRangeKHR {
-    VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = 0,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = 1,
-    VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
-    VK_SAMPLER_YCBCR_RANGE_END_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR,
-    VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR - VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR + 1),
-    VK_SAMPLER_YCBCR_RANGE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSamplerYcbcrRangeKHR;
-
-typedef enum VkChromaLocationKHR {
-    VK_CHROMA_LOCATION_COSITED_EVEN_KHR = 0,
-    VK_CHROMA_LOCATION_MIDPOINT_KHR = 1,
-    VK_CHROMA_LOCATION_BEGIN_RANGE_KHR = VK_CHROMA_LOCATION_COSITED_EVEN_KHR,
-    VK_CHROMA_LOCATION_END_RANGE_KHR = VK_CHROMA_LOCATION_MIDPOINT_KHR,
-    VK_CHROMA_LOCATION_RANGE_SIZE_KHR = (VK_CHROMA_LOCATION_MIDPOINT_KHR - VK_CHROMA_LOCATION_COSITED_EVEN_KHR + 1),
-    VK_CHROMA_LOCATION_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkChromaLocationKHR;
-
-typedef struct VkSamplerYcbcrConversionCreateInfoKHR {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    VkFormat                            format;
-    VkSamplerYcbcrModelConversionKHR    ycbcrModel;
-    VkSamplerYcbcrRangeKHR              ycbcrRange;
-    VkComponentMapping                  components;
-    VkChromaLocationKHR                 xChromaOffset;
-    VkChromaLocationKHR                 yChromaOffset;
-    VkFilter                            chromaFilter;
-    VkBool32                            forceExplicitReconstruction;
-} VkSamplerYcbcrConversionCreateInfoKHR;
-
-typedef struct VkSamplerYcbcrConversionInfoKHR {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkSamplerYcbcrConversionKHR    conversion;
-} VkSamplerYcbcrConversionInfoKHR;
-
-typedef struct VkBindImagePlaneMemoryInfoKHR {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkImageAspectFlagBits    planeAspect;
-} VkBindImagePlaneMemoryInfoKHR;
-
-typedef struct VkImagePlaneMemoryRequirementsInfoKHR {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkImageAspectFlagBits    planeAspect;
-} VkImagePlaneMemoryRequirementsInfoKHR;
-
-typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           samplerYcbcrConversion;
-} VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
-
-typedef struct VkSamplerYcbcrConversionImageFormatPropertiesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           combinedImageSamplerDescriptorCount;
-} VkSamplerYcbcrConversionImageFormatPropertiesKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversionKHR* pYcbcrConversion);
-typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversionKHR ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR(
     VkDevice                                    device,
-    const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo,
+    const VkSamplerYcbcrConversionCreateInfo*   pCreateInfo,
     const VkAllocationCallbacks*                pAllocator,
-    VkSamplerYcbcrConversionKHR*                pYcbcrConversion);
+    VkSamplerYcbcrConversion*                   pYcbcrConversion);
 
 VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR(
     VkDevice                                    device,
-    VkSamplerYcbcrConversionKHR                 ycbcrConversion,
+    VkSamplerYcbcrConversion                    ycbcrConversion,
     const VkAllocationCallbacks*                pAllocator);
 #endif
 
 #define VK_KHR_bind_memory2 1
+typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR;
+typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR;
+
 #define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1
 #define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2"
+#define VK_IMAGE_CREATE_ALIAS_BIT_KHR     VK_IMAGE_CREATE_ALIAS_BIT
+#define VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO
 
-typedef struct VkBindBufferMemoryInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBuffer           buffer;
-    VkDeviceMemory     memory;
-    VkDeviceSize       memoryOffset;
-} VkBindBufferMemoryInfoKHR;
-
-typedef struct VkBindImageMemoryInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkImage            image;
-    VkDeviceMemory     memory;
-    VkDeviceSize       memoryOffset;
-} VkBindImageMemoryInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos);
-typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR(
     VkDevice                                    device,
     uint32_t                                    bindInfoCount,
-    const VkBindBufferMemoryInfoKHR*            pBindInfos);
+    const VkBindBufferMemoryInfo*               pBindInfos);
 
 VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR(
     VkDevice                                    device,
     uint32_t                                    bindInfoCount,
-    const VkBindImageMemoryInfoKHR*             pBindInfos);
+    const VkBindImageMemoryInfo*                pBindInfos);
+#endif
+
+#define VK_KHR_maintenance3 1
+typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
+typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR;
+
+#define VK_KHR_MAINTENANCE3_SPEC_VERSION  1
+#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+#define VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES
+
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR(
+    VkDevice                                    device,
+    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+    VkDescriptorSetLayoutSupport*               pSupport);
 #endif
 
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  8
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  9
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
 #define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
 #define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
@@ -5232,8 +6010,8 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
     VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = 33,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
     VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -5486,38 +6264,6 @@
 
 
 
-#define VK_KHX_multiview 1
-#define VK_KHX_MULTIVIEW_SPEC_VERSION     1
-#define VK_KHX_MULTIVIEW_EXTENSION_NAME   "VK_KHX_multiview"
-
-typedef struct VkRenderPassMultiviewCreateInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           subpassCount;
-    const uint32_t*    pViewMasks;
-    uint32_t           dependencyCount;
-    const int32_t*     pViewOffsets;
-    uint32_t           correlationMaskCount;
-    const uint32_t*    pCorrelationMasks;
-} VkRenderPassMultiviewCreateInfoKHX;
-
-typedef struct VkPhysicalDeviceMultiviewFeaturesKHX {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           multiview;
-    VkBool32           multiviewGeometryShader;
-    VkBool32           multiviewTessellationShader;
-} VkPhysicalDeviceMultiviewFeaturesKHX;
-
-typedef struct VkPhysicalDeviceMultiviewPropertiesKHX {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxMultiviewViewCount;
-    uint32_t           maxMultiviewInstanceIndex;
-} VkPhysicalDeviceMultiviewPropertiesKHX;
-
-
-
 #define VK_IMG_format_pvrtc 1
 #define VK_IMG_FORMAT_PVRTC_SPEC_VERSION  1
 #define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
@@ -5636,186 +6382,6 @@
 
 #endif /* VK_USE_PLATFORM_WIN32_KHR */
 
-#define VK_KHX_device_group 1
-#define VK_KHX_DEVICE_GROUP_SPEC_VERSION  2
-#define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
-#define VK_MAX_DEVICE_GROUP_SIZE_KHX      32
-
-
-typedef enum VkPeerMemoryFeatureFlagBitsKHX {
-    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001,
-    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002,
-    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008,
-    VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkPeerMemoryFeatureFlagBitsKHX;
-typedef VkFlags VkPeerMemoryFeatureFlagsKHX;
-
-typedef enum VkMemoryAllocateFlagBitsKHX {
-    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001,
-    VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkMemoryAllocateFlagBitsKHX;
-typedef VkFlags VkMemoryAllocateFlagsKHX;
-
-typedef enum VkDeviceGroupPresentModeFlagBitsKHX {
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001,
-    VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002,
-    VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004,
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
-    VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkDeviceGroupPresentModeFlagBitsKHX;
-typedef VkFlags VkDeviceGroupPresentModeFlagsKHX;
-
-typedef struct VkMemoryAllocateFlagsInfoKHX {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkMemoryAllocateFlagsKHX    flags;
-    uint32_t                    deviceMask;
-} VkMemoryAllocateFlagsInfoKHX;
-
-typedef struct VkDeviceGroupRenderPassBeginInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           deviceMask;
-    uint32_t           deviceRenderAreaCount;
-    const VkRect2D*    pDeviceRenderAreas;
-} VkDeviceGroupRenderPassBeginInfoKHX;
-
-typedef struct VkDeviceGroupCommandBufferBeginInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           deviceMask;
-} VkDeviceGroupCommandBufferBeginInfoKHX;
-
-typedef struct VkDeviceGroupSubmitInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           waitSemaphoreCount;
-    const uint32_t*    pWaitSemaphoreDeviceIndices;
-    uint32_t           commandBufferCount;
-    const uint32_t*    pCommandBufferDeviceMasks;
-    uint32_t           signalSemaphoreCount;
-    const uint32_t*    pSignalSemaphoreDeviceIndices;
-} VkDeviceGroupSubmitInfoKHX;
-
-typedef struct VkDeviceGroupBindSparseInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           resourceDeviceIndex;
-    uint32_t           memoryDeviceIndex;
-} VkDeviceGroupBindSparseInfoKHX;
-
-typedef struct VkBindBufferMemoryDeviceGroupInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           deviceIndexCount;
-    const uint32_t*    pDeviceIndices;
-} VkBindBufferMemoryDeviceGroupInfoKHX;
-
-typedef struct VkBindImageMemoryDeviceGroupInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           deviceIndexCount;
-    const uint32_t*    pDeviceIndices;
-    uint32_t           SFRRectCount;
-    const VkRect2D*    pSFRRects;
-} VkBindImageMemoryDeviceGroupInfoKHX;
-
-typedef struct VkDeviceGroupPresentCapabilitiesKHX {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    uint32_t                            presentMask[VK_MAX_DEVICE_GROUP_SIZE_KHX];
-    VkDeviceGroupPresentModeFlagsKHX    modes;
-} VkDeviceGroupPresentCapabilitiesKHX;
-
-typedef struct VkImageSwapchainCreateInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSwapchainKHR     swapchain;
-} VkImageSwapchainCreateInfoKHX;
-
-typedef struct VkBindImageMemorySwapchainInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSwapchainKHR     swapchain;
-    uint32_t           imageIndex;
-} VkBindImageMemorySwapchainInfoKHX;
-
-typedef struct VkAcquireNextImageInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSwapchainKHR     swapchain;
-    uint64_t           timeout;
-    VkSemaphore        semaphore;
-    VkFence            fence;
-    uint32_t           deviceMask;
-} VkAcquireNextImageInfoKHX;
-
-typedef struct VkDeviceGroupPresentInfoKHX {
-    VkStructureType                        sType;
-    const void*                            pNext;
-    uint32_t                               swapchainCount;
-    const uint32_t*                        pDeviceMasks;
-    VkDeviceGroupPresentModeFlagBitsKHX    mode;
-} VkDeviceGroupPresentInfoKHX;
-
-typedef struct VkDeviceGroupSwapchainCreateInfoKHX {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    VkDeviceGroupPresentModeFlagsKHX    modes;
-} VkDeviceGroupSwapchainCreateInfoKHX;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHX)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures);
-typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHX)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
-typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHX)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHX)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHX)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHX* pModes);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHX)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
-typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHX)(VkDevice device, const VkAcquireNextImageInfoKHX* pAcquireInfo, uint32_t* pImageIndex);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHX(
-    VkDevice                                    device,
-    uint32_t                                    heapIndex,
-    uint32_t                                    localDeviceIndex,
-    uint32_t                                    remoteDeviceIndex,
-    VkPeerMemoryFeatureFlagsKHX*                pPeerMemoryFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHX(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    deviceMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHX(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    baseGroupX,
-    uint32_t                                    baseGroupY,
-    uint32_t                                    baseGroupZ,
-    uint32_t                                    groupCountX,
-    uint32_t                                    groupCountY,
-    uint32_t                                    groupCountZ);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHX(
-    VkDevice                                    device,
-    VkDeviceGroupPresentCapabilitiesKHX*        pDeviceGroupPresentCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX(
-    VkDevice                                    device,
-    VkSurfaceKHR                                surface,
-    VkDeviceGroupPresentModeFlagsKHX*           pModes);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX(
-    VkPhysicalDevice                            physicalDevice,
-    VkSurfaceKHR                                surface,
-    uint32_t*                                   pRectCount,
-    VkRect2D*                                   pRects);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHX(
-    VkDevice                                    device,
-    const VkAcquireNextImageInfoKHX*            pAcquireInfo,
-    uint32_t*                                   pImageIndex);
-#endif
-
 #define VK_EXT_validation_flags 1
 #define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
 #define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
@@ -5875,35 +6441,6 @@
 #define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
 
 
-#define VK_KHX_device_group_creation 1
-#define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
-#define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
-
-typedef struct VkPhysicalDeviceGroupPropertiesKHX {
-    VkStructureType     sType;
-    void*               pNext;
-    uint32_t            physicalDeviceCount;
-    VkPhysicalDevice    physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
-    VkBool32            subsetAllocation;
-} VkPhysicalDeviceGroupPropertiesKHX;
-
-typedef struct VkDeviceGroupDeviceCreateInfoKHX {
-    VkStructureType            sType;
-    const void*                pNext;
-    uint32_t                   physicalDeviceCount;
-    const VkPhysicalDevice*    pPhysicalDevices;
-} VkDeviceGroupDeviceCreateInfoKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHX)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHX(
-    VkInstance                                  instance,
-    uint32_t*                                   pPhysicalDeviceGroupCount,
-    VkPhysicalDeviceGroupPropertiesKHX*         pPhysicalDeviceGroupProperties);
-#endif
-
 #define VK_NVX_device_generated_commands 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
diff --git a/vulkan/include/vulkan/vulkan_loader_data.h b/vulkan/include/vulkan/vulkan_loader_data.h
deleted file mode 100644
index 8ea4666..0000000
--- a/vulkan/include/vulkan/vulkan_loader_data.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2015 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 VULKAN_VULKAN_LOADER_DATA_H
-#define VULKAN_VULKAN_LOADER_DATA_H
-
-#include <string>
-
-struct android_namespace_t;
-
-namespace vulkan {
-    struct LoaderData {
-        std::string layer_path;
-        android_namespace_t* app_namespace;
-
-        __attribute__((visibility("default"))) static LoaderData& GetInstance();
-    };
-}
-
-#endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5f9b357..c9faf28 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -61,7 +61,6 @@
         "layers_extensions.cpp",
         "stubhal.cpp",
         "swapchain.cpp",
-        "vulkan_loader_data.cpp",
     ],
 
     export_header_lib_headers: ["vulkan_headers"],
@@ -80,6 +79,7 @@
         "libcutils",
         "libz",
         "libnativewindow",
+        "android.hardware.graphics.common@1.0",
     ],
     static_libs: ["libgrallocusage"],
 }
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index e05ca5a..673a066 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -29,14 +29,17 @@
 #include <new>
 #include <utility>
 
+#include <android-base/strings.h>
 #include <cutils/properties.h>
 #include <log/log.h>
 
 #include <vulkan/vk_layer_interface.h>
+#include <graphicsenv/GraphicsEnv.h>
 #include "api.h"
 #include "driver.h"
 #include "layers_extensions.h"
 
+
 namespace vulkan {
 namespace api {
 
@@ -121,15 +124,33 @@
         if (!is_instance_ || !driver::Debuggable())
             return;
 
-        ParseDebugVulkanLayers();
-        property_list(ParseDebugVulkanLayer, this);
+        GetLayersFromSettings();
 
-        // sort by priorities
-        auto& arr = implicit_layers_;
-        std::sort(arr.elements, arr.elements + arr.count,
-                  [](const ImplicitLayer& a, const ImplicitLayer& b) {
-                      return (a.priority < b.priority);
-                  });
+        // If no layers specified via Settings, check legacy properties
+        if (implicit_layers_.count <= 0) {
+            ParseDebugVulkanLayers();
+            property_list(ParseDebugVulkanLayer, this);
+
+            // sort by priorities
+            auto& arr = implicit_layers_;
+            std::sort(arr.elements, arr.elements + arr.count,
+                      [](const ImplicitLayer& a, const ImplicitLayer& b) {
+                          return (a.priority < b.priority);
+                      });
+        }
+    }
+
+    void GetLayersFromSettings() {
+        // These will only be available if conditions are met in GraphicsEnvironemnt
+        // gpu_debug_layers = layer1:layer2:layerN
+        const std::string layers = android::GraphicsEnv::getInstance().getDebugLayers();
+        if (!layers.empty()) {
+            ALOGV("Debug layer list: %s", layers.c_str());
+            std::vector<std::string> paths = android::base::Split(layers, ":");
+            for (uint32_t i = 0; i < paths.size(); i++) {
+                AddImplicitLayer(int(i), paths[i].c_str(), paths[i].length());
+            }
+        }
     }
 
     void ParseDebugVulkanLayers() {
@@ -1280,5 +1301,10 @@
         physicalDevice, nullptr, pPropertyCount, pProperties);
 }
 
+VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
+    *pApiVersion = VK_API_VERSION_1_1;
+    return VK_SUCCESS;
+}
+
 }  // namespace api
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/api.h b/vulkan/libvulkan/api.h
index ded7d17..416cba0 100644
--- a/vulkan/libvulkan/api.h
+++ b/vulkan/libvulkan/api.h
@@ -33,6 +33,7 @@
 VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
 VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
 VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
 // clang-format on
 
 inline InstanceData& GetData(VkInstance instance) {
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 8dd55f4..2aa1d5a 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -103,6 +103,26 @@
     return VK_SUCCESS;
 }
 
+VKAPI_ATTR VkResult disabledGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR*) {
+    driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkGetDeviceGroupPresentCapabilitiesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR, VkDeviceGroupPresentModeFlagsKHR*) {
+    driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkGetDeviceGroupSurfacePresentModesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkRect2D*) {
+    driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_swapchain not enabled. Exported vkGetPhysicalDevicePresentRectanglesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR*, uint32_t*) {
+    driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkAcquireNextImage2KHR not executed.");
+    return VK_SUCCESS;
+}
+
 VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
     driver::Logger(instance).Err(instance, "VK_KHR_android_surface not enabled. Exported vkCreateAndroidSurfaceKHR not executed.");
     return VK_SUCCESS;
@@ -132,11 +152,23 @@
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
     INIT_PROC(true, instance, GetPhysicalDeviceSparseImageFormatProperties);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+    INIT_PROC(false, instance, GetPhysicalDeviceFeatures2);
+    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceFormatProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceImageFormatProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceQueueFamilyProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceMemoryProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceSparseImageFormatProperties2);
+    INIT_PROC(false, instance, GetPhysicalDeviceExternalBufferProperties);
+    INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
+    INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties);
     INIT_PROC_EXT(KHR_surface, true, instance, DestroySurfaceKHR);
     INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceSupportKHR);
     INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
     INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceFormatsKHR);
     INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+    INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR);
     INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
     // clang-format on
 
@@ -272,11 +304,30 @@
     INIT_PROC(true, dev, CmdNextSubpass);
     INIT_PROC(true, dev, CmdEndRenderPass);
     INIT_PROC(true, dev, CmdExecuteCommands);
+    INIT_PROC(false, dev, BindBufferMemory2);
+    INIT_PROC(false, dev, BindImageMemory2);
+    INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
+    INIT_PROC(false, dev, CmdSetDeviceMask);
+    INIT_PROC(false, dev, CmdDispatchBase);
+    INIT_PROC(false, dev, GetImageMemoryRequirements2);
+    INIT_PROC(false, dev, GetBufferMemoryRequirements2);
+    INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
+    INIT_PROC(false, dev, TrimCommandPool);
+    INIT_PROC(false, dev, GetDeviceQueue2);
+    INIT_PROC(false, dev, CreateSamplerYcbcrConversion);
+    INIT_PROC(false, dev, DestroySamplerYcbcrConversion);
+    INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
+    INIT_PROC(false, dev, GetDescriptorSetLayoutSupport);
     INIT_PROC_EXT(KHR_swapchain, true, dev, CreateSwapchainKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, DestroySwapchainKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, GetSwapchainImagesKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImageKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, QueuePresentKHR);
+    INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR);
+    INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR);
+    INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR);
     // clang-format on
 
     return success;
@@ -416,6 +467,33 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
 VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
@@ -426,6 +504,10 @@
 VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
 VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
 VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
 VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
 
 VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
@@ -451,29 +533,41 @@
         "vkEnumerateDeviceLayerProperties",
         "vkEnumerateInstanceExtensionProperties",
         "vkEnumerateInstanceLayerProperties",
-        "vkEnumeratePhysicalDeviceGroupsKHX",
+        "vkEnumerateInstanceVersion",
+        "vkEnumeratePhysicalDeviceGroups",
+        "vkEnumeratePhysicalDeviceGroupsKHR",
         "vkEnumeratePhysicalDevices",
         "vkGetInstanceProcAddr",
+        "vkGetPhysicalDeviceExternalBufferProperties",
         "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
+        "vkGetPhysicalDeviceExternalFenceProperties",
         "vkGetPhysicalDeviceExternalFencePropertiesKHR",
         "vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
+        "vkGetPhysicalDeviceExternalSemaphoreProperties",
         "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR",
         "vkGetPhysicalDeviceFeatures",
+        "vkGetPhysicalDeviceFeatures2",
         "vkGetPhysicalDeviceFeatures2KHR",
         "vkGetPhysicalDeviceFormatProperties",
+        "vkGetPhysicalDeviceFormatProperties2",
         "vkGetPhysicalDeviceFormatProperties2KHR",
         "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX",
         "vkGetPhysicalDeviceImageFormatProperties",
+        "vkGetPhysicalDeviceImageFormatProperties2",
         "vkGetPhysicalDeviceImageFormatProperties2KHR",
         "vkGetPhysicalDeviceMemoryProperties",
+        "vkGetPhysicalDeviceMemoryProperties2",
         "vkGetPhysicalDeviceMemoryProperties2KHR",
         "vkGetPhysicalDeviceMultisamplePropertiesEXT",
-        "vkGetPhysicalDevicePresentRectanglesKHX",
+        "vkGetPhysicalDevicePresentRectanglesKHR",
         "vkGetPhysicalDeviceProperties",
+        "vkGetPhysicalDeviceProperties2",
         "vkGetPhysicalDeviceProperties2KHR",
         "vkGetPhysicalDeviceQueueFamilyProperties",
+        "vkGetPhysicalDeviceQueueFamilyProperties2",
         "vkGetPhysicalDeviceQueueFamilyProperties2KHR",
         "vkGetPhysicalDeviceSparseImageFormatProperties",
+        "vkGetPhysicalDeviceSparseImageFormatProperties2",
         "vkGetPhysicalDeviceSparseImageFormatProperties2KHR",
         "vkGetPhysicalDeviceSurfaceCapabilities2KHR",
         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
@@ -508,6 +602,7 @@
         if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
         if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties);
         if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties);
+        if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
 
         ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
         return nullptr;
@@ -517,13 +612,16 @@
         const char* name;
         PFN_vkVoidFunction proc;
     } hooks[] = {
+        { "vkAcquireNextImage2KHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImage2KHR) },
         { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
         { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
         { "vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets) },
         { "vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory) },
         { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
         { "vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory) },
+        { "vkBindBufferMemory2", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory2) },
         { "vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory) },
+        { "vkBindImageMemory2", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2) },
         { "vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery) },
         { "vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass) },
         { "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets) },
@@ -540,6 +638,7 @@
         { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer) },
         { "vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults) },
         { "vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch) },
+        { "vkCmdDispatchBase", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchBase) },
         { "vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect) },
         { "vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw) },
         { "vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed) },
@@ -558,6 +657,7 @@
         { "vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants) },
         { "vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias) },
         { "vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds) },
+        { "vkCmdSetDeviceMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDeviceMask) },
         { "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent) },
         { "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth) },
         { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
@@ -574,6 +674,7 @@
         { "vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines) },
         { "vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool) },
         { "vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout) },
+        { "vkCreateDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorUpdateTemplate) },
         { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
         { "vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent) },
         { "vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence) },
@@ -587,6 +688,7 @@
         { "vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool) },
         { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
         { "vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler) },
+        { "vkCreateSamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(CreateSamplerYcbcrConversion) },
         { "vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore) },
         { "vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule) },
         { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
@@ -595,6 +697,7 @@
         { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool) },
         { "vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool) },
         { "vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout) },
+        { "vkDestroyDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorUpdateTemplate) },
         { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
         { "vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent) },
         { "vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence) },
@@ -608,6 +711,7 @@
         { "vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool) },
         { "vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass) },
         { "vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler) },
+        { "vkDestroySamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(DestroySamplerYcbcrConversion) },
         { "vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore) },
         { "vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule) },
         { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
@@ -617,18 +721,27 @@
         { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
         { "vkEnumerateInstanceExtensionProperties", nullptr },
         { "vkEnumerateInstanceLayerProperties", nullptr },
+        { "vkEnumerateInstanceVersion", nullptr },
         { "vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges) },
         { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
         { "vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets) },
         { "vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory) },
         { "vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements) },
+        { "vkGetBufferMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements2) },
+        { "vkGetDescriptorSetLayoutSupport", reinterpret_cast<PFN_vkVoidFunction>(GetDescriptorSetLayoutSupport) },
+        { "vkGetDeviceGroupPeerMemoryFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPeerMemoryFeatures) },
+        { "vkGetDeviceGroupPresentCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPresentCapabilitiesKHR) },
+        { "vkGetDeviceGroupSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupSurfacePresentModesKHR) },
         { "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryCommitment) },
         { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
         { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
+        { "vkGetDeviceQueue2", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2) },
         { "vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(GetEventStatus) },
         { "vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus) },
         { "vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements) },
+        { "vkGetImageMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements2) },
         { "vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements) },
+        { "vkGetImageSparseMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements2) },
         { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
         { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
         { "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData) },
@@ -648,7 +761,9 @@
         { "vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(ResetEvent) },
         { "vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences) },
         { "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent) },
+        { "vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(TrimCommandPool) },
         { "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory) },
+        { "vkUpdateDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSetWithTemplate) },
         { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
         { "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences) },
     };
@@ -1174,6 +1289,114 @@
     GetData(commandBuffer).dispatch.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
 }
 
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+    return GetData(device).dispatch.BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    return GetData(device).dispatch.BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+    GetData(device).dispatch.GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    GetData(commandBuffer).dispatch.CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+    GetData(commandBuffer).dispatch.CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return GetData(instance).dispatch.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+    GetData(device).dispatch.GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+    return GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+    GetData(device).dispatch.TrimCommandPool(device, commandPool, flags);
+}
+
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    GetData(device).dispatch.GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return GetData(device).dispatch.CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+    GetData(device).dispatch.DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return GetData(device).dispatch.CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+    GetData(device).dispatch.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+    GetData(device).dispatch.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    GetData(device).dispatch.GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+}
+
 VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
     GetData(instance).dispatch.DestroySurfaceKHR(instance, surface, pAllocator);
 }
@@ -1214,6 +1437,22 @@
     return GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
 }
 
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+    return GetData(device).dispatch.GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+}
+
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+    return GetData(device).dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return GetData(physicalDevice).dispatch.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+    return GetData(device).dispatch.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+}
+
 VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
     return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
@@ -1914,6 +2153,146 @@
 }
 
 __attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
+    return vulkan::api::EnumerateInstanceVersion(pApiVersion);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+    return vulkan::api::BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    return vulkan::api::BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+    vulkan::api::GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    vulkan::api::CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+    vulkan::api::CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return vulkan::api::EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    vulkan::api::GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+    vulkan::api::GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+    vulkan::api::GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+    vulkan::api::GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+    vulkan::api::GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+    return vulkan::api::GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+    vulkan::api::GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+    vulkan::api::GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+    vulkan::api::GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+    vulkan::api::TrimCommandPool(device, commandPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    vulkan::api::GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return vulkan::api::CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return vulkan::api::CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+    vulkan::api::UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    vulkan::api::GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    vulkan::api::GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+    vulkan::api::GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    vulkan::api::GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR void vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
     vulkan::api::DestroySurfaceKHR(instance, surface, pAllocator);
 }
@@ -1964,6 +2343,26 @@
 }
 
 __attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+    return vulkan::api::GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+    return vulkan::api::GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return vulkan::api::GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+    return vulkan::api::AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
     return vulkan::api::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 3e50fda..939dc73 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -40,11 +40,23 @@
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+    PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
+    PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+    PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+    PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
+    PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
+    PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
+    PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+    PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
     PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
     PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
     PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
     PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
     PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+    PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
     PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
     // clang-format on
 };
@@ -172,11 +184,30 @@
     PFN_vkCmdNextSubpass CmdNextSubpass;
     PFN_vkCmdEndRenderPass CmdEndRenderPass;
     PFN_vkCmdExecuteCommands CmdExecuteCommands;
+    PFN_vkBindBufferMemory2 BindBufferMemory2;
+    PFN_vkBindImageMemory2 BindImageMemory2;
+    PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
+    PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
+    PFN_vkCmdDispatchBase CmdDispatchBase;
+    PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
+    PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
+    PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
+    PFN_vkTrimCommandPool TrimCommandPool;
+    PFN_vkGetDeviceQueue2 GetDeviceQueue2;
+    PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
+    PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
+    PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
+    PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
+    PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+    PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
     PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
     PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
     PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
     PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
     PFN_vkQueuePresentKHR QueuePresentKHR;
+    PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR;
+    PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
+    PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR;
     // clang-format on
 };
 
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index cb2d26a..3b48e08 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -419,7 +419,7 @@
     INIT_PROC(§
   {{end}}
 
-  {{if GetAnnotation $ "optional"}}false{{else}}true{{end}}, §
+  {{if GetAnnotation $ "optional"}}false{{else if GetAnnotation $ "vulkan1_1"}}false{{else}}true{{end}}, §
 
   {{if (Macro "IsInstanceDispatched" $)}}
     instance, §
@@ -733,7 +733,9 @@
     {{     if eq $.Name "vkCreateInstance"}}true
     {{else if eq $.Name "vkCreateDevice"}}true
     {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
     {{else if eq $.Name "vkGetDeviceQueue"}}true
+    {{else if eq $.Name "vkGetDeviceQueue2"}}true
     {{else if eq $.Name "vkAllocateCommandBuffers"}}true
 
     {{/* Destroy functions of dispatchable objects */}}
@@ -958,6 +960,7 @@
     {{/* Create functions of dispatchable objects */}}
     {{     if eq $.Name "vkCreateDevice"}}true
     {{else if eq $.Name "vkGetDeviceQueue"}}true
+    {{else if eq $.Name "vkGetDeviceQueue2"}}true
     {{else if eq $.Name "vkAllocateCommandBuffers"}}true
 
     {{/* Destroy functions of dispatchable objects */}}
@@ -969,6 +972,7 @@
 
     {{/* We cache physical devices in loader.cpp */}}
     {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
 
     {{else if eq $.Name "vkGetInstanceProcAddr"}}true
     {{else if eq $.Name "vkGetDeviceProcAddr"}}true
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 947a2f7..ade0bde 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -880,19 +880,6 @@
     const VkAllocationCallbacks& data_allocator =
         (pAllocator) ? *pAllocator : GetDefaultAllocator();
 
-    if (pCreateInfo->pApplicationInfo &&
-        pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
-        ALOGI(
-            "Requested Vulkan instance version %d.%d is greater than max "
-            "supported version (1.0)",
-            VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion),
-            VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion));
-#pragma clang diagnostic pop
-        return VK_ERROR_INCOMPATIBLE_DRIVER;
-    }
-
     CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
     VkResult result = wrapper.Validate();
     if (result != VK_SUCCESS)
@@ -1056,6 +1043,28 @@
     return result;
 }
 
+VkResult EnumeratePhysicalDeviceGroups(
+    VkInstance instance,
+    uint32_t* pPhysicalDeviceGroupCount,
+    VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    const auto& data = GetData(instance);
+
+    VkResult result = data.driver.EnumeratePhysicalDeviceGroups(
+        instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+    if ((result == VK_SUCCESS || result == VK_INCOMPLETE) &&
+        *pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
+        for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
+            for (uint32_t j = 0;
+                 j < pPhysicalDeviceGroupProperties->physicalDeviceCount; j++) {
+                SetData(pPhysicalDeviceGroupProperties->physicalDevices[j],
+                        data);
+            }
+        }
+    }
+
+    return result;
+}
+
 void GetDeviceQueue(VkDevice device,
                     uint32_t queueFamilyIndex,
                     uint32_t queueIndex,
@@ -1066,6 +1075,15 @@
     SetData(*pQueue, data);
 }
 
+void GetDeviceQueue2(VkDevice device,
+                     const VkDeviceQueueInfo2* pQueueInfo,
+                     VkQueue* pQueue) {
+    const auto& data = GetData(device);
+
+    data.driver.GetDeviceQueue2(device, pQueueInfo, pQueue);
+    SetData(*pQueue, data);
+}
+
 VKAPI_ATTR VkResult
 AllocateCommandBuffers(VkDevice device,
                        const VkCommandBufferAllocateInfo* pAllocateInfo,
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 7f8ae98..57c956d 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -126,7 +126,10 @@
 VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
 
 VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
 VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
 VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
 // clang-format on
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 82b464e..c6e8a7a 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -75,6 +75,33 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+    } else {
+        Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkGetDeviceGroupPresentCapabilitiesKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+    } else {
+        Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkGetDeviceGroupSurfacePresentModesKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+    } else {
+        Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkAcquireNextImage2KHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
     if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
         return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
@@ -122,6 +149,13 @@
         nullptr,
     },
     {
+        "vkAcquireNextImage2KHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImage2KHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedAcquireNextImage2KHR),
+    },
+    {
         "vkAcquireNextImageKHR",
         ProcHook::DEVICE,
         ProcHook::KHR_swapchain,
@@ -227,6 +261,13 @@
         nullptr,
     },
     {
+        "vkEnumeratePhysicalDeviceGroups",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
+        nullptr,
+    },
+    {
         "vkEnumeratePhysicalDevices",
         ProcHook::INSTANCE,
         ProcHook::EXTENSION_CORE,
@@ -234,6 +275,20 @@
         nullptr,
     },
     {
+        "vkGetDeviceGroupPresentCapabilitiesKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPresentCapabilitiesKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceGroupPresentCapabilitiesKHR),
+    },
+    {
+        "vkGetDeviceGroupSurfacePresentModesKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupSurfacePresentModesKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceGroupSurfacePresentModesKHR),
+    },
+    {
         "vkGetDeviceProcAddr",
         ProcHook::DEVICE,
         ProcHook::EXTENSION_CORE,
@@ -248,6 +303,13 @@
         nullptr,
     },
     {
+        "vkGetDeviceQueue2",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
+        nullptr,
+    },
+    {
         "vkGetInstanceProcAddr",
         ProcHook::INSTANCE,
         ProcHook::EXTENSION_CORE,
@@ -262,6 +324,13 @@
         reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
     },
     {
+        "vkGetPhysicalDevicePresentRectanglesKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDevicePresentRectanglesKHR),
+        nullptr,
+    },
+    {
         "vkGetPhysicalDeviceSurfaceCapabilities2KHR",
         ProcHook::INSTANCE,
         ProcHook::KHR_get_surface_capabilities2,
@@ -423,6 +492,7 @@
     INIT_PROC(true, instance, GetPhysicalDeviceProperties);
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
     INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
@@ -445,6 +515,7 @@
     INIT_PROC(true, dev, CreateImage);
     INIT_PROC(true, dev, DestroyImage);
     INIT_PROC(true, dev, AllocateCommandBuffers);
+    INIT_PROC(false, dev, GetDeviceQueue2);
     INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsageANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID);
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 3b26a80..646662f 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -67,6 +67,7 @@
     PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
     PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
     PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
     PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
@@ -82,6 +83,7 @@
     PFN_vkCreateImage CreateImage;
     PFN_vkDestroyImage DestroyImage;
     PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+    PFN_vkGetDeviceQueue2 GetDeviceQueue2;
     PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
     PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     PFN_vkAcquireImageANDROID AcquireImageANDROID;
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 05856d3..3a59208 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -29,11 +29,10 @@
 #include <android/dlext.h>
 #include <android-base/strings.h>
 #include <cutils/properties.h>
+#include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
 #include <ziparchive/zip_archive.h>
 
-#include <vulkan/vulkan_loader_data.h>
-
 // TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
 // not a good long-term solution. Having a hard-coded enum of extensions is
 // bad, of course. Representing sets of extensions (requested, supported, etc.)
@@ -69,11 +68,16 @@
 
 class LayerLibrary {
    public:
-    explicit LayerLibrary(const std::string& path)
-        : path_(path), dlhandle_(nullptr), refcount_(0) {}
+    explicit LayerLibrary(const std::string& path,
+                          const std::string& filename)
+        : path_(path),
+          filename_(filename),
+          dlhandle_(nullptr),
+          refcount_(0) {}
 
     LayerLibrary(LayerLibrary&& other)
         : path_(std::move(other.path_)),
+          filename_(std::move(other.filename_)),
           dlhandle_(other.dlhandle_),
           refcount_(other.refcount_) {
         other.dlhandle_ = nullptr;
@@ -94,9 +98,14 @@
                  const char* gpa_name,
                  size_t gpa_name_len) const;
 
+    const std::string GetFilename() { return filename_; }
+
    private:
     const std::string path_;
 
+    // Track the filename alone so we can detect duplicates
+    const std::string filename_;
+
     std::mutex mutex_;
     void* dlhandle_;
     size_t refcount_;
@@ -111,7 +120,7 @@
         // any symbol dependencies will be resolved by system libraries. They
         // can't safely use libc++_shared, for example. Which is one reason
         // (among several) we only allow them in non-user builds.
-        auto app_namespace = LoaderData::GetInstance().app_namespace;
+        auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
         if (app_namespace &&
             !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
             android_dlextinfo dlextinfo = {};
@@ -305,8 +314,8 @@
 std::vector<LayerLibrary> g_layer_libraries;
 std::vector<Layer> g_instance_layers;
 
-void AddLayerLibrary(const std::string& path) {
-    LayerLibrary library(path);
+void AddLayerLibrary(const std::string& path, const std::string& filename) {
+    LayerLibrary library(path + "/" + filename, filename);
     if (!library.Open())
         return;
 
@@ -398,7 +407,25 @@
         ForEachFileInPath(path, [&](const std::string& filename) {
             if (android::base::StartsWith(filename, "libVkLayer") &&
                 android::base::EndsWith(filename, ".so")) {
-                AddLayerLibrary(path + "/" + filename);
+
+                // Check to ensure we haven't seen this layer already
+                // Let the first instance of the shared object be enumerated
+                // We're searching for layers in following order:
+                // 1. system path
+                // 2. libraryPermittedPath (if enabled)
+                // 3. libraryPath
+
+                bool duplicate = false;
+                for (auto& layer : g_layer_libraries) {
+                    if (layer.GetFilename() == filename) {
+                        ALOGV("Skipping duplicate layer %s in %s",
+                              filename.c_str(), path.c_str());
+                        duplicate = true;
+                    }
+                }
+
+                if (!duplicate)
+                    AddLayerLibrary(path, filename);
             }
         });
     }
@@ -428,8 +455,8 @@
         prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
         DiscoverLayersInPathList(kSystemLayerLibraryDir);
     }
-    if (!LoaderData::GetInstance().layer_path.empty())
-        DiscoverLayersInPathList(LoaderData::GetInstance().layer_path);
+    if (!android::GraphicsEnv::getInstance().getLayerPaths().empty())
+        DiscoverLayersInPathList(android::GraphicsEnv::getInstance().getLayerPaths());
 }
 
 uint32_t GetLayerCount() {
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 2926268..726e854 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -97,7 +97,7 @@
     return VK_SUCCESS;
 }
 
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
                                                   const char* name) {
     if (strcmp(name, "vkCreateInstance") == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
@@ -110,7 +110,9 @@
         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
-
+    // Per the spec, return NULL if instance is NULL.
+    if (!instance)
+        return nullptr;
     // None of the other Vulkan functions should ever be called, as they all
     // take a VkPhysicalDevice or other object obtained from a physical device.
     return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 665a32b..03e6ee0 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -23,9 +23,12 @@
 #include <utils/StrongPointer.h>
 #include <utils/Vector.h>
 #include <system/window.h>
+#include <android/hardware/graphics/common/1.0/types.h>
 
 #include "driver.h"
 
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
 // TODO(jessehall): Currently we don't have a good error code for when a native
 // window operation fails. Just returning INITIALIZATION_FAILED for now. Later
 // versions (post SDK 0.9) of the API/extension have a better error code.
@@ -771,6 +774,77 @@
 }
 
 VKAPI_ATTR
+VkResult GetDeviceGroupPresentCapabilitiesKHR(
+    VkDevice,
+    VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+    ALOGV_IF(pDeviceGroupPresentCapabilities->sType !=
+                 VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
+             "vkGetDeviceGroupPresentCapabilitiesKHR: invalid "
+             "VkDeviceGroupPresentCapabilitiesKHR structure type %d",
+             pDeviceGroupPresentCapabilities->sType);
+
+    memset(pDeviceGroupPresentCapabilities->presentMask, 0,
+           sizeof(pDeviceGroupPresentCapabilities->presentMask));
+
+    // assume device group of size 1
+    pDeviceGroupPresentCapabilities->presentMask[0] = 1 << 0;
+    pDeviceGroupPresentCapabilities->modes =
+        VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetDeviceGroupSurfacePresentModesKHR(
+    VkDevice,
+    VkSurfaceKHR,
+    VkDeviceGroupPresentModeFlagsKHR* pModes) {
+    *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
+                                               VkSurfaceKHR surface,
+                                               uint32_t* pRectCount,
+                                               VkRect2D* pRects) {
+    if (!pRects) {
+        *pRectCount = 1;
+    } else {
+        uint32_t count = std::min(*pRectCount, 1u);
+        bool incomplete = *pRectCount < 1;
+
+        *pRectCount = count;
+
+        if (incomplete) {
+            return VK_INCOMPLETE;
+        }
+
+        int err;
+        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+        int width = 0, height = 0;
+        err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+        if (err != 0) {
+            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+                  strerror(-err), err);
+        }
+        err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+        if (err != 0) {
+            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+                  strerror(-err), err);
+        }
+
+        // TODO: Return something better than "whole window"
+        pRects[0].offset.x = 0;
+        pRects[0].offset.y = 0;
+        pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
+                                      static_cast<uint32_t>(height)};
+    }
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
 VkResult CreateSwapchainKHR(VkDevice device,
                             const VkSwapchainCreateInfoKHR* create_info,
                             const VkAllocationCallbacks* allocator,
@@ -996,7 +1070,7 @@
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    int gralloc_usage = 0;
+    int32_t legacy_usage = 0;
     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
         uint64_t consumer_usage, producer_usage;
         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
@@ -1006,18 +1080,25 @@
             ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
             return VK_ERROR_SURFACE_LOST_KHR;
         }
-        gralloc_usage =
+        legacy_usage =
             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
         result = dispatch.GetSwapchainGrallocUsageANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
-            &gralloc_usage);
+            &legacy_usage);
         if (result != VK_SUCCESS) {
             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
             return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
-    err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage));
+    uint64_t native_usage = static_cast<uint64_t>(legacy_usage);
+
+    bool createProtectedSwapchain = false;
+    if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {
+        createProtectedSwapchain = true;
+        native_usage |= BufferUsage::PROTECTED;
+    }
+    err = native_window_set_usage(surface.window.get(), native_usage);
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
@@ -1065,7 +1146,7 @@
         .samples = VK_SAMPLE_COUNT_1_BIT,
         .tiling = VK_IMAGE_TILING_OPTIMAL,
         .usage = create_info->imageUsage,
-        .flags = 0,
+        .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
         .sharingMode = create_info->imageSharingMode,
         .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
@@ -1273,6 +1354,17 @@
     return VK_SUCCESS;
 }
 
+VKAPI_ATTR
+VkResult AcquireNextImage2KHR(VkDevice device,
+                              const VkAcquireNextImageInfoKHR* pAcquireInfo,
+                              uint32_t* pImageIndex) {
+    // TODO: this should actually be the other way around and this function
+    // should handle any additional structures that get passed in
+    return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
+                               pAcquireInfo->timeout, pAcquireInfo->semaphore,
+                               pAcquireInfo->fence, pImageIndex);
+}
+
 static VkResult WorstPresentResult(VkResult a, VkResult b) {
     // See the error ranking for vkQueuePresentKHR at the end of section 29.6
     // (in spec version 1.0.14).
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index e3cf624..ed5718c 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -29,11 +29,15 @@
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface_handle, uint32_t* count, VkSurfaceFormatKHR* formats);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
 VKAPI_ATTR VkResult CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
 VKAPI_ATTR void DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
 VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
 VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
 VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
 VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
 VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
 VKAPI_ATTR VkResult GetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain);
diff --git a/vulkan/libvulkan/vulkan_loader_data.cpp b/vulkan/libvulkan/vulkan_loader_data.cpp
deleted file mode 100644
index 0eda0af..0000000
--- a/vulkan/libvulkan/vulkan_loader_data.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2015 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 <vulkan/vulkan_loader_data.h>
-
-using namespace vulkan;
-
-LoaderData& LoaderData::GetInstance() {
-    static LoaderData loader_data = {};
-    return loader_data;
-}
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index b4ca42c..4647a80 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -16,6 +16,7 @@
 
 #include <hardware/hwvulkan.h>
 
+#include <errno.h>
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
@@ -258,6 +259,12 @@
 // Global
 
 VKAPI_ATTR
+VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
+    *pApiVersion = VK_API_VERSION_1_1;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
 VkResult EnumerateInstanceExtensionProperties(
     const char* layer_name,
     uint32_t* count,
@@ -1474,6 +1481,93 @@
 void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage) {
 }
 
+VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+    return VK_SUCCESS;
+}
+
+VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    return VK_SUCCESS;
+}
+
+void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+}
+
+void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+}
+
+void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+}
+
+VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return VK_SUCCESS;
+}
+
+void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+}
+
+void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+}
+
+void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+}
+
+void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+}
+
+VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+    return VK_SUCCESS;
+}
+
+void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+}
+
+void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+}
+
+void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+}
+
+void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+}
+
+void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+}
+
+VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return VK_SUCCESS;
+}
+
+void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+}
+
+VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return VK_SUCCESS;
+}
+
+void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+}
+
+void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+}
+
+void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+}
+
+void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+}
+
+void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+}
+
+void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+}
+
 #pragma clang diagnostic pop
 // clang-format on
 
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 25ee65a..92b7468 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -49,6 +49,7 @@
     {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance))},
     {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
     {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+    {"vkEnumerateInstanceVersion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceVersion>(EnumerateInstanceVersion))},
     // clang-format on
 };
 
@@ -60,7 +61,9 @@
     {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateMemory>(AllocateMemory))},
     {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBeginCommandBuffer>(BeginCommandBuffer))},
     {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindBufferMemory>(BindBufferMemory))},
+    {"vkBindBufferMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindBufferMemory2>(BindBufferMemory2))},
     {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindImageMemory>(BindImageMemory))},
+    {"vkBindImageMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindImageMemory2>(BindImageMemory2))},
     {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginQuery>(CmdBeginQuery))},
     {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginRenderPass>(CmdBeginRenderPass))},
     {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindDescriptorSets>(CmdBindDescriptorSets))},
@@ -77,6 +80,7 @@
     {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyImageToBuffer>(CmdCopyImageToBuffer))},
     {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyQueryPoolResults>(CmdCopyQueryPoolResults))},
     {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatch>(CmdDispatch))},
+    {"vkCmdDispatchBase", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatchBase>(CmdDispatchBase))},
     {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatchIndirect>(CmdDispatchIndirect))},
     {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDraw>(CmdDraw))},
     {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDrawIndexed>(CmdDrawIndexed))},
@@ -95,6 +99,7 @@
     {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetBlendConstants>(CmdSetBlendConstants))},
     {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBias>(CmdSetDepthBias))},
     {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBounds>(CmdSetDepthBounds))},
+    {"vkCmdSetDeviceMask", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDeviceMask>(CmdSetDeviceMask))},
     {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetEvent>(CmdSetEvent))},
     {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetLineWidth>(CmdSetLineWidth))},
     {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetScissor>(CmdSetScissor))},
@@ -112,6 +117,7 @@
     {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT))},
     {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorPool>(CreateDescriptorPool))},
     {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorSetLayout>(CreateDescriptorSetLayout))},
+    {"vkCreateDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorUpdateTemplate>(CreateDescriptorUpdateTemplate))},
     {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice))},
     {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateEvent>(CreateEvent))},
     {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateFence>(CreateFence))},
@@ -125,6 +131,7 @@
     {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateQueryPool>(CreateQueryPool))},
     {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateRenderPass>(CreateRenderPass))},
     {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSampler>(CreateSampler))},
+    {"vkCreateSamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSamplerYcbcrConversion>(CreateSamplerYcbcrConversion))},
     {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSemaphore>(CreateSemaphore))},
     {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateShaderModule>(CreateShaderModule))},
     {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT))},
@@ -134,6 +141,7 @@
     {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT))},
     {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorPool>(DestroyDescriptorPool))},
     {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorSetLayout>(DestroyDescriptorSetLayout))},
+    {"vkDestroyDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorUpdateTemplate>(DestroyDescriptorUpdateTemplate))},
     {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice))},
     {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyEvent>(DestroyEvent))},
     {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyFence>(DestroyFence))},
@@ -147,6 +155,7 @@
     {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyQueryPool>(DestroyQueryPool))},
     {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyRenderPass>(DestroyRenderPass))},
     {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySampler>(DestroySampler))},
+    {"vkDestroySamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySamplerYcbcrConversion>(DestroySamplerYcbcrConversion))},
     {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySemaphore>(DestroySemaphore))},
     {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyShaderModule>(DestroyShaderModule))},
     {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDeviceWaitIdle>(DeviceWaitIdle))},
@@ -155,34 +164,52 @@
     {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties))},
     {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
     {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+    {"vkEnumerateInstanceVersion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceVersion>(EnumerateInstanceVersion))},
+    {"vkEnumeratePhysicalDeviceGroups", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDeviceGroups>(EnumeratePhysicalDeviceGroups))},
     {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices))},
     {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFlushMappedMemoryRanges>(FlushMappedMemoryRanges))},
     {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeCommandBuffers>(FreeCommandBuffers))},
     {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeDescriptorSets>(FreeDescriptorSets))},
     {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeMemory>(FreeMemory))},
     {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetBufferMemoryRequirements>(GetBufferMemoryRequirements))},
+    {"vkGetBufferMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetBufferMemoryRequirements2>(GetBufferMemoryRequirements2))},
+    {"vkGetDescriptorSetLayoutSupport", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDescriptorSetLayoutSupport>(GetDescriptorSetLayoutSupport))},
+    {"vkGetDeviceGroupPeerMemoryFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceGroupPeerMemoryFeatures>(GetDeviceGroupPeerMemoryFeatures))},
     {"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceMemoryCommitment))},
     {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr))},
     {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue))},
+    {"vkGetDeviceQueue2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue2>(GetDeviceQueue2))},
     {"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetEventStatus>(GetEventStatus))},
     {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetFenceStatus>(GetFenceStatus))},
     {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageMemoryRequirements>(GetImageMemoryRequirements))},
+    {"vkGetImageMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageMemoryRequirements2>(GetImageMemoryRequirements2))},
     {"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSparseMemoryRequirements>(GetImageSparseMemoryRequirements))},
+    {"vkGetImageSparseMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSparseMemoryRequirements2>(GetImageSparseMemoryRequirements2))},
     {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSubresourceLayout>(GetImageSubresourceLayout))},
     {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr))},
+    {"vkGetPhysicalDeviceExternalBufferProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalBufferProperties>(GetPhysicalDeviceExternalBufferProperties))},
+    {"vkGetPhysicalDeviceExternalFenceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>(GetPhysicalDeviceExternalFenceProperties))},
+    {"vkGetPhysicalDeviceExternalSemaphoreProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>(GetPhysicalDeviceExternalSemaphoreProperties))},
     {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures))},
+    {"vkGetPhysicalDeviceFeatures2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures2>(GetPhysicalDeviceFeatures2))},
     {"vkGetPhysicalDeviceFeatures2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(GetPhysicalDeviceFeatures2KHR))},
     {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties))},
+    {"vkGetPhysicalDeviceFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(GetPhysicalDeviceFormatProperties2))},
     {"vkGetPhysicalDeviceFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(GetPhysicalDeviceFormatProperties2KHR))},
     {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties))},
+    {"vkGetPhysicalDeviceImageFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(GetPhysicalDeviceImageFormatProperties2))},
     {"vkGetPhysicalDeviceImageFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(GetPhysicalDeviceImageFormatProperties2KHR))},
     {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties))},
+    {"vkGetPhysicalDeviceMemoryProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties2>(GetPhysicalDeviceMemoryProperties2))},
     {"vkGetPhysicalDeviceMemoryProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(GetPhysicalDeviceMemoryProperties2KHR))},
     {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties))},
+    {"vkGetPhysicalDeviceProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties2>(GetPhysicalDeviceProperties2))},
     {"vkGetPhysicalDeviceProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(GetPhysicalDeviceProperties2KHR))},
     {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties))},
+    {"vkGetPhysicalDeviceQueueFamilyProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2>(GetPhysicalDeviceQueueFamilyProperties2))},
     {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(GetPhysicalDeviceQueueFamilyProperties2KHR))},
     {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties))},
+    {"vkGetPhysicalDeviceSparseImageFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2>(GetPhysicalDeviceSparseImageFormatProperties2))},
     {"vkGetPhysicalDeviceSparseImageFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(GetPhysicalDeviceSparseImageFormatProperties2KHR))},
     {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPipelineCacheData>(GetPipelineCacheData))},
     {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetQueryPoolResults>(GetQueryPoolResults))},
@@ -202,7 +229,9 @@
     {"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetEvent>(ResetEvent))},
     {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetFences>(ResetFences))},
     {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSetEvent>(SetEvent))},
+    {"vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkTrimCommandPool>(TrimCommandPool))},
     {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUnmapMemory>(UnmapMemory))},
+    {"vkUpdateDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUpdateDescriptorSetWithTemplate>(UpdateDescriptorSetWithTemplate))},
     {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUpdateDescriptorSets>(UpdateDescriptorSets))},
     {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkWaitForFences>(WaitForFences))},
     // clang-format on
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 8a9a963..c6ad537 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -165,6 +165,34 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int32_t* grallocUsage);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);