Merge "Refactor setInputWindows"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 5836f11..587d25f 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -62,7 +62,7 @@
 
 using std::string;
 
-#define MAX_SYS_FILES 10
+#define MAX_SYS_FILES 11
 
 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
 const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
@@ -133,7 +133,11 @@
         { OPT,      "events/sched/sched_blocked_reason/enable" },
         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
         { OPT,      "events/sched/sched_pi_setprio/enable" },
+        { OPT,      "events/sched/sched_process_exit/enable" },
         { OPT,      "events/cgroup/enable" },
+        { OPT,      "events/oom/oom_score_adj_update/enable" },
+        { OPT,      "events/task/task_rename/enable" },
+        { OPT,      "events/task/task_newtask/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "events/irq/enable" },
@@ -231,10 +235,6 @@
         { OPT,      "events/kmem/rss_stat/enable" },
         { OPT,      "events/kmem/ion_heap_grow/enable" },
         { OPT,      "events/kmem/ion_heap_shrink/enable" },
-        { OPT,      "events/oom/oom_score_adj_update/enable" },
-        { OPT,      "events/sched/sched_process_exit/enable" },
-        { OPT,      "events/task/task_rename/enable" },
-        { OPT,      "events/task/task_newtask/enable" },
     } },
 };
 
@@ -890,6 +890,7 @@
     setTagsProperty(0);
     clearAppProperties();
     pokeBinderServices();
+    pokeHalServices();
 
     if (g_tracePdx) {
         ServiceUtility::PokeServices();
@@ -1466,10 +1467,11 @@
 
     // Reset the trace buffer size to 1.
     if (traceStop) {
-        cleanUpVendorTracing();
         cleanUpUserspaceTracing();
-        if (!onlyUserspace)
+        if (!onlyUserspace) {
+            cleanUpVendorTracing();
             cleanUpKernelTracing();
+        }
     }
 
     return g_traceAborted ? 1 : 0;
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 66c9cc6..f1426b6 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -33,6 +33,10 @@
     chmod 0666 /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
     chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_pi_setprio/enable
     chmod 0666 /sys/kernel/tracing/events/sched/sched_pi_setprio/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_process_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable
     chmod 0666 /sys/kernel/tracing/events/cgroup/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
@@ -43,6 +47,8 @@
     chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
     chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
+    chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
     chmod 0666 /sys/kernel/tracing/events/cpufreq_interactive/enable
     chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 917c813..840ae47 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -37,7 +37,7 @@
   property_set("ctl.start", "dumpstate");
 
   // Socket will not be available until service starts.
-  int s;
+  int s = -1;
   for (int i = 0; i < 20; i++) {
     s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
                             SOCK_STREAM);
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index 74a95b0..40346be 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -72,7 +72,7 @@
     property_set("ctl.start", "dumpstatez");
 
     // Socket will not be available until service starts.
-    int s;
+    int s = -1;
     for (int i = 0; i < 20; i++) {
         s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
         if (s >= 0) break;
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index ee32cb4..8d383f5 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -86,6 +86,7 @@
         "libdumpstateaidl",
         "libdumpstateutil",
         "libdumputils",
+        "libhardware_legacy",
         "libhidlbase",
         "libhidltransport",
         "liblog",
@@ -94,7 +95,6 @@
     srcs: [
         "DumpstateSectionReporter.cpp",
         "DumpstateService.cpp",
-        "utils.cpp",
     ],
     static_libs: [
         "libincidentcompanion",
@@ -123,7 +123,6 @@
         "lsmod",
         "lsof",
         "netstat",
-        "parse_radio_log",
         "printenv",
         "procrank",
         "screencap",
@@ -146,6 +145,12 @@
         "tests/dumpstate_test.cpp",
     ],
     static_libs: ["libgmock"],
+    test_config: "dumpstate_test.xml",
+    data: [
+        ":dumpstate_test_fixture",
+        "tests/testdata/**/*",
+    ],
+    test_suites: ["device-tests"],
 }
 
 cc_test {
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index 33e35f7..bbc724c 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -68,7 +68,8 @@
     }
 
     static const std::vector<std::string> group_names{
-        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats", "readproc", "bluetooth"};
+        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats",
+            "readproc", "bluetooth", "wakelock"};
     std::vector<gid_t> groups(group_names.size(), 0);
     for (size_t i = 0; i < group_names.size(); ++i) {
         grp = getgrnam(group_names[i].c_str());
@@ -116,6 +117,11 @@
         capdata[cap_syslog_index].effective |= cap_syslog_mask;
     }
 
+    const uint32_t cap_block_suspend_mask = CAP_TO_MASK(CAP_BLOCK_SUSPEND);
+    const uint32_t cap_block_suspend_index = CAP_TO_INDEX(CAP_BLOCK_SUSPEND);
+    capdata[cap_block_suspend_index].permitted |= cap_block_suspend_mask;
+    capdata[cap_block_suspend_index].effective |= cap_block_suspend_mask;
+
     if (capset(&capheader, &capdata[0]) != 0) {
         MYLOGE("capset({%#x, %#x}) failed: %s\n", capdata[0].effective,
                capdata[1].effective, strerror(errno));
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index ddae9ea..37ba4f9 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -151,15 +151,15 @@
         signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
     }
 
-    if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
-        // TODO(b/111441001): screenshot fd should be optional
+    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
+    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+                        screenshot_fd);
+
+    if (bugreport_fd.get() == -1 || (options->do_fb && screenshot_fd.get() == -1)) {
         MYLOGE("Invalid filedescriptor");
         signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
     }
 
-    std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
-    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
-                        screenshot_fd);
 
     ds_ = &(Dumpstate::GetInstance());
     ds_->SetOptions(std::move(options));
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 97c8ae2..4b69607 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -378,34 +378,6 @@
     return status;
 }
 
-int GetPidByName(const std::string& ps_name) {
-    DIR* proc_dir;
-    struct dirent* ps;
-    unsigned int pid;
-    std::string cmdline;
-
-    if (!(proc_dir = opendir("/proc"))) {
-        MYLOGE("Can't open /proc\n");
-        return -1;
-    }
-
-    while ((ps = readdir(proc_dir))) {
-        if (!(pid = atoi(ps->d_name))) {
-            continue;
-        }
-        android::base::ReadFileToString("/proc/" + std::string(ps->d_name) + "/cmdline", &cmdline);
-        if (cmdline.find(ps_name) == std::string::npos) {
-            continue;
-        } else {
-            closedir(proc_dir);
-            return pid;
-        }
-    }
-    MYLOGE("can't find the pid\n");
-    closedir(proc_dir);
-    return -1;
-}
-
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index d75b08c..b7ac25c 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -205,12 +205,6 @@
  */
 int DumpFileToFd(int fd, const std::string& title, const std::string& path);
 
-/*
- * Finds the process id by process name.
- * |ps_name| the process name we want to search for
- */
-int GetPidByName(const std::string& ps_name);
-
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index c818c05..26dabbb 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -92,6 +92,12 @@
 adb shell setprop dumpstate.version default
 ```
 
+## To set Bugreport API workflow for bugreport
+
+```
+adb shell setprop settings_call_bugreport_api true
+```
+
 ## Code style and formatting
 
 Use the style defined at the
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
new file mode 100644
index 0000000..083944f
--- /dev/null
+++ b/cmds/dumpstate/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "dumpstate_test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 347856d..cb2d8b8 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -73,7 +73,7 @@
      * @param callingUid UID of the original application that requested the report.
      * @param callingPackage package of the original application that requested the report.
      * @param bugreportFd the file to which the zipped bugreport should be written
-     * @param screenshotFd the file to which screenshot should be written; optional
+     * @param screenshotFd the file to which screenshot should be written
      * @param bugreportMode the mode that specifies other run time options; must be one of above
      * @param listener callback for updates; optional
      */
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 2cc1b32..1416629 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -19,8 +19,11 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <libgen.h>
 #include <limits.h>
+#include <math.h>
+#include <poll.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,6 +34,13 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/wait.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/inotify.h>
+#include <sys/klog.h>
+#include <time.h>
 #include <unistd.h>
 
 #include <chrono>
@@ -50,15 +60,20 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <android/content/pm/IPackageManagerNative.h>
 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android/os/IIncidentCompanion.h>
+#include <binder/IServiceManager.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
+#include <cutils/sockets.h>
 #include <debuggerd/client.h>
 #include <dumpsys.h>
 #include <dumputils/dump_utils.h>
+#include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
+#include <log/log.h>
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
@@ -91,9 +106,28 @@
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
 using android::os::dumpstate::DumpstateSectionReporter;
-using android::os::dumpstate::GetPidByName;
 using android::os::dumpstate::PropertiesHelper;
 
+// Keep in sync with
+// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
+
+/* Most simple commands have 10 as timeout, so 5 is a good estimate */
+static const int32_t WEIGHT_FILE = 5;
+
+// TODO: temporary variables and functions used during C++ refactoring
+static Dumpstate& ds = Dumpstate::GetInstance();
+static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+                      const CommandOptions& options = CommandOptions::DEFAULT) {
+    return ds.RunCommand(title, full_command, options);
+}
+
+// Reasonable value for max stats.
+static const int STATS_MAX_N_RUNS = 1000;
+static const long STATS_MAX_AVERAGE = 100000;
+
+CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
+
 typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
 
 /* read before root is shed */
@@ -130,7 +164,6 @@
 static const std::string ANR_FILE_PREFIX = "anr_";
 
 // TODO: temporary variables and functions used during C++ refactoring
-static Dumpstate& ds = Dumpstate::GetInstance();
 
 #define RETURN_IF_USER_DENIED_CONSENT()                                                        \
     if (ds.IsUserConsentDenied()) {                                                            \
@@ -145,6 +178,8 @@
     func_ptr(__VA_ARGS__);                                  \
     RETURN_IF_USER_DENIED_CONSENT();
 
+static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
+
 namespace android {
 namespace os {
 namespace {
@@ -204,14 +239,34 @@
     return file.tellg() <= 0;
 }
 
+int64_t GetModuleMetadataVersion() {
+    auto binder = defaultServiceManager()->getService(android::String16("package_native"));
+    if (binder == nullptr) {
+        MYLOGE("Failed to retrieve package_native service");
+        return 0L;
+    }
+    auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
+    std::string package_name;
+    auto status = package_service->getModuleMetadataPackageName(&package_name);
+    if (!status.isOk()) {
+        MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
+        return 0L;
+    }
+    MYLOGD("Module metadata package name: %s", package_name.c_str());
+    int64_t version_code;
+    status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
+                                                       &version_code);
+    if (!status.isOk()) {
+        MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
+        return 0L;
+    }
+    return version_code;
+}
+
 }  // namespace
 }  // namespace os
 }  // namespace android
 
-static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
-                      const CommandOptions& options = CommandOptions::DEFAULT) {
-    return ds.RunCommand(title, fullCommand, options);
-}
 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
                        long dumpsysTimeoutMs = 0) {
@@ -394,108 +449,6 @@
     closedir(d);
 }
 
-
-
-// dump anrd's trace and add to the zip file.
-// 1. check if anrd is running on this device.
-// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
-// 3. wait until the trace generation completes and add to the zip file.
-static bool dump_anrd_trace() {
-    unsigned int pid;
-    char buf[50], path[PATH_MAX];
-    struct dirent *trace;
-    struct stat st;
-    DIR *trace_dir;
-    int retry = 5;
-    long max_ctime = 0, old_mtime;
-    long long cur_size = 0;
-    const char *trace_path = "/data/misc/anrd/";
-
-    if (!ds.IsZipping()) {
-        MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
-        return false;
-    }
-
-    // find anrd's pid if it is running.
-    pid = GetPidByName("/system/bin/anrd");
-
-    if (pid > 0) {
-        if (stat(trace_path, &st) == 0) {
-            old_mtime = st.st_mtime;
-        } else {
-            MYLOGE("Failed to find: %s\n", trace_path);
-            return false;
-        }
-
-        // send SIGUSR1 to the anrd to generate a trace.
-        sprintf(buf, "%u", pid);
-        if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
-                       CommandOptions::WithTimeout(1).Build())) {
-            MYLOGE("anrd signal timed out. Please manually collect trace\n");
-            return false;
-        }
-
-        while (retry-- > 0 && old_mtime == st.st_mtime) {
-            sleep(1);
-            stat(trace_path, &st);
-        }
-
-        if (retry < 0 && old_mtime == st.st_mtime) {
-            MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
-            return false;
-        }
-
-        // identify the trace file by its creation time.
-        if (!(trace_dir = opendir(trace_path))) {
-            MYLOGE("Can't open trace file under %s\n", trace_path);
-        }
-        while ((trace = readdir(trace_dir))) {
-            if (strcmp(trace->d_name, ".") == 0
-                    || strcmp(trace->d_name, "..") == 0) {
-                continue;
-            }
-            sprintf(path, "%s%s", trace_path, trace->d_name);
-            if (stat(path, &st) == 0) {
-                if (st.st_ctime > max_ctime) {
-                    max_ctime = st.st_ctime;
-                    sprintf(buf, "%s", trace->d_name);
-                }
-            }
-        }
-        closedir(trace_dir);
-
-        // Wait until the dump completes by checking the size of the trace.
-        if (max_ctime > 0) {
-            sprintf(path, "%s%s", trace_path, buf);
-            while(true) {
-                sleep(1);
-                if (stat(path, &st) == 0) {
-                    if (st.st_size == cur_size) {
-                        break;
-                    } else if (st.st_size > cur_size) {
-                        cur_size = st.st_size;
-                    } else {
-                        return false;
-                    }
-                } else {
-                    MYLOGE("Cant stat() %s anymore\n", path);
-                    return false;
-                }
-            }
-            // Add to the zip file.
-            if (!ds.AddZipEntry("anrd_trace.txt", path)) {
-                MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
-            } else {
-                android::os::UnlinkAndLogOnError(path);
-                return true;
-            }
-        } else {
-            MYLOGE("Can't stats any trace file under %s\n", trace_path);
-        }
-    }
-    return false;
-}
-
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -741,6 +694,10 @@
     printf("Bootloader: %s\n", bootloader.c_str());
     printf("Radio: %s\n", radio.c_str());
     printf("Network: %s\n", network.c_str());
+    int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
+    if (module_metadata_version != 0) {
+        printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
+    }
 
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -1232,7 +1189,7 @@
     }
     DurationReporter duration_reporter("DUMP HALS");
     RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
-               CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+               CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
 
     using android::hidl::manager::V1_0::IServiceManager;
     using android::hardware::defaultServiceManager;
@@ -1349,7 +1306,7 @@
     /* Dump Bluetooth HCI logs */
     ds.AddDir("/data/misc/bluetooth/logs", true);
 
-    if (!ds.do_early_screenshot_) {
+    if (ds.options_->do_fb && !ds.do_early_screenshot_) {
         MYLOGI("taking late screenshot\n");
         ds.TakeScreenshot();
     }
@@ -1388,8 +1345,6 @@
 
     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
 
-    RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
-
     /* Binder state is expensive to look at as it uses a lot of memory. */
     DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
     DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
@@ -1397,7 +1352,6 @@
     DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
     DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
 
-    RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
     /* Add window and surface trace files. */
     if (!PropertiesHelper::IsUserBuild()) {
         ds.AddDir(WMTRACE_DATA_DIR, false);
@@ -1508,9 +1462,6 @@
  * with the caller.
  */
 static Dumpstate::RunStatus DumpstateDefault() {
-    // Try to dump anrd trace if the daemon is running.
-    dump_anrd_trace();
-
     // Invoking the following dumpsys calls before DumpTraces() to try and
     // keep the system stats as close to its initial state as possible.
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
@@ -1872,22 +1823,21 @@
 
 static void ShowUsage() {
     fprintf(stderr,
-            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
+            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
             "  -h: display this help message\n"
             "  -b: play sound file instead of vibrate, at beginning of job\n"
             "  -e: play sound file instead of vibrate, at end of job\n"
-            "  -o: write to file (instead of stdout)\n"
-            "  -d: append date to filename (requires -o)\n"
-            "  -p: capture screenshot to filename.png (requires -o)\n"
-            "  -z: generate zipped file (requires -o)\n"
+            "  -d: append date to filename\n"
+            "  -p: capture screenshot to filename.png\n"
+            "  -z: generate zipped file\n"
             "  -s: write output to control socket (for init)\n"
-            "  -S: write file location to control socket (for init; requires -o and -z)\n"
+            "  -S: write file location to control socket (for init; requires -z)\n"
             "  -q: disable vibrate\n"
-            "  -B: send broadcast when finished (requires -o)\n"
+            "  -B: send broadcast when finished\n"
             "  -P: send broadcast when started and update system properties on "
-            "progress (requires -o and -B)\n"
-            "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
+            "progress (requires -B)\n"
+            "  -R: take bugreport in remote mode (requires -z, -d and -B, "
             "shouldn't be used with -P)\n"
             "  -w: start binder service and make it wait for a call to startBugreport\n"
             "  -v: prints the dumpstate header and exit\n");
@@ -2371,7 +2321,6 @@
         }
     }
 
-    // TODO: use helper function to convert argv into a string
     for (int i = 0; i < argc; i++) {
         args += argv[i];
         if (i < argc - 1) {
@@ -2522,6 +2471,13 @@
 
     MYLOGI("begin\n");
 
+    if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
+        MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
+    } else {
+        // Wake lock will be released automatically on process death
+        MYLOGD("Wake lock acquired.\n");
+    }
+
     register_sig_handler();
 
     // TODO(b/111441001): maybe skip if already started?
@@ -2595,13 +2551,8 @@
     }
 
     if (options_->do_fb && do_early_screenshot_) {
-        if (screenshot_path_.empty()) {
-            // should not have happened
-            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
-        } else {
-            MYLOGI("taking early screenshot\n");
-            TakeScreenshot();
-        }
+        MYLOGI("taking early screenshot\n");
+        TakeScreenshot();
     }
 
     if (options_->do_zip_file && zip_file != nullptr) {
@@ -2697,7 +2648,15 @@
             MYLOGI(
                 "Did not receive user consent yet."
                 " Will not copy the bugreport artifacts to caller.\n");
-            // TODO(b/111441001): cancel outstanding requests
+            const String16 incidentcompanion("incidentcompanion");
+            sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
+            if (ics != nullptr) {
+                MYLOGD("Canceling user consent request via incidentcompanion service\n");
+                android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
+                        consent_callback_.get());
+            } else {
+                MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
+            }
         }
     }
 
@@ -2845,3 +2804,947 @@
             exit(2);
     }
 }
+
+// TODO(111441001): Default DumpOptions to sensible values.
+Dumpstate::Dumpstate(const std::string& version)
+    : pid_(getpid()),
+      options_(new Dumpstate::DumpOptions()),
+      version_(version),
+      now_(time(nullptr)) {
+}
+
+Dumpstate& Dumpstate::GetInstance() {
+    static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
+    return singleton_;
+}
+
+DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
+    : title_(title), logcat_only_(logcat_only) {
+    if (!title_.empty()) {
+        started_ = Nanotime();
+    }
+}
+
+DurationReporter::~DurationReporter() {
+    if (!title_.empty()) {
+        float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
+        if (elapsed < .5f) {
+            return;
+        }
+        MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
+        if (logcat_only_) {
+            return;
+        }
+        // Use "Yoda grammar" to make it easier to grep|sort sections.
+        printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
+    }
+}
+
+const int32_t Progress::kDefaultMax = 5000;
+
+Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
+}
+
+Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
+    : Progress(initial_max, growth_factor, "") {
+    progress_ = progress;
+}
+
+Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
+    : initial_max_(initial_max),
+      progress_(0),
+      max_(initial_max),
+      growth_factor_(growth_factor),
+      n_runs_(0),
+      average_max_(0),
+      path_(path) {
+    if (!path_.empty()) {
+        Load();
+    }
+}
+
+void Progress::Load() {
+    MYLOGD("Loading stats from %s\n", path_.c_str());
+    std::string content;
+    if (!android::base::ReadFileToString(path_, &content)) {
+        MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
+        return;
+    }
+    if (content.empty()) {
+        MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
+        return;
+    }
+    std::vector<std::string> lines = android::base::Split(content, "\n");
+
+    if (lines.size() < 1) {
+        MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
+               (int)lines.size(), max_);
+        return;
+    }
+    char* ptr;
+    n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
+    average_max_ = strtol(ptr, nullptr, 10);
+    if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
+        average_max_ > STATS_MAX_AVERAGE) {
+        MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
+        initial_max_ = Progress::kDefaultMax;
+    } else {
+        initial_max_ = average_max_;
+    }
+    max_ = initial_max_;
+
+    MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
+}
+
+void Progress::Save() {
+    int32_t total = n_runs_ * average_max_ + progress_;
+    int32_t runs = n_runs_ + 1;
+    int32_t average = floor(((float)total) / runs);
+    MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
+           path_.c_str());
+    if (path_.empty()) {
+        return;
+    }
+
+    std::string content = android::base::StringPrintf("%d %d\n", runs, average);
+    if (!android::base::WriteStringToFile(content, path_)) {
+        MYLOGE("Could not save stats on %s\n", path_.c_str());
+    }
+}
+
+int32_t Progress::Get() const {
+    return progress_;
+}
+
+bool Progress::Inc(int32_t delta_sec) {
+    bool changed = false;
+    if (delta_sec >= 0) {
+        progress_ += delta_sec;
+        if (progress_ > max_) {
+            int32_t old_max = max_;
+            max_ = floor((float)progress_ * growth_factor_);
+            MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
+            changed = true;
+        }
+    }
+    return changed;
+}
+
+int32_t Progress::GetMax() const {
+    return max_;
+}
+
+int32_t Progress::GetInitialMax() const {
+    return initial_max_;
+}
+
+void Progress::Dump(int fd, const std::string& prefix) const {
+    const char* pr = prefix.c_str();
+    dprintf(fd, "%sprogress: %d\n", pr, progress_);
+    dprintf(fd, "%smax: %d\n", pr, max_);
+    dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
+    dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
+    dprintf(fd, "%spath: %s\n", pr, path_.c_str());
+    dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
+    dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
+}
+
+bool Dumpstate::IsZipping() const {
+    return zip_writer_ != nullptr;
+}
+
+std::string Dumpstate::GetPath(const std::string& suffix) const {
+    return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+    return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
+                                       name_.c_str(), suffix.c_str());
+}
+
+void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
+    progress_ = std::move(progress);
+}
+
+void for_each_userid(void (*func)(int), const char *header) {
+    std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
+                                                                    "for_each_userid(%s)", header);
+    DurationReporter duration_reporter(title);
+    if (PropertiesHelper::IsDryRun()) return;
+
+    DIR *d;
+    struct dirent *de;
+
+    if (header) printf("\n------ %s ------\n", header);
+    func(0);
+
+    if (!(d = opendir("/data/system/users"))) {
+        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        int userid;
+        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
+            continue;
+        }
+        func(userid);
+    }
+
+    closedir(d);
+}
+
+static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
+    DIR *d;
+    struct dirent *de;
+
+    if (!(d = opendir("/proc"))) {
+        printf("Failed to open /proc (%s)\n", strerror(errno));
+        return;
+    }
+
+    if (header) printf("\n------ %s ------\n", header);
+    while ((de = readdir(d))) {
+        if (ds.IsUserConsentDenied()) {
+            MYLOGE(
+                "Returning early because user denied consent to share bugreport with calling app.");
+            closedir(d);
+            return;
+        }
+        int pid;
+        int fd;
+        char cmdpath[255];
+        char cmdline[255];
+
+        if (!(pid = atoi(de->d_name))) {
+            continue;
+        }
+
+        memset(cmdline, 0, sizeof(cmdline));
+
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
+            close(fd);
+            if (cmdline[0]) {
+                helper(pid, cmdline, arg);
+                continue;
+            }
+        }
+
+        // if no cmdline, a kernel thread has comm
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
+            close(fd);
+            if (cmdline[1]) {
+                cmdline[0] = '[';
+                size_t len = strcspn(cmdline, "\f\b\r\n");
+                cmdline[len] = ']';
+                cmdline[len+1] = '\0';
+            }
+        }
+        if (!cmdline[0]) {
+            strcpy(cmdline, "N/A");
+        }
+        helper(pid, cmdline, arg);
+    }
+
+    closedir(d);
+}
+
+static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
+    for_each_pid_func *func = (for_each_pid_func*) arg;
+    func(pid, cmdline);
+}
+
+void for_each_pid(for_each_pid_func func, const char *header) {
+    std::string title = header == nullptr ? "for_each_pid"
+                                          : android::base::StringPrintf("for_each_pid(%s)", header);
+    DurationReporter duration_reporter(title);
+    if (PropertiesHelper::IsDryRun()) return;
+
+    __for_each_pid(for_each_pid_helper, header, (void *) func);
+}
+
+static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
+    DIR *d;
+    struct dirent *de;
+    char taskpath[255];
+    for_each_tid_func *func = (for_each_tid_func *) arg;
+
+    snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
+
+    if (!(d = opendir(taskpath))) {
+        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
+        return;
+    }
+
+    func(pid, pid, cmdline);
+
+    while ((de = readdir(d))) {
+        if (ds.IsUserConsentDenied()) {
+            MYLOGE(
+                "Returning early because user denied consent to share bugreport with calling app.");
+            closedir(d);
+            return;
+        }
+        int tid;
+        int fd;
+        char commpath[255];
+        char comm[255];
+
+        if (!(tid = atoi(de->d_name))) {
+            continue;
+        }
+
+        if (tid == pid)
+            continue;
+
+        snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
+        memset(comm, 0, sizeof(comm));
+        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
+            strcpy(comm, "N/A");
+        } else {
+            char *c;
+            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
+            close(fd);
+
+            c = strrchr(comm, '\n');
+            if (c) {
+                *c = '\0';
+            }
+        }
+        func(pid, tid, comm);
+    }
+
+    closedir(d);
+}
+
+void for_each_tid(for_each_tid_func func, const char *header) {
+    std::string title = header == nullptr ? "for_each_tid"
+                                          : android::base::StringPrintf("for_each_tid(%s)", header);
+    DurationReporter duration_reporter(title);
+
+    if (PropertiesHelper::IsDryRun()) return;
+
+    __for_each_pid(for_each_tid_helper, header, (void *) func);
+}
+
+void show_wchan(int pid, int tid, const char *name) {
+    if (PropertiesHelper::IsDryRun()) return;
+
+    char path[255];
+    char buffer[255];
+    int fd, ret, save_errno;
+    char name_buffer[255];
+
+    memset(buffer, 0, sizeof(buffer));
+
+    snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
+             pid == tid ? 0 : 3, "", name);
+
+    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
+
+    return;
+}
+
+// print time in centiseconds
+static void snprcent(char *buffer, size_t len, size_t spc,
+                     unsigned long long time) {
+    static long hz; // cache discovered hz
+
+    if (hz <= 0) {
+        hz = sysconf(_SC_CLK_TCK);
+        if (hz <= 0) {
+            hz = 1000;
+        }
+    }
+
+    // convert to centiseconds
+    time = (time * 100 + (hz / 2)) / hz;
+
+    char str[16];
+
+    snprintf(str, sizeof(str), " %llu.%02u",
+             time / 100, (unsigned)(time % 100));
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+// print permille as a percent
+static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
+    char str[16];
+
+    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+void show_showtime(int pid, const char *name) {
+    if (PropertiesHelper::IsDryRun()) return;
+
+    char path[255];
+    char buffer[1023];
+    int fd, ret, save_errno;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    // field 14 is utime
+    // field 15 is stime
+    // field 42 is iotime
+    unsigned long long utime = 0, stime = 0, iotime = 0;
+    if (sscanf(buffer,
+               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
+               &utime, &stime, &iotime) != 3) {
+        return;
+    }
+
+    unsigned long long total = utime + stime;
+    if (!total) {
+        return;
+    }
+
+    unsigned permille = (iotime * 1000 + (total / 2)) / total;
+    if (permille > 1000) {
+        permille = 1000;
+    }
+
+    // try to beautify and stabilize columns at <80 characters
+    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
+    if ((name[0] != '[') || utime) {
+        snprcent(buffer, sizeof(buffer), 57, utime);
+    }
+    snprcent(buffer, sizeof(buffer), 65, stime);
+    if ((name[0] != '[') || iotime) {
+        snprcent(buffer, sizeof(buffer), 73, iotime);
+    }
+    if (iotime) {
+        snprdec(buffer, sizeof(buffer), 79, permille);
+    }
+    puts(buffer);  // adds a trailing newline
+
+    return;
+}
+
+void do_dmesg() {
+    const char *title = "KERNEL LOG (dmesg)";
+    DurationReporter duration_reporter(title);
+    printf("------ %s ------\n", title);
+
+    if (PropertiesHelper::IsDryRun()) return;
+
+    /* Get size of kernel buffer */
+    int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
+    if (size <= 0) {
+        printf("Unexpected klogctl return value: %d\n\n", size);
+        return;
+    }
+    char *buf = (char *) malloc(size + 1);
+    if (buf == nullptr) {
+        printf("memory allocation failed\n\n");
+        return;
+    }
+    int retval = klogctl(KLOG_READ_ALL, buf, size);
+    if (retval < 0) {
+        printf("klogctl failure\n\n");
+        free(buf);
+        return;
+    }
+    buf[retval] = '\0';
+    printf("%s\n\n", buf);
+    free(buf);
+    return;
+}
+
+void do_showmap(int pid, const char *name) {
+    char title[255];
+    char arg[255];
+
+    snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
+    snprintf(arg, sizeof(arg), "%d", pid);
+    RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
+}
+
+int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
+    DurationReporter duration_reporter(title);
+
+    int status = DumpFileToFd(STDOUT_FILENO, title, path);
+
+    UpdateProgress(WEIGHT_FILE);
+
+    return status;
+}
+
+int read_file_as_long(const char *path, long int *output) {
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+    if (fd < 0) {
+        int err = errno;
+        MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
+        return -1;
+    }
+    char buffer[50];
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    if (bytes_read == -1) {
+        MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
+        return -2;
+    }
+    if (bytes_read == 0) {
+        MYLOGE("File %s is empty\n", path);
+        return -3;
+    }
+    *output = atoi(buffer);
+    return 0;
+}
+
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
+               int (*dump_from_fd)(const char* title, const char* path, int fd)) {
+    DurationReporter duration_reporter(title);
+    DIR *dirp;
+    struct dirent *d;
+    char *newpath = nullptr;
+    const char *slash = "/";
+    int retval = 0;
+
+    if (!title.empty()) {
+        printf("------ %s (%s) ------\n", title.c_str(), dir);
+    }
+    if (PropertiesHelper::IsDryRun()) return 0;
+
+    if (dir[strlen(dir) - 1] == '/') {
+        ++slash;
+    }
+    dirp = opendir(dir);
+    if (dirp == nullptr) {
+        retval = -errno;
+        MYLOGE("%s: %s\n", dir, strerror(errno));
+        return retval;
+    }
+
+    if (!dump_from_fd) {
+        dump_from_fd = dump_file_from_fd;
+    }
+    for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
+        if ((d->d_name[0] == '.')
+         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+          || (d->d_name[1] == '\0'))) {
+            continue;
+        }
+        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
+                 (d->d_type == DT_DIR) ? "/" : "");
+        if (!newpath) {
+            retval = -errno;
+            continue;
+        }
+        if (skip && (*skip)(newpath)) {
+            continue;
+        }
+        if (d->d_type == DT_DIR) {
+            int ret = dump_files("", newpath, skip, dump_from_fd);
+            if (ret < 0) {
+                retval = ret;
+            }
+            continue;
+        }
+        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
+        if (fd.get() < 0) {
+            retval = -1;
+            printf("*** %s: %s\n", newpath, strerror(errno));
+            continue;
+        }
+        (*dump_from_fd)(nullptr, newpath, fd.get());
+    }
+    closedir(dirp);
+    if (!title.empty()) {
+        printf("\n");
+    }
+    return retval;
+}
+
+/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
+ * it's possible to avoid issues where opening the file itself can get
+ * stuck.
+ */
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+    if (PropertiesHelper::IsDryRun()) return 0;
+
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
+        return -1;
+    } else if (!(flags & O_NONBLOCK)) {
+        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
+        return -1;
+    }
+    return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
+}
+
+int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
+                          const CommandOptions& options) {
+    DurationReporter duration_reporter(title);
+
+    int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
+
+    /* TODO: for now we're simplifying the progress calculation by using the
+     * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
+     * where its weight should be much higher proportionally to its timeout.
+     * Ideally, it should use a options.EstimatedDuration() instead...*/
+    UpdateProgress(options.Timeout());
+
+    return status;
+}
+
+void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
+                           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);
+}
+
+int open_socket(const char *service) {
+    int s = android_get_control_socket(service);
+    if (s < 0) {
+        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
+        return -1;
+    }
+    fcntl(s, F_SETFD, FD_CLOEXEC);
+
+    // Set backlog to 0 to make sure that queue size will be minimum.
+    // In Linux, because the minimum queue will be 1, connect() will be blocked
+    // if the other clients already called connect() and the connection request was not accepted.
+    if (listen(s, 0) < 0) {
+        MYLOGE("listen(control socket): %s\n", strerror(errno));
+        return -1;
+    }
+
+    struct sockaddr addr;
+    socklen_t alen = sizeof(addr);
+    int fd = accept(s, &addr, &alen);
+
+    // Close socket just after accept(), to make sure that connect() by client will get error
+    // when the socket is used by the other services.
+    // There is still a race condition possibility between accept and close, but there is no way
+    // to close-on-accept atomically.
+    // See detail; b/123306389#comment25
+    close(s);
+
+    if (fd < 0) {
+        MYLOGE("accept(control socket): %s\n", strerror(errno));
+        return -1;
+    }
+
+    return fd;
+}
+
+/* redirect output to a service control socket */
+bool redirect_to_socket(FILE* redirect, const char* service) {
+    int fd = open_socket(service);
+    if (fd == -1) {
+        return false;
+    }
+    fflush(redirect);
+    // TODO: handle dup2 failure
+    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+    close(fd);
+    return true;
+}
+
+// TODO: should call is_valid_output_file and/or be merged into it.
+void create_parent_dirs(const char *path) {
+    char *chp = const_cast<char *> (path);
+
+    /* skip initial slash */
+    if (chp[0] == '/')
+        chp++;
+
+    /* create leading directories, if necessary */
+    struct stat dir_stat;
+    while (chp && chp[0]) {
+        chp = strchr(chp, '/');
+        if (chp) {
+            *chp = 0;
+            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
+                MYLOGI("Creating directory %s\n", path);
+                if (mkdir(path, 0770)) { /* drwxrwx--- */
+                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
+                } else if (chown(path, AID_SHELL, AID_SHELL)) {
+                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
+                }
+            }
+            *chp++ = '/';
+        }
+    }
+}
+
+bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
+    create_parent_dirs(path);
+
+    int fd = TEMP_FAILURE_RETRY(open(path,
+                                     O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
+                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+    if (fd < 0) {
+        MYLOGE("%s: %s\n", path, strerror(errno));
+        return false;
+    }
+
+    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+    close(fd);
+    return true;
+}
+
+bool redirect_to_file(FILE* redirect, char* path) {
+    return _redirect_to_file(redirect, path, O_TRUNC);
+}
+
+bool redirect_to_existing_file(FILE* redirect, char* path) {
+    return _redirect_to_file(redirect, path, O_APPEND);
+}
+
+void dump_route_tables() {
+    DurationReporter duration_reporter("DUMP ROUTE TABLES");
+    if (PropertiesHelper::IsDryRun()) return;
+    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
+    ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
+    FILE* fp = fopen(RT_TABLES_PATH, "re");
+    if (!fp) {
+        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
+        return;
+    }
+    char table[16];
+    // Each line has an integer (the table number), a space, and a string (the table name). We only
+    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
+    // Add a fixed max limit so this doesn't go awry.
+    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
+        RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
+        RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
+    }
+    fclose(fp);
+}
+
+// TODO: make this function thread safe if sections are generated in parallel.
+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_sec);
+
+    // ...but only notifiy listeners when necessary.
+    if (!options_->do_progress_updates) return;
+
+    int progress = progress_->Get();
+    int max = progress_->GetMax();
+
+    // adjusts max on the fly
+    if (max_changed && listener_ != nullptr) {
+        listener_->onMaxProgressUpdated(max);
+    }
+
+    int32_t last_update_delta = progress - last_updated_progress_;
+    if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
+        return;
+    }
+    last_updated_progress_ = progress;
+
+    if (control_socket_fd_ >= 0) {
+        dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
+        fsync(control_socket_fd_);
+    }
+
+    int percent = 100 * progress / max;
+    if (listener_ != nullptr) {
+        if (percent % 5 == 0) {
+            // We don't want to spam logcat, so only log multiples of 5.
+            MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+                   percent);
+        } else {
+            // stderr is ignored on normal invocations, but useful when calling
+            // /system/bin/dumpstate directly for debuggging.
+            fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+                    progress, max, percent);
+        }
+        // TODO(b/111441001): Remove in favor of onProgress
+        listener_->onProgressUpdated(progress);
+
+        listener_->onProgress(percent);
+    }
+}
+
+void Dumpstate::TakeScreenshot(const std::string& path) {
+    const std::string& real_path = path.empty() ? screenshot_path_ : path;
+    int status =
+        RunCommand("", {"/system/bin/screencap", "-p", real_path},
+                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+    if (status == 0) {
+        MYLOGD("Screenshot saved on %s\n", real_path.c_str());
+    } else {
+        MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
+    }
+}
+
+bool is_dir(const char* pathname) {
+    struct stat info;
+    if (stat(pathname, &info) == -1) {
+        return false;
+    }
+    return S_ISDIR(info.st_mode);
+}
+
+time_t get_mtime(int fd, time_t default_mtime) {
+    struct stat info;
+    if (fstat(fd, &info) == -1) {
+        return default_mtime;
+    }
+    return info.st_mtime;
+}
+
+void dump_emmc_ecsd(const char *ext_csd_path) {
+    // List of interesting offsets
+    struct hex {
+        char str[2];
+    };
+    static const size_t EXT_CSD_REV = 192 * sizeof(hex);
+    static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
+
+    std::string buffer;
+    if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
+        return;
+    }
+
+    printf("------ %s Extended CSD ------\n", ext_csd_path);
+
+    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
+        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+        return;
+    }
+
+    int ext_csd_rev = 0;
+    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
+    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
+        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+        return;
+    }
+
+    static const char *ver_str[] = {
+        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
+    };
+    printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
+           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
+                                                                       : "Unknown");
+    if (ext_csd_rev < 7) {
+        printf("\n");
+        return;
+    }
+
+    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
+        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
+        return;
+    }
+
+    int ext_pre_eol_info = 0;
+    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
+    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
+        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
+        return;
+    }
+
+    static const char *eol_str[] = {
+        "Undefined",
+        "Normal",
+        "Warning (consumed 80% of reserve)",
+        "Urgent (consumed 90% of reserve)"
+    };
+    printf(
+        "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
+        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
+                                                                                 : 0]);
+
+    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
+            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
+            lifetime += sizeof(hex)) {
+        int ext_device_life_time_est;
+        static const char *est_str[] = {
+            "Undefined",
+            "0-10% of device lifetime used",
+            "10-20% of device lifetime used",
+            "20-30% of device lifetime used",
+            "30-40% of device lifetime used",
+            "40-50% of device lifetime used",
+            "50-60% of device lifetime used",
+            "60-70% of device lifetime used",
+            "70-80% of device lifetime used",
+            "80-90% of device lifetime used",
+            "90-100% of device lifetime used",
+            "Exceeded the maximum estimated device lifetime",
+        };
+
+        if (buffer.length() < (lifetime + sizeof(hex))) {
+            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
+            break;
+        }
+
+        ext_device_life_time_est = 0;
+        sub = buffer.substr(lifetime, sizeof(hex));
+        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
+            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
+                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+                   sub.c_str());
+            continue;
+        }
+        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
+               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
+               ext_device_life_time_est,
+               est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
+                           ? ext_device_life_time_est
+                           : 0]);
+    }
+
+    printf("\n");
+}
+
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index d02ec75..ae6a721 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -441,8 +441,7 @@
     // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
     std::string path_;
 
-    // TODO: If temporary this should be removed at the end.
-    // Full path of the temporary file containing the screenshot (when requested).
+    // Full path of the file containing the screenshot (when requested).
     std::string screenshot_path_;
 
     // Pointer to the zipped file.
diff --git a/cmds/dumpstate/dumpstate_test.xml b/cmds/dumpstate/dumpstate_test.xml
new file mode 100644
index 0000000..e4e4a30
--- /dev/null
+++ b/cmds/dumpstate/dumpstate_test.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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 dumpstate_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="dumpstate_test->/data/local/tmp/dumpstate_test" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <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="file-exclusion-filter-regex" value=".*/dumpstate_test_fixture" />
+        <option name="file-exclusion-filter-regex" value=".*/tests/.*" />
+        <option name="module-name" value="dumpstate_test" />
+    </test>
+</configuration>
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index fc3642c..5bde7db 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -208,7 +208,7 @@
 
     void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
         ZipEntry entry;
-        EXPECT_EQ(FindEntry(handle, ZipString(filename), &entry), 0);
+        EXPECT_EQ(FindEntry(handle, filename, &entry), 0);
         EXPECT_GT(entry.uncompressed_length, minsize);
         EXPECT_LT(entry.uncompressed_length, maxsize);
     }
@@ -217,7 +217,7 @@
 TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) {
     ZipEntry mainEntryLoc;
     // contains main entry name file
-    EXPECT_EQ(FindEntry(handle, ZipString("main_entry.txt"), &mainEntryLoc), 0);
+    EXPECT_EQ(FindEntry(handle, "main_entry.txt", &mainEntryLoc), 0);
 
     char* buf = new char[mainEntryLoc.uncompressed_length];
     ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length);
@@ -230,7 +230,7 @@
 TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
     ZipEntry entry;
     // contains main entry name file
-    EXPECT_EQ(FindEntry(handle, ZipString("version.txt"), &entry), 0);
+    EXPECT_EQ(FindEntry(handle, "version.txt", &entry), 0);
 
     char* buf = new char[entry.uncompressed_length + 1];
     ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length);
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index e6a7735..4e6b084 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -105,9 +105,8 @@
 
   protected:
     const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
-    const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
-    const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
-    const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
+    const std::string kTestDataPath = kTestPath + "/tests/testdata/";
+    const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
     const std::string kEchoCommand = "/system/bin/echo";
 
     /*
@@ -664,10 +663,10 @@
 TEST_F(DumpstateTest, RunCommandWithTitle) {
     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
     EXPECT_THAT(err, StrEq("stderr\n"));
-    // We don't know the exact duration, so we check the prefix and suffix
+    // The duration may not get output, depending on how long it takes,
+    // so we just check the prefix.
     EXPECT_THAT(out,
-                StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------"));
-    EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
+                StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
 }
 
 TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
@@ -700,10 +699,10 @@
 TEST_F(DumpstateTest, RunCommandDryRun) {
     SetDryRun(true);
     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
-    // We don't know the exact duration, so we check the prefix and suffix
+    // The duration may not get output, depending on how long it takes,
+    // so we just check the prefix.
     EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
-                                ") ------\n\t(skipped on dry run)\n------"));
-    EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
+                                ") ------\n\t(skipped on dry run)\n"));
     EXPECT_THAT(err, IsEmpty());
 }
 
@@ -1039,10 +1038,10 @@
 TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
     EXPECT_THAT(err, IsEmpty());
-    // We don't know the exact duration, so we check the prefix and suffix
+    // The duration may not get output, depending on how long it takes,
+    // so we just check the prefix.
     EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
                                 "such file or directory\n"));
-    EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n"));
 }
 
 TEST_F(DumpstateTest, DumpFileSingleLine) {
@@ -1082,8 +1081,7 @@
     EXPECT_THAT(err, IsEmpty());
     EXPECT_THAT(
         out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
-    EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------"));
-    EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n"));
+    EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
 }
 
 TEST_F(DumpstateTest, DumpFileUpdateProgress) {
@@ -1408,14 +1406,6 @@
         return status;
     }
 
-    // Find out the pid of the process_name
-    int FindPidOfProcess(const std::string& process_name) {
-        CaptureStderr();
-        int status = GetPidByName(process_name);
-        err = GetCapturedStderr();
-        return status;
-    }
-
     int fd;
 
     // 'fd` output and `stderr` from the last command ran.
@@ -1765,18 +1755,6 @@
     EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
 }
 
-TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
-    // init process always has pid 1.
-    EXPECT_EQ(1, FindPidOfProcess("init"));
-    EXPECT_THAT(err, IsEmpty());
-}
-
-TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
-    // find the process with abnormal name.
-    EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
-    EXPECT_THAT(err, StrEq("can't find the pid\n"));
-}
-
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
deleted file mode 100644
index 0bb80dc..0000000
--- a/cmds/dumpstate/utils.cpp
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
- * Copyright (C) 2008 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 "dumpstate"
-
-#include "dumpstate.h"
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <math.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <sys/inotify.h>
-#include <sys/klog.h>
-#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-#include <log/log.h>
-#include <private/android_filesystem_config.h>
-
-#include "DumpstateInternal.h"
-
-// TODO: remove once moved to namespace
-using android::os::dumpstate::CommandOptions;
-using android::os::dumpstate::DumpFileToFd;
-using android::os::dumpstate::PropertiesHelper;
-
-// Keep in sync with
-// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
-static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
-
-/* Most simple commands have 10 as timeout, so 5 is a good estimate */
-static const int32_t WEIGHT_FILE = 5;
-
-// TODO: temporary variables and functions used during C++ refactoring
-static Dumpstate& ds = Dumpstate::GetInstance();
-static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                      const CommandOptions& options = CommandOptions::DEFAULT) {
-    return ds.RunCommand(title, full_command, options);
-}
-
-// Reasonable value for max stats.
-static const int STATS_MAX_N_RUNS = 1000;
-static const long STATS_MAX_AVERAGE = 100000;
-
-CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
-
-// TODO(111441001): Default DumpOptions to sensible values.
-Dumpstate::Dumpstate(const std::string& version)
-    : pid_(getpid()),
-      options_(new Dumpstate::DumpOptions()),
-      version_(version),
-      now_(time(nullptr)) {
-}
-
-Dumpstate& Dumpstate::GetInstance() {
-    static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
-    return singleton_;
-}
-
-DurationReporter::DurationReporter(const std::string& title, bool logcat_only)
-    : title_(title), logcat_only_(logcat_only) {
-    if (!title_.empty()) {
-        started_ = Nanotime();
-    }
-}
-
-DurationReporter::~DurationReporter() {
-    if (!title_.empty()) {
-        float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
-        if (elapsed < .5f) {
-            return;
-        }
-        MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
-        if (logcat_only_) {
-            return;
-        }
-        // Use "Yoda grammar" to make it easier to grep|sort sections.
-        printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
-    }
-}
-
-const int32_t Progress::kDefaultMax = 5000;
-
-Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
-}
-
-Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
-    : Progress(initial_max, growth_factor, "") {
-    progress_ = progress;
-}
-
-Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
-    : initial_max_(initial_max),
-      progress_(0),
-      max_(initial_max),
-      growth_factor_(growth_factor),
-      n_runs_(0),
-      average_max_(0),
-      path_(path) {
-    if (!path_.empty()) {
-        Load();
-    }
-}
-
-void Progress::Load() {
-    MYLOGD("Loading stats from %s\n", path_.c_str());
-    std::string content;
-    if (!android::base::ReadFileToString(path_, &content)) {
-        MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
-        return;
-    }
-    if (content.empty()) {
-        MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
-        return;
-    }
-    std::vector<std::string> lines = android::base::Split(content, "\n");
-
-    if (lines.size() < 1) {
-        MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
-               (int)lines.size(), max_);
-        return;
-    }
-    char* ptr;
-    n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
-    average_max_ = strtol(ptr, nullptr, 10);
-    if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
-        average_max_ > STATS_MAX_AVERAGE) {
-        MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
-        initial_max_ = Progress::kDefaultMax;
-    } else {
-        initial_max_ = average_max_;
-    }
-    max_ = initial_max_;
-
-    MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
-}
-
-void Progress::Save() {
-    int32_t total = n_runs_ * average_max_ + progress_;
-    int32_t runs = n_runs_ + 1;
-    int32_t average = floor(((float)total) / runs);
-    MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
-           path_.c_str());
-    if (path_.empty()) {
-        return;
-    }
-
-    std::string content = android::base::StringPrintf("%d %d\n", runs, average);
-    if (!android::base::WriteStringToFile(content, path_)) {
-        MYLOGE("Could not save stats on %s\n", path_.c_str());
-    }
-}
-
-int32_t Progress::Get() const {
-    return progress_;
-}
-
-bool Progress::Inc(int32_t delta_sec) {
-    bool changed = false;
-    if (delta_sec >= 0) {
-        progress_ += delta_sec;
-        if (progress_ > max_) {
-            int32_t old_max = max_;
-            max_ = floor((float)progress_ * growth_factor_);
-            MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
-            changed = true;
-        }
-    }
-    return changed;
-}
-
-int32_t Progress::GetMax() const {
-    return max_;
-}
-
-int32_t Progress::GetInitialMax() const {
-    return initial_max_;
-}
-
-void Progress::Dump(int fd, const std::string& prefix) const {
-    const char* pr = prefix.c_str();
-    dprintf(fd, "%sprogress: %d\n", pr, progress_);
-    dprintf(fd, "%smax: %d\n", pr, max_);
-    dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
-    dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
-    dprintf(fd, "%spath: %s\n", pr, path_.c_str());
-    dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
-    dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
-}
-
-bool Dumpstate::IsZipping() const {
-    return zip_writer_ != nullptr;
-}
-
-std::string Dumpstate::GetPath(const std::string& suffix) const {
-    return GetPath(bugreport_internal_dir_, suffix);
-}
-
-std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
-    return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
-                                       name_.c_str(), suffix.c_str());
-}
-
-void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
-    progress_ = std::move(progress);
-}
-
-void for_each_userid(void (*func)(int), const char *header) {
-    std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
-                                                                    "for_each_userid(%s)", header);
-    DurationReporter duration_reporter(title);
-    if (PropertiesHelper::IsDryRun()) return;
-
-    DIR *d;
-    struct dirent *de;
-
-    if (header) printf("\n------ %s ------\n", header);
-    func(0);
-
-    if (!(d = opendir("/data/system/users"))) {
-        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        int userid;
-        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
-            continue;
-        }
-        func(userid);
-    }
-
-    closedir(d);
-}
-
-static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
-    DIR *d;
-    struct dirent *de;
-
-    if (!(d = opendir("/proc"))) {
-        printf("Failed to open /proc (%s)\n", strerror(errno));
-        return;
-    }
-
-    if (header) printf("\n------ %s ------\n", header);
-    while ((de = readdir(d))) {
-        if (ds.IsUserConsentDenied()) {
-            MYLOGE(
-                "Returning early because user denied consent to share bugreport with calling app.");
-            closedir(d);
-            return;
-        }
-        int pid;
-        int fd;
-        char cmdpath[255];
-        char cmdline[255];
-
-        if (!(pid = atoi(de->d_name))) {
-            continue;
-        }
-
-        memset(cmdline, 0, sizeof(cmdline));
-
-        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
-            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
-            close(fd);
-            if (cmdline[0]) {
-                helper(pid, cmdline, arg);
-                continue;
-            }
-        }
-
-        // if no cmdline, a kernel thread has comm
-        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
-            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
-            close(fd);
-            if (cmdline[1]) {
-                cmdline[0] = '[';
-                size_t len = strcspn(cmdline, "\f\b\r\n");
-                cmdline[len] = ']';
-                cmdline[len+1] = '\0';
-            }
-        }
-        if (!cmdline[0]) {
-            strcpy(cmdline, "N/A");
-        }
-        helper(pid, cmdline, arg);
-    }
-
-    closedir(d);
-}
-
-static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
-    for_each_pid_func *func = (for_each_pid_func*) arg;
-    func(pid, cmdline);
-}
-
-void for_each_pid(for_each_pid_func func, const char *header) {
-    std::string title = header == nullptr ? "for_each_pid"
-                                          : android::base::StringPrintf("for_each_pid(%s)", header);
-    DurationReporter duration_reporter(title);
-    if (PropertiesHelper::IsDryRun()) return;
-
-    __for_each_pid(for_each_pid_helper, header, (void *) func);
-}
-
-static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
-    DIR *d;
-    struct dirent *de;
-    char taskpath[255];
-    for_each_tid_func *func = (for_each_tid_func *) arg;
-
-    snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
-
-    if (!(d = opendir(taskpath))) {
-        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
-        return;
-    }
-
-    func(pid, pid, cmdline);
-
-    while ((de = readdir(d))) {
-        if (ds.IsUserConsentDenied()) {
-            MYLOGE(
-                "Returning early because user denied consent to share bugreport with calling app.");
-            closedir(d);
-            return;
-        }
-        int tid;
-        int fd;
-        char commpath[255];
-        char comm[255];
-
-        if (!(tid = atoi(de->d_name))) {
-            continue;
-        }
-
-        if (tid == pid)
-            continue;
-
-        snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
-        memset(comm, 0, sizeof(comm));
-        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
-            strcpy(comm, "N/A");
-        } else {
-            char *c;
-            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
-            close(fd);
-
-            c = strrchr(comm, '\n');
-            if (c) {
-                *c = '\0';
-            }
-        }
-        func(pid, tid, comm);
-    }
-
-    closedir(d);
-}
-
-void for_each_tid(for_each_tid_func func, const char *header) {
-    std::string title = header == nullptr ? "for_each_tid"
-                                          : android::base::StringPrintf("for_each_tid(%s)", header);
-    DurationReporter duration_reporter(title);
-
-    if (PropertiesHelper::IsDryRun()) return;
-
-    __for_each_pid(for_each_tid_helper, header, (void *) func);
-}
-
-void show_wchan(int pid, int tid, const char *name) {
-    if (PropertiesHelper::IsDryRun()) return;
-
-    char path[255];
-    char buffer[255];
-    int fd, ret, save_errno;
-    char name_buffer[255];
-
-    memset(buffer, 0, sizeof(buffer));
-
-    snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
-        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
-        return;
-    }
-
-    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    save_errno = errno;
-    close(fd);
-
-    if (ret < 0) {
-        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
-        return;
-    }
-
-    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
-             pid == tid ? 0 : 3, "", name);
-
-    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
-
-    return;
-}
-
-// print time in centiseconds
-static void snprcent(char *buffer, size_t len, size_t spc,
-                     unsigned long long time) {
-    static long hz; // cache discovered hz
-
-    if (hz <= 0) {
-        hz = sysconf(_SC_CLK_TCK);
-        if (hz <= 0) {
-            hz = 1000;
-        }
-    }
-
-    // convert to centiseconds
-    time = (time * 100 + (hz / 2)) / hz;
-
-    char str[16];
-
-    snprintf(str, sizeof(str), " %llu.%02u",
-             time / 100, (unsigned)(time % 100));
-    size_t offset = strlen(buffer);
-    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
-             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-// print permille as a percent
-static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
-    char str[16];
-
-    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
-    size_t offset = strlen(buffer);
-    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
-             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
-}
-
-void show_showtime(int pid, const char *name) {
-    if (PropertiesHelper::IsDryRun()) return;
-
-    char path[255];
-    char buffer[1023];
-    int fd, ret, save_errno;
-
-    memset(buffer, 0, sizeof(buffer));
-
-    snprintf(path, sizeof(path), "/proc/%d/stat", pid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
-        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
-        return;
-    }
-
-    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    save_errno = errno;
-    close(fd);
-
-    if (ret < 0) {
-        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
-        return;
-    }
-
-    // field 14 is utime
-    // field 15 is stime
-    // field 42 is iotime
-    unsigned long long utime = 0, stime = 0, iotime = 0;
-    if (sscanf(buffer,
-               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
-               &utime, &stime, &iotime) != 3) {
-        return;
-    }
-
-    unsigned long long total = utime + stime;
-    if (!total) {
-        return;
-    }
-
-    unsigned permille = (iotime * 1000 + (total / 2)) / total;
-    if (permille > 1000) {
-        permille = 1000;
-    }
-
-    // try to beautify and stabilize columns at <80 characters
-    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
-    if ((name[0] != '[') || utime) {
-        snprcent(buffer, sizeof(buffer), 57, utime);
-    }
-    snprcent(buffer, sizeof(buffer), 65, stime);
-    if ((name[0] != '[') || iotime) {
-        snprcent(buffer, sizeof(buffer), 73, iotime);
-    }
-    if (iotime) {
-        snprdec(buffer, sizeof(buffer), 79, permille);
-    }
-    puts(buffer);  // adds a trailing newline
-
-    return;
-}
-
-void do_dmesg() {
-    const char *title = "KERNEL LOG (dmesg)";
-    DurationReporter duration_reporter(title);
-    printf("------ %s ------\n", title);
-
-    if (PropertiesHelper::IsDryRun()) return;
-
-    /* Get size of kernel buffer */
-    int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
-    if (size <= 0) {
-        printf("Unexpected klogctl return value: %d\n\n", size);
-        return;
-    }
-    char *buf = (char *) malloc(size + 1);
-    if (buf == nullptr) {
-        printf("memory allocation failed\n\n");
-        return;
-    }
-    int retval = klogctl(KLOG_READ_ALL, buf, size);
-    if (retval < 0) {
-        printf("klogctl failure\n\n");
-        free(buf);
-        return;
-    }
-    buf[retval] = '\0';
-    printf("%s\n\n", buf);
-    free(buf);
-    return;
-}
-
-void do_showmap(int pid, const char *name) {
-    char title[255];
-    char arg[255];
-
-    snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
-    snprintf(arg, sizeof(arg), "%d", pid);
-    RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
-}
-
-int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
-    DurationReporter duration_reporter(title);
-
-    int status = DumpFileToFd(STDOUT_FILENO, title, path);
-
-    UpdateProgress(WEIGHT_FILE);
-
-    return status;
-}
-
-int read_file_as_long(const char *path, long int *output) {
-    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
-    if (fd < 0) {
-        int err = errno;
-        MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
-        return -1;
-    }
-    char buffer[50];
-    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-    if (bytes_read == -1) {
-        MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
-        return -2;
-    }
-    if (bytes_read == 0) {
-        MYLOGE("File %s is empty\n", path);
-        return -3;
-    }
-    *output = atoi(buffer);
-    return 0;
-}
-
-/* calls skip to gate calling dump_from_fd recursively
- * in the specified directory. dump_from_fd defaults to
- * dump_file_from_fd above when set to NULL. skip defaults
- * to false when set to NULL. dump_from_fd will always be
- * called with title NULL.
- */
-int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
-               int (*dump_from_fd)(const char* title, const char* path, int fd)) {
-    DurationReporter duration_reporter(title);
-    DIR *dirp;
-    struct dirent *d;
-    char *newpath = nullptr;
-    const char *slash = "/";
-    int retval = 0;
-
-    if (!title.empty()) {
-        printf("------ %s (%s) ------\n", title.c_str(), dir);
-    }
-    if (PropertiesHelper::IsDryRun()) return 0;
-
-    if (dir[strlen(dir) - 1] == '/') {
-        ++slash;
-    }
-    dirp = opendir(dir);
-    if (dirp == nullptr) {
-        retval = -errno;
-        MYLOGE("%s: %s\n", dir, strerror(errno));
-        return retval;
-    }
-
-    if (!dump_from_fd) {
-        dump_from_fd = dump_file_from_fd;
-    }
-    for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
-        if ((d->d_name[0] == '.')
-         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
-          || (d->d_name[1] == '\0'))) {
-            continue;
-        }
-        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
-                 (d->d_type == DT_DIR) ? "/" : "");
-        if (!newpath) {
-            retval = -errno;
-            continue;
-        }
-        if (skip && (*skip)(newpath)) {
-            continue;
-        }
-        if (d->d_type == DT_DIR) {
-            int ret = dump_files("", newpath, skip, dump_from_fd);
-            if (ret < 0) {
-                retval = ret;
-            }
-            continue;
-        }
-        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
-        if (fd.get() < 0) {
-            retval = -1;
-            printf("*** %s: %s\n", newpath, strerror(errno));
-            continue;
-        }
-        (*dump_from_fd)(nullptr, newpath, fd.get());
-    }
-    closedir(dirp);
-    if (!title.empty()) {
-        printf("\n");
-    }
-    return retval;
-}
-
-/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
- * it's possible to avoid issues where opening the file itself can get
- * stuck.
- */
-int dump_file_from_fd(const char *title, const char *path, int fd) {
-    if (PropertiesHelper::IsDryRun()) return 0;
-
-    int flags = fcntl(fd, F_GETFL);
-    if (flags == -1) {
-        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
-        return -1;
-    } else if (!(flags & O_NONBLOCK)) {
-        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
-        return -1;
-    }
-    return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
-}
-
-int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
-                          const CommandOptions& options) {
-    DurationReporter duration_reporter(title);
-
-    int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
-
-    /* TODO: for now we're simplifying the progress calculation by using the
-     * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
-     * where its weight should be much higher proportionally to its timeout.
-     * Ideally, it should use a options.EstimatedDuration() instead...*/
-    UpdateProgress(options.Timeout());
-
-    return status;
-}
-
-void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
-                           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);
-}
-
-int open_socket(const char *service) {
-    int s = android_get_control_socket(service);
-    if (s < 0) {
-        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
-        return -1;
-    }
-    fcntl(s, F_SETFD, FD_CLOEXEC);
-    if (listen(s, 4) < 0) {
-        MYLOGE("listen(control socket): %s\n", strerror(errno));
-        return -1;
-    }
-
-    struct sockaddr addr;
-    socklen_t alen = sizeof(addr);
-    int fd = accept(s, &addr, &alen);
-    if (fd < 0) {
-        MYLOGE("accept(control socket): %s\n", strerror(errno));
-        return -1;
-    }
-
-    return fd;
-}
-
-/* redirect output to a service control socket */
-bool redirect_to_socket(FILE* redirect, const char* service) {
-    int fd = open_socket(service);
-    if (fd == -1) {
-        return false;
-    }
-    fflush(redirect);
-    // TODO: handle dup2 failure
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-    return true;
-}
-
-// TODO: should call is_valid_output_file and/or be merged into it.
-void create_parent_dirs(const char *path) {
-    char *chp = const_cast<char *> (path);
-
-    /* skip initial slash */
-    if (chp[0] == '/')
-        chp++;
-
-    /* create leading directories, if necessary */
-    struct stat dir_stat;
-    while (chp && chp[0]) {
-        chp = strchr(chp, '/');
-        if (chp) {
-            *chp = 0;
-            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
-                MYLOGI("Creating directory %s\n", path);
-                if (mkdir(path, 0770)) { /* drwxrwx--- */
-                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
-                } else if (chown(path, AID_SHELL, AID_SHELL)) {
-                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
-                }
-            }
-            *chp++ = '/';
-        }
-    }
-}
-
-bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
-    create_parent_dirs(path);
-
-    int fd = TEMP_FAILURE_RETRY(open(path,
-                                     O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
-                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
-    if (fd < 0) {
-        MYLOGE("%s: %s\n", path, strerror(errno));
-        return false;
-    }
-
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-    return true;
-}
-
-bool redirect_to_file(FILE* redirect, char* path) {
-    return _redirect_to_file(redirect, path, O_TRUNC);
-}
-
-bool redirect_to_existing_file(FILE* redirect, char* path) {
-    return _redirect_to_file(redirect, path, O_APPEND);
-}
-
-void dump_route_tables() {
-    DurationReporter duration_reporter("DUMP ROUTE TABLES");
-    if (PropertiesHelper::IsDryRun()) return;
-    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
-    ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
-    FILE* fp = fopen(RT_TABLES_PATH, "re");
-    if (!fp) {
-        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
-        return;
-    }
-    char table[16];
-    // Each line has an integer (the table number), a space, and a string (the table name). We only
-    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
-    // Add a fixed max limit so this doesn't go awry.
-    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
-        RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
-        RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
-    }
-    fclose(fp);
-}
-
-// TODO: make this function thread safe if sections are generated in parallel.
-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_sec);
-
-    // ...but only notifiy listeners when necessary.
-    if (!options_->do_progress_updates) return;
-
-    int progress = progress_->Get();
-    int max = progress_->GetMax();
-
-    // adjusts max on the fly
-    if (max_changed && listener_ != nullptr) {
-        listener_->onMaxProgressUpdated(max);
-    }
-
-    int32_t last_update_delta = progress - last_updated_progress_;
-    if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
-        return;
-    }
-    last_updated_progress_ = progress;
-
-    if (control_socket_fd_ >= 0) {
-        dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
-        fsync(control_socket_fd_);
-    }
-
-    int percent = 100 * progress / max;
-    if (listener_ != nullptr) {
-        if (percent % 5 == 0) {
-            // We don't want to spam logcat, so only log multiples of 5.
-            MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
-                   percent);
-        } else {
-            // stderr is ignored on normal invocations, but useful when calling
-            // /system/bin/dumpstate directly for debuggging.
-            fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
-                    progress, max, percent);
-        }
-        // TODO(b/111441001): Remove in favor of onProgress
-        listener_->onProgressUpdated(progress);
-
-        listener_->onProgress(percent);
-    }
-}
-
-void Dumpstate::TakeScreenshot(const std::string& path) {
-    const std::string& real_path = path.empty() ? screenshot_path_ : path;
-    int status =
-        RunCommand("", {"/system/bin/screencap", "-p", real_path},
-                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
-    if (status == 0) {
-        MYLOGD("Screenshot saved on %s\n", real_path.c_str());
-    } else {
-        MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
-    }
-}
-
-bool is_dir(const char* pathname) {
-    struct stat info;
-    if (stat(pathname, &info) == -1) {
-        return false;
-    }
-    return S_ISDIR(info.st_mode);
-}
-
-time_t get_mtime(int fd, time_t default_mtime) {
-    struct stat info;
-    if (fstat(fd, &info) == -1) {
-        return default_mtime;
-    }
-    return info.st_mtime;
-}
-
-void dump_emmc_ecsd(const char *ext_csd_path) {
-    // List of interesting offsets
-    struct hex {
-        char str[2];
-    };
-    static const size_t EXT_CSD_REV = 192 * sizeof(hex);
-    static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
-
-    std::string buffer;
-    if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
-        return;
-    }
-
-    printf("------ %s Extended CSD ------\n", ext_csd_path);
-
-    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_csd_rev = 0;
-    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
-        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *ver_str[] = {
-        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
-    };
-    printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
-           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
-                                                                       : "Unknown");
-    if (ext_csd_rev < 7) {
-        printf("\n");
-        return;
-    }
-
-    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_pre_eol_info = 0;
-    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
-        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *eol_str[] = {
-        "Undefined",
-        "Normal",
-        "Warning (consumed 80% of reserve)",
-        "Urgent (consumed 90% of reserve)"
-    };
-    printf(
-        "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
-        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
-                                                                                 : 0]);
-
-    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
-            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
-            lifetime += sizeof(hex)) {
-        int ext_device_life_time_est;
-        static const char *est_str[] = {
-            "Undefined",
-            "0-10% of device lifetime used",
-            "10-20% of device lifetime used",
-            "20-30% of device lifetime used",
-            "30-40% of device lifetime used",
-            "40-50% of device lifetime used",
-            "50-60% of device lifetime used",
-            "60-70% of device lifetime used",
-            "70-80% of device lifetime used",
-            "80-90% of device lifetime used",
-            "90-100% of device lifetime used",
-            "Exceeded the maximum estimated device lifetime",
-        };
-
-        if (buffer.length() < (lifetime + sizeof(hex))) {
-            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
-            break;
-        }
-
-        ext_device_life_time_est = 0;
-        sub = buffer.substr(lifetime, sizeof(hex));
-        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
-            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
-                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-                   sub.c_str());
-            continue;
-        }
-        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
-               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-               ext_device_life_time_est,
-               est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
-                           ? ext_device_life_time_est
-                           : 0]);
-    }
-
-    printf("\n");
-}
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index d66066e..75dec37 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -128,12 +128,17 @@
             ],
         },
     },
+
+    // Needs to be wherever installd is as it's execed by
+    // installd.
+    required: [ "migrate_legacy_obb_data.sh" ],
 }
 
 // OTA chroot tool
 
 cc_binary {
     name: "otapreopt_chroot",
+    defaults: ["libapexd-deps"],
     cflags: [
         "-Wall",
         "-Werror",
@@ -146,20 +151,11 @@
     ],
     shared_libs: [
         "libbase",
-        "libbinder",
         "liblog",
-        "libprotobuf-cpp-full",
-        "libselinux",
         "libutils",
-        "libziparchive",
     ],
     static_libs: [
-        "libapex",
         "libapexd",
-        "lib_apex_manifest_proto",
-        "libavb",
-        "libdm",
-        "libvold_binder",
     ],
 }
 
@@ -168,6 +164,7 @@
     srcs: [
         "binder/android/os/IInstalld.aidl",
     ],
+    path: "binder",
 }
 
 //
@@ -254,3 +251,9 @@
         "otapreopt_slot",
     ],
 }
+
+// Script to migrate legacy obb data.
+sh_binary {
+    name: "migrate_legacy_obb_data.sh",
+    src: "migrate_legacy_obb_data.sh"
+}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c730ab9..dd51898 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -569,35 +569,6 @@
                 remove_path_xattr(path, kXattrInodeCodeCache);
             }
         }
-
-        auto extPath = findDataMediaPath(uuid, userId);
-        if (flags & FLAG_CLEAR_CACHE_ONLY) {
-            // Clear only cached data from shared storage
-            path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
-        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
-            // No code cache on shared storage
-        } else {
-            // Clear everything on shared storage
-            path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
-            path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
-            path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
-            path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
-            if (delete_dir_contents(path, true) != 0) {
-                res = error("Failed to delete contents of " + path);
-            }
-        }
     }
     if (flags & FLAG_STORAGE_DE) {
         std::string suffix = "";
@@ -617,6 +588,41 @@
             }
         }
     }
+    if (flags & FLAG_STORAGE_EXTERNAL) {
+        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+        for (const auto& n : mStorageMounts) {
+            auto extPath = n.second;
+            if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
+                extPath += StringPrintf("/%d", userId);
+            } else if (userId != 0) {
+                // TODO: support devices mounted under secondary users
+                continue;
+            }
+            if (flags & FLAG_CLEAR_CACHE_ONLY) {
+                // Clear only cached data from shared storage
+                auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
+                if (delete_dir_contents(path, true) != 0) {
+                    res = error("Failed to delete contents of " + path);
+                }
+            } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
+                // No code cache on shared storage
+            } else {
+                // Clear everything on shared storage
+                auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
+                if (delete_dir_contents(path, true) != 0) {
+                    res = error("Failed to delete contents of " + path);
+                }
+                path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
+                if (delete_dir_contents(path, true) != 0) {
+                    res = error("Failed to delete contents of " + path);
+                }
+                path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
+                if (delete_dir_contents(path, true) != 0) {
+                    res = error("Failed to delete contents of " + path);
+                }
+            }
+        }
+    }
     return res;
 }
 
@@ -666,24 +672,6 @@
         if (delete_dir_contents_and_dir(path) != 0) {
             res = error("Failed to delete " + path);
         }
-
-        auto extPath = findDataMediaPath(uuid, userId);
-        path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname);
-        if (delete_dir_contents_and_dir(path, true) != 0) {
-            res = error("Failed to delete " + path);
-        }
-        path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
-        if (delete_dir_contents_and_dir(path, true) != 0) {
-            res = error("Failed to delete " + path);
-        }
-        path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
-        if (delete_dir_contents_and_dir(path, true) != 0) {
-            res = error("Failed to delete " + path);
-        }
-        path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
-        if (delete_dir_contents_and_dir(path, true) != 0) {
-            res = error("Failed to delete " + path);
-        }
     }
     if (flags & FLAG_STORAGE_DE) {
         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
@@ -696,6 +684,30 @@
         // Verify if it's ok to do that.
         destroy_app_reference_profile(packageName);
     }
+    if (flags & FLAG_STORAGE_EXTERNAL) {
+        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+        for (const auto& n : mStorageMounts) {
+            auto extPath = n.second;
+            if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
+                extPath += StringPrintf("/%d", userId);
+            } else if (userId != 0) {
+                // TODO: support devices mounted under secondary users
+                continue;
+            }
+            auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents_and_dir(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+            path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents_and_dir(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+            path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents_and_dir(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+        }
+    }
     return res;
 }
 
@@ -1694,8 +1706,6 @@
             }
 
             ATRACE_BEGIN("external");
-            auto sandboxPath = create_data_media_package_path(uuid_, userId, "sandbox", pkgname);
-            calculate_tree_size(sandboxPath, &extStats.dataSize);
             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
             collectManualStats(extPath, &extStats);
             auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
@@ -2097,10 +2107,15 @@
     CHECK_ARGUMENT_PATH(dexMetadataPath);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
+    const char* oat_dir = getCStr(outputPath);
+    const char* instruction_set = instructionSet.c_str();
+    if (oat_dir != nullptr && !createOatDir(oat_dir, instruction_set).isOk()) {
+        // Can't create oat dir - let dexopt use cache dir.
+        oat_dir = nullptr;
+    }
+
     const char* apk_path = apkPath.c_str();
     const char* pkgname = getCStr(packageName, "*");
-    const char* instruction_set = instructionSet.c_str();
-    const char* oat_dir = getCStr(outputPath);
     const char* compiler_filter = compilerFilter.c_str();
     const char* volume_uuid = getCStr(uuid);
     const char* class_loader_context = getCStr(classLoaderContext);
@@ -2806,5 +2821,16 @@
     return ok();
 }
 
+binder::Status InstalldNativeService::migrateLegacyObbData() {
+    ENFORCE_UID(AID_SYSTEM);
+    // NOTE: The lint warning doesn't apply to the use of system(3) with
+    // absolute parse and no command line arguments.
+    if (system("/system/bin/migrate_legacy_obb_data.sh") != 0) { // NOLINT(cert-env33-c)
+        LOG(ERROR) << "Unable to migrate legacy obb data";
+    }
+
+    return ok();
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 0e91cb2..2b7bf33 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -155,6 +155,8 @@
             const std::string& codePath, const std::unique_ptr<std::string>& dexMetadata,
             bool* _aidl_return);
 
+    binder::Status migrateLegacyObbData();
+
 private:
     std::recursive_mutex mLock;
 
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index 5673918..9a21104 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -4,7 +4,9 @@
 calin@google.com
 jsharkey@android.com
 maco@google.com
+mast@google.com
 mathieuc@google.com
 narayan@google.com
 ngeoffray@google.com
+rpl@google.com
 toddke@google.com
diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp
deleted file mode 100644
index c47dd72..0000000
--- a/cmds/installd/art_helper/Android.bp
+++ /dev/null
@@ -1,12 +0,0 @@
-// Inherit image values.
-art_global_defaults {
-    name: "libartimagevalues_defaults",
-}
-
-cc_library_static {
-    name: "libartimagevalues",
-    defaults: ["libartimagevalues_defaults"],
-    srcs: ["art_image_values.cpp"],
-    export_include_dirs: ["."],
-    cflags: ["-Wconversion"],
-}
diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp
deleted file mode 100644
index a139049..0000000
--- a/cmds/installd/art_helper/art_image_values.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "art_image_values.h"
-
-namespace android {
-namespace installd {
-namespace art {
-
-uint32_t GetImageBaseAddress() {
-    return ART_BASE_ADDRESS;
-}
-int32_t GetImageMinBaseAddressDelta() {
-    return ART_BASE_ADDRESS_MIN_DELTA;
-}
-int32_t GetImageMaxBaseAddressDelta() {
-    return ART_BASE_ADDRESS_MAX_DELTA;
-}
-
-static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
-
-}  // namespace art
-}  // namespace installd
-}  // namespace android
diff --git a/cmds/installd/art_helper/art_image_values.h b/cmds/installd/art_helper/art_image_values.h
deleted file mode 100644
index 20c44c9..0000000
--- a/cmds/installd/art_helper/art_image_values.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
-#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
-
-#include <cstdint>
-
-namespace android {
-namespace installd {
-namespace art {
-
-uint32_t GetImageBaseAddress();
-int32_t GetImageMinBaseAddressDelta();
-int32_t GetImageMaxBaseAddressDelta();
-
-}  // namespace art
-}  // namespace installd
-}  // namespace android
-
-#endif  // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 63c9765..d99bcc8 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -112,8 +112,11 @@
     void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
             int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
 
+    void migrateLegacyObbData();
+
     const int FLAG_STORAGE_DE = 0x1;
     const int FLAG_STORAGE_CE = 0x2;
+    const int FLAG_STORAGE_EXTERNAL = 0x4;
 
     const int FLAG_CLEAR_CACHE_ONLY = 0x10;
     const int FLAG_CLEAR_CODE_CACHE_ONLY = 0x20;
@@ -124,4 +127,6 @@
 
     const int FLAG_USE_QUOTA = 0x1000;
     const int FLAG_FORCE = 0x2000;
+
+    const int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES = 0x20000;
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index a5cc0df..7eee749 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -534,7 +534,7 @@
         }
         AddRuntimeArg(target_sdk_version_arg);
         if (enable_hidden_api_checks) {
-            AddRuntimeArg("-Xhidden-api-checks");
+            AddRuntimeArg("-Xhidden-api-policy:enabled");
         }
 
         if (dex_metadata_fd > -1) {
@@ -2117,14 +2117,20 @@
     // Create a swap file if necessary.
     unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
 
-    // Create the app image file if needed.
-    Dex2oatFileWrapper image_fd = maybe_open_app_image(
-            out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
-
     // Open the reference profile if needed.
     Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
             pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
 
+    if (reference_profile_fd.get() == -1) {
+        // We don't create an app image without reference profile since there is no speedup from
+        // loading it in that case and instead will be a small overhead.
+        generate_app_image = false;
+    }
+
+    // Create the app image file if needed.
+    Dex2oatFileWrapper image_fd = maybe_open_app_image(
+            out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
+
     unique_fd dex_metadata_fd;
     if (dex_metadata_path != nullptr) {
         dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
new file mode 100644
index 0000000..1075688
--- /dev/null
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -0,0 +1,40 @@
+#!/system/bin/sh
+
+#
+# Copyright (C) 2019 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.
+
+rm -rf /sdcard/Android/obb/test_probe
+mkdir -p /sdcard/Android/obb/
+touch /sdcard/Android/obb/test_probe
+if ! test -f /data/media/0/Android/obb/test_probe ; then
+  log -p i -t migrate_legacy_obb_data "No support for 'unshared_obb'. Not migrating"
+  rm -rf /sdcard/Android/obb/test_probe
+  exit 0
+fi
+
+# Delete the test file, and remove the obb folder if it is empty
+rm -rf /sdcard/Android/obb/test_probe
+rmdir /data/media/obb
+
+if ! test -d /data/media/obb ; then
+  log -p i -t migrate_legacy_obb_data "No legacy obb data to migrate."
+  exit 0
+fi
+
+log -p i -t migrate_legacy_obb_data "Migrating legacy obb data."
+rm -rf /data/media/0/Android/obb
+cp -F -p -R -P -d /data/media/obb /data/media/0/Android
+rm -rf /data/media/obb
+log -p i -t migrate_legacy_obb_data "Done."
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index de7b249..db36ce3 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -445,9 +445,11 @@
         }
         cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
 
-        int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
-                                                          art::GetImageMaxBaseAddressDelta());
-        cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset));
+        int32_t base_offset = ChooseRelocationOffsetDelta(
+                art::imagevalues::GetImageMinBaseAddressDelta(),
+                art::imagevalues::GetImageMaxBaseAddressDelta());
+        cmd.push_back(StringPrintf("--base=0x%x",
+                art::imagevalues::GetImageBaseAddress() + base_offset));
 
         cmd.push_back(StringPrintf("--instruction-set=%s", isa));
 
@@ -464,7 +466,7 @@
                 "--compiler-filter=",
                 false,
                 cmd);
-        cmd.push_back("--image-classes=/system/etc/preloaded-classes");
+        cmd.push_back("--profile-file=/system/etc/boot-image.prof");
         // TODO: Compiled-classes.
         const std::string* extra_opts =
                 system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 2e2cc18..b4bcd53 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -64,16 +64,18 @@
     // system/apex/apexd/apexd_main.cpp.
     //
     // Only scan the APEX directory under /system (within the chroot dir).
-    apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
+    // Cast call to void to suppress warn_unused_result.
+    static_cast<void>(apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir));
     return apex::getActivePackages();
 }
 
 static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
     for (const apex::ApexFile& apex_file : active_packages) {
         const std::string& package_path = apex_file.GetPath();
-        apex::Status status = apex::deactivatePackage(package_path);
-        if (!status.Ok()) {
-            LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
+        base::Result<void> status = apex::deactivatePackage(package_path);
+        if (!status) {
+            LOG(ERROR) << "Failed to deactivate " << package_path << ": "
+                       << status.error();
         }
     }
 }
@@ -234,6 +236,18 @@
     // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
     std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
 
+    // Check that an Android Runtime APEX has been activated; clean up and exit
+    // early otherwise.
+    if (std::none_of(active_packages.begin(),
+                     active_packages.end(),
+                     [](const apex::ApexFile& package){
+                         return package.GetManifest().name() == "com.android.runtime";
+                     })) {
+        LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.runtime APEX package.";
+        DeactivateApexPackages(active_packages);
+        exit(217);
+    }
+
     // Now go on and run otapreopt.
 
     // Incoming:  cmd + status-fd + target-slot + cmd...      | Incoming | = argc
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index aa79fdc..bd45005 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -89,6 +89,8 @@
         "libinstalld",
         "liblog",
         "liblogwrap",
+        "libziparchive",
+        "libz",
     ],
     test_config: "installd_dexopt_test.xml",
 }
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index fa2b0d9..73780ec 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -41,6 +41,7 @@
 #include "globals.h"
 #include "tests/test_utils.h"
 #include "utils.h"
+#include "ziparchive/zip_writer.h"
 
 using android::base::ReadFully;
 using android::base::unique_fd;
@@ -195,6 +196,7 @@
     std::unique_ptr<std::string> volume_uuid_;
     std::string package_name_;
     std::string apk_path_;
+    std::string empty_dm_file_;
     std::string app_apk_dir_;
     std::string app_private_dir_ce_;
     std::string app_private_dir_de_;
@@ -239,18 +241,14 @@
     }
 
     ::testing::AssertionResult create_mock_app() {
-        // Create the oat dir.
-        app_oat_dir_ = app_apk_dir_ + "/oat";
         // For debug mode, the directory might already exist. Avoid erroring out.
         if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
             return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
                                                  << " : " << strerror(errno);
         }
-        binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
-        if (!status.isOk()) {
-            return ::testing::AssertionFailure() << "Could not create oat dir: "
-                                                 << status.toString8().c_str();
-        }
+
+        // Initialize the oat dir path.
+        app_oat_dir_ = app_apk_dir_ + "/oat";
 
         // Copy the primary apk.
         apk_path_ = app_apk_dir_ + "/base.jar";
@@ -260,8 +258,28 @@
                                                  << " : " << error_msg;
         }
 
+        // Create an empty dm file.
+        empty_dm_file_ = apk_path_ + ".dm";
+        {
+            int fd = open(empty_dm_file_.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+            if (fd < 0) {
+                return ::testing::AssertionFailure() << "Could not open " << empty_dm_file_;
+            }
+            FILE* file = fdopen(fd, "wb");
+            if (file == nullptr) {
+                return ::testing::AssertionFailure() << "Null file for " << empty_dm_file_
+                         << " fd=" << fd;
+            }
+            ZipWriter writer(file);
+            // Add vdex to zip.
+            writer.StartEntry("primary.prof", ZipWriter::kCompress);
+            writer.FinishEntry();
+            writer.Finish();
+            close(fd);
+          }
+
         // Create the app user data.
-        status = service_->createAppData(
+        binder::Status status = service_->createAppData(
                 volume_uuid_,
                 package_name_,
                 kTestUserId,
@@ -479,7 +497,7 @@
         bool prof_result;
         ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
                 package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
-                /*dex_metadata*/ nullptr, &prof_result));
+                dm_path_ptr, &prof_result));
         ASSERT_TRUE(prof_result);
 
         binder::Status result = service_->dexopt(apk_path_,
@@ -625,6 +643,16 @@
                         DEX2OAT_FROM_SCRATCH);
 }
 
+TEST_F(DexoptTest, DexoptPrimaryPublicCreateOatDir) {
+    LOG(INFO) << "DexoptPrimaryPublic";
+    ASSERT_BINDER_SUCCESS(service_->createOatDir(app_oat_dir_, kRuntimeIsa));
+    CompilePrimaryDexOk("verify",
+                        DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
+                        app_oat_dir_.c_str(),
+                        kTestAppGid,
+                        DEX2OAT_FROM_SCRATCH);
+}
+
 TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
     LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
     binder::Status status;
@@ -645,7 +673,9 @@
                         DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
@@ -655,7 +685,9 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
@@ -665,7 +697,9 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, ResolveStartupConstStrings) {
@@ -684,7 +718,9 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
@@ -701,7 +737,9 @@
                                 DEXOPT_GENERATE_APP_IMAGE,
                         app_oat_dir_.c_str(),
                         kTestAppGid,
-                        DEX2OAT_FROM_SCRATCH);
+                        DEX2OAT_FROM_SCRATCH,
+                        /*binder_result=*/nullptr,
+                        empty_dm_file_.c_str());
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp
index f1ac717..60d6492 100644
--- a/cmds/installd/view_compiler.cpp
+++ b/cmds/installd/view_compiler.cpp
@@ -45,7 +45,7 @@
     // and pass file descriptors.
 
     // Open input file
-    unique_fd infd{open(apk_path, 0)};
+    unique_fd infd{open(apk_path, O_RDONLY)}; // NOLINT(android-cloexec-open)
     if (infd.get() < 0) {
         PLOG(ERROR) << "Could not open input file: " << apk_path;
         return false;
@@ -53,7 +53,7 @@
 
     // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so
     // we close stdout and open it towards the right output.
-    unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY, 0644)};
+    unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644)};
     if (outfd.get() < 0) {
         PLOG(ERROR) << "Could not open output file: " << out_dex_file;
         return false;
@@ -62,10 +62,6 @@
         PLOG(ERROR) << "Could not change output file permissions";
         return false;
     }
-    if (close(STDOUT_FILENO) != 0) {
-        PLOG(ERROR) << "Could not close stdout";
-        return false;
-    }
     if (dup2(outfd, STDOUT_FILENO) < 0) {
         PLOG(ERROR) << "Could not duplicate output file descriptor";
         return false;
@@ -96,4 +92,4 @@
 }
 
 } // namespace installd
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h
index f7c6e57..aa141ca 100644
--- a/cmds/installd/view_compiler.h
+++ b/cmds/installd/view_compiler.h
@@ -26,4 +26,4 @@
 } // namespace installd
 } // namespace android
 
-#endif // VIEW_COMPILER_H_
\ No newline at end of file
+#endif // VIEW_COMPILER_H_
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 93d878b..f8b8c68 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library_shared {
+cc_library_static {
     name: "liblshal",
     shared_libs: [
         "libbase",
@@ -36,6 +36,7 @@
         "TableEntry.cpp",
         "TextTable.cpp",
         "utils.cpp",
+        "WaitCommand.cpp",
     ],
     cflags: [
         "-Wall",
@@ -47,13 +48,16 @@
     name: "lshal_defaults",
     shared_libs: [
         "libbase",
-        "libhidlbase",
-        "libhidl-gen-utils",
-        "libhidltransport",
-        "liblshal",
+        "libcutils",
         "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhidl-gen-hash",
+        "libhidl-gen-utils",
+        "libvintf",
     ],
     static_libs: [
+        "liblshal",
         "libprocpartition",
     ],
     cflags: ["-Wall", "-Werror"],
@@ -69,14 +73,18 @@
 
 cc_test {
     name: "lshal_test",
+    test_suites: ["device-tests"],
     defaults: ["lshal_defaults"],
     gtest: true,
     static_libs: [
-        "libgmock"
+        "android.hardware.tests.baz@1.0",
+        "libgmock",
     ],
     shared_libs: [
+        "libhwbinder",
+        "libhidlbase",
+        "libhidltransport",
         "libvintf",
-        "android.hardware.tests.baz@1.0"
     ],
     srcs: [
         "test.cpp"
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index e19e3f7..84809d9 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_COMMAND_H_
+#pragma once
 
 #include "utils.h"
 
@@ -48,5 +47,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 0952db6..af22ac9 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -79,7 +79,7 @@
             "    lshal debug [-E] <interface> [options [options [...]]] \n"
             "        Print debug information of a specified interface.\n"
             "        -E: excludes debug output if HAL is actually a subclass.\n"
-            "        <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
+            "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
             "            If instance name is missing `default` is used.\n"
             "        options: space separated options to IBase::debug.\n";
 
@@ -88,4 +88,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 3c3f56f..cd57e31 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+#pragma once
 
 #include <string>
 
@@ -53,5 +52,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index da0cba6..bfa8500 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
+#pragma once
 
 #include <string>
 
@@ -44,5 +43,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_HELP_COMMAND_H_
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index c706d91..ad7e4c4 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -975,7 +975,8 @@
        "    - DM: if the HAL is in the device manifest\n"
        "    - DC: if the HAL is in the device compatibility matrix\n"
        "    - FM: if the HAL is in the framework manifest\n"
-       "    - FC: if the HAL is in the framework compatibility matrix"});
+       "    - FC: if the HAL is in the framework compatibility matrix\n"
+       "    - X: if the HAL is in none of the above lists"});
     mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
         thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
         return OK;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 85195fc..b3ed23d 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
+#pragma once
 
 #include <getopt.h>
 #include <stdint.h>
@@ -206,5 +205,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LIST_COMMAND_H_
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 8c83457..132b31e 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -26,7 +26,9 @@
 #include <hidl/HidlTransportUtils.h>
 
 #include "DebugCommand.h"
+#include "HelpCommand.h"
 #include "ListCommand.h"
+#include "WaitCommand.h"
 #include "PipeRelay.h"
 
 namespace android {
@@ -49,6 +51,7 @@
     mRegisteredCommands.push_back({std::make_unique<ListCommand>(*this)});
     mRegisteredCommands.push_back({std::make_unique<DebugCommand>(*this)});
     mRegisteredCommands.push_back({std::make_unique<HelpCommand>(*this)});
+    mRegisteredCommands.push_back({std::make_unique<WaitCommand>(*this)});
 }
 
 void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const {
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 9457f1e..830bd87 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
+#pragma once
 
 #include <iostream>
 #include <string>
@@ -25,7 +24,6 @@
 #include <utils/StrongPointer.h>
 
 #include "Command.h"
-#include "HelpCommand.h"
 #include "NullableOStream.h"
 #include "utils.h"
 
@@ -76,5 +74,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index 737d3a2..7cffcf8 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
+#pragma once
 
 #include <iostream>
 
@@ -69,5 +68,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_NULLABLE_O_STREAM_H_
diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h
index 8dc3093..835016041 100644
--- a/cmds/lshal/PipeRelay.h
+++ b/cmds/lshal/PipeRelay.h
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
-
-#define FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
+#pragma once
 
 #include <android-base/macros.h>
 #include <ostream>
@@ -53,6 +51,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORKS_NATIVE_CMDS_LSHAL_PIPE_RELAY_H_
-
diff --git a/cmds/lshal/TEST_MAPPING b/cmds/lshal/TEST_MAPPING
new file mode 100644
index 0000000..0320624
--- /dev/null
+++ b/cmds/lshal/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+  "presubmit": [
+    {
+      "name": "lshal_test"
+    }
+  ]
+}
+
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 601b7e2..0ff0c96 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
+#pragma once
 
 #include <stdint.h>
 
@@ -157,5 +156,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index 301b4bd..be41a08 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
+#pragma once
 
 #include <iostream>
 #include <string>
@@ -80,5 +79,3 @@
 
 } // namespace lshal
 } // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TEXT_TABLE_H_
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index 46d8177..e8d22d9 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#pragma once
+
 #include <condition_variable>
 #include <chrono>
 #include <functional>
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
new file mode 100644
index 0000000..65b41b9
--- /dev/null
+++ b/cmds/lshal/WaitCommand.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 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 "WaitCommand.h"
+
+#include "Lshal.h"
+
+#include <hidl/ServiceManagement.h>
+#include <hidl-util/FQName.h>
+
+namespace android {
+namespace lshal {
+
+std::string WaitCommand::getName() const {
+    return "wait";
+}
+
+std::string WaitCommand::getSimpleDescription() const {
+    return "Wait for HAL to start if it is not already started.";
+}
+
+Status WaitCommand::parseArgs(const Arg &arg) {
+    if (optind + 1 != arg.argc) {
+        return USAGE;
+    }
+
+    mInterfaceName = arg.argv[optind];
+    ++optind;
+    return OK;
+}
+
+Status WaitCommand::main(const Arg &arg) {
+    Status status = parseArgs(arg);
+    if (status != OK) {
+        return status;
+    }
+
+    auto [interface, instance] = splitFirst(mInterfaceName, '/');
+    instance = instance.empty() ? "default" : instance;
+
+    FQName fqName;
+    if (!FQName::parse(interface, &fqName) || fqName.isIdentifier() || !fqName.isFullyQualified()) {
+        mLshal.err() << "Invalid fully-qualified name '" << interface << "'\n\n";
+        return USAGE;
+    }
+
+    using android::hidl::manager::V1_0::IServiceManager;
+
+    using android::hardware::details::getRawServiceInternal;
+    auto service = getRawServiceInternal(interface, instance, true /*retry*/, false /*getStub*/);
+
+    if (service == nullptr) {
+        mLshal.err() << "Service not found (missing permissions or not in VINTF manifest?).\n";
+        return NO_INTERFACE;
+    }
+
+    return OK;
+}
+
+void WaitCommand::usage() const {
+    static const std::string debug =
+            "wait:\n"
+            "    lshal wait <interface/instance> \n"
+            "        For a HAL that is on the device, wait for the HAL to start.\n"
+            "        This will not start a HAL unless it is configured as a lazy HAL.\n"
+            "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
+            "            If instance name is missing `default` is used.\n";
+
+    mLshal.err() << debug;
+}
+
+}  // namespace lshal
+}  // namespace android
+
diff --git a/cmds/lshal/WaitCommand.h b/cmds/lshal/WaitCommand.h
new file mode 100644
index 0000000..c9f67c2
--- /dev/null
+++ b/cmds/lshal/WaitCommand.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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 <string>
+
+#include <android-base/macros.h>
+
+#include "Command.h"
+#include "utils.h"
+
+namespace android {
+namespace lshal {
+
+class Lshal;
+
+class WaitCommand : public Command {
+public:
+    explicit WaitCommand(Lshal &lshal) : Command(lshal) {}
+    ~WaitCommand() = default;
+    Status main(const Arg &arg) override;
+    void usage() const override;
+    std::string getSimpleDescription() const override;
+    std::string getName() const override;
+private:
+    Status parseArgs(const Arg &arg);
+
+    std::string mInterfaceName;
+
+    DISALLOW_COPY_AND_ASSIGN(WaitCommand);
+};
+
+
+}  // namespace lshal
+}  // namespace android
diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
index 7e86432..ca1e690 100644
--- a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
+++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
+#pragma once
 
 #include <sys/types.h>
 
@@ -44,5 +43,3 @@
 
 }  // namespace procpartition
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index fc8d58b..76f7c7f 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -493,19 +493,19 @@
 TEST_F(ListTest, DumpDefault) {
     const std::string expected =
         "[fake description 0]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
-        "Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
+        "X     Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
         "\n"
         "[fake description 1]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
-        "? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     ? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
+        "X     ? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
         "\n"
         "[fake description 2]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
-        "? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     ? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
+        "X     ? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
         "\n";
 
     optind = 1; // mimic Lshal::parseArg()
diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h
index 240155e..04f5272 100644
--- a/cmds/lshal/utils.h
+++ b/cmds/lshal/utils.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
-#define FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
+#pragma once
 
 #include <iomanip>
 #include <iostream>
@@ -88,5 +87,3 @@
 
 }  // namespace lshal
 }  // namespace android
-
-#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_UTILS_H_
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index 9513ec1..a5b1ac5 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -4,6 +4,7 @@
     srcs: ["service.cpp"],
 
     shared_libs: [
+        "libcutils",
         "libutils",
         "libbinder",
     ],
@@ -22,6 +23,7 @@
     srcs: ["service.cpp"],
 
     shared_libs: [
+        "libcutils",
         "libutils",
         "libbinder",
     ],
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index d5dc6b7..18b6b58 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -18,13 +18,18 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <binder/TextOutput.h>
+#include <cutils/ashmem.h>
 
 #include <getopt.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/mman.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 using namespace android;
 
@@ -70,7 +75,7 @@
 {
     bool wantsUsage = false;
     int result = 0;
-    
+
     while (1) {
         int ic = getopt(argc, argv, "h?");
         if (ic < 0)
@@ -97,7 +102,7 @@
         aerr << "service: Unable to get default service manager!" << endl;
         return 20;
     }
-    
+
     if (optind >= argc) {
         wantsUsage = true;
     } else if (!wantsUsage) {
@@ -119,8 +124,8 @@
             for (unsigned i = 0; i < services.size(); i++) {
                 String16 name = services[i];
                 sp<IBinder> service = sm->checkService(name);
-                aout << i 
-                     << "\t" << good_old_string(name) 
+                aout << i
+                     << "\t" << good_old_string(name)
                      << ": [" << good_old_string(get_interface_name(service)) << "]"
                      << endl;
             }
@@ -187,69 +192,120 @@
                         } else if (strcmp(argv[optind], "null") == 0) {
                             optind++;
                             data.writeStrongBinder(nullptr);
-                        } else if (strcmp(argv[optind], "intent") == 0) {
-                        	
-                        	char* action = nullptr;
-                        	char* dataArg = nullptr;
-                        	char* type = nullptr;
-                        	int launchFlags = 0;
-                        	char* component = nullptr;
-                        	int categoryCount = 0;
-                        	char* categories[16];
-                        	
-                        	char* context1 = nullptr;
-                        	
+                        } else if (strcmp(argv[optind], "fd") == 0) {
                             optind++;
-                            
-                        	while (optind < argc)
-                        	{
-                        		char* key = strtok_r(argv[optind], "=", &context1);
-                        		char* value = strtok_r(nullptr, "=", &context1);
-                                
+                            if (optind >= argc) {
+                                aerr << "service: no path supplied for 'fd'" << endl;
+                                wantsUsage = true;
+                                result = 10;
+                                break;
+                            }
+                            const char *path = argv[optind++];
+                            int fd = open(path, O_RDONLY);
+                            if (fd < 0) {
+                                aerr << "service: could not open '" << path << "'" << endl;
+                                wantsUsage = true;
+                                result = 10;
+                                break;
+                            }
+                            data.writeFileDescriptor(fd, true /* take ownership */);
+                        } else if (strcmp(argv[optind], "afd") == 0) {
+                            optind++;
+                            if (optind >= argc) {
+                                aerr << "service: no path supplied for 'afd'" << endl;
+                                wantsUsage = true;
+                                result = 10;
+                                break;
+                            }
+                            const char *path = argv[optind++];
+                            int fd = open(path, O_RDONLY);
+                            struct stat statbuf;
+                            if (fd < 0 || fstat(fd, &statbuf) != 0) {
+                                aerr << "service: could not open or stat '" << path << "'" << endl;
+                                wantsUsage = true;
+                                result = 10;
+                                break;
+                            }
+                            int afd = ashmem_create_region("test", statbuf.st_size);
+                            void* ptr = mmap(NULL, statbuf.st_size,
+                                   PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
+                            read(fd, ptr, statbuf.st_size);
+                            close(fd);
+                            data.writeFileDescriptor(afd, true /* take ownership */);
+                        } else if (strcmp(argv[optind], "nfd") == 0) {
+                            optind++;
+                            if (optind >= argc) {
+                                aerr << "service: no file descriptor supplied for 'nfd'" << endl;
+                                wantsUsage = true;
+                                result = 10;
+                                break;
+                            }
+                            data.writeFileDescriptor(
+                                    atoi(argv[optind++]), true /* take ownership */);
+
+                        } else if (strcmp(argv[optind], "intent") == 0) {
+
+                            char* action = nullptr;
+                            char* dataArg = nullptr;
+                            char* type = nullptr;
+                            int launchFlags = 0;
+                            char* component = nullptr;
+                            int categoryCount = 0;
+                            char* categories[16];
+
+                            char* context1 = nullptr;
+
+                            optind++;
+
+                            while (optind < argc)
+                            {
+                                char* key = strtok_r(argv[optind], "=", &context1);
+                                char* value = strtok_r(nullptr, "=", &context1);
+
                                 // we have reached the end of the XXX=XXX args.
                                 if (key == nullptr) break;
-                        		
-                        		if (strcmp(key, "action") == 0)
-                        		{
-                        			action = value;
-                        		}
-                        		else if (strcmp(key, "data") == 0)
-                        		{
-                        			dataArg = value;
-                        		}
-                        		else if (strcmp(key, "type") == 0)
-                        		{
-                        			type = value;
-                        		}
-                        		else if (strcmp(key, "launchFlags") == 0)
-                        		{
-                        			launchFlags = atoi(value);
-                        		}
-                        		else if (strcmp(key, "component") == 0)
-                        		{
-                        			component = value;
-                        		}
-                        		else if (strcmp(key, "categories") == 0)
-                        		{
-                        			char* context2 = nullptr;
-                        			categories[categoryCount] = strtok_r(value, ",", &context2);
-                        			
-                        			while (categories[categoryCount] != nullptr)
-                        			{
-                        				categoryCount++;
-                        				categories[categoryCount] = strtok_r(nullptr, ",", &context2);
-                        			}
-                        		}
-                                
+
+                                if (strcmp(key, "action") == 0)
+                                {
+                                    action = value;
+                                }
+                                else if (strcmp(key, "data") == 0)
+                                {
+                                    dataArg = value;
+                                }
+                                else if (strcmp(key, "type") == 0)
+                                {
+                                    type = value;
+                                }
+                                else if (strcmp(key, "launchFlags") == 0)
+                                {
+                                    launchFlags = atoi(value);
+                                }
+                                else if (strcmp(key, "component") == 0)
+                                {
+                                    component = value;
+                                }
+                                else if (strcmp(key, "categories") == 0)
+                                {
+                                    char* context2 = nullptr;
+                                    categories[categoryCount] = strtok_r(value, ",", &context2);
+
+                                    while (categories[categoryCount] != nullptr)
+                                    {
+                                        categoryCount++;
+                                        categories[categoryCount] = strtok_r(nullptr, ",", &context2);
+                                    }
+                                }
+
                                 optind++;
-                        	} 
-                        	
+                            }
+
                             writeString16(data, action);
                             writeString16(data, dataArg);
                             writeString16(data, type);
-                       		data.writeInt32(launchFlags);
+                            data.writeInt32(launchFlags);
                             writeString16(data, component);
-                        	
+
                             if (categoryCount > 0)
                             {
                                 data.writeInt32(categoryCount);
@@ -261,10 +317,10 @@
                             else
                             {
                                 data.writeInt32(0);
-                            }                            
-  
+                            }
+
                             // for now just set the extra field to be null.
-                       		data.writeInt32(-1);
+                            data.writeInt32(-1);
                         } else {
                             aerr << "service: unknown option " << argv[optind] << endl;
                             wantsUsage = true;
@@ -272,7 +328,7 @@
                             break;
                         }
                     }
-                    
+
                     service->transact(code, data, &reply);
                     aout << "Result: " << reply << endl;
                 } else {
@@ -295,23 +351,29 @@
             result = 10;
         }
     }
-    
+
     if (wantsUsage) {
         aout << "Usage: service [-h|-?]\n"
                 "       service list\n"
                 "       service check SERVICE\n"
-                "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
+                "       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null"
+                " | fd f | nfd n | afd f ] ...\n"
                 "Options:\n"
                 "   i32: Write the 32-bit integer N into the send parcel.\n"
                 "   i64: Write the 64-bit integer N into the send parcel.\n"
                 "   f:   Write the 32-bit single-precision number N into the send parcel.\n"
                 "   d:   Write the 64-bit double-precision number N into the send parcel.\n"
-                "   s16: Write the UTF-16 string STR into the send parcel.\n";
+                "   s16: Write the UTF-16 string STR into the send parcel.\n"
+                "  null: Write a null binder into the send parcel.\n"
+                "    fd: Write a file descriptor for the file f to the send parcel.\n"
+                "   nfd: Write file descriptor n to the send parcel.\n"
+                "   afd: Write an ashmem file descriptor for a region containing the data from"
+                " file f to the send parcel.\n";
 //                "   intent: Write and Intent int the send parcel. ARGS can be\n"
 //                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
         return result;
     }
-    
+
     return result;
 }
 
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
new file mode 100644
index 0000000..d936dbe
--- /dev/null
+++ b/cmds/servicemanager/Access.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2019 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 "Access.h"
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+#include <log/log_safetynet.h>
+#include <selinux/android.h>
+#include <selinux/avc.h>
+
+namespace android {
+
+#ifdef VENDORSERVICEMANAGER
+constexpr bool kIsVendor = true;
+#else
+constexpr bool kIsVendor = false;
+#endif
+
+static std::string getPidcon(pid_t pid) {
+    android_errorWriteLog(0x534e4554, "121035042");
+
+    char* lookup = nullptr;
+    if (getpidcon(pid, &lookup) < 0) {
+        LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
+        return "";
+    }
+    std::string result = lookup;
+    freecon(lookup);
+    return result;
+}
+
+static struct selabel_handle* getSehandle() {
+    static struct selabel_handle* gSehandle = nullptr;
+
+    if (gSehandle != nullptr && selinux_status_updated()) {
+        selabel_close(gSehandle);
+        gSehandle = nullptr;
+    }
+
+    if (gSehandle == nullptr) {
+        gSehandle = kIsVendor
+            ? selinux_android_vendor_service_context_handle()
+            : selinux_android_service_context_handle();
+    }
+
+    CHECK(gSehandle != nullptr);
+    return gSehandle;
+}
+
+static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
+    const Access::CallingContext* ad = reinterpret_cast<Access::CallingContext*>(data);
+
+    if (!ad) {
+        LOG(ERROR) << "No service manager audit data";
+        return 0;
+    }
+
+    snprintf(buf, len, "pid=%d uid=%d", ad->debugPid, ad->uid);
+    return 0;
+}
+
+Access::Access() {
+    union selinux_callback cb;
+
+    cb.func_audit = auditCallback;
+    selinux_set_callback(SELINUX_CB_AUDIT, cb);
+
+    cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+    CHECK(selinux_status_open(true /*fallback*/) >= 0);
+
+    CHECK(getcon(&mThisProcessContext) == 0);
+}
+
+Access::~Access() {
+    freecon(mThisProcessContext);
+}
+
+Access::CallingContext Access::getCallingContext() {
+    IPCThreadState* ipc = IPCThreadState::self();
+
+    const char* callingSid = ipc->getCallingSid();
+    pid_t callingPid = ipc->getCallingPid();
+
+    return CallingContext {
+        .debugPid = callingPid,
+        .uid = ipc->getCallingUid(),
+        .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
+    };
+}
+
+bool Access::canFind(const CallingContext& ctx,const std::string& name) {
+    return actionAllowedFromLookup(ctx, name, "find");
+}
+
+bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
+    return actionAllowedFromLookup(ctx, name, "add");
+}
+
+bool Access::canList(const CallingContext& ctx) {
+    return actionAllowed(ctx, mThisProcessContext, "list");
+}
+
+bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm) {
+    const char* tclass = "service_manager";
+
+    return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm, reinterpret_cast<void*>(const_cast<CallingContext*>((&sctx))));
+}
+
+bool Access::actionAllowedFromLookup(const CallingContext& sctx, const std::string& name, const char *perm) {
+    char *tctx = nullptr;
+    if (selabel_lookup(getSehandle(), &tctx, name.c_str(), 0) != 0) {
+        LOG(ERROR) << "SELinux: No match for " << name << " in service_contexts.\n";
+        return false;
+    }
+
+    bool allowed = actionAllowed(sctx, tctx, perm);
+    freecon(tctx);
+    return allowed;
+}
+
+}  // android
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
new file mode 100644
index 0000000..05a60d3
--- /dev/null
+++ b/cmds/servicemanager/Access.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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 <string>
+#include <sys/types.h>
+
+namespace android {
+
+// singleton
+class Access {
+public:
+    Access();
+    virtual ~Access();
+
+    Access(const Access&) = delete;
+    Access& operator=(const Access&) = delete;
+    Access(Access&&) = delete;
+    Access& operator=(Access&&) = delete;
+
+    struct CallingContext {
+        pid_t debugPid;
+        uid_t uid;
+        std::string sid;
+    };
+
+    virtual CallingContext getCallingContext();
+
+    virtual bool canFind(const CallingContext& ctx, const std::string& name);
+    virtual bool canAdd(const CallingContext& ctx, const std::string& name);
+    virtual bool canList(const CallingContext& ctx);
+
+private:
+    bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm);
+    bool actionAllowedFromLookup(const CallingContext& sctx, const std::string& name,
+            const char *perm);
+
+    char* mThisProcessContext = nullptr;
+};
+
+};
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 428561b..9cf3c5c 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,51 +1,51 @@
 cc_defaults {
-    name: "servicemanager_flags",
+    name: "servicemanager_defaults",
 
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
     ],
-    product_variables: {
-        binder32bit: {
-            cflags: ["-DBINDER_IPC_32BIT=1"],
-        },
-    },
 
-    shared_libs: ["liblog"],
-}
-
-cc_binary {
-    name: "bctest",
-    defaults: ["servicemanager_flags"],
     srcs: [
-        "bctest.c",
-        "binder.c",
+        "Access.cpp",
+        "ServiceManager.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder", // also contains servicemanager_interface
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libselinux",
     ],
 }
 
 cc_binary {
     name: "servicemanager",
-    defaults: ["servicemanager_flags"],
-    srcs: [
-        "service_manager.c",
-        "binder.c",
-    ],
-    shared_libs: ["libcutils", "libselinux"],
+    defaults: ["servicemanager_defaults"],
     init_rc: ["servicemanager.rc"],
+    srcs: ["main.cpp"],
 }
 
 cc_binary {
     name: "vndservicemanager",
-    defaults: ["servicemanager_flags"],
+    defaults: ["servicemanager_defaults"],
+    init_rc: ["vndservicemanager.rc"],
     vendor: true,
-    srcs: [
-        "service_manager.c",
-        "binder.c",
-    ],
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils", "libselinux"],
-    init_rc: ["vndservicemanager.rc"],
+    srcs: ["main.cpp"],
+}
+
+cc_test {
+    name: "servicemanager_test",
+    test_suites: ["device-tests"],
+    defaults: ["servicemanager_defaults"],
+    srcs: [
+        "test_sm.cpp",
+    ],
+    static_libs: ["libgmock"],
 }
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
new file mode 100644
index 0000000..c2c71e0
--- /dev/null
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2019 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 "ServiceManager.h"
+
+#include <android-base/logging.h>
+#include <cutils/android_filesystem_config.h>
+#include <cutils/multiuser.h>
+
+using ::android::binder::Status;
+
+namespace android {
+
+ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
+
+Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
+    // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
+    return checkService(name, outBinder);
+}
+
+Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+    auto ctx = mAccess->getCallingContext();
+
+    auto it = mNameToService.find(name);
+    if (it == mNameToService.end()) {
+        *outBinder = nullptr;
+        return Status::ok();
+    }
+
+    const Service& service = it->second;
+
+    if (!service.allowIsolated) {
+        uid_t appid = multiuser_get_app_id(ctx.uid);
+        bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
+
+        if (isIsolated) {
+            *outBinder = nullptr;
+            return Status::ok();
+        }
+    }
+
+    // TODO(b/136023468): move this check to be first
+    if (!mAccess->canFind(ctx, name)) {
+        // returns ok and null for legacy reasons
+        *outBinder = nullptr;
+        return Status::ok();
+    }
+
+    *outBinder = service.binder;
+    return Status::ok();
+}
+
+bool isValidServiceName(const std::string& name) {
+    if (name.size() == 0) return false;
+    if (name.size() > 127) return false;
+
+    for (char c : name) {
+        if (c == '_' || c == '-' || c == '.') continue;
+        if (c >= 'a' && c <= 'z') continue;
+        if (c >= 'A' && c <= 'Z') continue;
+        if (c >= '0' && c <= '9') continue;
+        return false;
+    }
+
+    return true;
+}
+
+Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
+    auto ctx = mAccess->getCallingContext();
+
+    // apps cannot add services
+    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    if (!mAccess->canAdd(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    if (binder == nullptr) {
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (!isValidServiceName(name)) {
+        LOG(ERROR) << "Invalid service name: " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (OK != binder->linkToDeath(this)) {
+        LOG(ERROR) << "Could not linkToDeath when adding " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+    }
+
+    auto it = mNameToService.find(name);
+    if (it != mNameToService.end()) {
+        if (OK != it->second.binder->unlinkToDeath(this)) {
+            LOG(WARNING) << "Could not unlinkToDeath when adding " << name;
+        }
+    }
+
+    mNameToService[name] = Service {
+        .binder = binder,
+        .allowIsolated = allowIsolated,
+        .dumpPriority = dumpPriority,
+    };
+
+    return Status::ok();
+}
+
+Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
+    if (!mAccess->canList(mAccess->getCallingContext())) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    size_t toReserve = 0;
+    for (auto const& [name, service] : mNameToService) {
+        (void) name;
+
+        if (service.dumpPriority & dumpPriority) ++toReserve;
+    }
+
+    CHECK(outList->empty());
+
+    outList->reserve(toReserve);
+    for (auto const& [name, service] : mNameToService) {
+        (void) service;
+
+        if (service.dumpPriority & dumpPriority) {
+            outList->push_back(name);
+        }
+    }
+
+    return Status::ok();
+}
+
+void ServiceManager::binderDied(const wp<IBinder>& who) {
+    for (auto it = mNameToService.begin(); it != mNameToService.end();) {
+        if (who == it->second.binder) {
+            it = mNameToService.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
new file mode 100644
index 0000000..78e4805
--- /dev/null
+++ b/cmds/servicemanager/ServiceManager.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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 <android/os/BnServiceManager.h>
+
+#include "Access.h"
+
+namespace android {
+
+class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
+public:
+    ServiceManager(std::unique_ptr<Access>&& access);
+
+    binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
+    binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
+    binder::Status addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) override;
+    binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
+
+    void binderDied(const wp<IBinder>& who) override;
+
+private:
+    struct Service {
+        sp<IBinder> binder;
+        bool allowIsolated;
+        int32_t dumpPriority;
+    };
+
+    std::map<std::string, Service> mNameToService;
+    std::unique_ptr<Access> mAccess;
+};
+
+}  // namespace android
diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING
new file mode 100644
index 0000000..739740a
--- /dev/null
+++ b/cmds/servicemanager/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "servicemanager_test"
+    }
+  ],
+  "imports": [
+    {
+      "path": "frameworks/native/libs/binder"
+    }
+  ]
+}
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
deleted file mode 100644
index 354df67..0000000
--- a/cmds/servicemanager/bctest.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "binder.h"
-
-uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
-{
-    uint32_t handle;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
-        return 0;
-
-    handle = bio_get_ref(&reply);
-
-    if (handle)
-        binder_acquire(bs, handle);
-
-    binder_done(bs, &msg, &reply);
-
-    return handle;
-}
-
-int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
-{
-    int status;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-    bio_put_obj(&msg, ptr);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
-        return -1;
-
-    status = bio_get_uint32(&reply);
-
-    binder_done(bs, &msg, &reply);
-
-    return status;
-}
-
-unsigned token;
-
-int main(int argc, char **argv)
-{
-    struct binder_state *bs;
-    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
-    uint32_t handle;
-
-    bs = binder_open("/dev/binder", 128*1024);
-    if (!bs) {
-        fprintf(stderr, "failed to open binder driver\n");
-        return -1;
-    }
-
-    argc--;
-    argv++;
-    while (argc > 0) {
-        if (!strcmp(argv[0],"alt")) {
-            handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
-            if (!handle) {
-                fprintf(stderr,"cannot find alt_svc_mgr\n");
-                return -1;
-            }
-            svcmgr = handle;
-            fprintf(stderr,"svcmgr is via %x\n", handle);
-        } else if (!strcmp(argv[0],"lookup")) {
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            handle = svcmgr_lookup(bs, svcmgr, argv[1]);
-            fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle);
-            argc--;
-            argv++;
-        } else if (!strcmp(argv[0],"publish")) {
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            svcmgr_publish(bs, svcmgr, argv[1], &token);
-            argc--;
-            argv++;
-        } else {
-            fprintf(stderr,"unknown command %s\n", argv[0]);
-            return -1;
-        }
-        argc--;
-        argv++;
-    }
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
deleted file mode 100644
index cf3b172..0000000
--- a/cmds/servicemanager/binder.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#define LOG_TAG "Binder"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include "binder.h"
-
-#define MAX_BIO_SIZE (1 << 30)
-
-#define TRACE 0
-
-void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
-
-#if TRACE
-void hexdump(void *_data, size_t len)
-{
-    unsigned char *data = _data;
-    size_t count;
-
-    for (count = 0; count < len; count++) {
-        if ((count & 15) == 0)
-            fprintf(stderr,"%04zu:", count);
-        fprintf(stderr," %02x %c", *data,
-                (*data < 32) || (*data > 126) ? '.' : *data);
-        data++;
-        if ((count & 15) == 15)
-            fprintf(stderr,"\n");
-    }
-    if ((count & 15) != 0)
-        fprintf(stderr,"\n");
-}
-
-void binder_dump_txn(struct binder_transaction_data *txn)
-{
-    struct flat_binder_object *obj;
-    binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
-    size_t count = txn->offsets_size / sizeof(binder_size_t);
-
-    fprintf(stderr,"  target %016"PRIx64"  cookie %016"PRIx64"  code %08x  flags %08x\n",
-            (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
-    fprintf(stderr,"  pid %8d  uid %8d  data %"PRIu64"  offs %"PRIu64"\n",
-            txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
-    hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
-    while (count--) {
-        obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
-        fprintf(stderr,"  - type %08x  flags %08x  ptr %016"PRIx64"  cookie %016"PRIx64"\n",
-                obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
-    }
-}
-
-#define NAME(n) case n: return #n
-const char *cmd_name(uint32_t cmd)
-{
-    switch(cmd) {
-        NAME(BR_NOOP);
-        NAME(BR_TRANSACTION_COMPLETE);
-        NAME(BR_INCREFS);
-        NAME(BR_ACQUIRE);
-        NAME(BR_RELEASE);
-        NAME(BR_DECREFS);
-        NAME(BR_TRANSACTION);
-        NAME(BR_REPLY);
-        NAME(BR_FAILED_REPLY);
-        NAME(BR_DEAD_REPLY);
-        NAME(BR_DEAD_BINDER);
-    default: return "???";
-    }
-}
-#else
-#define hexdump(a,b) do{} while (0)
-#define binder_dump_txn(txn)  do{} while (0)
-#endif
-
-#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
-#define BIO_F_OVERFLOW  0x02  /* ran out of space */
-#define BIO_F_IOERROR   0x04
-#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
-
-struct binder_state
-{
-    int fd;
-    void *mapped;
-    size_t mapsize;
-};
-
-struct binder_state *binder_open(const char* driver, size_t mapsize)
-{
-    struct binder_state *bs;
-    struct binder_version vers;
-
-    bs = malloc(sizeof(*bs));
-    if (!bs) {
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
-    if (bs->fd < 0) {
-        fprintf(stderr,"binder: cannot open %s (%s)\n",
-                driver, strerror(errno));
-        goto fail_open;
-    }
-
-    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
-        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
-        fprintf(stderr,
-                "binder: kernel driver version (%d) differs from user space version (%d)\n",
-                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
-        goto fail_open;
-    }
-
-    bs->mapsize = mapsize;
-    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
-    if (bs->mapped == MAP_FAILED) {
-        fprintf(stderr,"binder: cannot map device (%s)\n",
-                strerror(errno));
-        goto fail_map;
-    }
-
-    return bs;
-
-fail_map:
-    close(bs->fd);
-fail_open:
-    free(bs);
-    return NULL;
-}
-
-void binder_close(struct binder_state *bs)
-{
-    munmap(bs->mapped, bs->mapsize);
-    close(bs->fd);
-    free(bs);
-}
-
-int binder_become_context_manager(struct binder_state *bs)
-{
-    struct flat_binder_object obj;
-    memset(&obj, 0, sizeof(obj));
-    obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
-
-    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
-
-    // fallback to original method
-    if (result != 0) {
-        android_errorWriteLog(0x534e4554, "121035042");
-
-        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
-    }
-    return result;
-}
-
-int binder_write(struct binder_state *bs, void *data, size_t len)
-{
-    struct binder_write_read bwr;
-    int res;
-
-    bwr.write_size = len;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (uintptr_t) data;
-    bwr.read_size = 0;
-    bwr.read_consumed = 0;
-    bwr.read_buffer = 0;
-    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-    if (res < 0) {
-        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
-                strerror(errno));
-    }
-    return res;
-}
-
-void binder_free_buffer(struct binder_state *bs,
-                        binder_uintptr_t buffer_to_free)
-{
-    struct {
-        uint32_t cmd_free;
-        binder_uintptr_t buffer;
-    } __attribute__((packed)) data;
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
-    binder_write(bs, &data, sizeof(data));
-}
-
-void binder_send_reply(struct binder_state *bs,
-                       struct binder_io *reply,
-                       binder_uintptr_t buffer_to_free,
-                       int status)
-{
-    struct {
-        uint32_t cmd_free;
-        binder_uintptr_t buffer;
-        uint32_t cmd_reply;
-        struct binder_transaction_data txn;
-    } __attribute__((packed)) data;
-
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
-    data.cmd_reply = BC_REPLY;
-    data.txn.target.ptr = 0;
-    data.txn.cookie = 0;
-    data.txn.code = 0;
-    if (status) {
-        data.txn.flags = TF_STATUS_CODE;
-        data.txn.data_size = sizeof(int);
-        data.txn.offsets_size = 0;
-        data.txn.data.ptr.buffer = (uintptr_t)&status;
-        data.txn.data.ptr.offsets = 0;
-    } else {
-        data.txn.flags = 0;
-        data.txn.data_size = reply->data - reply->data0;
-        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
-        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
-        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
-    }
-    binder_write(bs, &data, sizeof(data));
-}
-
-int binder_parse(struct binder_state *bs, struct binder_io *bio,
-                 uintptr_t ptr, size_t size, binder_handler func)
-{
-    int r = 1;
-    uintptr_t end = ptr + (uintptr_t) size;
-
-    while (ptr < end) {
-        uint32_t cmd = *(uint32_t *) ptr;
-        ptr += sizeof(uint32_t);
-#if TRACE
-        fprintf(stderr,"%s:\n", cmd_name(cmd));
-#endif
-        switch(cmd) {
-        case BR_NOOP:
-            break;
-        case BR_TRANSACTION_COMPLETE:
-            break;
-        case BR_INCREFS:
-        case BR_ACQUIRE:
-        case BR_RELEASE:
-        case BR_DECREFS:
-#if TRACE
-            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
-#endif
-            ptr += sizeof(struct binder_ptr_cookie);
-            break;
-        case BR_TRANSACTION_SEC_CTX:
-        case BR_TRANSACTION: {
-            struct binder_transaction_data_secctx txn;
-            if (cmd == BR_TRANSACTION_SEC_CTX) {
-                if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
-                    ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
-                    return -1;
-                }
-                memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
-                ptr += sizeof(struct binder_transaction_data_secctx);
-            } else /* BR_TRANSACTION */ {
-                if ((end - ptr) < sizeof(struct binder_transaction_data)) {
-                    ALOGE("parse: txn too small (binder_transaction_data)!\n");
-                    return -1;
-                }
-                memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
-                ptr += sizeof(struct binder_transaction_data);
-
-                txn.secctx = 0;
-            }
-
-            binder_dump_txn(&txn.transaction_data);
-            if (func) {
-                unsigned rdata[256/4];
-                struct binder_io msg;
-                struct binder_io reply;
-                int res;
-
-                bio_init(&reply, rdata, sizeof(rdata), 4);
-                bio_init_from_txn(&msg, &txn.transaction_data);
-                res = func(bs, &txn, &msg, &reply);
-                if (txn.transaction_data.flags & TF_ONE_WAY) {
-                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
-                } else {
-                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
-                }
-            }
-            break;
-        }
-        case BR_REPLY: {
-            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
-            if ((end - ptr) < sizeof(*txn)) {
-                ALOGE("parse: reply too small!\n");
-                return -1;
-            }
-            binder_dump_txn(txn);
-            if (bio) {
-                bio_init_from_txn(bio, txn);
-                bio = 0;
-            } else {
-                /* todo FREE BUFFER */
-            }
-            ptr += sizeof(*txn);
-            r = 0;
-            break;
-        }
-        case BR_DEAD_BINDER: {
-            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
-            ptr += sizeof(binder_uintptr_t);
-            death->func(bs, death->ptr);
-            break;
-        }
-        case BR_FAILED_REPLY:
-            r = -1;
-            break;
-        case BR_DEAD_REPLY:
-            r = -1;
-            break;
-        default:
-            ALOGE("parse: OOPS %d\n", cmd);
-            return -1;
-        }
-    }
-
-    return r;
-}
-
-void binder_acquire(struct binder_state *bs, uint32_t target)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_ACQUIRE;
-    cmd[1] = target;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_release(struct binder_state *bs, uint32_t target)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_RELEASE;
-    cmd[1] = target;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
-{
-    struct {
-        uint32_t cmd;
-        struct binder_handle_cookie payload;
-    } __attribute__((packed)) data;
-
-    data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
-    data.payload.handle = target;
-    data.payload.cookie = (uintptr_t) death;
-    binder_write(bs, &data, sizeof(data));
-}
-
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                uint32_t target, uint32_t code)
-{
-    int res;
-    struct binder_write_read bwr;
-    struct {
-        uint32_t cmd;
-        struct binder_transaction_data txn;
-    } __attribute__((packed)) writebuf;
-    unsigned readbuf[32];
-
-    if (msg->flags & BIO_F_OVERFLOW) {
-        fprintf(stderr,"binder: txn buffer overflow\n");
-        goto fail;
-    }
-
-    writebuf.cmd = BC_TRANSACTION;
-    writebuf.txn.target.handle = target;
-    writebuf.txn.code = code;
-    writebuf.txn.flags = 0;
-    writebuf.txn.data_size = msg->data - msg->data0;
-    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
-    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
-    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
-
-    bwr.write_size = sizeof(writebuf);
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (uintptr_t) &writebuf;
-
-    hexdump(msg->data0, msg->data - msg->data0);
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (uintptr_t) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
-            goto fail;
-        }
-
-        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
-        if (res == 0) return 0;
-        if (res < 0) goto fail;
-    }
-
-fail:
-    memset(reply, 0, sizeof(*reply));
-    reply->flags |= BIO_F_IOERROR;
-    return -1;
-}
-
-void binder_loop(struct binder_state *bs, binder_handler func)
-{
-    int res;
-    struct binder_write_read bwr;
-    uint32_t readbuf[32];
-
-    bwr.write_size = 0;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = 0;
-
-    readbuf[0] = BC_ENTER_LOOPER;
-    binder_write(bs, readbuf, sizeof(uint32_t));
-
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (uintptr_t) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
-            break;
-        }
-
-        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
-        if (res == 0) {
-            ALOGE("binder_loop: unexpected reply?!\n");
-            break;
-        }
-        if (res < 0) {
-            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
-            break;
-        }
-    }
-}
-
-void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
-{
-    bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
-    bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
-    bio->data_avail = txn->data_size;
-    bio->offs_avail = txn->offsets_size / sizeof(size_t);
-    bio->flags = BIO_F_SHARED;
-}
-
-void bio_init(struct binder_io *bio, void *data,
-              size_t maxdata, size_t maxoffs)
-{
-    size_t n = maxoffs * sizeof(size_t);
-
-    if (n > maxdata) {
-        bio->flags = BIO_F_OVERFLOW;
-        bio->data_avail = 0;
-        bio->offs_avail = 0;
-        return;
-    }
-
-    bio->data = bio->data0 = (char *) data + n;
-    bio->offs = bio->offs0 = data;
-    bio->data_avail = maxdata - n;
-    bio->offs_avail = maxoffs;
-    bio->flags = 0;
-}
-
-static void *bio_alloc(struct binder_io *bio, size_t size)
-{
-    size = (size + 3) & (~3);
-    if (size > bio->data_avail) {
-        bio->flags |= BIO_F_OVERFLOW;
-        return NULL;
-    } else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-void binder_done(struct binder_state *bs,
-                 __unused struct binder_io *msg,
-                 struct binder_io *reply)
-{
-    struct {
-        uint32_t cmd;
-        uintptr_t buffer;
-    } __attribute__((packed)) data;
-
-    if (reply->flags & BIO_F_SHARED) {
-        data.cmd = BC_FREE_BUFFER;
-        data.buffer = (uintptr_t) reply->data0;
-        binder_write(bs, &data, sizeof(data));
-        reply->flags = 0;
-    }
-}
-
-static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
-{
-    struct flat_binder_object *obj;
-
-    obj = bio_alloc(bio, sizeof(*obj));
-
-    if (obj && bio->offs_avail) {
-        bio->offs_avail--;
-        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
-        return obj;
-    }
-
-    bio->flags |= BIO_F_OVERFLOW;
-    return NULL;
-}
-
-void bio_put_uint32(struct binder_io *bio, uint32_t n)
-{
-    uint32_t *ptr = bio_alloc(bio, sizeof(n));
-    if (ptr)
-        *ptr = n;
-}
-
-void bio_put_obj(struct binder_io *bio, void *ptr)
-{
-    struct flat_binder_object *obj;
-
-    obj = bio_alloc_obj(bio);
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->hdr.type = BINDER_TYPE_BINDER;
-    obj->binder = (uintptr_t)ptr;
-    obj->cookie = 0;
-}
-
-void bio_put_ref(struct binder_io *bio, uint32_t handle)
-{
-    struct flat_binder_object *obj;
-
-    if (handle)
-        obj = bio_alloc_obj(bio);
-    else
-        obj = bio_alloc(bio, sizeof(*obj));
-
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->hdr.type = BINDER_TYPE_HANDLE;
-    obj->handle = handle;
-    obj->cookie = 0;
-}
-
-void bio_put_string16(struct binder_io *bio, const uint16_t *str)
-{
-    size_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = 0;
-    while (str[len]) len++;
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    bio_put_uint32(bio, (uint32_t) len);
-    len = (len + 1) * sizeof(uint16_t);
-    ptr = bio_alloc(bio, len);
-    if (ptr)
-        memcpy(ptr, str, len);
-}
-
-void bio_put_string16_x(struct binder_io *bio, const char *_str)
-{
-    unsigned char *str = (unsigned char*) _str;
-    size_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = strlen(_str);
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    bio_put_uint32(bio, len);
-    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
-    if (!ptr)
-        return;
-
-    while (*str)
-        *ptr++ = *str++;
-    *ptr++ = 0;
-}
-
-static void *bio_get(struct binder_io *bio, size_t size)
-{
-    size = (size + 3) & (~3);
-
-    if (bio->data_avail < size){
-        bio->data_avail = 0;
-        bio->flags |= BIO_F_OVERFLOW;
-        return NULL;
-    }  else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-uint32_t bio_get_uint32(struct binder_io *bio)
-{
-    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
-    return ptr ? *ptr : 0;
-}
-
-uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
-{
-    size_t len;
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    len = (size_t) bio_get_uint32(bio);
-    if (sz)
-        *sz = len;
-    return bio_get(bio, (len + 1) * sizeof(uint16_t));
-}
-
-static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
-{
-    size_t n;
-    size_t off = bio->data - bio->data0;
-
-    /* TODO: be smarter about this? */
-    for (n = 0; n < bio->offs_avail; n++) {
-        if (bio->offs[n] == off)
-            return bio_get(bio, sizeof(struct flat_binder_object));
-    }
-
-    bio->data_avail = 0;
-    bio->flags |= BIO_F_OVERFLOW;
-    return NULL;
-}
-
-uint32_t bio_get_ref(struct binder_io *bio)
-{
-    struct flat_binder_object *obj;
-
-    obj = _bio_get_obj(bio);
-    if (!obj)
-        return 0;
-
-    if (obj->hdr.type == BINDER_TYPE_HANDLE)
-        return obj->handle;
-
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
deleted file mode 100644
index a9ccc74..0000000
--- a/cmds/servicemanager/binder.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#ifndef _BINDER_H_
-#define _BINDER_H_
-
-#include <linux/android/binder.h>
-#include <sys/ioctl.h>
-
-struct binder_state;
-
-struct binder_io
-{
-    char *data;            /* pointer to read/write from */
-    binder_size_t *offs;   /* array of offsets */
-    size_t data_avail;     /* bytes available in data buffer */
-    size_t offs_avail;     /* entries available in offsets array */
-
-    char *data0;           /* start of data buffer */
-    binder_size_t *offs0;  /* start of offsets buffer */
-    uint32_t flags;
-    uint32_t unused;
-};
-
-struct binder_death {
-    void (*func)(struct binder_state *bs, void *ptr);
-    void *ptr;
-};
-
-/* the one magic handle */
-#define BINDER_SERVICE_MANAGER  0U
-
-#define SVC_MGR_NAME "android.os.IServiceManager"
-
-enum {
-    /* Must match definitions in IBinder.h and IServiceManager.h */
-    PING_TRANSACTION  = B_PACK_CHARS('_','P','N','G'),
-    SVC_MGR_GET_SERVICE = 1,
-    SVC_MGR_CHECK_SERVICE,
-    SVC_MGR_ADD_SERVICE,
-    SVC_MGR_LIST_SERVICES,
-};
-
-typedef int (*binder_handler)(struct binder_state *bs,
-                              struct binder_transaction_data_secctx *txn,
-                              struct binder_io *msg,
-                              struct binder_io *reply);
-
-struct binder_state *binder_open(const char* driver, size_t mapsize);
-void binder_close(struct binder_state *bs);
-
-/* initiate a blocking binder call
- * - returns zero on success
- */
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                uint32_t target, uint32_t code);
-
-/* release any state associate with the binder_io
- * - call once any necessary data has been extracted from the
- *   binder_io after binder_call() returns
- * - can safely be called even if binder_call() fails
- */
-void binder_done(struct binder_state *bs,
-                 struct binder_io *msg, struct binder_io *reply);
-
-/* manipulate strong references */
-void binder_acquire(struct binder_state *bs, uint32_t target);
-void binder_release(struct binder_state *bs, uint32_t target);
-
-void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death);
-
-void binder_loop(struct binder_state *bs, binder_handler func);
-
-int binder_become_context_manager(struct binder_state *bs);
-
-/* allocate a binder_io, providing a stack-allocated working
- * buffer, size of the working buffer, and how many object
- * offset entries to reserve from the buffer
- */
-void bio_init(struct binder_io *bio, void *data,
-           size_t maxdata, size_t maxobjects);
-
-void bio_put_obj(struct binder_io *bio, void *ptr);
-void bio_put_ref(struct binder_io *bio, uint32_t handle);
-void bio_put_uint32(struct binder_io *bio, uint32_t n);
-void bio_put_string16(struct binder_io *bio, const uint16_t *str);
-void bio_put_string16_x(struct binder_io *bio, const char *_str);
-
-uint32_t bio_get_uint32(struct binder_io *bio);
-uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz);
-uint32_t bio_get_ref(struct binder_io *bio);
-
-#endif
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
new file mode 100644
index 0000000..9f6193b
--- /dev/null
+++ b/cmds/servicemanager/main.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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/logging.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/Status.h>
+#include <utils/StrongPointer.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using ::android::sp;
+using ::android::ProcessState;
+using ::android::IPCThreadState;
+using ::android::ServiceManager;
+using ::android::Access;
+
+int main(int argc, char** argv) {
+    if (argc > 2) {
+        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
+    }
+
+    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
+
+    android::base::InitLogging(nullptr, &android::base::KernelLogger);
+
+    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
+    ps->setThreadPoolMaxThreadCount(0);
+    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
+
+    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
+    IPCThreadState::self()->setTheContextObject(manager);
+    ps->becomeContextManager(nullptr, nullptr);
+
+    IPCThreadState::self()->joinThreadPool();
+
+    // should not be reached
+    return EXIT_FAILURE;
+}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
deleted file mode 100644
index ec3fac5..0000000
--- a/cmds/servicemanager/service_manager.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <cutils/android_filesystem_config.h>
-#include <cutils/multiuser.h>
-
-#include <selinux/android.h>
-#include <selinux/avc.h>
-
-#include "binder.h"
-
-#ifdef VENDORSERVICEMANAGER
-#define LOG_TAG "VendorServiceManager"
-#else
-#define LOG_TAG "ServiceManager"
-#endif
-#include <log/log.h>
-
-struct audit_data {
-    pid_t pid;
-    uid_t uid;
-    const char *name;
-};
-
-const char *str8(const uint16_t *x, size_t x_len)
-{
-    static char buf[128];
-    size_t max = 127;
-    char *p = buf;
-
-    if (x_len < max) {
-        max = x_len;
-    }
-
-    if (x) {
-        while ((max > 0) && (*x != '\0')) {
-            *p++ = *x++;
-            max--;
-        }
-    }
-    *p++ = 0;
-    return buf;
-}
-
-int str16eq(const uint16_t *a, const char *b)
-{
-    while (*a && *b)
-        if (*a++ != *b++) return 0;
-    if (*a || *b)
-        return 0;
-    return 1;
-}
-
-static char *service_manager_context;
-static struct selabel_handle* sehandle;
-
-static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
-{
-    char *lookup_sid = NULL;
-    const char *class = "service_manager";
-    bool allowed;
-    struct audit_data ad;
-
-    if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
-        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
-        return false;
-    }
-
-    ad.pid = spid;
-    ad.uid = uid;
-    ad.name = name;
-
-    if (sid == NULL) {
-        android_errorWriteLog(0x534e4554, "121035042");
-    }
-
-    int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
-    allowed = (result == 0);
-
-    freecon(lookup_sid);
-    return allowed;
-}
-
-static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
-{
-    return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
-}
-
-static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
-{
-    bool allowed;
-    char *tctx = NULL;
-
-    if (!sehandle) {
-        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
-        abort();
-    }
-
-    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
-        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
-        return false;
-    }
-
-    allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
-    freecon(tctx);
-    return allowed;
-}
-
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "add";
-
-    if (multiuser_get_app_id(uid) >= AID_APP) {
-        return 0; /* Don't allow apps to register services */
-    }
-
-    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
-}
-
-static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "list";
-    return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
-}
-
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "find";
-    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
-}
-
-struct svcinfo
-{
-    struct svcinfo *next;
-    uint32_t handle;
-    struct binder_death death;
-    int allow_isolated;
-    uint32_t dumpsys_priority;
-    size_t len;
-    uint16_t name[0];
-};
-
-struct svcinfo *svclist = NULL;
-
-struct svcinfo *find_svc(const uint16_t *s16, size_t len)
-{
-    struct svcinfo *si;
-
-    for (si = svclist; si; si = si->next) {
-        if ((len == si->len) &&
-            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
-            return si;
-        }
-    }
-    return NULL;
-}
-
-void svcinfo_death(struct binder_state *bs, void *ptr)
-{
-    struct svcinfo *si = (struct svcinfo* ) ptr;
-
-    ALOGI("service '%s' died\n", str8(si->name, si->len));
-    if (si->handle) {
-        binder_release(bs, si->handle);
-        si->handle = 0;
-    }
-}
-
-uint16_t svcmgr_id[] = {
-    'a','n','d','r','o','i','d','.','o','s','.',
-    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
-};
-
-
-uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
-{
-    struct svcinfo *si = find_svc(s, len);
-
-    if (!si || !si->handle) {
-        return 0;
-    }
-
-    if (!si->allow_isolated) {
-        // If this service doesn't allow access from isolated processes,
-        // then check the uid to see if it is isolated.
-        uid_t appid = uid % AID_USER;
-        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
-            return 0;
-        }
-    }
-
-    if (!svc_can_find(s, len, spid, sid, uid)) {
-        return 0;
-    }
-
-    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, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
-    struct svcinfo *si;
-
-    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
-    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
-
-    if (!handle || (len == 0) || (len > 127))
-        return -1;
-
-    if (!svc_can_register(s, len, spid, sid, uid)) {
-        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
-             str8(s, len), handle, uid);
-        return -1;
-    }
-
-    si = find_svc(s, len);
-    if (si) {
-        if (si->handle) {
-            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
-                 str8(s, len), handle, uid);
-            svcinfo_death(bs, si);
-        }
-        si->handle = handle;
-    } else {
-        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
-        if (!si) {
-            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
-                 str8(s, len), handle, uid);
-            return -1;
-        }
-        si->handle = handle;
-        si->len = len;
-        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
-        si->name[len] = '\0';
-        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;
-    }
-
-    binder_acquire(bs, handle);
-    binder_link_to_death(bs, handle, &si->death);
-    return 0;
-}
-
-int svcmgr_handler(struct binder_state *bs,
-                   struct binder_transaction_data_secctx *txn_secctx,
-                   struct binder_io *msg,
-                   struct binder_io *reply)
-{
-    struct svcinfo *si;
-    uint16_t *s;
-    size_t len;
-    uint32_t handle;
-    uint32_t strict_policy;
-    int allow_isolated;
-    uint32_t dumpsys_priority;
-
-    struct binder_transaction_data *txn = &txn_secctx->transaction_data;
-
-    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
-    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
-
-    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
-        return -1;
-
-    if (txn->code == PING_TRANSACTION)
-        return 0;
-
-    // Equivalent to Parcel::enforceInterface(), reading the RPC
-    // header with the strict mode policy mask and the interface name.
-    // Note that we ignore the strict_policy and don't propagate it
-    // further (since we do no outbound RPCs anyway).
-    strict_policy = bio_get_uint32(msg);
-    bio_get_uint32(msg);  // Ignore worksource header.
-    s = bio_get_string16(msg, &len);
-    if (s == NULL) {
-        return -1;
-    }
-
-    if ((len != (sizeof(svcmgr_id) / 2)) ||
-        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
-        fprintf(stderr,"invalid id %s\n", str8(s, len));
-        return -1;
-    }
-
-    if (sehandle && selinux_status_updated() > 0) {
-#ifdef VENDORSERVICEMANAGER
-        struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
-#else
-        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
-#endif
-        if (tmp_sehandle) {
-            selabel_close(sehandle);
-            sehandle = tmp_sehandle;
-        }
-    }
-
-    switch(txn->code) {
-    case SVC_MGR_GET_SERVICE:
-    case SVC_MGR_CHECK_SERVICE:
-        s = bio_get_string16(msg, &len);
-        if (s == NULL) {
-            return -1;
-        }
-        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
-                                 (const char*) txn_secctx->secctx);
-        if (!handle)
-            break;
-        bio_put_ref(reply, handle);
-        return 0;
-
-    case SVC_MGR_ADD_SERVICE:
-        s = bio_get_string16(msg, &len);
-        if (s == NULL) {
-            return -1;
-        }
-        handle = bio_get_ref(msg);
-        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
-        dumpsys_priority = bio_get_uint32(msg);
-        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
-                           txn->sender_pid, (const char*) txn_secctx->secctx))
-            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, (const char*) txn_secctx->secctx, txn->sender_euid)) {
-            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
-                    txn->sender_euid);
-            return -1;
-        }
-        si = svclist;
-        // 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;
-        }
-        return -1;
-    }
-    default:
-        ALOGE("unknown code %d\n", txn->code);
-        return -1;
-    }
-
-    bio_put_uint32(reply, 0);
-    return 0;
-}
-
-
-static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
-{
-    struct audit_data *ad = (struct audit_data *)data;
-
-    if (!ad || !ad->name) {
-        ALOGE("No service manager audit data");
-        return 0;
-    }
-
-    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
-    return 0;
-}
-
-int main(int argc, char** argv)
-{
-    struct binder_state *bs;
-    union selinux_callback cb;
-    char *driver;
-
-    if (argc > 1) {
-        driver = argv[1];
-    } else {
-        driver = "/dev/binder";
-    }
-
-    bs = binder_open(driver, 128*1024);
-    if (!bs) {
-#ifdef VENDORSERVICEMANAGER
-        ALOGW("failed to open binder driver %s\n", driver);
-        while (true) {
-            sleep(UINT_MAX);
-        }
-#else
-        ALOGE("failed to open binder driver %s\n", driver);
-#endif
-        return -1;
-    }
-
-    if (binder_become_context_manager(bs)) {
-        ALOGE("cannot become context manager (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    cb.func_audit = audit_callback;
-    selinux_set_callback(SELINUX_CB_AUDIT, cb);
-#ifdef VENDORSERVICEMANAGER
-    cb.func_log = selinux_vendor_log_callback;
-#else
-    cb.func_log = selinux_log_callback;
-#endif
-    selinux_set_callback(SELINUX_CB_LOG, cb);
-
-#ifdef VENDORSERVICEMANAGER
-    sehandle = selinux_android_vendor_service_context_handle();
-#else
-    sehandle = selinux_android_service_context_handle();
-#endif
-    selinux_status_open(true);
-
-    if (sehandle == NULL) {
-        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
-        abort();
-    }
-
-    if (getcon(&service_manager_context) != 0) {
-        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
-        abort();
-    }
-
-
-    binder_loop(bs, svcmgr_handler);
-
-    return 0;
-}
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
new file mode 100644
index 0000000..91485e4
--- /dev/null
+++ b/cmds/servicemanager/test_sm.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2019 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 <binder/ProcessState.h>
+#include <cutils/android_filesystem_config.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using android::sp;
+using android::Access;
+using android::IBinder;
+using android::ServiceManager;
+using android::os::IServiceManager;
+using testing::_;
+using testing::ElementsAre;
+using testing::NiceMock;
+using testing::Return;
+
+static sp<IBinder> getBinder() {
+    // It doesn't matter what remote binder it is, we just need one so that linkToDeath will work.
+    // The context manager (servicemanager) is easy to get and is in another process.
+    return android::ProcessState::self()->getContextObject(nullptr);
+}
+
+class MockAccess : public Access {
+public:
+    MOCK_METHOD0(getCallingContext, CallingContext());
+    MOCK_METHOD2(canAdd, bool(const CallingContext&, const std::string& name));
+    MOCK_METHOD2(canFind, bool(const CallingContext&, const std::string& name));
+    MOCK_METHOD1(canList, bool(const CallingContext&));
+};
+
+static sp<ServiceManager> getPermissiveServiceManager() {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    ON_CALL(*access, getCallingContext()).WillByDefault(Return(Access::CallingContext{}));
+    ON_CALL(*access, canAdd(_, _)).WillByDefault(Return(true));
+    ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
+    ON_CALL(*access, canList(_)).WillByDefault(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    return sm;
+}
+
+TEST(AddService, HappyHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, EmptyNameDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, JustShortEnoughServiceNameHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, TooLongNameDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, WeirdCharactersDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService("happy$foo$foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, AddNullServiceDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, AddDisallowedFromApp) {
+    for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) {
+        std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+        EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{
+            .debugPid = 1337,
+            .uid = uid,
+        }));
+        EXPECT_CALL(*access, canAdd(_, _)).Times(0);
+        sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+        EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+            IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    }
+
+}
+
+TEST(AddService, HappyOverExistingService) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, NoPermissions) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(GetService, HappyHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(getBinder(), out);
+}
+
+TEST(GetService, NonExistant) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(GetService, NoPermissionsForGettingService) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext()).WillRepeatedly(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    // returns nullptr but has OK status for legacy compatibility
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(GetService, AllowedFromIsolated) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext())
+        // something adds it
+        .WillOnce(Return(Access::CallingContext{}))
+        // next call is from isolated app
+        .WillOnce(Return(Access::CallingContext{
+            .uid = AID_ISOLATED_START,
+        }));
+    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), true /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(getBinder(), out.get());
+}
+
+TEST(GetService, NotAllowedFromIsolated) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext())
+        // something adds it
+        .WillOnce(Return(Access::CallingContext{}))
+        // next call is from isolated app
+        .WillOnce(Return(Access::CallingContext{
+            .uid = AID_ISOLATED_START,
+        }));
+    EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
+
+    // TODO(b/136023468): when security check is first, this should be called first
+    // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    // returns nullptr but has OK status for legacy compatibility
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(ListServices, NoPermissions) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    std::vector<std::string> out;
+    EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
+    EXPECT_TRUE(out.empty());
+}
+
+TEST(ListServices, AllServices) {
+    auto sm = getPermissiveServiceManager();
+
+    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
+    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
+    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
+
+    std::vector<std::string> out;
+    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
+
+    // all there and in the right order
+    EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd"));
+}
+
+TEST(ListServices, CriticalServices) {
+    auto sm = getPermissiveServiceManager();
+
+    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
+    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
+    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
+
+    std::vector<std::string> out;
+    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk());
+
+    // all there and in the right order
+    EXPECT_THAT(out, ElementsAre("sa"));
+}
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c70bc3e..a738527 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -46,6 +46,10 @@
         SecureFlagChange            secure_flag             = 14;
         DeferredTransactionChange   deferred_transaction    = 15;
         CornerRadiusChange          corner_radius           = 16;
+        ReparentChange              reparent                = 17;
+        RelativeParentChange        relative_parent         = 18;
+        DetachChildrenChange        detach_children         = 19;
+        ReparentChildrenChange      reparent_children       = 20;
     }
 }
 
@@ -177,3 +181,20 @@
     required int32  id   = 1;
     required int32  mode = 2;
 }
+
+message ReparentChange {
+    required int32 parent_id = 1;
+}
+
+message ReparentChildrenChange {
+    required int32 parent_id = 1;
+}
+
+message RelativeParentChange {
+    required int32 relative_parent_id = 1;
+    required int32 z = 2;
+}
+
+message DetachChildrenChange {
+    required bool detach_children = 1;
+}
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 34886a9..a4a9b6a 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -412,6 +412,18 @@
                 setDeferredTransaction(transaction, change.id(),
                         change.deferred_transaction());
                 break;
+            case SurfaceChange::SurfaceChangeCase::kReparent:
+                setReparentChange(transaction, change.id(), change.reparent());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kReparentChildren:
+                setReparentChildrenChange(transaction, change.id(), change.reparent_children());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kRelativeParent:
+                setRelativeParentChange(transaction, change.id(), change.relative_parent());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kDetachChildren:
+                setDetachChildrenChange(transaction, change.id(), change.detach_children());
+                break;
             default:
                 status = 1;
                 break;
@@ -680,3 +692,35 @@
     mComposerClient = new SurfaceComposerClient;
     return mComposerClient->initCheck();
 }
+
+void Replayer::setReparentChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const ReparentChange& c) {
+    sp<IBinder> newParentHandle = nullptr;
+    if (mLayers.count(c.parent_id()) != 0 && mLayers[c.parent_id()] != nullptr) {
+        newParentHandle = mLayers[c.parent_id()]->getHandle();
+    }
+    t.reparent(mLayers[id], newParentHandle);
+}
+
+void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const RelativeParentChange& c) {
+    if (mLayers.count(c.relative_parent_id()) == 0 || mLayers[c.relative_parent_id()] == nullptr) {
+        ALOGE("Layer %d not found in set relative parent transaction", c.relative_parent_id());
+        return;
+    }
+    t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()]->getHandle(), c.z());
+}
+
+void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const DetachChildrenChange& c) {
+    t.detachChildren(mLayers[id]);
+}
+
+void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const ReparentChildrenChange& c) {
+    if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
+        ALOGE("Layer %d not found in reparent children transaction", c.parent_id());
+        return;
+    }
+    t.reparentChildren(mLayers[id], mLayers[c.parent_id()]->getHandle());
+}
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index ad807ee..d7709cc 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -108,6 +108,14 @@
             layer_id id, const SecureFlagChange& sfc);
     void setDeferredTransaction(SurfaceComposerClient::Transaction& t,
             layer_id id, const DeferredTransactionChange& dtc);
+    void setReparentChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const ReparentChange& c);
+    void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const RelativeParentChange& c);
+    void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const DetachChildrenChange& c);
+    void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const ReparentChildrenChange& c);
 
     void setDisplaySurface(SurfaceComposerClient::Transaction& t,
             display_id id, const DispSurfaceChange& dsc);
diff --git a/headers/media_plugin/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
index 59bd292..17b9993 100644
--- a/headers/media_plugin/media/drm/DrmAPI.h
+++ b/headers/media_plugin/media/drm/DrmAPI.h
@@ -115,7 +115,8 @@
             kKeyStatusType_Expired,
             kKeyStatusType_OutputNotAllowed,
             kKeyStatusType_StatusPending,
-            kKeyStatusType_InternalError
+            kKeyStatusType_InternalError,
+            kKeyStatusType_UsableInFuture
         };
 
         // Used by sendKeysChange to report the usability status of each
diff --git a/include/OWNERS b/include/OWNERS
index 22be776..db52850 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,8 +1,10 @@
 alexeykuzmin@google.com
 dangittik@google.com
+jreck@google.com
 lajos@google.com
 mathias@google.com
 michaelwr@google.com
+nona@google.com
 racarr@google.com
 romainguy@android.com
 santoscordon@google.com
diff --git a/include/android/font.h b/include/android/font.h
new file mode 100644
index 0000000..8001ee1
--- /dev/null
+++ b/include/android/font.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/**
+ * @addtogroup Font
+ * @{
+ */
+
+/**
+ * @file font.h
+ * @brief Provides some constants used in system_fonts.h or fonts_matcher.h
+ *
+ * Available since API level 29.
+ */
+
+#ifndef ANDROID_FONT_H
+#define ANDROID_FONT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/cdefs.h>
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit).
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 29
+
+enum {
+    /** The minimum value fot the font weight value. */
+    AFONT_WEIGHT_MIN = 0,
+
+    /** A font weight value for the thin weight. */
+    AFONT_WEIGHT_THIN = 100,
+
+    /** A font weight value for the extra-light weight. */
+    AFONT_WEIGHT_EXTRA_LIGHT = 200,
+
+    /** A font weight value for the light weight. */
+    AFONT_WEIGHT_LIGHT = 300,
+
+    /** A font weight value for the normal weight. */
+    AFONT_WEIGHT_NORMAL = 400,
+
+    /** A font weight value for the medium weight. */
+    AFONT_WEIGHT_MEDIUM = 500,
+
+    /** A font weight value for the semi-bold weight. */
+    AFONT_WEIGHT_SEMI_BOLD = 600,
+
+    /** A font weight value for the bold weight. */
+    AFONT_WEIGHT_BOLD = 700,
+
+    /** A font weight value for the extra-bold weight. */
+    AFONT_WEIGHT_EXTRA_BOLD = 800,
+
+    /** A font weight value for the black weight. */
+    AFONT_WEIGHT_BLACK = 900,
+
+    /** The maximum value for the font weight value. */
+    AFONT_WEIGHT_MAX = 1000
+};
+
+/**
+ * AFont provides information of the single font configuration.
+ */
+struct AFont;
+
+/**
+ * Close an AFont.
+ *
+ * \param font a font returned by ASystemFontIterator_next or AFontMatchert_match.
+ *        Do nothing if NULL is passed.
+ */
+void AFont_close(AFont* _Nullable font) __INTRODUCED_IN(29);
+
+/**
+ * Return an absolute path to the current font file.
+ *
+ * Here is a list of font formats returned by this method:
+ * <ul>
+ *   <li>OpenType</li>
+ *   <li>OpenType Font Collection</li>
+ *   <li>TrueType</li>
+ *   <li>TrueType Collection</li>
+ * </ul>
+ * The file extension could be one of *.otf, *.ttf, *.otc or *.ttc.
+ *
+ * The font file returned is guaranteed to be opend with O_RDONLY.
+ * Note that the returned pointer is valid until AFont_close() is called for the given font.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return a string of the font file path.
+ */
+const char* _Nonnull AFont_getFontFilePath(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+/**
+ * Return a weight value associated with the current font.
+ *
+ * The weight values are positive and less than or equal to 1000.
+ * Here are pairs of the common names and their values.
+ * <p>
+ *  <table>
+ *  <tr>
+ *  <th align="center">Value</th>
+ *  <th align="center">Name</th>
+ *  <th align="center">NDK Definition</th>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">100</td>
+ *  <td align="center">Thin</td>
+ *  <td align="center">{@link AFONT_WEIGHT_THIN}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">200</td>
+ *  <td align="center">Extra Light (Ultra Light)</td>
+ *  <td align="center">{@link AFONT_WEIGHT_EXTRA_LIGHT}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">300</td>
+ *  <td align="center">Light</td>
+ *  <td align="center">{@link AFONT_WEIGHT_LIGHT}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">400</td>
+ *  <td align="center">Normal (Regular)</td>
+ *  <td align="center">{@link AFONT_WEIGHT_NORMAL}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">500</td>
+ *  <td align="center">Medium</td>
+ *  <td align="center">{@link AFONT_WEIGHT_MEDIUM}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">600</td>
+ *  <td align="center">Semi Bold (Demi Bold)</td>
+ *  <td align="center">{@link AFONT_WEIGHT_SEMI_BOLD}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">700</td>
+ *  <td align="center">Bold</td>
+ *  <td align="center">{@link AFONT_WEIGHT_BOLD}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">800</td>
+ *  <td align="center">Extra Bold (Ultra Bold)</td>
+ *  <td align="center">{@link AFONT_WEIGHT_EXTRA_BOLD}</td>
+ *  </tr>
+ *  <tr>
+ *  <td align="center">900</td>
+ *  <td align="center">Black (Heavy)</td>
+ *  <td align="center">{@link AFONT_WEIGHT_BLACK}</td>
+ *  </tr>
+ *  </table>
+ * </p>
+ * Note that the weight value may fall in between above values, e.g. 250 weight.
+ *
+ * For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
+ */
+uint16_t AFont_getWeight(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+/**
+ * Return true if the current font is italic, otherwise returns false.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return true if italic, otherwise false.
+ */
+bool AFont_isItalic(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+/**
+ * Return a IETF BCP47 compliant language tag associated with the current font.
+ *
+ * For information about IETF BCP47, read [Locale.forLanguageTag(java.lang.String)](https://developer.android.com/reference/java/util/Locale.html#forLanguageTag(java.lang.String)")
+ *
+ * Note that the returned pointer is valid until AFont_close() is called.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return a IETF BCP47 compliant language tag or nullptr if not available.
+ */
+const char* _Nullable AFont_getLocale(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+/**
+ * Return a font collection index value associated with the current font.
+ *
+ * In case the target font file is a font collection (e.g. .ttc or .otc), this
+ * returns a non-negative value as an font offset in the collection. This
+ * always returns 0 if the target font file is a regular font.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return a font collection index.
+ */
+size_t AFont_getCollectionIndex(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+/**
+ * Return a count of font variation settings associated with the current font
+ *
+ * The font variation settings are provided as multiple tag-values pairs.
+ *
+ * For example, bold italic font may have following font variation settings:
+ *     'wght' 700, 'slnt' -12
+ * In this case, AFont_getAxisCount returns 2 and AFont_getAxisTag
+ * and AFont_getAxisValue will return following values.
+ * \code{.cpp}
+ *     AFont* font = AFontIterator_next(ite);
+ *
+ *     // Returns the number of axes
+ *     AFont_getAxisCount(font);  // Returns 2
+ *
+ *     // Returns the tag-value pair for the first axis.
+ *     AFont_getAxisTag(font, 0);  // Returns 'wght'(0x77676874)
+ *     AFont_getAxisValue(font, 0);  // Returns 700.0
+ *
+ *     // Returns the tag-value pair for the second axis.
+ *     AFont_getAxisTag(font, 1);  // Returns 'slnt'(0x736c6e74)
+ *     AFont_getAxisValue(font, 1);  // Returns -12.0
+ * \endcode
+ *
+ * For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar)
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \return a number of font variation settings.
+ */
+size_t AFont_getAxisCount(const AFont* _Nonnull font) __INTRODUCED_IN(29);
+
+
+/**
+ * Return an OpenType axis tag associated with the current font.
+ *
+ * See AFont_getAxisCount for more details.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \param axisIndex an index to the font variation settings. Passing value larger than or
+ *        equal to {@link AFont_getAxisCount} is not allowed.
+ * \return an OpenType axis tag value for the given font variation setting.
+ */
+uint32_t AFont_getAxisTag(const AFont* _Nonnull font, uint32_t axisIndex)
+      __INTRODUCED_IN(29);
+
+/**
+ * Return an OpenType axis value associated with the current font.
+ *
+ * See AFont_getAxisCount for more details.
+ *
+ * \param font a font object. Passing NULL is not allowed.
+ * \param axisIndex an index to the font variation settings. Passing value larger than or
+ *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
+ * \return a float value for the given font variation setting.
+ */
+float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
+      __INTRODUCED_IN(29);
+
+#endif // __ANDROID_API__ >= 29
+
+__END_DECLS
+
+#endif // ANDROID_FONT_H
+
+/** @} */
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
new file mode 100644
index 0000000..0b8f892
--- /dev/null
+++ b/include/android/font_matcher.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/**
+ * @addtogroup Font
+ * @{
+ */
+
+/**
+ * @file font_matcher.h
+ * @brief Provides the font matching logic with various inputs.
+ *
+ * You can use this class for deciding what font is to be used for drawing text.
+ *
+ * A matcher is created from text style, locales and UI compatibility. The match function for
+ * matcher object can be called multiple times until close function is called.
+ *
+ * Even if no font can render the given text, the match function will return a non-null result for
+ * drawing Tofu character.
+ *
+ * Examples:
+ * \code{.cpp}
+ *  // Simple font query for the ASCII character.
+ *  std::vector<uint16_t> text = { 'A' };
+ *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
+ *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  // runLength will be 1 and the font will points a valid font file.
+ *  AFontMatcher_destroy(matcher);
+ *
+ *  // Querying font for CJK characters
+ *  std::vector<uint16_t> text = { 0x9AA8 };
+ *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
+ *  AFontMatcher_setLocales(matcher, "zh-CN,ja-JP");
+ *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  // runLength will be 1 and the font will points a Simplified Chinese font.
+ *  AFontMatcher_setLocales(matcher, "ja-JP,zh-CN");
+ *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  // runLength will be 1 and the font will points a Japanese font.
+ *  AFontMatcher_destroy(matcher);
+ *
+ *  // Querying font for text/color emoji
+ *  std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 };
+ *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
+ *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  // runLength will be 8 and the font will points a color emoji font.
+ *  AFontMatcher_destroy(matcher);
+ *
+ *  // Mixture of multiple script of characters.
+ *  // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character.
+ *  std::vector<uint16_t> text = { 0x05D0, 0x0E01 };
+ *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
+ *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  // runLength will be 1 and the font will points a Hebrew font.
+ *  AFontMatcher_destroy(matcher);
+ * \endcode
+ *
+ * Available since API level 29.
+ */
+
+#ifndef ANDROID_FONT_MATCHER_H
+#define ANDROID_FONT_MATCHER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/cdefs.h>
+
+#include <android/font.h>
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit).
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 29
+
+enum {
+    /** A family variant value for the system default variant. */
+    AFAMILY_VARIANT_DEFAULT = 0,
+
+    /**
+     * A family variant value for the compact font family variant.
+     *
+     * The compact font family has Latin-based vertical metrics.
+     */
+    AFAMILY_VARIANT_COMPACT = 1,
+
+    /**
+     * A family variant value for the elegant font family variant.
+     *
+     * The elegant font family may have larger vertical metrics than Latin font.
+     */
+    AFAMILY_VARIANT_ELEGANT = 2,
+};
+
+/**
+ * AFontMatcher performs match operation on given parameters and available font files.
+ * This matcher is not a thread-safe object. Do not pass this matcher to other threads.
+ */
+struct AFontMatcher;
+
+/**
+ * Select the best font from given parameters.
+ *
+ */
+
+/**
+ * Creates a new AFontMatcher object
+ */
+AFontMatcher* _Nonnull AFontMatcher_create() __INTRODUCED_IN(29);
+
+/**
+ * Destroy the matcher object.
+ *
+ * \param matcher a matcher object. Passing NULL is not allowed.
+ */
+void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29);
+
+/**
+ * Set font style to matcher.
+ *
+ * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
+ * with non-italic style.
+ *
+ * \param matcher a matcher object. Passing NULL is not allowed.
+ * \param weight a font weight value. Only from 0 to 1000 value is valid
+ * \param italic true if italic, otherwise false.
+ */
+void AFontMatcher_setStyle(
+        AFontMatcher* _Nonnull matcher,
+        uint16_t weight,
+        bool italic) __INTRODUCED_IN(29);
+
+/**
+ * Set font locales to matcher.
+ *
+ * If this function is not called, the matcher performs with empty locale list.
+ *
+ * \param matcher a matcher object. Passing NULL is not allowed.
+ * \param languageTags a null character terminated comma separated IETF BCP47 compliant language
+ *                     tags.
+ */
+void AFontMatcher_setLocales(
+        AFontMatcher* _Nonnull matcher,
+        const char* _Nonnull languageTags) __INTRODUCED_IN(29);
+
+/**
+ * Set family variant to matcher.
+ *
+ * If this function is not called, the matcher performs with {@link AFAMILY_VARIANT_DEFAULT}.
+ *
+ * \param matcher a matcher object. Passing NULL is not allowed.
+ * \param familyVariant Must be one of {@link AFAMILY_VARIANT_DEFAULT},
+ *                      {@link AFAMILY_VARIANT_COMPACT} or {@link AFAMILY_VARIANT_ELEGANT} is valid.
+ */
+void AFontMatcher_setFamilyVariant(
+        AFontMatcher* _Nonnull matcher,
+        uint32_t familyVariant) __INTRODUCED_IN(29);
+
+/**
+ * Performs the matching from the generic font family for the text and select one font.
+ *
+ * For more information about generic font families, read [W3C spec](https://www.w3.org/TR/css-fonts-4/#generic-font-families)
+ *
+ * Even if no font can render the given text, this function will return a non-null result for
+ * drawing Tofu character.
+ *
+ * \param matcher a matcher object. Passing NULL is not allowed.
+ * \param familyName a null character terminated font family name
+ * \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string.
+ * \param textLength a length of the given text buffer. This must not be zero.
+ * \param runLengthOut if not null, the font run length will be filled.
+ * \return a font to be used for given text and params. You need to release the returned font by
+ *         ASystemFont_close when it is no longer needed.
+ */
+AFont* _Nonnull AFontMatcher_match(
+        const AFontMatcher* _Nonnull matcher,
+        const char* _Nonnull familyName,
+        const uint16_t* _Nonnull text,
+        const uint32_t textLength,
+        uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
+
+#endif // __ANDROID_API__ >= 29
+
+__END_DECLS
+
+#endif // ANDROID_FONT_MATCHER_H
+
+/** @} */
diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h
index 7c4be24..aedf369 100644
--- a/include/android/hardware_buffer_jni.h
+++ b/include/android/hardware_buffer_jni.h
@@ -15,7 +15,13 @@
  */
 
 /**
+ * @addtogroup AHardwareBuffer
+ * @{
+ */
+
+/**
  * @file hardware_buffer_jni.h
+ * @brief JNI glue for native hardware buffers.
  */
 
 #ifndef ANDROID_HARDWARE_BUFFER_JNI_H
@@ -30,23 +36,25 @@
 __BEGIN_DECLS
 
 /**
- * Return the AHardwareBuffer associated with a Java HardwareBuffer object,
- * for interacting with it through native code. This method does not acquire any
- * additional reference to the AHardwareBuffer that is returned. To keep the
- * AHardwareBuffer live after the Java HardwareBuffer object got garbage
- * collected, be sure to use AHardwareBuffer_acquire() to acquire an additional
- * reference.
+ * Return the AHardwareBuffer wrapped by a Java HardwareBuffer object.
+ *
+ * This method does not acquire any additional reference to the AHardwareBuffer
+ * that is returned. To keep the AHardwareBuffer live after the Java
+ * HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire()
+ * to acquire an additional reference.
  */
 AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
-        jobject hardwareBufferObj);
+        jobject hardwareBufferObj) __INTRODUCED_IN(26);
 
 /**
  * Return a new Java HardwareBuffer object that wraps the passed native
  * AHardwareBuffer object.
  */
 jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
-        AHardwareBuffer* hardwareBuffer);
+        AHardwareBuffer* hardwareBuffer) __INTRODUCED_IN(26);
 
 __END_DECLS
 
 #endif // ANDROID_HARDWARE_BUFFER_JNI_H
+
+/** @} */
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index ef2ad99..abb8368 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -130,7 +130,7 @@
 /**
  * Returns a sync fence that signals when the transaction has been presented.
  * The recipient of the callback takes ownership of the fence and is responsible for closing
- * it.
+ * it. If a device does not support present fences, a -1 will be returned.
  */
 int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
                                                __INTRODUCED_IN(29);
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 38f036e..f0485a1 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -15,6 +15,11 @@
  */
 
 /**
+ * @addtogroup Font
+ * @{
+ */
+
+/**
  * @file system_fonts.h
  * @brief Provides the system font configurations.
  *
@@ -62,6 +67,8 @@
 #include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <android/font.h>
+
 /******************************************************************
  *
  * IMPORTANT NOTICE:
@@ -82,41 +89,6 @@
 
 #if __ANDROID_API__ >= 29
 
-enum {
-    /** The minimum value fot the font weight value. */
-    ASYSTEM_FONT_WEIGHT_MIN = 0,
-
-    /** A font weight value for the thin weight. */
-    ASYSTEM_FONT_WEIGHT_THIN = 100,
-
-    /** A font weight value for the extra-light weight. */
-    ASYSTEM_FONT_WEIGHT_EXTRA_LIGHT = 200,
-
-    /** A font weight value for the light weight. */
-    ASYSTEM_FONT_WEIGHT_LIGHT = 300,
-
-    /** A font weight value for the normal weight. */
-    ASYSTEM_FONT_WEIGHT_NORMAL = 400,
-
-    /** A font weight value for the medium weight. */
-    ASYSTEM_FONT_WEIGHT_MEDIUM = 500,
-
-    /** A font weight value for the semi-bold weight. */
-    ASYSTEM_FONT_WEIGHT_SEMI_BOLD = 600,
-
-    /** A font weight value for the bold weight. */
-    ASYSTEM_FONT_WEIGHT_BOLD = 700,
-
-    /** A font weight value for the extra-bold weight. */
-    ASYSTEM_FONT_WEIGHT_EXTRA_BOLD = 800,
-
-    /** A font weight value for the black weight. */
-    ASYSTEM_FONT_WEIGHT_BLACK = 900,
-
-    /** The maximum value for the font weight value. */
-    ASYSTEM_FONT_WEIGHT_MAX = 1000
-};
-
 /**
  * ASystemFontIterator provides access to the system font configuration.
  *
@@ -126,11 +98,6 @@
 struct ASystemFontIterator;
 
 /**
- * ASystemFont provides information of the single system font configuration.
- */
-struct ASystemFont;
-
-/**
  * Create a system font iterator.
  *
  * Use ASystemFont_close() to close the iterator.
@@ -153,257 +120,12 @@
  * \return a font. If no more font is available, returns nullptr. You need to release the returned
  *         font by ASystemFont_close when it is no longer needed.
  */
-ASystemFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
-
-/**
- * Close an ASystemFont returned by ASystemFontIterator_next.
- *
- * \param font a font returned by ASystemFontIterator_next or ASystemFont_matchFamilyStyleCharacter.
- *        Do nothing if NULL is passed.
- */
-void ASystemFont_close(ASystemFont* _Nullable font) __INTRODUCED_IN(29);
-
-
-/**
- * Select the best font from given parameters.
- *
- * Only generic font families are supported.
- * For more information about generic font families, read [W3C spec](https://www.w3.org/TR/css-fonts-4/#generic-font-families)
- *
- * Even if no font can render the given text, this function will return a non-null result for
- * drawing Tofu character.
- *
- * Examples:
- * \code{.cpp}
- *  // Simple font query for the ASCII character.
- *  std::vector<uint16_t> text = { 'A' };
- *  ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
- *      "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
- *  // runLength will be 1 and the font will points a valid font file.
- *
- *  // Querying font for CJK characters
- *  std::vector<uint16_t> text = { 0x9AA8 };
- *  ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
- *      "sans", 400, false, "zh-CN,ja-JP", text.data(), text.length(), &runLength);
- *  // runLength will be 1 and the font will points a Simplified Chinese font.
- *  ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
- *      "sans", 400, false, "ja-JP,zh-CN", text.data(), text.length(), &runLength);
- *  // runLength will be 1 and the font will points a Japanese font.
- *
- *  // Querying font for text/color emoji
- *  std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 };
- *  ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
- *      "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
- *  // runLength will be 8 and the font will points a color emoji font.
- *
- *  // Mixture of multiple script of characters.
- *  // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character.
- *  std::vector<uint16_t> text = { 0x05D0, 0x0E01 };
- *  ASystemFont font = ASystemFont_matchFamilyStyleCharacter(
- *      "sans", 400, false, "en-US", text.data(), text.length(), &runLength);
- *  // runLength will be 1 and the font will points a Hebrew font.
- * \endcode
- *
- * \param familyName a null character terminated font family name
- * \param weight a font weight value. Only from 0 to 1000 value is valid
- * \param italic true if italic, otherwise false.
- * \param languageTags a null character terminated comma separated IETF BCP47 compliant language
- *                     tags.
- * \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string.
- * \param textLength a length of the given text buffer. This must not be zero.
- * \param runLengthOut if not null, the font run length will be filled.
- * \return a font to be used for given text and params. You need to release the returned font by
- *         ASystemFont_close when it is no longer needed.
- */
-ASystemFont* _Nonnull ASystemFont_matchFamilyStyleCharacter(
-        const char* _Nonnull familyName,
-        uint16_t weight,
-        bool italic,
-        const char* _Nonnull languageTags,
-        const uint16_t* _Nonnull text,
-        uint32_t textLength,
-        uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
-
-/**
- * Return an absolute path to the current font file.
- *
- * Here is a list of font formats returned by this method:
- * <ul>
- *   <li>OpenType</li>
- *   <li>OpenType Font Collection</li>
- *   <li>TrueType</li>
- *   <li>TrueType Collection</li>
- * </ul>
- * The file extension could be one of *.otf, *.ttf, *.otc or *.ttc.
- *
- * The font file returned is guaranteed to be opend with O_RDONLY.
- * Note that the returned pointer is valid until ASystemFont_close() is called for the given font.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return a string of the font file path.
- */
-const char* _Nonnull ASystemFont_getFontFilePath(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-/**
- * Return a weight value associated with the current font.
- *
- * The weight values are positive and less than or equal to 1000.
- * Here are pairs of the common names and their values.
- * <p>
- *  <table>
- *  <tr>
- *  <th align="center">Value</th>
- *  <th align="center">Name</th>
- *  <th align="center">NDK Definition</th>
- *  </tr>
- *  <tr>
- *  <td align="center">100</td>
- *  <td align="center">Thin</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_THIN}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">200</td>
- *  <td align="center">Extra Light (Ultra Light)</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_EXTRA_LIGHT}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">300</td>
- *  <td align="center">Light</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_LIGHT}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">400</td>
- *  <td align="center">Normal (Regular)</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_NORMAL}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">500</td>
- *  <td align="center">Medium</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_MEDIUM}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">600</td>
- *  <td align="center">Semi Bold (Demi Bold)</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_SEMI_BOLD}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">700</td>
- *  <td align="center">Bold</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_BOLD}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">800</td>
- *  <td align="center">Extra Bold (Ultra Bold)</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_EXTRA_BOLD}</td>
- *  </tr>
- *  <tr>
- *  <td align="center">900</td>
- *  <td align="center">Black (Heavy)</td>
- *  <td align="center">{@link ASYSTEM_FONT_WEIGHT_BLACK}</td>
- *  </tr>
- *  </table>
- * </p>
- * Note that the weight value may fall in between above values, e.g. 250 weight.
- *
- * For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
- */
-uint16_t ASystemFont_getWeight(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-/**
- * Return true if the current font is italic, otherwise returns false.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return true if italic, otherwise false.
- */
-bool ASystemFont_isItalic(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-/**
- * Return a IETF BCP47 compliant language tag associated with the current font.
- *
- * For information about IETF BCP47, read [Locale.forLanguageTag(java.lang.String)](https://developer.android.com/reference/java/util/Locale.html#forLanguageTag(java.lang.String)")
- *
- * Note that the returned pointer is valid until ASystemFont_close() is called.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return a IETF BCP47 compliant langauge tag or nullptr if not available.
- */
-const char* _Nullable ASystemFont_getLocale(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-/**
- * Return a font collection index value associated with the current font.
- *
- * In case the target font file is a font collection (e.g. .ttc or .otc), this
- * returns a non-negative value as an font offset in the collection. This
- * always returns 0 if the target font file is a regular font.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return a font collection index.
- */
-size_t ASystemFont_getCollectionIndex(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-/**
- * Return a count of font variation settings associated with the current font
- *
- * The font variation settings are provided as multiple tag-values pairs.
- *
- * For example, bold italic font may have following font variation settings:
- *     'wght' 700, 'slnt' -12
- * In this case, ASystemFont_getAxisCount returns 2 and ASystemFont_getAxisTag
- * and ASystemFont_getAxisValue will return following values.
- * \code{.cpp}
- *     ASystemFont* font = ASystemFontIterator_next(ite);
- *
- *     // Returns the number of axes
- *     ASystemFont_getAxisCount(font);  // Returns 2
- *
- *     // Returns the tag-value pair for the first axis.
- *     ASystemFont_getAxisTag(font, 0);  // Returns 'wght'(0x77676874)
- *     ASystemFont_getAxisValue(font, 0);  // Returns 700.0
- *
- *     // Returns the tag-value pair for the second axis.
- *     ASystemFont_getAxisTag(font, 1);  // Returns 'slnt'(0x736c6e74)
- *     ASystemFont_getAxisValue(font, 1);  // Returns -12.0
- * \endcode
- *
- * For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar)
- *
- * \param font a font object. Passing NULL is not allowed.
- * \return a number of font variation settings.
- */
-size_t ASystemFont_getAxisCount(const ASystemFont* _Nonnull font) __INTRODUCED_IN(29);
-
-
-/**
- * Return an OpenType axis tag associated with the current font.
- *
- * See ASystemFont_getAxisCount for more details.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \param axisIndex an index to the font variation settings. Passing value larger than or
- *        equal to {@link ASystemFont_getAxisCount} is not allowed.
- * \return an OpenType axis tag value for the given font variation setting.
- */
-uint32_t ASystemFont_getAxisTag(const ASystemFont* _Nonnull font, uint32_t axisIndex)
-      __INTRODUCED_IN(29);
-
-/**
- * Return an OpenType axis value associated with the current font.
- *
- * See ASystemFont_getAxisCount for more details.
- *
- * \param font a font object. Passing NULL is not allowed.
- * \param axisIndex an index to the font variation settings. Passing value larger than or
- *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
- * \return a float value for the given font variation setting.
- */
-float ASystemFont_getAxisValue(const ASystemFont* _Nonnull font, uint32_t axisIndex)
-      __INTRODUCED_IN(29);
+AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
 
 #endif // __ANDROID_API__ >= 29
 
 __END_DECLS
 
 #endif // ANDROID_SYSTEM_FONTS_H
+
+/** @} */
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 009dc52..639df7a 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -20,7 +20,6 @@
 namespace android {
 
 // must be kept in sync with definitions in AudioPlaybackConfiguration.java
-
 #define PLAYER_PIID_INVALID -1
 
 typedef enum {
@@ -40,6 +39,15 @@
     PLAYER_STATE_STOPPED  = 4,
 } player_state_t;
 
+// must be kept in sync with definitions in AudioManager.java
+#define RECORD_RIID_INVALID -1
+
+typedef enum {
+    RECORDER_STATE_UNKNOWN  = -1,
+    RECORDER_STATE_STARTED  = 0,
+    RECORDER_STATE_STOPPED  = 1,
+} recorder_state_t;
+
 }; // namespace android
 
 #endif // ANDROID_AUDIOMANAGER_H
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index d279bbd..2f5ccb8 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -36,6 +36,9 @@
         PLAYER_ATTRIBUTES                     = IBinder::FIRST_CALL_TRANSACTION + 1,
         PLAYER_EVENT                          = IBinder::FIRST_CALL_TRANSACTION + 2,
         RELEASE_PLAYER                        = IBinder::FIRST_CALL_TRANSACTION + 3,
+        TRACK_RECORDER                        = IBinder::FIRST_CALL_TRANSACTION + 4,
+        RECORDER_EVENT                        = IBinder::FIRST_CALL_TRANSACTION + 5,
+        RELEASE_RECORDER                      = IBinder::FIRST_CALL_TRANSACTION + 6,
     };
 
     DECLARE_META_INTERFACE(AudioManager)
@@ -48,6 +51,9 @@
                 audio_content_type_t content)= 0;
     /*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event) = 0;
     /*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
+    virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
+    /*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
+    /*oneway*/ virtual status_t releaseRecorder(audio_unique_id_t riid) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/audiomanager/OWNERS b/include/audiomanager/OWNERS
new file mode 100644
index 0000000..2bd527c
--- /dev/null
+++ b/include/audiomanager/OWNERS
@@ -0,0 +1,2 @@
+elaurent@google.com
+jmtrivi@google.com
diff --git a/include/input/Input.h b/include/input/Input.h
index 805957a..a976246 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -24,12 +24,14 @@
  */
 
 #include <android/input.h>
+#include <stdint.h>
 #include <utils/BitSet.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
 #include <utils/Vector.h>
-#include <stdint.h>
+
+#include <limits>
 
 /*
  * Additional private constants not defined in ndk/ui/input.h.
@@ -246,6 +248,13 @@
  */
 const char* motionClassificationToString(MotionClassification classification);
 
+/**
+ * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
+ * use it for direct comparison with any other value, because NaN isn't equal to itself according to
+ * IEEE 754. Use isnan() instead to check if a cursor position is valid.
+ */
+constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN();
+
 /*
  * Pointer coordinate data.
  */
@@ -459,6 +468,14 @@
 
     inline float getYPrecision() const { return mYPrecision; }
 
+    inline float getRawXCursorPosition() const { return mXCursorPosition; }
+
+    float getXCursorPosition() const;
+
+    inline float getRawYCursorPosition() const { return mYCursorPosition; }
+
+    float getYCursorPosition() const;
+
     inline nsecs_t getDownTime() const { return mDownTime; }
 
     inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
@@ -600,26 +617,13 @@
 
     ssize_t findPointerIndex(int32_t pointerId) const;
 
-    void initialize(
-            int32_t deviceId,
-            int32_t source,
-            int32_t displayId,
-            int32_t action,
-            int32_t actionButton,
-            int32_t flags,
-            int32_t edgeFlags,
-            int32_t metaState,
-            int32_t buttonState,
-            MotionClassification classification,
-            float xOffset,
-            float yOffset,
-            float xPrecision,
-            float yPrecision,
-            nsecs_t downTime,
-            nsecs_t eventTime,
-            size_t pointerCount,
-            const PointerProperties* pointerProperties,
-            const PointerCoords* pointerCoords);
+    void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+                    int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
+                    int32_t buttonState, MotionClassification classification, float xOffset,
+                    float yOffset, float xPrecision, float yPrecision, float mXCursorPosition,
+                    float mYCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                    size_t pointerCount, const PointerProperties* pointerProperties,
+                    const PointerCoords* pointerCoords);
 
     void copyFrom(const MotionEvent* other, bool keepHistory);
 
@@ -669,6 +673,8 @@
     float mYOffset;
     float mXPrecision;
     float mYPrecision;
+    float mXCursorPosition;
+    float mYCursorPosition;
     nsecs_t mDownTime;
     Vector<PointerProperties> mPointerProperties;
     Vector<nsecs_t> mSampleEventTimes;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 63606e5..df23f61 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -113,6 +113,8 @@
             float yOffset;
             float xPrecision;
             float yPrecision;
+            float xCursorPosition;
+            float yCursorPosition;
             uint32_t pointerCount;
             uint32_t empty3;
             // Note that PointerCoords requires 8 byte alignment.
@@ -261,27 +263,14 @@
      * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
      * Other errors probably indicate that the channel is broken.
      */
-    status_t publishMotionEvent(
-            uint32_t seq,
-            int32_t deviceId,
-            int32_t source,
-            int32_t displayId,
-            int32_t action,
-            int32_t actionButton,
-            int32_t flags,
-            int32_t edgeFlags,
-            int32_t metaState,
-            int32_t buttonState,
-            MotionClassification classification,
-            float xOffset,
-            float yOffset,
-            float xPrecision,
-            float yPrecision,
-            nsecs_t downTime,
-            nsecs_t eventTime,
-            uint32_t pointerCount,
-            const PointerProperties* pointerProperties,
-            const PointerCoords* pointerCoords);
+    status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
+                                int32_t action, int32_t actionButton, int32_t flags,
+                                int32_t edgeFlags, int32_t metaState, int32_t buttonState,
+                                MotionClassification classification, float xOffset, float yOffset,
+                                float xPrecision, float yPrecision, float xCursorPosition,
+                                float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                                uint32_t pointerCount, const PointerProperties* pointerProperties,
+                                const PointerCoords* pointerCoords);
 
     /* Receives the finished signal from the consumer in reply to the original dispatch signal.
      * If a signal was received, returns the message sequence number,
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index aedf6b0..b230943 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,7 +73,6 @@
         "Status.cpp",
         "TextOutput.cpp",
         "IpPrefix.cpp",
-        "Value.cpp",
         ":libbinder_aidl",
     ],
 
@@ -94,7 +93,6 @@
                 "PermissionController.cpp",
                 "ProcessInfoService.cpp",
                 "IpPrefix.cpp",
-                ":libbinder_aidl",
             ],
         },
     },
@@ -116,7 +114,6 @@
     },
 
     shared_libs: [
-        "libbase",
         "liblog",
         "libcutils",
         "libutils",
@@ -142,7 +139,7 @@
     name: "libbinder_aidl",
     srcs: [
         "aidl/android/content/pm/IPackageManagerNative.aidl",
+        "aidl/android/os/IServiceManager.aidl",
     ],
+    path: "aidl",
 }
-
-subdirs = ["tests"]
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index a494e22..525685c 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -93,6 +93,14 @@
             : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
+int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
+        const String16& callingPackage) {
+    sp<IAppOpsService> service = getService();
+    return service != nullptr
+           ? service->checkAudioOperation(op, usage, uid, callingPackage)
+           : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+}
+
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
     return service != nullptr
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index cb0e08d..bdf0f8e 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -128,7 +128,7 @@
     status_t err = NO_ERROR;
     switch (code) {
         case PING_TRANSACTION:
-            reply->writeInt32(pingBinder());
+            err = pingBinder();
             break;
         default:
             err = onTransact(code, data, reply, flags);
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index ec170f7..5ceb218 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -148,6 +148,10 @@
     IPCThreadState::self()->incWeakHandle(handle, this);
 }
 
+int32_t BpBinder::handle() const {
+    return mHandle;
+}
+
 bool BpBinder::isDescriptorCached() const {
     Mutex::Autolock _l(mLock);
     return mDescriptorCache.size() ? true : false;
@@ -186,10 +190,7 @@
 {
     Parcel send;
     Parcel reply;
-    status_t err = transact(PING_TRANSACTION, send, &reply);
-    if (err != NO_ERROR) return err;
-    if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
-    return (status_t)reply.readInt32();
+    return transact(PING_TRANSACTION, send, &reply);
 }
 
 status_t BpBinder::dump(int fd, const Vector<String16>& args)
@@ -387,21 +388,6 @@
         }
     }
 
-    mLock.lock();
-    Vector<Obituary>* obits = mObituaries;
-    if(obits != nullptr) {
-        if (ipc) ipc->clearDeathNotification(mHandle, this);
-        mObituaries = nullptr;
-    }
-    mLock.unlock();
-
-    if (obits != nullptr) {
-        // XXX Should we tell any remaining DeathRecipient
-        // objects that the last strong ref has gone away, so they
-        // are no longer linked?
-        delete obits;
-    }
-
     if (ipc) {
         ipc->expungeHandle(mHandle, this);
         ipc->decWeakHandle(mHandle);
@@ -423,6 +409,25 @@
     }
     IPCThreadState* ipc = IPCThreadState::self();
     if (ipc) ipc->decStrongHandle(mHandle);
+
+    mLock.lock();
+    Vector<Obituary>* obits = mObituaries;
+    if(obits != nullptr) {
+        if (!obits->isEmpty()) {
+            ALOGI("onLastStrongRef automatically unlinking death recipients");
+        }
+
+        if (ipc) ipc->clearDeathNotification(mHandle, this);
+        mObituaries = nullptr;
+    }
+    mLock.unlock();
+
+    if (obits != nullptr) {
+        // XXX Should we tell any remaining DeathRecipient
+        // objects that the last strong ref has gone away, so they
+        // are no longer linked?
+        delete obits;
+    }
 }
 
 bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 857bbf9..a7d5240 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -23,12 +23,12 @@
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 
-#include <private/binder/Static.h>
-
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "Static.h"
+
 // ---------------------------------------------------------------------------
 
 namespace android {
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index f38bbb2..a1c2a8b 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -221,7 +221,11 @@
 
         for (word = 0; word < bytesPerLine; ) {
 
-            const size_t startIndex = word+(alignment-(alignment?1:0));
+            size_t align_offset = alignment-(alignment?1:0);
+            if (remain > 0 && (size_t)remain <= align_offset) {
+                align_offset = remain - 1;
+            }
+            const size_t startIndex = word+align_offset;
 
             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
 
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 2f4dbee..4c151e7 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -22,8 +22,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -57,7 +55,8 @@
         case OP_CHANGED_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsCallback, data, reply);
             int32_t op = data.readInt32();
-            String16 packageName = data.readString16();
+            String16 packageName;
+            (void)data.readString16(&packageName);
             opChanged(op, packageName);
             reply->writeNoException();
             return NO_ERROR;
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index fb0d521..c426f3a 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -22,8 +22,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -123,6 +121,22 @@
         if (reply.readExceptionCode() != 0) return -1;
         return reply.readInt32();
     }
+
+    virtual int32_t checkAudioOperation(int32_t code, int32_t usage,
+            int32_t uid, const String16& packageName) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(code);
+        data.writeInt32(usage);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        remote()->transact(CHECK_AUDIO_OPERATION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) {
+            return MODE_ERRORED;
+        }
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -209,6 +223,17 @@
             reply->writeInt32(opCode);
             return NO_ERROR;
         } break;
+        case CHECK_AUDIO_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            const int32_t code = data.readInt32();
+            const int32_t usage = data.readInt32();
+            const int32_t uid = data.readInt32();
+            const String16 packageName = data.readString16();
+            const int32_t res = checkAudioOperation(code, usage, uid, packageName);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index b307e3e..cc0022a 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -20,8 +20,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index 6b77291..59d51ed 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -47,21 +47,3 @@
 // ---------------------------------------------------------------------------
 
 }; // namespace android
-
-extern "C" {
-
-void _ZN7android10IInterface8asBinderEv(void *retval, void* self) {
-    ALOGW("deprecated asBinder call, please update your code");
-    //ALOGI("self: %p, retval: %p", self, retval);
-    android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
-    *ret = android::IInterface::asBinder((android::IInterface*)self);
-}
-
-void _ZNK7android10IInterface8asBinderEv(void *retval, void *self) {
-    ALOGW("deprecated asBinder call, please update your code");
-    //ALOGI("self: %p, retval: %p", self, retval);
-    android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
-    *ret = android::IInterface::asBinder((android::IInterface*)self);
-}
-
-} // extern "C"
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 9a561cb..cfb86f0 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -31,8 +31,8 @@
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
-#include <private/binder/Static.h>
 
+#include <atomic>
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
@@ -43,6 +43,8 @@
 #include <sys/resource.h>
 #include <unistd.h>
 
+#include "Static.h"
+
 #if LOG_NDEBUG
 
 #define IF_LOG_TRANSACTIONS() if (false)
@@ -116,7 +118,7 @@
 
 static const char* getReturnString(uint32_t cmd)
 {
-    size_t idx = cmd & 0xff;
+    size_t idx = cmd & _IOC_NRMASK;
     if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0]))
         return kReturnStrings[idx];
     else
@@ -278,14 +280,14 @@
 }
 
 static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
+static std::atomic<bool> gHaveTLS(false);
 static pthread_key_t gTLS = 0;
-static bool gShutdown = false;
-static bool gDisableBackgroundScheduling = false;
+static std::atomic<bool> gShutdown = false;
+static std::atomic<bool> gDisableBackgroundScheduling = false;
 
 IPCThreadState* IPCThreadState::self()
 {
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
 restart:
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
@@ -293,13 +295,14 @@
         return new IPCThreadState;
     }
 
-    if (gShutdown) {
+    // Racey, heuristic test for simultaneous shutdown.
+    if (gShutdown.load(std::memory_order_relaxed)) {
         ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
         return nullptr;
     }
 
     pthread_mutex_lock(&gTLSMutex);
-    if (!gHaveTLS) {
+    if (!gHaveTLS.load(std::memory_order_relaxed)) {
         int key_create_value = pthread_key_create(&gTLS, threadDestructor);
         if (key_create_value != 0) {
             pthread_mutex_unlock(&gTLSMutex);
@@ -307,7 +310,7 @@
                     strerror(key_create_value));
             return nullptr;
         }
-        gHaveTLS = true;
+        gHaveTLS.store(true, std::memory_order_release);
     }
     pthread_mutex_unlock(&gTLSMutex);
     goto restart;
@@ -315,7 +318,7 @@
 
 IPCThreadState* IPCThreadState::selfOrNull()
 {
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
         return st;
@@ -325,9 +328,9 @@
 
 void IPCThreadState::shutdown()
 {
-    gShutdown = true;
+    gShutdown.store(true, std::memory_order_relaxed);
 
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
         // XXX Need to wait for all thread pool threads to exit!
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
         if (st) {
@@ -335,18 +338,18 @@
             pthread_setspecific(gTLS, nullptr);
         }
         pthread_key_delete(gTLS);
-        gHaveTLS = false;
+        gHaveTLS.store(false, std::memory_order_release);
     }
 }
 
 void IPCThreadState::disableBackgroundScheduling(bool disable)
 {
-    gDisableBackgroundScheduling = disable;
+    gDisableBackgroundScheduling.store(disable, std::memory_order_relaxed);
 }
 
 bool IPCThreadState::backgroundSchedulingDisabled()
 {
-    return gDisableBackgroundScheduling;
+    return gDisableBackgroundScheduling.load(std::memory_order_relaxed);
 }
 
 sp<ProcessState> IPCThreadState::process()
@@ -674,11 +677,11 @@
     if ((flags & TF_ONE_WAY) == 0) {
         if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
             if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
-                ALOGE("Process making non-oneway call but is restricted.");
+                ALOGE("Process making non-oneway call (code: %u) but is restricted.", code);
                 CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
                     ANDROID_LOG_ERROR);
             } else /* FATAL_IF_NOT_ONEWAY */ {
-                LOG_ALWAYS_FATAL("Process may not make oneway calls.");
+                LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
             }
         }
 
@@ -996,7 +999,7 @@
     if (err >= NO_ERROR) {
         if (bwr.write_consumed > 0) {
             if (bwr.write_consumed < mOut.dataSize())
-                mOut.remove(0, bwr.write_consumed);
+                LOG_ALWAYS_FATAL("Driver did not consume write buffer");
             else {
                 mOut.setDataSize(0);
                 processPostWriteDerefs();
@@ -1060,7 +1063,7 @@
 
 sp<BBinder> the_context_object;
 
-void setTheContextObject(sp<BBinder> obj)
+void IPCThreadState::setTheContextObject(sp<BBinder> obj)
 {
     the_context_object = obj;
 }
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index 6b99150..bf2f20a 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -22,8 +22,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index 159763d..1e11941 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -22,8 +22,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 4ba6c2a..74f1f47 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,6 +18,7 @@
 
 #include <binder/IServiceManager.h>
 
+#include <android/os/IServiceManager.h>
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
 #ifndef __ANDROID_VNDK__
@@ -28,14 +29,20 @@
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
 
-#include <private/binder/Static.h>
+#include "Static.h"
 
 #include <unistd.h>
 
 namespace android {
 
+using AidlServiceManager = android::os::IServiceManager;
+using android::binder::Status;
+
 sp<IServiceManager> defaultServiceManager()
 {
+    static Mutex gDefaultServiceManagerLock;
+    static sp<IServiceManager> gDefaultServiceManager;
+
     if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
 
     {
@@ -74,10 +81,13 @@
 
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
 {
+    static Mutex gPermissionControllerLock;
+    static sp<IPermissionController> gPermissionController;
+
     sp<IPermissionController> pc;
-    gDefaultServiceManagerLock.lock();
+    gPermissionControllerLock.lock();
     pc = gPermissionController;
-    gDefaultServiceManagerLock.unlock();
+    gPermissionControllerLock.unlock();
 
     int64_t startTime = 0;
 
@@ -101,11 +111,11 @@
             }
 
             // Object is dead!
-            gDefaultServiceManagerLock.lock();
+            gPermissionControllerLock.lock();
             if (gPermissionController == pc) {
                 gPermissionController = nullptr;
             }
-            gDefaultServiceManagerLock.unlock();
+            gPermissionControllerLock.unlock();
         }
 
         // Need to retrieve the permission controller.
@@ -121,9 +131,9 @@
         } else {
             pc = interface_cast<IPermissionController>(binder);
             // Install the new permission controller, and try again.
-            gDefaultServiceManagerLock.lock();
+            gPermissionControllerLock.lock();
             gPermissionController = pc;
-            gDefaultServiceManagerLock.unlock();
+            gPermissionControllerLock.unlock();
         }
     }
 }
@@ -136,12 +146,15 @@
 {
 public:
     explicit BpServiceManager(const sp<IBinder>& impl)
-        : BpInterface<IServiceManager>(impl)
+        : BpInterface<IServiceManager>(impl),
+          mTheRealServiceManager(interface_cast<AidlServiceManager>(impl))
     {
     }
 
-    virtual sp<IBinder> getService(const String16& name) const
+    sp<IBinder> getService(const String16& name) const override
     {
+        static bool gSystemBootCompleted = false;
+
         sp<IBinder> svc = checkService(name);
         if (svc != nullptr) return svc;
 
@@ -171,43 +184,36 @@
         return nullptr;
     }
 
-    virtual sp<IBinder> checkService( const String16& name) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
-        data.writeString16(name);
-        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
-        return reply.readStrongBinder();
+    sp<IBinder> checkService(const String16& name) const override {
+        sp<IBinder> ret;
+        if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
+            return nullptr;
+        }
+        return ret;
     }
 
-    virtual status_t addService(const String16& name, const sp<IBinder>& service,
-                                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;
+    status_t addService(const String16& name, const sp<IBinder>& service,
+                        bool allowIsolated, int dumpsysPriority) override {
+        Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority);
+        return status.exceptionCode();
     }
 
     virtual Vector<String16> listServices(int dumpsysPriority) {
-        Vector<String16> res;
-        int n = 0;
+        std::vector<std::string> ret;
+        if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
+            return {};
+        }
 
-        for (;;) {
-            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;
-            res.add(reply.readString16());
+        Vector<String16> res;
+        res.setCapacity(ret.size());
+        for (const std::string& name : ret) {
+            res.push(String16(name.c_str()));
         }
         return res;
     }
+
+private:
+    sp<AidlServiceManager> mTheRealServiceManager;
 };
 
 IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index 6c697de..88cc603 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -25,8 +25,6 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/binder/Static.h>
-
 namespace android {
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a595c01..b5fbf42 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -37,7 +37,6 @@
 #include <binder/ProcessState.h>
 #include <binder/Status.h>
 #include <binder/TextOutput.h>
-#include <binder/Value.h>
 
 #include <cutils/ashmem.h>
 #include <utils/Debug.h>
@@ -48,7 +47,7 @@
 #include <utils/String16.h>
 
 #include <private/binder/binder_module.h>
-#include <private/binder/Static.h>
+#include "Static.h"
 
 #ifndef INT32_MAX
 #define INT32_MAX ((int32_t)(2147483647))
@@ -76,14 +75,6 @@
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (1 << 31)
 
-// XXX This can be made public if we want to provide
-// support for typed data.
-struct small_flat_data
-{
-    uint32_t type;
-    uint32_t data;
-};
-
 namespace android {
 
 static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER;
@@ -101,7 +92,7 @@
     BLOB_ASHMEM_MUTABLE = 2,
 };
 
-void acquire_object(const sp<ProcessState>& proc,
+static void acquire_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
     switch (obj.hdr.type) {
@@ -143,12 +134,6 @@
     ALOGD("Invalid object type 0x%08x", obj.hdr.type);
 }
 
-void acquire_object(const sp<ProcessState>& proc,
-    const flat_binder_object& obj, const void* who)
-{
-    acquire_object(proc, obj, who, nullptr);
-}
-
 static void release_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
@@ -197,19 +182,13 @@
     ALOGE("Invalid object type 0x%08x", obj.hdr.type);
 }
 
-void release_object(const sp<ProcessState>& proc,
-    const flat_binder_object& obj, const void* who)
-{
-    release_object(proc, obj, who, nullptr);
-}
-
 inline static status_t finish_flatten_binder(
     const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
 {
     return out->writeObject(flat, false);
 }
 
-status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+static status_t flatten_binder(const sp<ProcessState>& /*proc*/,
     const sp<IBinder>& binder, Parcel* out)
 {
     flat_binder_object obj;
@@ -251,7 +230,7 @@
     return finish_flatten_binder(binder, obj, out);
 }
 
-status_t flatten_binder(const sp<ProcessState>& /*proc*/,
+static status_t flatten_binder(const sp<ProcessState>& /*proc*/,
     const wp<IBinder>& binder, Parcel* out)
 {
     flat_binder_object obj;
@@ -307,7 +286,7 @@
     return NO_ERROR;
 }
 
-status_t unflatten_binder(const sp<ProcessState>& proc,
+static status_t unflatten_binder(const sp<ProcessState>& proc,
     const Parcel& in, sp<IBinder>* out)
 {
     const flat_binder_object* flat = in.readObject(false);
@@ -326,7 +305,7 @@
     return BAD_TYPE;
 }
 
-status_t unflatten_binder(const sp<ProcessState>& proc,
+static status_t unflatten_binder(const sp<ProcessState>& proc,
     const Parcel& in, wp<IBinder>* out)
 {
     const flat_binder_object* flat = in.readObject(false);
@@ -636,7 +615,7 @@
     return err == NO_ERROR;
 }
 
-uid_t Parcel::readCallingWorkSourceUid()
+uid_t Parcel::readCallingWorkSourceUid() const
 {
     if (!mRequestHeaderPresent) {
         return IPCThreadState::kUnsetWorkSource;
@@ -687,11 +666,6 @@
     }
 }
 
-const binder_size_t* Parcel::objects() const
-{
-    return mObjects;
-}
-
 size_t Parcel::objectsCount() const
 {
     return mObjectsSize;
@@ -1183,10 +1157,6 @@
     return parcelable.writeToParcel(this);
 }
 
-status_t Parcel::writeValue(const binder::Value& value) {
-    return value.writeToParcel(this);
-}
-
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -1424,125 +1394,6 @@
     return status.writeToParcel(this);
 }
 
-status_t Parcel::writeMap(const ::android::binder::Map& map_in)
-{
-    using ::std::map;
-    using ::android::binder::Value;
-    using ::android::binder::Map;
-
-    Map::const_iterator iter;
-    status_t ret;
-
-    ret = writeInt32(map_in.size());
-
-    if (ret != NO_ERROR) {
-        return ret;
-    }
-
-    for (iter = map_in.begin(); iter != map_in.end(); ++iter) {
-        ret = writeValue(Value(iter->first));
-        if (ret != NO_ERROR) {
-            return ret;
-        }
-
-        ret = writeValue(iter->second);
-        if (ret != NO_ERROR) {
-            return ret;
-        }
-    }
-
-    return ret;
-}
-
-status_t Parcel::writeNullableMap(const std::unique_ptr<binder::Map>& map)
-{
-    if (map == nullptr) {
-        return writeInt32(-1);
-    }
-
-    return writeMap(*map.get());
-}
-
-status_t Parcel::readMap(::android::binder::Map* map_out)const
-{
-    using ::std::map;
-    using ::android::String16;
-    using ::android::String8;
-    using ::android::binder::Value;
-    using ::android::binder::Map;
-
-    status_t ret = NO_ERROR;
-    int32_t count;
-
-    ret = readInt32(&count);
-    if (ret != NO_ERROR) {
-        return ret;
-    }
-
-    if (count < 0) {
-        ALOGE("readMap: Unexpected count: %d", count);
-        return (count == -1)
-            ? UNEXPECTED_NULL
-            : BAD_VALUE;
-    }
-
-    map_out->clear();
-
-    while (count--) {
-        Map::key_type key;
-        Value value;
-
-        ret = readValue(&value);
-        if (ret != NO_ERROR) {
-            return ret;
-        }
-
-        if (!value.getString(&key)) {
-            ALOGE("readMap: Key type not a string (parcelType = %d)", value.parcelType());
-            return BAD_VALUE;
-        }
-
-        ret = readValue(&value);
-        if (ret != NO_ERROR) {
-            return ret;
-        }
-
-        (*map_out)[key] = value;
-    }
-
-    return ret;
-}
-
-status_t Parcel::readNullableMap(std::unique_ptr<binder::Map>* map) const
-{
-    const size_t start = dataPosition();
-    int32_t count;
-    status_t status = readInt32(&count);
-    map->reset();
-
-    if (status != OK || count == -1) {
-        return status;
-    }
-
-    setDataPosition(start);
-    map->reset(new binder::Map());
-
-    status = readMap(map->get());
-
-    if (status != OK) {
-        map->reset();
-    }
-
-    return status;
-}
-
-
-
-void Parcel::remove(size_t /*start*/, size_t /*amt*/)
-{
-    LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
-}
-
 status_t Parcel::validateReadData(size_t upperBound) const
 {
     // Don't allow non-object reads on object data
@@ -2094,8 +1945,8 @@
 
 const char* Parcel::readCString() const
 {
-    const size_t avail = mDataSize-mDataPos;
-    if (avail > 0) {
+    if (mDataPos < mDataSize) {
+        const size_t avail = mDataSize-mDataPos;
         const char* str = reinterpret_cast<const char*>(mData+mDataPos);
         // is the string's trailing NUL within the parcel's valid bounds?
         const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
@@ -2247,10 +2098,6 @@
     return parcelable->readFromParcel(this);
 }
 
-status_t Parcel::readValue(binder::Value* value) const {
-    return value->readFromParcel(this);
-}
-
 int32_t Parcel::readExceptionCode() const
 {
     binder::Status status;
@@ -2602,7 +2449,7 @@
     } else if (dataSize() > 0) {
         const uint8_t* DATA = data();
         to << indent << HexDump(DATA, dataSize()) << dedent;
-        const binder_size_t* OBJS = objects();
+        const binder_size_t* OBJS = mObjects;
         const size_t N = objectsCount();
         for (size_t i=0; i<N; i++) {
             const flat_binder_object* flat
@@ -2843,10 +2690,16 @@
                 }
                 release_object(proc, *flat, this, &mOpenAshmemSize);
             }
-            binder_size_t* objects =
-                (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
-            if (objects) {
-                mObjects = objects;
+
+            if (objectsSize == 0) {
+                free(mObjects);
+                mObjects = nullptr;
+            } else {
+                binder_size_t* objects =
+                    (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
+                if (objects) {
+                    mObjects = objects;
+                }
             }
             mObjectsSize = objectsSize;
             mNextObjectHint = 0;
diff --git a/libs/binder/include/private/binder/ParcelValTypes.h b/libs/binder/ParcelValTypes.h
similarity index 100%
rename from libs/binder/include/private/binder/ParcelValTypes.h
rename to libs/binder/ParcelValTypes.h
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c0aec0a..97a6c94 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "PersistableBundle"
 
 #include <binder/PersistableBundle.h>
-#include <private/binder/ParcelValTypes.h>
 
 #include <limits>
 
@@ -26,6 +25,8 @@
 #include <log/log.h>
 #include <utils/Errors.h>
 
+#include "ParcelValTypes.h"
+
 using android::BAD_TYPE;
 using android::BAD_VALUE;
 using android::NO_ERROR;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 79db0cb..a07b3a0 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -24,11 +24,10 @@
 #include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
-#include <utils/String8.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
-#include <private/binder/Static.h>
+#include "Static.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -108,58 +107,11 @@
     return gProcess;
 }
 
-void ProcessState::setContextObject(const sp<IBinder>& object)
-{
-    setContextObject(object, String16("default"));
-}
-
 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
 {
     return getStrongProxyForHandle(0);
 }
 
-void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
-{
-    AutoMutex _l(mLock);
-    mContexts.add(name, object);
-}
-
-sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
-{
-    mLock.lock();
-    sp<IBinder> object(
-        mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
-    mLock.unlock();
-    
-    //printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
-    
-    if (object != nullptr) return object;
-
-    // Don't attempt to retrieve contexts if we manage them
-    if (mManagesContexts) {
-        ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
-            String8(name).string());
-        return nullptr;
-    }
-    
-    IPCThreadState* ipc = IPCThreadState::self();
-    {
-        Parcel data, reply;
-        // no interface token on this magic transaction
-        data.writeString16(name);
-        data.writeStrongBinder(caller);
-        status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0);
-        if (result == NO_ERROR) {
-            object = reply.readStrongBinder();
-        }
-    }
-    
-    ipc->flushCommands();
-    
-    if (object != nullptr) setContextObject(object, name);
-    return object;
-}
-
 void ProcessState::startThreadPool()
 {
     AutoMutex _l(mLock);
@@ -169,41 +121,33 @@
     }
 }
 
-bool ProcessState::isContextManager(void) const
-{
-    return mManagesContexts;
-}
-
 bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
 {
-    if (!mManagesContexts) {
-        AutoMutex _l(mLock);
-        mBinderContextCheckFunc = checkFunc;
-        mBinderContextUserData = userData;
+    AutoMutex _l(mLock);
+    mBinderContextCheckFunc = checkFunc;
+    mBinderContextUserData = userData;
 
-        flat_binder_object obj {
-            .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
-        };
+    flat_binder_object obj {
+        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
+    };
 
-        status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
 
-        // fallback to original method
-        if (result != 0) {
-            android_errorWriteLog(0x534e4554, "121035042");
+    // fallback to original method
+    if (result != 0) {
+        android_errorWriteLog(0x534e4554, "121035042");
 
-            int dummy = 0;
-            result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
-        }
-
-        if (result == 0) {
-            mManagesContexts = true;
-        } else if (result == -1) {
-            mBinderContextCheckFunc = nullptr;
-            mBinderContextUserData = nullptr;
-            ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
-        }
+        int dummy = 0;
+        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
     }
-    return mManagesContexts;
+
+    if (result == -1) {
+        mBinderContextCheckFunc = nullptr;
+        mBinderContextUserData = nullptr;
+        ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
+    }
+
+    return result == 0;
 }
 
 // Get references to userspace objects held by the kernel binder driver
@@ -214,15 +158,6 @@
 // already be invalid.
 ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf)
 {
-    // TODO: remove these when they are defined by bionic's binder.h
-    struct binder_node_debug_info {
-        binder_uintptr_t ptr;
-        binder_uintptr_t cookie;
-        __u32 has_strong_ref;
-        __u32 has_weak_ref;
-    };
-#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
-
     binder_node_debug_info info = {};
 
     uintptr_t* end = buf ? buf + buf_count : nullptr;
@@ -439,7 +374,6 @@
     , mExecutingThreadsCount(0)
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
     , mStarvationStartTimeMs(0)
-    , mManagesContexts(false)
     , mBinderContextCheckFunc(nullptr)
     , mBinderContextUserData(nullptr)
     , mThreadPoolStarted(false)
@@ -458,7 +392,7 @@
         }
     }
 
-    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
+    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
 }
 
 ProcessState::~ProcessState()
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index bd0e6f9..a6fd8c4 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -17,7 +17,7 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
-#include <private/binder/Static.h>
+#include "Static.h"
 
 #include <binder/BufferedTextOutput.h>
 #include <binder/IPCThreadState.h>
@@ -75,13 +75,4 @@
 Mutex& gProcessMutex = *new Mutex;
 sp<ProcessState> gProcess;
 
-// ------------ IServiceManager.cpp
-
-Mutex gDefaultServiceManagerLock;
-sp<IServiceManager> gDefaultServiceManager;
-#ifndef __ANDROID_VNDK__
-sp<IPermissionController> gPermissionController;
-#endif
-bool gSystemBootCompleted = false;
-
 }   // namespace android
diff --git a/libs/binder/include/private/binder/Static.h b/libs/binder/Static.h
similarity index 73%
rename from libs/binder/include/private/binder/Static.h
rename to libs/binder/Static.h
index 171be77..f8e0ee5 100644
--- a/libs/binder/include/private/binder/Static.h
+++ b/libs/binder/Static.h
@@ -21,10 +21,6 @@
 
 #include <binder/IBinder.h>
 #include <binder/ProcessState.h>
-#ifndef __ANDROID_VNDK__
-#include <binder/IPermissionController.h>
-#endif
-#include <binder/IServiceManager.h>
 
 namespace android {
 
@@ -35,12 +31,4 @@
 extern Mutex& gProcessMutex;
 extern sp<ProcessState> gProcess;
 
-// For IServiceManager.cpp
-extern Mutex gDefaultServiceManagerLock;
-extern sp<IServiceManager> gDefaultServiceManager;
-#ifndef __ANDROID_VNDK__
-extern sp<IPermissionController> gPermissionController;
-#endif
-extern bool gSystemBootCompleted;
-
 }   // namespace android
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 8b33a56..0ad99ce 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,13 +102,23 @@
     // Skip over fat response headers.  Not used (or propagated) in native code.
     if (mException == EX_HAS_REPLY_HEADER) {
         // Note that the header size includes the 4 byte size field.
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
         // And fat response headers are currently only used when there are no
         // exceptions, so act like there was no error.
@@ -135,19 +145,36 @@
         setFromStatusT(status);
         return status;
     }
+    if (remote_stack_trace_header_size < 0 ||
+        static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+        android_errorWriteLog(0x534e4554, "132650049");
+        setFromStatusT(UNKNOWN_ERROR);
+        return UNKNOWN_ERROR;
+    }
     parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
 
     if (mException == EX_SERVICE_SPECIFIC) {
         status = parcel.readInt32(&mErrorCode);
     } else if (mException == EX_PARCELABLE) {
         // Skip over the blob of Parcelable data
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
     }
     if (status != OK) {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
new file mode 100644
index 0000000..01e57d3
--- /dev/null
+++ b/libs/binder/TEST_MAPPING
@@ -0,0 +1,16 @@
+{
+  "presubmit": [
+    {
+      "name": "binderSafeInterfaceTest"
+    },
+    {
+      "name": "binderDriverInterfaceTest"
+    },
+    {
+      "name": "binderTextOutputTest"
+    },
+    {
+      "name": "binderLibTest"
+    }
+  ]
+}
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
deleted file mode 100644
index 19c57ba..0000000
--- a/libs/binder/Value.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#define LOG_TAG "Value"
-
-#include <binder/Value.h>
-
-#include <limits>
-
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-#include <binder/Map.h>
-#include <private/binder/ParcelValTypes.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-
-using android::BAD_TYPE;
-using android::BAD_VALUE;
-using android::NO_ERROR;
-using android::UNEXPECTED_NULL;
-using android::Parcel;
-using android::sp;
-using android::status_t;
-using std::map;
-using std::set;
-using std::vector;
-using android::binder::Value;
-using android::IBinder;
-using android::os::PersistableBundle;
-using namespace android::binder;
-
-// ====================================================================
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    do {                                                                 \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    } while(false)
-
-// ====================================================================
-
-/* These `internal_type_ptr()` functions allow this
- * class to work without C++ RTTI support. This technique
- * only works properly when called directly from this file,
- * but that is OK because that is the only place we will
- * be calling them from. */
-template<class T> const void* internal_type_ptr()
-{
-    static const T *marker;
-    return (void*)&marker;
-}
-
-/* Allows the type to be specified by the argument
- * instead of inside angle brackets. */
-template<class T> const void* internal_type_ptr(const T&)
-{
-    return internal_type_ptr<T>();
-}
-
-// ====================================================================
-
-namespace android {
-
-namespace binder {
-
-class Value::ContentBase {
-public:
-    virtual ~ContentBase() = default;
-    virtual const void* type_ptr() const = 0;
-    virtual ContentBase * clone() const = 0;
-    virtual bool operator==(const ContentBase& rhs) const = 0;
-
-#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
-    virtual const std::type_info &type() const = 0;
-#endif
-
-    template<typename T> bool get(T* out) const;
-};
-
-/* This is the actual class that holds the value. */
-template<typename T> class Value::Content : public Value::ContentBase {
-public:
-    Content() = default;
-    explicit Content(const T & value) : mValue(value) { }
-
-    virtual ~Content() = default;
-
-#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
-    virtual const std::type_info &type() const override
-    {
-        return typeid(T);
-    }
-#endif
-
-    virtual const void* type_ptr() const override
-    {
-        return internal_type_ptr<T>();
-    }
-
-    virtual ContentBase * clone() const override
-    {
-        return new Content(mValue);
-    };
-
-    virtual bool operator==(const ContentBase& rhs) const override
-    {
-        if (type_ptr() != rhs.type_ptr()) {
-            return false;
-        }
-        return mValue == static_cast<const Content<T>* >(&rhs)->mValue;
-    }
-
-    T mValue;
-};
-
-template<typename T> bool Value::ContentBase::get(T* out) const
-{
-    if (internal_type_ptr(*out) != type_ptr())
-    {
-        return false;
-    }
-
-    *out = static_cast<const Content<T>*>(this)->mValue;
-
-    return true;
-}
-
-// ====================================================================
-
-Value::Value() : mContent(nullptr)
-{
-}
-
-Value::Value(const Value& value)
-    : mContent(value.mContent ? value.mContent->clone() : nullptr)
-{
-}
-
-Value::~Value()
-{
-    delete mContent;
-}
-
-bool Value::operator==(const Value& rhs) const
-{
-    const Value& lhs(*this);
-
-    if (lhs.empty() && rhs.empty()) {
-        return true;
-    }
-
-    if ( (lhs.mContent == nullptr)
-      || (rhs.mContent == nullptr)
-    ) {
-        return false;
-    }
-
-    return *lhs.mContent == *rhs.mContent;
-}
-
-Value& Value::swap(Value &rhs)
-{
-    std::swap(mContent, rhs.mContent);
-    return *this;
-}
-
-Value& Value::operator=(const Value& rhs)
-{
-    if (this != &rhs) {
-        delete mContent;
-        mContent = rhs.mContent
-            ? rhs.mContent->clone()
-            : nullptr;
-    }
-    return *this;
-}
-
-bool Value::empty() const
-{
-    return mContent == nullptr;
-}
-
-void Value::clear()
-{
-    delete mContent;
-    mContent = nullptr;
-}
-
-int32_t Value::parcelType() const
-{
-    const void* t_info(mContent ? mContent->type_ptr() : nullptr);
-
-    if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
-    if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
-    if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER;
-    if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG;
-    if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE;
-    if (t_info == internal_type_ptr<String16>()) return VAL_STRING;
-
-    if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY;
-    if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY;
-    if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY;
-    if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY;
-    if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY;
-    if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY;
-
-    if (t_info == internal_type_ptr<Map>()) return VAL_MAP;
-    if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE;
-
-    return VAL_NULL;
-}
-
-#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
-const std::type_info& Value::type() const
-{
-    return mContent != nullptr
-        ? mContent->type()
-        : typeid(void);
-}
-#endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
-
-#define DEF_TYPE_ACCESSORS(T, TYPENAME)                      \
-    bool Value::is ## TYPENAME() const                       \
-    {                                                        \
-        return mContent                                      \
-            ? internal_type_ptr<T>() == mContent->type_ptr() \
-            : false;                                         \
-    }                                                        \
-    bool Value::get ## TYPENAME(T* out) const                \
-    {                                                        \
-        return mContent                                      \
-            ? mContent->get(out)                             \
-            : false;                                         \
-    }                                                        \
-    void Value::put ## TYPENAME(const T& in)                 \
-    {                                                        \
-        *this = in;                                          \
-    }                                                        \
-    Value& Value::operator=(const T& rhs)                    \
-    {                                                        \
-        delete mContent;                                     \
-        mContent = new Content< T >(rhs);                    \
-        return *this;                                        \
-    }                                                        \
-    Value::Value(const T& value)                             \
-        : mContent(new Content< T >(value))                  \
-    { }
-
-DEF_TYPE_ACCESSORS(bool, Boolean)
-DEF_TYPE_ACCESSORS(int8_t, Byte)
-DEF_TYPE_ACCESSORS(int32_t, Int)
-DEF_TYPE_ACCESSORS(int64_t, Long)
-DEF_TYPE_ACCESSORS(double, Double)
-DEF_TYPE_ACCESSORS(String16, String)
-
-DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
-DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
-DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
-DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
-DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
-DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
-
-DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
-DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
-
-bool Value::getString(String8* out) const
-{
-    String16 val;
-    bool ret = getString(&val);
-    if (ret) {
-        *out = String8(val);
-    }
-    return ret;
-}
-
-bool Value::getString(::std::string* out) const
-{
-    String8 val;
-    bool ret = getString(&val);
-    if (ret) {
-        *out = val.string();
-    }
-    return ret;
-}
-
-status_t Value::writeToParcel(Parcel* parcel) const
-{
-    // This implementation needs to be kept in sync with the writeValue
-    // implementation in frameworks/base/core/java/android/os/Parcel.java
-
-#define BEGIN_HANDLE_WRITE()                                                                      \
-    do {                                                                                          \
-        const void* t_info(mContent?mContent->type_ptr():nullptr);                                \
-        if (false) { }
-#define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD)                                                 \
-    else if (t_info == internal_type_ptr<T>()) {                                                  \
-        RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL));                                            \
-        RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue));   \
-    }
-#define HANDLE_WRITE_PARCELABLE(T, TYPEVAL)                                                       \
-    else if (t_info == internal_type_ptr<T>()) {                                                  \
-        RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL));                                            \
-        RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \
-    }
-#define END_HANDLE_WRITE()                                                                        \
-        else {                                                                                    \
-            ALOGE("writeToParcel: Type not supported");                                           \
-            return BAD_TYPE;                                                                      \
-        }                                                                                         \
-    } while (false);
-
-    BEGIN_HANDLE_WRITE()
-
-    HANDLE_WRITE_TYPE(bool,     VAL_BOOLEAN, writeBool)
-    HANDLE_WRITE_TYPE(int8_t,   VAL_BYTE,    writeByte)
-    HANDLE_WRITE_TYPE(int8_t,   VAL_BYTE,    writeByte)
-    HANDLE_WRITE_TYPE(int32_t,  VAL_INTEGER, writeInt32)
-    HANDLE_WRITE_TYPE(int64_t,  VAL_LONG,    writeInt64)
-    HANDLE_WRITE_TYPE(double,   VAL_DOUBLE,  writeDouble)
-    HANDLE_WRITE_TYPE(String16, VAL_STRING,  writeString16)
-
-    HANDLE_WRITE_TYPE(vector<bool>,     VAL_BOOLEANARRAY, writeBoolVector)
-    HANDLE_WRITE_TYPE(vector<uint8_t>,  VAL_BYTEARRAY,    writeByteVector)
-    HANDLE_WRITE_TYPE(vector<int8_t>,   VAL_BYTEARRAY,    writeByteVector)
-    HANDLE_WRITE_TYPE(vector<int32_t>,  VAL_INTARRAY,     writeInt32Vector)
-    HANDLE_WRITE_TYPE(vector<int64_t>,  VAL_LONGARRAY,    writeInt64Vector)
-    HANDLE_WRITE_TYPE(vector<double>,   VAL_DOUBLEARRAY,  writeDoubleVector)
-    HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY,  writeString16Vector)
-
-    HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
-
-    END_HANDLE_WRITE()
-
-    return NO_ERROR;
-
-#undef BEGIN_HANDLE_WRITE
-#undef HANDLE_WRITE_TYPE
-#undef HANDLE_WRITE_PARCELABLE
-#undef END_HANDLE_WRITE
-}
-
-status_t Value::readFromParcel(const Parcel* parcel)
-{
-    // This implementation needs to be kept in sync with the readValue
-    // implementation in frameworks/base/core/java/android/os/Parcel.javai
-
-#define BEGIN_HANDLE_READ()                                                                      \
-    switch(value_type) {                                                                         \
-        default:                                                                                 \
-            ALOGE("readFromParcel: Parcel type %d is not supported", value_type);                \
-            return BAD_TYPE;
-#define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD)                                                 \
-        case TYPEVAL:                                                                            \
-            mContent = new Content<T>();                                                         \
-            RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue));   \
-            break;
-#define HANDLE_READ_PARCELABLE(T, TYPEVAL)                                                       \
-        case TYPEVAL:                                                                            \
-            mContent = new Content<T>();                                                         \
-            RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \
-            break;
-#define END_HANDLE_READ()                                                                        \
-    }
-
-    int32_t value_type = VAL_NULL;
-
-    delete mContent;
-    mContent = nullptr;
-
-    RETURN_IF_FAILED(parcel->readInt32(&value_type));
-
-    BEGIN_HANDLE_READ()
-
-    HANDLE_READ_TYPE(bool,     VAL_BOOLEAN, readBool)
-    HANDLE_READ_TYPE(int8_t,   VAL_BYTE,    readByte)
-    HANDLE_READ_TYPE(int32_t,  VAL_INTEGER, readInt32)
-    HANDLE_READ_TYPE(int64_t,  VAL_LONG,    readInt64)
-    HANDLE_READ_TYPE(double,   VAL_DOUBLE,  readDouble)
-    HANDLE_READ_TYPE(String16, VAL_STRING,  readString16)
-
-    HANDLE_READ_TYPE(vector<bool>,     VAL_BOOLEANARRAY, readBoolVector)
-    HANDLE_READ_TYPE(vector<uint8_t>,  VAL_BYTEARRAY,    readByteVector)
-    HANDLE_READ_TYPE(vector<int32_t>,  VAL_INTARRAY,     readInt32Vector)
-    HANDLE_READ_TYPE(vector<int64_t>,  VAL_LONGARRAY,    readInt64Vector)
-    HANDLE_READ_TYPE(vector<double>,   VAL_DOUBLEARRAY,  readDoubleVector)
-    HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY,  readString16Vector)
-
-    HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
-
-    END_HANDLE_READ()
-
-    return NO_ERROR;
-
-#undef BEGIN_HANDLE_READ
-#undef HANDLE_READ_TYPE
-#undef HANDLE_READ_PARCELABLE
-#undef END_HANDLE_READ
-}
-
-}  // namespace binder
-
-}  // namespace android
-
-/* vim: set ts=4 sw=4 tw=0 et :*/
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index b1c577e..a7a7292 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -66,15 +66,25 @@
     const int LOCATION_VENDOR = 0x2;
     /*  ApplicationInfo.isProduct() == true */
     const int LOCATION_PRODUCT = 0x4;
-    /*  ApplicationInfo.isProductServices() == true */
-    const int LOCATION_PRODUCT_SERVICES = 0x8;
 
     /**
      * Returns a set of bitflags about package location.
      * LOCATION_SYSTEM: getApplicationInfo(packageName).isSystemApp()
      * LOCATION_VENDOR: getApplicationInfo(packageName).isVendor()
      * LOCATION_PRODUCT: getApplicationInfo(packageName).isProduct()
-     * LOCATION_PRODUCT_SERVICES: getApplicationInfo(packageName).isProductService()
      */
     int getLocationFlags(in @utf8InCpp String packageName);
+
+    /**
+     * Returns the target SDK version for the given package.
+     * Unknown packages will cause the call to fail. The caller must check the
+     * returned Status before using the result of this function.
+     */
+    int getTargetSdkVersionForPackage(in String packageName);
+
+    /**
+     * Returns the name of module metadata package, or empty string if device doesn't have such
+     * package.
+     */
+    @utf8InCpp String getModuleMetadataPackageName();
 }
diff --git a/libs/binder/aidl/android/content/pm/OWNERS b/libs/binder/aidl/android/content/pm/OWNERS
new file mode 100644
index 0000000..b99ca09
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/OWNERS
@@ -0,0 +1,4 @@
+narayan@google.com
+patb@google.com
+svetoslavganov@google.com
+toddke@google.com
\ No newline at end of file
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
new file mode 100644
index 0000000..50a72aa
--- /dev/null
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+package android.os;
+
+/**
+ * Basic interface for finding and publishing system services.
+ *
+ * You likely want to use android.os.ServiceManager in Java or
+ * android::IServiceManager in C++ in order to use this interface.
+ *
+ * @hide
+ */
+interface IServiceManager {
+    /*
+     * Must update values in IServiceManager.h
+     */
+    /* Allows services to dump sections according to priorities. */
+    const int DUMP_FLAG_PRIORITY_CRITICAL = 1; // 1 << 0
+    const int DUMP_FLAG_PRIORITY_HIGH = 2; // 1 << 1
+    const int DUMP_FLAG_PRIORITY_NORMAL = 4; // 1 << 2
+    /**
+     * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
+     * same priority as NORMAL priority but the services are not called with dump priority
+     * arguments.
+     */
+    const int DUMP_FLAG_PRIORITY_DEFAULT = 8; // 1 << 3
+
+    const int DUMP_FLAG_PRIORITY_ALL = 15;
+             // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
+             // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
+
+    /* Allows services to dump sections in protobuf format. */
+    const int DUMP_FLAG_PROTO = 16; // 1 << 4
+
+    /**
+     * Retrieve an existing service called @a name from the
+     * service manager.
+     *
+     * This is the same as checkService (returns immediately) but
+     * exists for legacy purposes.
+     *
+     * Returns null if the service does not exist.
+     */
+    @UnsupportedAppUsage
+    IBinder getService(@utf8InCpp String name);
+
+    /**
+     * Retrieve an existing service called @a name from the service
+     * manager. Non-blocking. Returns null if the service does not
+     * exist.
+     */
+    @UnsupportedAppUsage
+    IBinder checkService(@utf8InCpp String name);
+
+    /**
+     * Place a new @a service called @a name into the service
+     * manager.
+     */
+    void addService(@utf8InCpp String name, IBinder service,
+        boolean allowIsolated, int dumpPriority);
+
+    /**
+     * Return a list of all currently running services.
+     */
+    @utf8InCpp String[] listServices(int dumpPriority);
+}
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 7b086d0..5f324c7 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -47,23 +47,24 @@
         PROCESS_STATE_PERSISTENT_UI = 1,
         PROCESS_STATE_TOP = 2,
         PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3,
-        PROCESS_STATE_FOREGROUND_SERVICE = 4,
-        PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5,
-        PROCESS_STATE_IMPORTANT_FOREGROUND = 6,
-        PROCESS_STATE_IMPORTANT_BACKGROUND = 7,
-        PROCESS_STATE_TRANSIENT_BACKGROUND = 8,
-        PROCESS_STATE_BACKUP = 9,
-        PROCESS_STATE_SERVICE = 10,
-        PROCESS_STATE_RECEIVER = 11,
-        PROCESS_STATE_TOP_SLEEPING = 12,
-        PROCESS_STATE_HEAVY_WEIGHT = 13,
-        PROCESS_STATE_HOME = 14,
-        PROCESS_STATE_LAST_ACTIVITY = 15,
-        PROCESS_STATE_CACHED_ACTIVITY = 16,
-        PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17,
-        PROCESS_STATE_CACHED_RECENT = 18,
-        PROCESS_STATE_CACHED_EMPTY = 19,
-        PROCESS_STATE_NONEXISTENT = 20,
+        PROCESS_STATE_BOUND_TOP = 4,
+        PROCESS_STATE_FOREGROUND_SERVICE = 5,
+        PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6,
+        PROCESS_STATE_IMPORTANT_FOREGROUND = 7,
+        PROCESS_STATE_IMPORTANT_BACKGROUND = 8,
+        PROCESS_STATE_TRANSIENT_BACKGROUND = 9,
+        PROCESS_STATE_BACKUP = 10,
+        PROCESS_STATE_SERVICE = 11,
+        PROCESS_STATE_RECEIVER = 12,
+        PROCESS_STATE_TOP_SLEEPING = 13,
+        PROCESS_STATE_HEAVY_WEIGHT = 14,
+        PROCESS_STATE_HOME = 15,
+        PROCESS_STATE_LAST_ACTIVITY = 16,
+        PROCESS_STATE_CACHED_ACTIVITY = 17,
+        PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18,
+        PROCESS_STATE_CACHED_RECENT = 19,
+        PROCESS_STATE_CACHED_EMPTY = 20,
+        PROCESS_STATE_NONEXISTENT = 21,
     };
 
     ActivityManager();
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 37237df..17493b4 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -114,6 +114,8 @@
     AppOpsManager();
 
     int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
+    int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
+            const String16& callingPackage);
     int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
     int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
             bool startIfModeDefault);
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 1d4f881..b3a1d0b 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -34,7 +34,7 @@
 public:
     static BpBinder*    create(int32_t handle);
 
-    inline  int32_t     handle() const { return mHandle; }
+    int32_t             handle() const;
 
     virtual const String16&    getInterfaceDescriptor() const;
     virtual bool        isBinderAlive() const;
@@ -67,7 +67,6 @@
 
     virtual BpBinder*   remoteBinder();
 
-            status_t    setConstantData(const void* data, size_t size);
             void        sendObituary();
 
     static uint32_t     getBinderProxyCount(uint32_t uid);
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 7807851..3dbd0d9 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -43,6 +43,8 @@
     virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
     virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) = 0;
     virtual int32_t permissionToOpCode(const String16& permission) = 0;
+    virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid,
+            const String16& packageName) = 0;
 
     enum {
         CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -53,6 +55,7 @@
         STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
         GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
         PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
+        CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
     };
 
     enum {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 614b0b3..b810f7e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -110,6 +110,8 @@
             // the maximum number of binder threads threads allowed for this process.
             void                blockUntilThreadAvailable();
 
+            // Service manager registration
+            void                setTheContextObject(sp<BBinder> obj);
 
             // Is this thread currently serving a binder call. This method
             // returns true if while traversing backwards from the function call
diff --git a/libs/binder/include/binder/Map.h b/libs/binder/include/binder/Map.h
deleted file mode 100644
index 96a4f8a..0000000
--- a/libs/binder/include/binder/Map.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2005 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_MAP_H
-#define ANDROID_MAP_H
-
-#include <map>
-#include <string>
-
-// ---------------------------------------------------------------------------
-namespace android {
-namespace binder {
-
-class Value;
-
-/**
- * Convenience typedef for ::std::map<::std::string,::android::binder::Value>
- */
-typedef ::std::map<::std::string, Value> Map;
-
-} // namespace binder
-} // namespace android
-
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_MAP_H
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index e5219a5..b65d456 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_PARCEL_H
 #define ANDROID_PARCEL_H
 
+#include <map> // for legacy reasons
 #include <string>
 #include <vector>
 
@@ -32,7 +33,6 @@
 
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
-#include <binder/Map.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -97,10 +97,6 @@
 
     void                freeData();
 
-private:
-    const binder_size_t* objects() const;
-
-public:
     size_t              objectsCount() const;
     
     status_t            errorCheck() const;
@@ -172,8 +168,6 @@
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
-    status_t            writeValue(const binder::Value& value);
-
     template<typename T>
     status_t            write(const Flattenable<T>& val);
 
@@ -185,9 +179,6 @@
     template<typename T>
     status_t            writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
 
-    status_t            writeMap(const binder::Map& map);
-    status_t            writeNullableMap(const std::unique_ptr<binder::Map>& map);
-
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
     // when this function returns).
@@ -244,8 +235,6 @@
     // Currently the native implementation doesn't do any of the StrictMode
     // stack gathering and serialization that the Java implementation does.
     status_t            writeNoException();
-
-    void                remove(size_t start, size_t amt);
     
     status_t            read(void* outData, size_t len) const;
     const void*         readInplace(size_t len) const;
@@ -297,8 +286,6 @@
     template<typename T>
     status_t            readParcelable(std::unique_ptr<T>* parcelable) const;
 
-    status_t            readValue(binder::Value* value) const;
-
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
@@ -344,9 +331,6 @@
     template<typename T>
     status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
 
-    status_t            readMap(binder::Map* map)const;
-    status_t            readNullableMap(std::unique_ptr<binder::Map>* map) const;
-
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
     // code on exceptions, but also deals with skipping over rich
@@ -399,7 +383,7 @@
     bool                replaceCallingWorkSourceUid(uid_t uid);
     // Returns the work source provided by the caller. This can only be trusted for trusted calling
     // uid.
-    uid_t               readCallingWorkSourceUid();
+    uid_t               readCallingWorkSourceUid() const;
     void                readRequestHeaders() const;
 
 private:
@@ -932,23 +916,6 @@
     return to;
 }
 
-// ---------------------------------------------------------------------------
-
-// Generic acquire and release of objects.
-void acquire_object(const sp<ProcessState>& proc,
-                    const flat_binder_object& obj, const void* who);
-void release_object(const sp<ProcessState>& proc,
-                    const flat_binder_object& obj, const void* who);
-
-void flatten_binder(const sp<ProcessState>& proc,
-                    const sp<IBinder>& binder, flat_binder_object* out);
-void flatten_binder(const sp<ProcessState>& proc,
-                    const wp<IBinder>& binder, flat_binder_object* out);
-status_t unflatten_binder(const sp<ProcessState>& proc,
-                          const flat_binder_object& flat, sp<IBinder>* out);
-status_t unflatten_binder(const sp<ProcessState>& proc,
-                          const flat_binder_object& flat, wp<IBinder>* out);
-
 }; // namespace android
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 224cb36..3af9eed 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -45,21 +45,14 @@
      */
     static  sp<ProcessState>    initWithDriver(const char *driver);
 
-            void                setContextObject(const sp<IBinder>& object);
             sp<IBinder>         getContextObject(const sp<IBinder>& caller);
-        
-            void                setContextObject(const sp<IBinder>& object,
-                                                 const String16& name);
-            sp<IBinder>         getContextObject(const String16& name,
-                                                 const sp<IBinder>& caller);
 
             void                startThreadPool();
                         
     typedef bool (*context_check_func)(const String16& name,
                                        const sp<IBinder>& caller,
                                        void* userData);
-        
-            bool                isContextManager(void) const;
+
             bool                becomeContextManager(
                                     context_check_func checkFunc,
                                     void* userData);
@@ -124,14 +117,9 @@
 
             Vector<handle_entry>mHandleToObject;
 
-            bool                mManagesContexts;
             context_check_func  mBinderContextCheckFunc;
             void*               mBinderContextUserData;
 
-            KeyedVector<String16, sp<IBinder> >
-                                mContexts;
-
-
             String8             mRootDir;
             bool                mThreadPoolStarted;
     volatile int32_t            mThreadPoolSeq;
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
deleted file mode 100644
index 735f40e..0000000
--- a/libs/binder/include/binder/Value.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 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 ANDROID_VALUE_H
-#define ANDROID_VALUE_H
-
-#include <stdint.h>
-#include <map>
-#include <set>
-#include <vector>
-#include <string>
-
-#include <binder/Parcelable.h>
-#include <binder/PersistableBundle.h>
-#include <binder/Map.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-class Parcel;
-
-namespace binder {
-
-/**
- * A limited C++ generic type. The purpose of this class is to allow C++
- * programs to make use of (or implement) Binder interfaces which make use
- * the Java "Object" generic type (either via the use of the Map type or
- * some other mechanism).
- *
- * This class only supports a limited set of types, but additional types
- * may be easily added to this class in the future as needed---without
- * breaking binary compatability.
- *
- * This class was written in such a way as to help avoid type errors by
- * giving each type their own explicity-named accessor methods (rather than
- * overloaded methods).
- *
- * When reading or writing this class to a Parcel, use the `writeValue()`
- * and `readValue()` methods.
- */
-class Value {
-public:
-    Value();
-    virtual ~Value();
-
-    Value& swap(Value &);
-
-    bool empty() const;
-
-    void clear();
-
-#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
-    const std::type_info& type() const;
-#endif
-
-    int32_t parcelType() const;
-
-    bool operator==(const Value& rhs) const;
-    bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
-
-    Value(const Value& value);
-    Value(const bool& value); // NOLINT(google-explicit-constructor)
-    Value(const int8_t& value); // NOLINT(google-explicit-constructor)
-    Value(const int32_t& value); // NOLINT(google-explicit-constructor)
-    Value(const int64_t& value); // NOLINT(google-explicit-constructor)
-    Value(const double& value); // NOLINT(google-explicit-constructor)
-    Value(const String16& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
-    Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
-    Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
-    Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
-
-    Value& operator=(const Value& rhs);
-    Value& operator=(const int8_t& rhs);
-    Value& operator=(const bool& rhs);
-    Value& operator=(const int32_t& rhs);
-    Value& operator=(const int64_t& rhs);
-    Value& operator=(const double& rhs);
-    Value& operator=(const String16& rhs);
-    Value& operator=(const std::vector<bool>& rhs);
-    Value& operator=(const std::vector<uint8_t>& rhs);
-    Value& operator=(const std::vector<int32_t>& rhs);
-    Value& operator=(const std::vector<int64_t>& rhs);
-    Value& operator=(const std::vector<double>& rhs);
-    Value& operator=(const std::vector<String16>& rhs);
-    Value& operator=(const os::PersistableBundle& rhs);
-    Value& operator=(const binder::Map& rhs);
-
-    void putBoolean(const bool& value);
-    void putByte(const int8_t& value);
-    void putInt(const int32_t& value);
-    void putLong(const int64_t& value);
-    void putDouble(const double& value);
-    void putString(const String16& value);
-    void putBooleanVector(const std::vector<bool>& value);
-    void putByteVector(const std::vector<uint8_t>& value);
-    void putIntVector(const std::vector<int32_t>& value);
-    void putLongVector(const std::vector<int64_t>& value);
-    void putDoubleVector(const std::vector<double>& value);
-    void putStringVector(const std::vector<String16>& value);
-    void putPersistableBundle(const os::PersistableBundle& value);
-    void putMap(const binder::Map& value);
-
-    bool getBoolean(bool* out) const;
-    bool getByte(int8_t* out) const;
-    bool getInt(int32_t* out) const;
-    bool getLong(int64_t* out) const;
-    bool getDouble(double* out) const;
-    bool getString(String16* out) const;
-    bool getBooleanVector(std::vector<bool>* out) const;
-    bool getByteVector(std::vector<uint8_t>* out) const;
-    bool getIntVector(std::vector<int32_t>* out) const;
-    bool getLongVector(std::vector<int64_t>* out) const;
-    bool getDoubleVector(std::vector<double>* out) const;
-    bool getStringVector(std::vector<String16>* out) const;
-    bool getPersistableBundle(os::PersistableBundle* out) const;
-    bool getMap(binder::Map* out) const;
-
-    bool isBoolean() const;
-    bool isByte() const;
-    bool isInt() const;
-    bool isLong() const;
-    bool isDouble() const;
-    bool isString() const;
-    bool isBooleanVector() const;
-    bool isByteVector() const;
-    bool isIntVector() const;
-    bool isLongVector() const;
-    bool isDoubleVector() const;
-    bool isStringVector() const;
-    bool isPersistableBundle() const;
-    bool isMap() const;
-
-    // String Convenience Adapters
-    // ---------------------------
-
-    explicit Value(const String8& value):               Value(String16(value)) { }
-    explicit Value(const ::std::string& value):         Value(String8(value.c_str())) { }
-    void putString(const String8& value)       { return putString(String16(value)); }
-    void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
-    Value& operator=(const String8& rhs)       { return *this = String16(rhs); }
-    Value& operator=(const ::std::string& rhs) { return *this = String8(rhs.c_str()); }
-    bool getString(String8* out) const;
-    bool getString(::std::string* out) const;
-
-private:
-
-    // This allows ::android::Parcel to call the two methods below.
-    friend class ::android::Parcel;
-
-    // This is called by ::android::Parcel::writeValue()
-    status_t writeToParcel(Parcel* parcel) const;
-
-    // This is called by ::android::Parcel::readValue()
-    status_t readFromParcel(const Parcel* parcel);
-
-    template<typename T> class Content;
-    class ContentBase;
-
-    ContentBase* mContent;
-};
-
-}  // namespace binder
-
-}  // namespace android
-
-#endif  // ANDROID_VALUE_H
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 21bef2e..6da3086 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -16,7 +16,6 @@
 
 cc_library {
     name: "libbinder_ndk",
-    vendor_available: true,
 
     export_include_dirs: [
         "include_ndk",
@@ -74,3 +73,12 @@
     symbol_file: "libbinder_ndk.map.txt",
     first_version: "29",
 }
+
+llndk_library {
+    name: "libbinder_ndk",
+    symbol_file: "libbinder_ndk.map.txt",
+    export_include_dirs: [
+        "include_ndk",
+        "include_apex",
+    ],
+}
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 7e65817..4f685d1 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,12 +89,12 @@
     AStatus_getStatus;
     AStatus_isOk;
     AStatus_newOk;
-    ABinderProcess_joinThreadPool; # apex
-    ABinderProcess_setThreadPoolMaxThreadCount; # apex
-    ABinderProcess_startThreadPool; # apex
-    AServiceManager_addService; # apex
-    AServiceManager_checkService; # apex
-    AServiceManager_getService; # apex
+    ABinderProcess_joinThreadPool; # apex vndk
+    ABinderProcess_setThreadPoolMaxThreadCount; # apex vndk
+    ABinderProcess_startThreadPool; # apex vndk
+    AServiceManager_addService; # apex vndk
+    AServiceManager_checkService; # apex vndk
+    AServiceManager_getService; # apex vndk
   local:
     *;
 };
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index c451780..44a691d 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -19,45 +19,34 @@
     cflags: [
         "-Wall",
         "-Werror",
-        "-Wno-unused-private-field",
-        "-Wno-unused-variable",
     ],
 }
 
 cc_test {
     name: "binderDriverInterfaceTest_IPC_32",
-    srcs: ["binderDriverInterfaceTest.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["binderDriverInterfaceTest.cpp"],
     compile_multilib: "32",
     cflags: ["-DBINDER_IPC_32BIT=1"],
 }
 
 cc_test {
+    name: "binderDriverInterfaceTest",
+    defaults: ["binder_test_defaults"],
     product_variables: {
         binder32bit: {
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
 
-    name: "binderDriverInterfaceTest",
     srcs: ["binderDriverInterfaceTest.cpp"],
-    defaults: ["binder_test_defaults"],
-}
-
-cc_test {
-    name: "binderValueTypeTest",
-    srcs: ["binderValueTypeTest.cpp"],
-    defaults: ["binder_test_defaults"],
-    shared_libs: [
-        "libbinder",
-        "libutils",
-    ],
+    test_suites: ["device-tests"],
 }
 
 cc_test {
     name: "binderLibTest_IPC_32",
-    srcs: ["binderLibTest.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["binderLibTest.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -67,25 +56,26 @@
 }
 
 cc_test {
+    name: "binderLibTest",
+    defaults: ["binder_test_defaults"],
     product_variables: {
         binder32bit: {
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
 
-    defaults: ["binder_test_defaults"],
-    name: "binderLibTest",
     srcs: ["binderLibTest.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
     ],
+    test_suites: ["device-tests"],
 }
 
 cc_test {
     name: "binderThroughputTest",
-    srcs: ["binderThroughputTest.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["binderThroughputTest.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -101,19 +91,20 @@
 
 cc_test {
     name: "binderTextOutputTest",
-    srcs: ["binderTextOutputTest.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["binderTextOutputTest.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
         "libbase",
     ],
+    test_suites: ["device-tests"],
 }
 
 cc_test {
     name: "schd-dbg",
-    srcs: ["schd-dbg.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["schd-dbg.cpp"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -123,8 +114,8 @@
 
 cc_test {
     name: "binderSafeInterfaceTest",
-    srcs: ["binderSafeInterfaceTest.cpp"],
     defaults: ["binder_test_defaults"],
+    srcs: ["binderSafeInterfaceTest.cpp"],
 
     cppflags: [
         "-Weverything",
@@ -144,4 +135,5 @@
         "liblog",
         "libutils",
     ],
+    test_suites: ["device-tests"],
 }
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index 77ebac8..f3ed6a6 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -230,7 +230,6 @@
 }
 
 TEST_F(BinderDriverInterfaceTest, Transaction) {
-    binder_uintptr_t cookie = 1234;
     struct {
         uint32_t cmd1;
         struct binder_transaction_data arg1;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 78f1159..e51bceb 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -553,50 +553,6 @@
     ASSERT_TRUE(server != nullptr);
 }
 
-TEST_F(BinderLibTest, DeathNotificationNoRefs)
-{
-    status_t ret;
-
-    sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
-
-    {
-        sp<IBinder> binder = addServer();
-        ASSERT_TRUE(binder != nullptr);
-        ret = binder->linkToDeath(testDeathRecipient);
-        EXPECT_EQ(NO_ERROR, ret);
-    }
-    IPCThreadState::self()->flushCommands();
-    ret = testDeathRecipient->waitEvent(5);
-    EXPECT_EQ(NO_ERROR, ret);
-#if 0 /* Is there an unlink api that does not require a strong reference? */
-    ret = binder->unlinkToDeath(testDeathRecipient);
-    EXPECT_EQ(NO_ERROR, ret);
-#endif
-}
-
-TEST_F(BinderLibTest, DeathNotificationWeakRef)
-{
-    status_t ret;
-    wp<IBinder> wbinder;
-
-    sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
-
-    {
-        sp<IBinder> binder = addServer();
-        ASSERT_TRUE(binder != nullptr);
-        ret = binder->linkToDeath(testDeathRecipient);
-        EXPECT_EQ(NO_ERROR, ret);
-        wbinder = binder;
-    }
-    IPCThreadState::self()->flushCommands();
-    ret = testDeathRecipient->waitEvent(5);
-    EXPECT_EQ(NO_ERROR, ret);
-#if 0 /* Is there an unlink api that does not require a strong reference? */
-    ret = binder->unlinkToDeath(testDeathRecipient);
-    EXPECT_EQ(NO_ERROR, ret);
-#endif
-}
-
 TEST_F(BinderLibTest, DeathNotificationStrongRef)
 {
     status_t ret;
@@ -1015,9 +971,6 @@
 
 TEST_F(BinderLibTest, PropagateFlagSet)
 {
-    status_t ret;
-    Parcel data, reply;
-
     IPCThreadState::self()->clearPropagateWorkSource();
     IPCThreadState::self()->setCallingWorkSourceUid(100);
     EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -1025,9 +978,6 @@
 
 TEST_F(BinderLibTest, PropagateFlagCleared)
 {
-    status_t ret;
-    Parcel data, reply;
-
     IPCThreadState::self()->setCallingWorkSourceUid(100);
     IPCThreadState::self()->clearPropagateWorkSource();
     EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
@@ -1035,9 +985,6 @@
 
 TEST_F(BinderLibTest, PropagateFlagRestored)
 {
-    status_t ret;
-    Parcel data, reply;
-
     int token = IPCThreadState::self()->setCallingWorkSourceUid(100);
     IPCThreadState::self()->restoreCallingWorkSource(token);
 
@@ -1136,7 +1083,6 @@
             case BINDER_LIB_TEST_ADD_POLL_SERVER:
             case BINDER_LIB_TEST_ADD_SERVER: {
                 int ret;
-                uint8_t buf[1] = { 0 };
                 int serverid;
 
                 if (m_id != 0) {
@@ -1399,7 +1345,6 @@
         bool m_serverStartRequested;
         sp<IBinder> m_serverStarted;
         sp<IBinder> m_strongRef;
-        bool m_callbackPending;
         sp<IBinder> m_callback;
 };
 
@@ -1461,7 +1406,7 @@
               * We simulate a single-threaded process using the binder poll
               * interface; besides handling binder commands, it can also
               * issue outgoing transactions, by storing a callback in
-              * m_callback and setting m_callbackPending.
+              * m_callback.
               *
               * processPendingCall() will then issue that transaction.
               */
@@ -1488,8 +1433,6 @@
 }
 
 int main(int argc, char **argv) {
-    int ret;
-
     if (argc == 4 && !strcmp(argv[1], "--servername")) {
         binderservername = argv[2];
     } else {
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 3b1db27..09f58cc 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -75,7 +75,7 @@
 
 private:
     int32_t mValue = 0;
-    uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
+    __attribute__((unused)) uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
 };
 
 struct TestFlattenable : Flattenable<TestFlattenable> {
@@ -743,6 +743,7 @@
     const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
     std::vector<TestParcelable> aPlusOne;
     status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+    ASSERT_EQ(NO_ERROR, result);
     ASSERT_EQ(a.size(), aPlusOne.size());
     for (size_t i = 0; i < a.size(); ++i) {
         ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
deleted file mode 100644
index f8922b0..0000000
--- a/libs/binder/tests/binderValueTypeTest.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits>
-#include <cstddef>
-#include <vector>
-
-#include "android-base/file.h"
-#include <gtest/gtest.h>
-
-#include <binder/Parcel.h>
-#include <binder/Value.h>
-#include <binder/Debug.h>
-
-using ::android::binder::Value;
-using ::android::os::PersistableBundle;
-using ::android::String16;
-using ::std::vector;
-
-#define VALUE_TYPE_TEST(T, TYPENAME, VAL)         \
-    TEST(ValueType, Handles ## TYPENAME) {        \
-        T x = VAL;                                \
-        T y = T();                                \
-        Value value = VAL;                        \
-        ASSERT_FALSE(value.empty());              \
-        ASSERT_TRUE(value.is ## TYPENAME ());     \
-        ASSERT_TRUE(value.get ## TYPENAME (&y));  \
-        ASSERT_EQ(x, y);                          \
-        ASSERT_EQ(value, Value(y));               \
-        value.put ## TYPENAME (x);                \
-        ASSERT_EQ(value, Value(y));               \
-        value = Value();                          \
-        ASSERT_TRUE(value.empty());               \
-        ASSERT_NE(value, Value(y));               \
-        value = y;                                \
-        ASSERT_EQ(value, Value(x));               \
-    }
-
-#define VALUE_TYPE_VECTOR_TEST(T, TYPENAME, VAL)      \
-    TEST(ValueType, Handles ## TYPENAME ## Vector) {  \
-        vector<T> x;                                  \
-        vector<T> y;                                  \
-        x.push_back(VAL);                             \
-        x.push_back(T());                             \
-        Value value(x);                               \
-        ASSERT_FALSE(value.empty());                  \
-        ASSERT_TRUE(value.is ## TYPENAME ## Vector());    \
-        ASSERT_TRUE(value.get ## TYPENAME ## Vector(&y)); \
-        ASSERT_EQ(x, y);                              \
-        ASSERT_EQ(value, Value(y));                   \
-        value.put ## TYPENAME ## Vector(x);           \
-        ASSERT_EQ(value, Value(y));                   \
-        value = Value();                              \
-        ASSERT_TRUE(value.empty());                   \
-        ASSERT_NE(value, Value(y));                   \
-        value = y;                                    \
-        ASSERT_EQ(value, Value(x));                   \
-    }
-
-VALUE_TYPE_TEST(bool, Boolean, true)
-VALUE_TYPE_TEST(int32_t, Int, 31337)
-VALUE_TYPE_TEST(int64_t, Long, 13370133701337L)
-VALUE_TYPE_TEST(double, Double, 3.14159265358979323846)
-VALUE_TYPE_TEST(String16, String, String16("Lovely"))
-
-VALUE_TYPE_VECTOR_TEST(bool, Boolean, true)
-VALUE_TYPE_VECTOR_TEST(int32_t, Int, 31337)
-VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337L)
-VALUE_TYPE_VECTOR_TEST(double, Double, 3.14159265358979323846)
-VALUE_TYPE_VECTOR_TEST(String16, String, String16("Lovely"))
-
-VALUE_TYPE_TEST(PersistableBundle, PersistableBundle, PersistableBundle())
-
-TEST(ValueType, HandlesClear) {
-    Value value;
-    ASSERT_TRUE(value.empty());
-    value.putInt(31337);
-    ASSERT_FALSE(value.empty());
-    value.clear();
-    ASSERT_TRUE(value.empty());
-}
-
-TEST(ValueType, HandlesSwap) {
-    Value value_a, value_b;
-    int32_t int_x;
-    value_a.putInt(31337);
-    ASSERT_FALSE(value_a.empty());
-    ASSERT_TRUE(value_b.empty());
-    value_a.swap(value_b);
-    ASSERT_FALSE(value_b.empty());
-    ASSERT_TRUE(value_a.empty());
-    ASSERT_TRUE(value_b.getInt(&int_x));
-    ASSERT_EQ(31337, int_x);
-}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index ec9534a..ab4c56a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -290,6 +290,7 @@
 
   sta = tickNow();
   status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
+  ASSERT(ret == NO_ERROR);
   end = tickNow();
   results_fifo->add_time(tickNano(sta, end));
 
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 28cb138..9080ce1 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -19,7 +19,11 @@
     name: "libtimeinstate_test",
     srcs: ["testtimeinstate.cpp"],
     shared_libs: [
+        "libbase",
+        "libbpf",
+        "libbpf_android",
         "libtimeinstate",
+        "libnetdutils",
     ],
     cflags: [
         "-Werror",
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 5fd4a95..0e68e62 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -17,12 +17,14 @@
 #define LOG_TAG "libtimeinstate"
 
 #include "cputimeinstate.h"
+#include "timeinstate.h"
 
 #include <dirent.h>
 #include <errno.h>
 #include <inttypes.h>
 
 #include <mutex>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -37,23 +39,12 @@
 #include <libbpf.h>
 #include <log/log.h>
 
-#define BPF_FS_PATH "/sys/fs/bpf/"
-
 using android::base::StringPrintf;
 using android::base::unique_fd;
 
 namespace android {
 namespace bpf {
 
-struct time_key_t {
-    uint32_t uid;
-    uint32_t freq;
-};
-
-struct val_t {
-    uint64_t ar[100];
-};
-
 static std::mutex gInitializedMutex;
 static bool gInitialized = false;
 static uint32_t gNPolicies = 0;
@@ -62,19 +53,20 @@
 static std::set<uint32_t> gAllFreqs;
 static unique_fd gMapFd;
 
-static bool readNumbersFromFile(const std::string &path, std::vector<uint32_t> *out) {
+static std::optional<std::vector<uint32_t>> readNumbersFromFile(const std::string &path) {
     std::string data;
 
-    if (!android::base::ReadFileToString(path, &data)) return false;
+    if (!android::base::ReadFileToString(path, &data)) return {};
 
     auto strings = android::base::Split(data, " \n");
+    std::vector<uint32_t> ret;
     for (const auto &s : strings) {
         if (s.empty()) continue;
         uint32_t n;
-        if (!android::base::ParseUint(s, &n)) return false;
-        out->emplace_back(n);
+        if (!android::base::ParseUint(s, &n)) return {};
+        ret.emplace_back(n);
     }
-    return true;
+    return ret;
 }
 
 static int isPolicyFile(const struct dirent *d) {
@@ -111,20 +103,22 @@
         for (const auto &name : {"available", "boost"}) {
             std::string path =
                     StringPrintf("%s/%s/scaling_%s_frequencies", basepath, policy.c_str(), name);
-            if (!readNumbersFromFile(path, &freqs)) return false;
+            auto nums = readNumbersFromFile(path);
+            if (!nums) return false;
+            freqs.insert(freqs.end(), nums->begin(), nums->end());
         }
         std::sort(freqs.begin(), freqs.end());
         gPolicyFreqs.emplace_back(freqs);
 
         for (auto freq : freqs) gAllFreqs.insert(freq);
 
-        std::vector<uint32_t> cpus;
         std::string path = StringPrintf("%s/%s/%s", basepath, policy.c_str(), "related_cpus");
-        if (!readNumbersFromFile(path, &cpus)) return false;
-        gPolicyCpus.emplace_back(cpus);
+        auto cpus = readNumbersFromFile(path);
+        if (!cpus) return false;
+        gPolicyCpus.emplace_back(*cpus);
     }
 
-    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times")};
+    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
     if (gMapFd < 0) return false;
 
     gInitialized = true;
@@ -151,17 +145,15 @@
 }
 
 // Retrieve the times in ns that uid spent running at each CPU frequency and store in freqTimes.
-// Returns false on error. Otherwise, returns true and populates freqTimes with a vector of vectors
-// using the format:
+// Return contains no value on error, otherwise it contains a vector of vectors using the format:
 // [[t0_0, t0_1, ...],
 //  [t1_0, t1_1, ...], ...]
 // where ti_j is the ns that uid spent running on the ith cluster at that cluster's jth lowest freq.
-bool getUidCpuFreqTimes(uint32_t uid, std::vector<std::vector<uint64_t>> *freqTimes) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid) {
+    if (!gInitialized && !initGlobals()) return {};
     time_key_t key = {.uid = uid, .freq = 0};
 
-    freqTimes->clear();
-    freqTimes->resize(gNPolicies);
+    std::vector<std::vector<uint64_t>> out(gNPolicies);
     std::vector<uint32_t> idxs(gNPolicies, 0);
 
     val_t value;
@@ -172,32 +164,32 @@
             if (errno == ENOENT)
                 memset(&value.ar, 0, sizeof(value.ar));
             else
-                return false;
+                return {};
         }
         for (uint32_t i = 0; i < gNPolicies; ++i) {
             if (idxs[i] == gPolicyFreqs[i].size() || freq != gPolicyFreqs[i][idxs[i]]) continue;
             uint64_t time = 0;
             for (uint32_t cpu : gPolicyCpus[i]) time += value.ar[cpu];
             idxs[i] += 1;
-            (*freqTimes)[i].emplace_back(time);
+            out[i].emplace_back(time);
         }
     }
 
-    return true;
+    return out;
 }
 
 // Retrieve the times in ns that each uid spent running at each CPU freq and store in freqTimeMap.
-// Returns false on error. Otherwise, returns true and populates freqTimeMap with a map from uids to
-// vectors of vectors using the format:
+// Return contains no value on error, otherwise it contains a map from uids to vectors of vectors
+// using the format:
 // { uid0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...],
 //   uid1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... }
 // where ti_j_k is the ns uid i spent running on the jth cluster at the cluster's kth lowest freq.
-bool getUidsCpuFreqTimes(
-        std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *freqTimeMap) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+getUidsCpuFreqTimes() {
+    if (!gInitialized && !initGlobals()) return {};
 
-    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times");
-    if (fd < 0) return false;
+    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map");
+    if (fd < 0) return {};
     BpfMap<time_key_t, val_t> m(fd);
 
     std::vector<std::unordered_map<uint32_t, uint32_t>> policyFreqIdxs;
@@ -206,25 +198,26 @@
         for (size_t j = 0; j < gPolicyFreqs[i].size(); ++j) freqIdxs[gPolicyFreqs[i][j]] = j;
         policyFreqIdxs.emplace_back(freqIdxs);
     }
-
-    auto fn = [freqTimeMap, &policyFreqIdxs](const time_key_t &key, const val_t &val,
+    std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> map;
+    auto fn = [&map, &policyFreqIdxs](const time_key_t &key, const val_t &val,
                                              const BpfMap<time_key_t, val_t> &) {
-        if (freqTimeMap->find(key.uid) == freqTimeMap->end()) {
-            (*freqTimeMap)[key.uid].resize(gNPolicies);
+        if (map.find(key.uid) == map.end()) {
+            map[key.uid].resize(gNPolicies);
             for (uint32_t i = 0; i < gNPolicies; ++i) {
-                (*freqTimeMap)[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
+                map[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
             }
         }
 
         for (size_t policy = 0; policy < gNPolicies; ++policy) {
             for (const auto &cpu : gPolicyCpus[policy]) {
                 auto freqIdx = policyFreqIdxs[policy][key.freq];
-                (*freqTimeMap)[key.uid][policy][freqIdx] += val.ar[cpu];
+                map[key.uid][policy][freqIdx] += val.ar[cpu];
             }
         }
         return android::netdutils::status::ok;
     };
-    return isOk(m.iterateWithValue(fn));
+    if (isOk(m.iterateWithValue(fn))) return map;
+    return {};
 }
 
 // Clear all time in state data for a given uid. Returns false on error, true otherwise.
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 9f6103e..d7b4587 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -23,8 +23,9 @@
 namespace bpf {
 
 bool startTrackingUidCpuFreqTimes();
-bool getUidCpuFreqTimes(unsigned int uid, std::vector<std::vector<uint64_t>> *freqTimes);
-bool getUidsCpuFreqTimes(std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *tisMap);
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+    getUidsCpuFreqTimes();
 bool clearUidCpuFreqTimes(unsigned int uid);
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 9837865..6347de1 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -1,57 +1,152 @@
 
+#include "timeinstate.h"
+
+#include <sys/sysinfo.h>
+
 #include <unordered_map>
 #include <vector>
 
 #include <gtest/gtest.h>
 
+#include <android-base/unique_fd.h>
+#include <bpf/BpfMap.h>
 #include <cputimeinstate.h>
+#include <libbpf.h>
 
 namespace android {
 namespace bpf {
 
+static constexpr uint64_t NSEC_PER_SEC = 1000000000;
+static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
+
 using std::vector;
 
 TEST(TimeInStateTest, SingleUid) {
-    vector<vector<uint64_t>> times;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    EXPECT_FALSE(times.empty());
+    auto times = getUidCpuFreqTimes(0);
+    ASSERT_TRUE(times.has_value());
+    EXPECT_FALSE(times->empty());
 }
 
 TEST(TimeInStateTest, AllUid) {
     vector<size_t> sizes;
-    std::unordered_map<uint32_t, vector<vector<uint64_t>>> map;
-    ASSERT_TRUE(getUidsCpuFreqTimes(&map));
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
 
-    ASSERT_FALSE(map.empty());
+    ASSERT_FALSE(map->empty());
 
-    auto firstEntry = map.begin()->second;
+    auto firstEntry = map->begin()->second;
     for (const auto &subEntry : firstEntry) sizes.emplace_back(subEntry.size());
 
-    for (const auto &vec : map) {
+    for (const auto &vec : *map) {
         ASSERT_EQ(vec.second.size(), sizes.size());
         for (size_t i = 0; i < vec.second.size(); ++i) ASSERT_EQ(vec.second[i].size(), sizes[i]);
     }
 }
 
+TEST(TimeInStateTest, SingleAndAllUidConsistent) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+    ASSERT_FALSE(map->empty());
+
+    for (const auto &kv : *map) {
+        uint32_t uid = kv.first;
+        auto times1 = kv.second;
+        auto times2 = getUidCpuFreqTimes(uid);
+        ASSERT_TRUE(times2.has_value());
+
+        ASSERT_EQ(times1.size(), times2->size());
+        for (uint32_t i = 0; i < times1.size(); ++i) {
+            ASSERT_EQ(times1[i].size(), (*times2)[i].size());
+            for (uint32_t j = 0; j < times1[i].size(); ++j) {
+                ASSERT_LE((*times2)[i][j] - times1[i][j], NSEC_PER_SEC);
+            }
+        }
+    }
+}
+
+void TestCheckDelta(uint64_t before, uint64_t after) {
+    // Times should never decrease
+    ASSERT_LE(before, after);
+    // UID can't have run for more than ~1s on each CPU
+    ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf());
+}
+
+TEST(TimeInStateTest, AllUidMonotonic) {
+    auto map1 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map1.has_value());
+    sleep(1);
+    auto map2 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map2.has_value());
+
+    for (const auto &kv : *map1) {
+        uint32_t uid = kv.first;
+        auto times = kv.second;
+        ASSERT_NE(map2->find(uid), map2->end());
+        for (uint32_t policy = 0; policy < times.size(); ++policy) {
+            for (uint32_t freqIdx = 0; freqIdx < times[policy].size(); ++freqIdx) {
+                auto before = times[policy][freqIdx];
+                auto after = (*map2)[uid][policy][freqIdx];
+                ASSERT_NO_FATAL_FAILURE(TestCheckDelta(before, after));
+            }
+        }
+    }
+}
+
+TEST(TimeInStateTest, AllUidSanityCheck) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+
+    bool foundLargeValue = false;
+    for (const auto &kv : *map) {
+        for (const auto &timeVec : kv.second) {
+            for (const auto &time : timeVec) {
+                ASSERT_LE(time, NSEC_PER_YEAR);
+                if (time > UINT32_MAX) foundLargeValue = true;
+            }
+        }
+    }
+    // UINT32_MAX nanoseconds is less than 5 seconds, so if every part of our pipeline is using
+    // uint64_t as expected, we should have some times higher than that.
+    ASSERT_TRUE(foundLargeValue);
+}
+
 TEST(TimeInStateTest, RemoveUid) {
-    vector<vector<uint64_t>> times, times2;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    ASSERT_FALSE(times.empty());
+    uint32_t uid = 0;
+    {
+        // Find an unused UID
+        auto times = getUidsCpuFreqTimes();
+        ASSERT_TRUE(times.has_value());
+        ASSERT_FALSE(times->empty());
+        for (const auto &kv : *times) uid = std::max(uid, kv.first);
+        ++uid;
+    }
+    {
+        // Add a map entry for our fake UID by copying a real map entry
+        android::base::unique_fd fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
+        ASSERT_GE(fd, 0);
+        time_key_t k;
+        ASSERT_FALSE(getFirstMapKey(fd, &k));
+        val_t val;
+        ASSERT_FALSE(findMapEntry(fd, &k, &val));
+        k.uid = uid;
+        ASSERT_FALSE(writeToMapEntry(fd, &k, &val, BPF_NOEXIST));
+    }
+    auto times = getUidCpuFreqTimes(uid);
+    ASSERT_TRUE(times.has_value());
+    ASSERT_FALSE(times->empty());
 
     uint64_t sum = 0;
-    for (size_t i = 0; i < times.size(); ++i) {
-        for (auto x : times[i]) sum += x;
+    for (size_t i = 0; i < times->size(); ++i) {
+        for (auto x : (*times)[i]) sum += x;
     }
     ASSERT_GT(sum, (uint64_t)0);
 
-    ASSERT_TRUE(clearUidCpuFreqTimes(0));
+    ASSERT_TRUE(clearUidCpuFreqTimes(uid));
 
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times2));
-    ASSERT_EQ(times2.size(), times.size());
-    for (size_t i = 0; i < times.size(); ++i) {
-        ASSERT_EQ(times2[i].size(), times[i].size());
-        for (size_t j = 0; j < times[i].size(); ++j) ASSERT_LE(times2[i][j], times[i][j]);
-    }
+    auto allTimes = getUidsCpuFreqTimes();
+    ASSERT_TRUE(allTimes.has_value());
+    ASSERT_FALSE(allTimes->empty());
+    ASSERT_EQ(allTimes->find(uid), allTimes->end());
 }
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/timeinstate.h b/libs/cputimeinstate/timeinstate.h
new file mode 100644
index 0000000..cf66ae7
--- /dev/null
+++ b/libs/cputimeinstate/timeinstate.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#define BPF_FS_PATH "/sys/fs/bpf/"
+
+struct time_key_t {
+    uint32_t uid;
+    uint32_t freq;
+};
+
+struct val_t {
+    uint64_t ar[100];
+};
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index 3412e14..e23de8e 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -17,7 +17,6 @@
 
     shared_libs: [
         "libbase",
-        "libbinder",
         "libhidlbase",
         "libhidltransport",
         "liblog",
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 04884bb..8e762f1 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -31,11 +31,14 @@
         "/system/bin/mediaextractor", // media.extractor
         "/system/bin/mediametrics", // media.metrics
         "/system/bin/mediaserver",
+        "/system/bin/netd",
+        "/system/bin/vold",
         "/system/bin/sdcard",
         "/system/bin/statsd",
         "/system/bin/surfaceflinger",
         "/system/bin/vehicle_network_service",
         "/vendor/bin/hw/android.hardware.media.omx@1.0-service", // media.codec
+        "/apex/com.android.media.swcodec/bin/mediaswcodec", // media.swcodec
         NULL,
 };
 
@@ -43,15 +46,20 @@
 static const char* hal_interfaces_to_dump[] {
         "android.hardware.audio@2.0::IDevicesFactory",
         "android.hardware.audio@4.0::IDevicesFactory",
+        "android.hardware.biometrics.face@1.0::IBiometricsFace",
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
         "android.hardware.drm@1.0::IDrmFactory",
         "android.hardware.graphics.allocator@2.0::IAllocator",
         "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.health@2.0::IHealth",
+        "android.hardware.media.c2@1.0::IComponentStore",
         "android.hardware.media.omx@1.0::IOmx",
         "android.hardware.media.omx@1.0::IOmxStore",
+        "android.hardware.power@1.3::IPower",
+        "android.hardware.power.stats@1.0::IPowerStats",
         "android.hardware.sensors@1.0::ISensors",
+        "android.hardware.thermal@2.0::IThermal",
         "android.hardware.vr@1.0::IVr",
         NULL,
 };
@@ -104,13 +112,15 @@
 }
 
 bool IsZygote(int pid) {
-    static const std::string kZygotePrefix = "zygote";
-
     std::string cmdline;
     if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
                                          &cmdline)) {
         return true;
     }
 
-    return (cmdline.find(kZygotePrefix) == 0);
+    // cmdline has embedded nulls; only consider argv[0].
+    cmdline = std::string(cmdline.c_str());
+
+    return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" ||
+            cmdline == "usap64";
 }
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index 0fa0d9e..85137f5 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -34,6 +34,11 @@
     if ((status = parcel->writeInt32(glLoadingFailureCount)) != OK) return status;
     if ((status = parcel->writeInt32(vkLoadingCount)) != OK) return status;
     if ((status = parcel->writeInt32(vkLoadingFailureCount)) != OK) return status;
+    if ((status = parcel->writeInt32(vulkanVersion)) != OK) return status;
+    if ((status = parcel->writeInt32(cpuVulkanVersion)) != OK) return status;
+    if ((status = parcel->writeInt32(glesVersion)) != OK) return status;
+    if ((status = parcel->writeInt32(angleLoadingCount)) != OK) return status;
+    if ((status = parcel->writeInt32(angleLoadingFailureCount)) != OK) return status;
     return OK;
 }
 
@@ -47,6 +52,11 @@
     if ((status = parcel->readInt32(&glLoadingFailureCount)) != OK) return status;
     if ((status = parcel->readInt32(&vkLoadingCount)) != OK) return status;
     if ((status = parcel->readInt32(&vkLoadingFailureCount)) != OK) return status;
+    if ((status = parcel->readInt32(&vulkanVersion)) != OK) return status;
+    if ((status = parcel->readInt32(&cpuVulkanVersion)) != OK) return status;
+    if ((status = parcel->readInt32(&glesVersion)) != OK) return status;
+    if ((status = parcel->readInt32(&angleLoadingCount)) != OK) return status;
+    if ((status = parcel->readInt32(&angleLoadingFailureCount)) != OK) return status;
     return OK;
 }
 
@@ -58,8 +68,13 @@
     StringAppendF(&result, "driverBuildTime = %" PRId64 "\n", driverBuildTime);
     StringAppendF(&result, "glLoadingCount = %d\n", glLoadingCount);
     StringAppendF(&result, "glLoadingFailureCount = %d\n", glLoadingFailureCount);
+    StringAppendF(&result, "angleLoadingCount = %d\n", angleLoadingCount);
+    StringAppendF(&result, "angleLoadingFailureCount = %d\n", angleLoadingFailureCount);
     StringAppendF(&result, "vkLoadingCount = %d\n", vkLoadingCount);
     StringAppendF(&result, "vkLoadingFailureCount = %d\n", vkLoadingFailureCount);
+    StringAppendF(&result, "vulkanVersion = %d\n", vulkanVersion);
+    StringAppendF(&result, "cpuVulkanVersion = %d\n", cpuVulkanVersion);
+    StringAppendF(&result, "glesVersion = %d\n", glesVersion);
     return result;
 }
 
@@ -69,6 +84,9 @@
     if ((status = parcel->writeUint64(driverVersionCode)) != OK) return status;
     if ((status = parcel->writeInt64Vector(glDriverLoadingTime)) != OK) return status;
     if ((status = parcel->writeInt64Vector(vkDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->writeInt64Vector(angleDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status;
+    if ((status = parcel->writeBool(falsePrerotation)) != OK) return status;
     return OK;
 }
 
@@ -78,6 +96,9 @@
     if ((status = parcel->readUint64(&driverVersionCode)) != OK) return status;
     if ((status = parcel->readInt64Vector(&glDriverLoadingTime)) != OK) return status;
     if ((status = parcel->readInt64Vector(&vkDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->readInt64Vector(&angleDriverLoadingTime)) != OK) return status;
+    if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status;
+    if ((status = parcel->readBool(&falsePrerotation)) != OK) return status;
     return OK;
 }
 
@@ -85,11 +106,18 @@
     std::string result;
     StringAppendF(&result, "appPackageName = %s\n", appPackageName.c_str());
     StringAppendF(&result, "driverVersionCode = %" PRIu64 "\n", driverVersionCode);
+    StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse);
+    StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation);
     result.append("glDriverLoadingTime:");
     for (int32_t loadingTime : glDriverLoadingTime) {
         StringAppendF(&result, " %d", loadingTime);
     }
     result.append("\n");
+    result.append("angleDriverLoadingTime:");
+    for (int32_t loadingTime : angleDriverLoadingTime) {
+        StringAppendF(&result, " %d", loadingTime);
+    }
+    result.append("\n");
     result.append("vkDriverLoadingTime:");
     for (int32_t loadingTime : vkDriverLoadingTime) {
         StringAppendF(&result, " %d", loadingTime);
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 13c0d87..3e29e88 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -37,6 +37,7 @@
 
 #include <memory>
 #include <string>
+#include <thread>
 
 // TODO(b/37049319) Get this from a header once one exists
 extern "C" {
@@ -160,9 +161,29 @@
     mSphalLibraries = sphalLibraries;
 }
 
+void GraphicsEnv::hintActivityLaunch() {
+    ATRACE_CALL();
+
+    std::thread trySendGpuStatsThread([this]() {
+        // If there's already graphics driver preloaded in the process, just send
+        // the stats info to GpuStats directly through async binder.
+        std::lock_guard<std::mutex> lock(mStatsLock);
+        if (mGpuStats.glDriverToSend) {
+            mGpuStats.glDriverToSend = false;
+            sendGpuStatsLocked(GpuStatsInfo::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
+        }
+        if (mGpuStats.vkDriverToSend) {
+            mGpuStats.vkDriverToSend = false;
+            sendGpuStatsLocked(GpuStatsInfo::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
+        }
+    });
+    trySendGpuStatsThread.detach();
+}
+
 void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
                               const std::string& driverVersionName, uint64_t driverVersionCode,
-                              int64_t driverBuildTime, const std::string& appPackageName) {
+                              int64_t driverBuildTime, const std::string& appPackageName,
+                              const int vulkanVersion) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStatsLock);
@@ -171,43 +192,45 @@
           "\tdriverVersionName[%s]\n"
           "\tdriverVersionCode[%" PRIu64 "]\n"
           "\tdriverBuildTime[%" PRId64 "]\n"
-          "\tappPackageName[%s]\n",
+          "\tappPackageName[%s]\n"
+          "\tvulkanVersion[%d]\n",
           driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
-          appPackageName.c_str());
+          appPackageName.c_str(), vulkanVersion);
 
     mGpuStats.driverPackageName = driverPackageName;
     mGpuStats.driverVersionName = driverVersionName;
     mGpuStats.driverVersionCode = driverVersionCode;
     mGpuStats.driverBuildTime = driverBuildTime;
     mGpuStats.appPackageName = appPackageName;
+    mGpuStats.vulkanVersion = vulkanVersion;
 }
 
-void GraphicsEnv::setDriverToLoad(GraphicsEnv::Driver driver) {
+void GraphicsEnv::setDriverToLoad(GpuStatsInfo::Driver driver) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStatsLock);
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
-        case GraphicsEnv::Driver::ANGLE: {
-            if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE) {
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
+        case GpuStatsInfo::Driver::ANGLE: {
+            if (mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.glDriverToLoad = driver;
                 break;
             }
 
-            if (mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.glDriverFallback = driver;
             }
             break;
         }
-        case Driver::VULKAN:
-        case Driver::VULKAN_UPDATED: {
-            if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE) {
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED: {
+            if (mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.vkDriverToLoad = driver;
                 break;
             }
 
-            if (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.vkDriverFallback = driver;
             }
             break;
@@ -217,38 +240,25 @@
     }
 }
 
-void GraphicsEnv::setDriverLoaded(GraphicsEnv::Api api, bool isLoaded, int64_t driverLoadingTime) {
+void GraphicsEnv::setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded,
+                                  int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStatsLock);
-    GraphicsEnv::Driver driver = GraphicsEnv::Driver::NONE;
-    bool isIntendedDriverLoaded = false;
-    if (api == GraphicsEnv::Api::API_GL) {
-        driver = mGpuStats.glDriverToLoad;
-        isIntendedDriverLoaded = isLoaded &&
-                ((mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) ||
-                 (mGpuStats.glDriverToLoad == mGpuStats.glDriverFallback));
+    const bool doNotSend = mGpuStats.appPackageName.empty();
+    if (api == GpuStatsInfo::Api::API_GL) {
+        if (doNotSend) mGpuStats.glDriverToSend = true;
+        mGpuStats.glDriverLoadingTime = driverLoadingTime;
     } else {
-        driver = mGpuStats.vkDriverToLoad;
-        isIntendedDriverLoaded =
-                isLoaded && (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE);
+        if (doNotSend) mGpuStats.vkDriverToSend = true;
+        mGpuStats.vkDriverLoadingTime = driverLoadingTime;
     }
 
-    sendGpuStatsLocked(driver, isIntendedDriverLoaded, driverLoadingTime);
-}
-
-void GraphicsEnv::clearDriverLoadingInfo(GraphicsEnv::Api api) {
-    ATRACE_CALL();
-
-    std::lock_guard<std::mutex> lock(mStatsLock);
-    if (api == GraphicsEnv::Api::API_GL) {
-        mGpuStats.glDriverToLoad = GraphicsEnv::Driver::NONE;
-        mGpuStats.glDriverFallback = GraphicsEnv::Driver::NONE;
-    }
+    sendGpuStatsLocked(api, isDriverLoaded, driverLoadingTime);
 }
 
 static sp<IGpuService> getGpuService() {
-    const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
     if (!binder) {
         ALOGE("Failed to get gpu service");
         return nullptr;
@@ -257,7 +267,18 @@
     return interface_cast<IGpuService>(binder);
 }
 
-void GraphicsEnv::sendGpuStatsLocked(GraphicsEnv::Driver driver, bool isDriverLoaded,
+void GraphicsEnv::setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value) {
+    ATRACE_CALL();
+
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    const sp<IGpuService> gpuService = getGpuService();
+    if (gpuService) {
+        gpuService->setTargetStats(mGpuStats.appPackageName, mGpuStats.driverVersionCode, stats,
+                                   value);
+    }
+}
+
+void GraphicsEnv::sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded,
                                      int64_t driverLoadingTime) {
     ATRACE_CALL();
 
@@ -270,19 +291,32 @@
           "\tdriverVersionCode[%" PRIu64 "]\n"
           "\tdriverBuildTime[%" PRId64 "]\n"
           "\tappPackageName[%s]\n"
-          "\tdriver[%d]\n"
+          "\tvulkanVersion[%d]\n"
+          "\tapi[%d]\n"
           "\tisDriverLoaded[%d]\n"
           "\tdriverLoadingTime[%" PRId64 "]",
           mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
           mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
-          static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
+          mGpuStats.vulkanVersion, static_cast<int32_t>(api), isDriverLoaded, driverLoadingTime);
+
+    GpuStatsInfo::Driver driver = GpuStatsInfo::Driver::NONE;
+    bool isIntendedDriverLoaded = false;
+    if (api == GpuStatsInfo::Api::API_GL) {
+        driver = mGpuStats.glDriverToLoad;
+        isIntendedDriverLoaded =
+                isDriverLoaded && (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE);
+    } else {
+        driver = mGpuStats.vkDriverToLoad;
+        isIntendedDriverLoaded =
+                isDriverLoaded && (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE);
+    }
 
     const sp<IGpuService> gpuService = getGpuService();
     if (gpuService) {
         gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
                                 mGpuStats.driverVersionCode, mGpuStats.driverBuildTime,
-                                mGpuStats.appPackageName, driver, isDriverLoaded,
-                                driverLoadingTime);
+                                mGpuStats.appPackageName, mGpuStats.vulkanVersion, driver,
+                                isIntendedDriverLoaded, driverLoadingTime);
     }
 }
 
@@ -504,60 +538,73 @@
     mDebugLayersGLES = layers;
 }
 
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the Game Driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+    if (llndkLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+        ALOGE("Failed to link default namespace[%s]", dlerror());
+        return false;
+    }
+
+    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+    if (vndkspLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+        ALOGE("Failed to link vndk namespace[%s]", dlerror());
+        return false;
+    }
+
+    if (mSphalLibraries.empty()) {
+        return true;
+    }
+
+    // Make additional libraries in sphal to be accessible
+    auto sphalNamespace = android_get_exported_namespace("sphal");
+    if (!sphalNamespace) {
+        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+              mSphalLibraries.c_str());
+        return false;
+    }
+
+    if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+        ALOGE("Failed to link sphal namespace[%s]", dlerror());
+        return false;
+    }
+
+    return true;
+}
+
 android_namespace_t* GraphicsEnv::getDriverNamespace() {
-    static std::once_flag once;
-    std::call_once(once, [this]() {
-        if (mDriverPath.empty()) return;
+    std::lock_guard<std::mutex> lock(mNamespaceMutex);
 
-        auto vndkNamespace = android_get_exported_namespace("vndk");
-        if (!vndkNamespace) return;
+    if (mDriverNamespace) {
+        return mDriverNamespace;
+    }
 
-        mDriverNamespace = android_create_namespace("gfx driver",
-                                                    mDriverPath.c_str(), // ld_library_path
-                                                    mDriverPath.c_str(), // default_library_path
-                                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
-                                                    nullptr, // permitted_when_isolated_path
-                                                    nullptr);
+    if (mDriverPath.empty()) {
+        return nullptr;
+    }
 
-        const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
-        if (llndkLibraries.empty()) {
-            mDriverNamespace = nullptr;
-            return;
-        }
-        if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
-            ALOGE("Failed to link default namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
 
-        const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
-        if (vndkspLibraries.empty()) {
-            mDriverNamespace = nullptr;
-            return;
-        }
-        if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
-            ALOGE("Failed to link vndk namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
+    mDriverNamespace = android_create_namespace("gfx driver",
+                                                mDriverPath.c_str(), // ld_library_path
+                                                mDriverPath.c_str(), // default_library_path
+                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                nullptr, // permitted_when_isolated_path
+                                                nullptr);
 
-        if (mSphalLibraries.empty()) return;
-
-        // Make additional libraries in sphal to be accessible
-        auto sphalNamespace = android_get_exported_namespace("sphal");
-        if (!sphalNamespace) {
-            ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
-                  mSphalLibraries.c_str());
-            mDriverNamespace = nullptr;
-            return;
-        }
-
-        if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
-            ALOGE("Failed to link sphal namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
-    });
+    if (!linkDriverNamespaceLocked(vndkNamespace)) {
+        mDriverNamespace = nullptr;
+    }
 
     return mDriverNamespace;
 }
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 1dc1c0e..9f5b0ff 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -30,8 +30,8 @@
     virtual void setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             GraphicsEnv::Driver driver, bool isDriverLoaded,
-                             int64_t driverLoadingTime) {
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
 
@@ -40,6 +40,7 @@
         data.writeUint64(driverVersionCode);
         data.writeInt64(driverBuildTime);
         data.writeUtf8AsUtf16(appPackageName);
+        data.writeInt32(vulkanVersion);
         data.writeInt32(static_cast<int32_t>(driver));
         data.writeBool(isDriverLoaded);
         data.writeInt64(driverLoadingTime);
@@ -90,6 +91,19 @@
         outStats->clear();
         return reply.readParcelableVector(outStats);
     }
+
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
+
+        data.writeUtf8AsUtf16(appPackageName);
+        data.writeUint64(driverVersionCode);
+        data.writeInt32(static_cast<int32_t>(stats));
+        data.writeUint64(value);
+
+        remote()->transact(BnGpuService::SET_TARGET_STATS, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(GpuService, "android.graphicsenv.IGpuService");
@@ -118,6 +132,9 @@
             std::string appPackageName;
             if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
 
+            int32_t vulkanVersion;
+            if ((status = data.readInt32(&vulkanVersion)) != OK) return status;
+
             int32_t driver;
             if ((status = data.readInt32(&driver)) != OK) return status;
 
@@ -128,8 +145,8 @@
             if ((status = data.readInt64(&driverLoadingTime)) != OK) return status;
 
             setGpuStats(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
-                        appPackageName, static_cast<GraphicsEnv::Driver>(driver), isDriverLoaded,
-                        driverLoadingTime);
+                        appPackageName, vulkanVersion, static_cast<GpuStatsInfo::Driver>(driver),
+                        isDriverLoaded, driverLoadingTime);
 
             return OK;
         }
@@ -159,6 +176,26 @@
 
             return OK;
         }
+        case SET_TARGET_STATS: {
+            CHECK_INTERFACE(IGpuService, data, reply);
+
+            std::string appPackageName;
+            if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
+
+            uint64_t driverVersionCode;
+            if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
+
+            int32_t stats;
+            if ((status = data.readInt32(&stats)) != OK) return status;
+
+            uint64_t value;
+            if ((status = data.readUint64(&value)) != OK) return status;
+
+            setTargetStats(appPackageName, driverVersionCode,
+                           static_cast<GpuStatsInfo::Stats>(stats), value);
+
+            return OK;
+        }
         case SHELL_COMMAND_TRANSACTION: {
             int in = data.readFileDescriptor();
             int out = data.readFileDescriptor();
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index a92ca70..7959652 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -44,6 +44,11 @@
     int32_t glLoadingFailureCount = 0;
     int32_t vkLoadingCount = 0;
     int32_t vkLoadingFailureCount = 0;
+    int32_t vulkanVersion = 0;
+    int32_t cpuVulkanVersion = 0;
+    int32_t glesVersion = 0;
+    int32_t angleLoadingCount = 0;
+    int32_t angleLoadingFailureCount = 0;
 };
 
 /*
@@ -63,6 +68,53 @@
     uint64_t driverVersionCode = 0;
     std::vector<int64_t> glDriverLoadingTime = {};
     std::vector<int64_t> vkDriverLoadingTime = {};
+    std::vector<int64_t> angleDriverLoadingTime = {};
+    bool cpuVulkanInUse = false;
+    bool falsePrerotation = false;
+};
+
+/*
+ * class for holding the gpu stats in GraphicsEnv before sending to GpuService.
+ */
+class GpuStatsInfo {
+public:
+    enum Api {
+        API_GL = 0,
+        API_VK = 1,
+    };
+
+    enum Driver {
+        NONE = 0,
+        GL = 1,
+        GL_UPDATED = 2,
+        VULKAN = 3,
+        VULKAN_UPDATED = 4,
+        ANGLE = 5,
+    };
+
+    enum Stats {
+        CPU_VULKAN_IN_USE = 0,
+        FALSE_PREROTATION = 1,
+    };
+
+    GpuStatsInfo() = default;
+    GpuStatsInfo(const GpuStatsInfo&) = default;
+    virtual ~GpuStatsInfo() = default;
+
+    std::string driverPackageName = "";
+    std::string driverVersionName = "";
+    uint64_t driverVersionCode = 0;
+    int64_t driverBuildTime = 0;
+    std::string appPackageName = "";
+    int32_t vulkanVersion = 0;
+    Driver glDriverToLoad = Driver::NONE;
+    Driver glDriverFallback = Driver::NONE;
+    Driver vkDriverToLoad = Driver::NONE;
+    Driver vkDriverFallback = Driver::NONE;
+    bool glDriverToSend = false;
+    bool vkDriverToSend = false;
+    int64_t glDriverLoadingTime = 0;
+    int64_t vkDriverLoadingTime = 0;
 };
 
 } // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index cb4239f..a47f468 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_UI_GRAPHICS_ENV_H
 #define ANDROID_UI_GRAPHICS_ENV_H 1
 
+#include <graphicsenv/GpuStatsInfo.h>
+
 #include <mutex>
 #include <string>
 #include <vector>
@@ -29,49 +31,14 @@
 
 class GraphicsEnv {
 public:
-    enum Api {
-        API_GL = 0,
-        API_VK = 1,
-    };
-
-    enum Driver {
-        NONE = 0,
-        GL = 1,
-        GL_UPDATED = 2,
-        VULKAN = 3,
-        VULKAN_UPDATED = 4,
-        ANGLE = 5,
-    };
-
-private:
-    struct GpuStats {
-        std::string driverPackageName;
-        std::string driverVersionName;
-        uint64_t driverVersionCode;
-        int64_t driverBuildTime;
-        std::string appPackageName;
-        Driver glDriverToLoad;
-        Driver glDriverFallback;
-        Driver vkDriverToLoad;
-        Driver vkDriverFallback;
-
-        GpuStats()
-              : driverPackageName(""),
-                driverVersionName(""),
-                driverVersionCode(0),
-                driverBuildTime(0),
-                appPackageName(""),
-                glDriverToLoad(Driver::NONE),
-                glDriverFallback(Driver::NONE),
-                vkDriverToLoad(Driver::NONE),
-                vkDriverFallback(Driver::NONE) {}
-    };
-
-public:
     static GraphicsEnv& getInstance();
 
+    // Check if device is debuggable.
     int getCanLoadSystemLibraries();
 
+    /*
+     * Apis for updatable driver
+     */
     // Set a search path for loading graphics drivers. The path is a list of
     // directories separated by ':'. A directory can be contained in a zip file
     // (drivers must be stored uncompressed and page aligned); such elements
@@ -81,16 +48,31 @@
     // graphics drivers. The string is a list of libraries separated by ':',
     // which is required by android_link_namespaces.
     void setDriverPathAndSphalLibraries(const std::string path, const std::string sphalLibraries);
+    // Get the updatable driver namespace.
     android_namespace_t* getDriverNamespace();
+
+    /*
+     * Apis for GpuStats
+     */
+    // Hint there's real activity launching on the app process.
+    void hintActivityLaunch();
+    // Set the initial GpuStats.
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
                      uint64_t versionCode, int64_t driverBuildTime,
-                     const std::string& appPackageName);
-    void setDriverToLoad(Driver driver);
-    void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
-    void clearDriverLoadingInfo(Api api);
-    void sendGpuStatsLocked(Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
+                     const std::string& appPackageName, const int32_t vulkanVersion);
+    // Set stats for target GpuStatsInfo::Stats type.
+    void setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value = 0);
+    // Set which driver is intended to load.
+    void setDriverToLoad(GpuStatsInfo::Driver driver);
+    // Set which driver is actually loaded.
+    void setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
+    /*
+     * Apis for ANGLE
+     */
+    // Check if the requested app should use ANGLE.
     bool shouldUseAngle(std::string appName);
+    // Check if this app process should use ANGLE.
     bool shouldUseAngle();
     // Set a search path for loading ANGLE libraries. The path is a list of
     // directories separated by ':'. A directory can be contained in a zip file
@@ -99,42 +81,75 @@
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
     void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
                       const int rulesFd, const long rulesOffset, const long rulesLength);
+    // Get the ANGLE driver namespace.
     android_namespace_t* getAngleNamespace();
+    // Get the app name for ANGLE debug message.
     std::string& getAngleAppName();
 
+    /*
+     * Apis for debug layer
+     */
+    // Set additional layer search paths.
     void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
+    // Get the app namespace for loading layers.
     NativeLoaderNamespace* getAppNamespace();
-
+    // Get additional layer search paths.
     const std::string& getLayerPaths();
-
+    // Set the Vulkan debug layers.
     void setDebugLayers(const std::string layers);
+    // Set the GL debug layers.
     void setDebugLayersGLES(const std::string layers);
+    // Get the debug layers to load.
     const std::string& getDebugLayers();
+    // Get the debug layers to load.
     const std::string& getDebugLayersGLES();
 
 private:
     enum UseAngle { UNKNOWN, YES, NO };
 
+    // Load requested ANGLE library.
     void* loadLibrary(std::string name);
+    // Check ANGLE support with the rules.
     bool checkAngleRules(void* so);
+    // Update whether ANGLE should be used.
     void updateUseAngle();
+    // Link updatable driver namespace with llndk and vndk-sp libs.
+    bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
+    // Send the initial complete GpuStats to GpuService.
+    void sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
     GraphicsEnv() = default;
+    // Path to updatable driver libs.
     std::string mDriverPath;
+    // Path to additional sphal libs linked to updatable driver namespace.
     std::string mSphalLibraries;
+    // This mutex protects mGpuStats and get gpuservice call.
     std::mutex mStatsLock;
-    GpuStats mGpuStats;
+    // Information bookkept for GpuStats.
+    GpuStatsInfo mGpuStats;
+    // Path to ANGLE libs.
     std::string mAnglePath;
+    // This App's name.
     std::string mAngleAppName;
+    // ANGLE developer opt in status.
     std::string mAngleDeveloperOptIn;
+    // ANGLE rules.
     std::vector<char> mRulesBuffer;
+    // Use ANGLE flag.
     UseAngle mUseAngle = UNKNOWN;
+    // Vulkan debug layers libs.
     std::string mDebugLayers;
+    // GL debug layers libs.
     std::string mDebugLayersGLES;
+    // Additional debug layers search path.
     std::string mLayerPaths;
+    // This mutex protects the namespace creation.
     std::mutex mNamespaceMutex;
+    // Updatable driver namespace.
     android_namespace_t* mDriverNamespace = nullptr;
+    // ANGLE namespace.
     android_namespace_t* mAngleNamespace = nullptr;
+    // This App's namespace.
     NativeLoaderNamespace* mAppNamespace = nullptr;
 };
 
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index ac022b5..f523d58 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -37,8 +37,12 @@
     virtual void setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             GraphicsEnv::Driver driver, bool isDriverLoaded,
-                             int64_t driverLoadingTime) = 0;
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) = 0;
+
+    // set target stats.
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value = 0) = 0;
 
     // get GPU global stats from GpuStats module.
     virtual status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const = 0;
@@ -53,6 +57,7 @@
         SET_GPU_STATS = IBinder::FIRST_CALL_TRANSACTION,
         GET_GPU_STATS_GLOBAL_INFO,
         GET_GPU_STATS_APP_INFO,
+        SET_TARGET_STATS,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4c2e653..beb13ad 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,6 +15,10 @@
     name: "libgui_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
+
+    // we must build this module to get the required header as that is generated
+    export_shared_lib_headers: [ "android.hidl.token@1.0-utils" ],
+    shared_libs: [ "android.hidl.token@1.0-utils" ],
 }
 
 cc_library_shared {
@@ -25,49 +29,20 @@
     },
     double_loadable: true,
 
-    clang: true,
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    cppflags: [
-        "-Wextra",
-        "-DDEBUG_ONLY_CODE=0",
-    ],
-
-    product_variables: {
-        eng: {
-            cppflags: [
-                "-UDEBUG_ONLY_CODE",
-                "-DDEBUG_ONLY_CODE=1",
-            ],
-        },
-    },
+    defaults: ["libgui_bufferqueue-defaults"],
 
     srcs: [
         "BitTube.cpp",
         "BufferHubConsumer.cpp",
         "BufferHubProducer.cpp",
-        "BufferItem.cpp",
         "BufferItemConsumer.cpp",
-        "BufferQueue.cpp",
-        "BufferQueueConsumer.cpp",
-        "BufferQueueCore.cpp",
-        "BufferQueueProducer.cpp",
-        "BufferQueueThreadState.cpp",
-        "BufferSlot.cpp",
         "ConsumerBase.cpp",
         "CpuConsumer.cpp",
+        "DebugEGLImageTracker.cpp",
         "DisplayEventReceiver.cpp",
-        "FrameTimestamps.cpp",
         "GLConsumer.cpp",
         "GuiConfig.cpp",
-        "HdrMetadata.cpp",
         "IDisplayEventConnection.cpp",
-        "IConsumerListener.cpp",
-        "IGraphicBufferConsumer.cpp",
-        "IGraphicBufferProducer.cpp",
-        "IProducerListener.cpp",
         "IRegionSamplingListener.cpp",
         "ISurfaceComposer.cpp",
         "ISurfaceComposerClient.cpp",
@@ -75,48 +50,20 @@
         "LayerDebugInfo.cpp",
         "LayerMetadata.cpp",
         "LayerState.cpp",
-        "OccupancyTracker.cpp",
         "StreamSplitter.cpp",
         "Surface.cpp",
         "SurfaceControl.cpp",
         "SurfaceComposerClient.cpp",
         "SyncFeatures.cpp",
         "view/Surface.cpp",
-        "bufferqueue/1.0/B2HProducerListener.cpp",
-        "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
-        "bufferqueue/1.0/H2BProducerListener.cpp",
-        "bufferqueue/2.0/B2HGraphicBufferProducer.cpp",
-        "bufferqueue/2.0/B2HProducerListener.cpp",
-        "bufferqueue/2.0/H2BGraphicBufferProducer.cpp",
-        "bufferqueue/2.0/H2BProducerListener.cpp",
-        "bufferqueue/2.0/types.cpp",
     ],
 
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
-        "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
-        "android.hardware.graphics.common@1.1",
-        "android.hardware.graphics.common@1.2",
-        "android.hidl.token@1.0-utils",
-        "libbase",
-        "libbinder",
         "libbufferhub",
         "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
-        "libcutils",
-        "libEGL",
-        "libGLESv2",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libinput",
-        "liblog",
-        "libnativewindow",
         "libpdx_default_transport",
-        "libsync",
-        "libui",
-        "libutils",
-        "libvndksupport",
     ],
 
     // bufferhub is not used when building libgui for vendors
@@ -142,9 +89,100 @@
 
     header_libs: [
         "libdvr_headers",
+        "libpdx_headers",
+    ],
+}
+
+// Used by media codec services exclusively as a static lib for
+// core bufferqueue support only.
+cc_library_static {
+    name: "libgui_bufferqueue_static",
+    vendor_available: true,
+
+    cflags: [
+        "-DNO_BUFFERHUB",
+    ],
+
+    defaults: ["libgui_bufferqueue-defaults"],
+}
+
+// Common build config shared by libgui and libgui_bufferqueue_static.
+cc_defaults {
+    name: "libgui_bufferqueue-defaults",
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    cppflags: [
+        "-Wextra",
+        "-DDEBUG_ONLY_CODE=0",
+    ],
+
+    product_variables: {
+        eng: {
+            cppflags: [
+                "-UDEBUG_ONLY_CODE",
+                "-DDEBUG_ONLY_CODE=1",
+            ],
+        },
+    },
+
+    srcs: [
+        "BufferItem.cpp",
+        "BufferQueue.cpp",
+        "BufferQueueConsumer.cpp",
+        "BufferQueueCore.cpp",
+        "BufferQueueProducer.cpp",
+        "BufferQueueThreadState.cpp",
+        "BufferSlot.cpp",
+        "FrameTimestamps.cpp",
+        "GLConsumerUtils.cpp",
+        "HdrMetadata.cpp",
+        "IConsumerListener.cpp",
+        "IGraphicBufferConsumer.cpp",
+        "IGraphicBufferProducer.cpp",
+        "IProducerListener.cpp",
+        "OccupancyTracker.cpp",
+        "bufferqueue/1.0/B2HProducerListener.cpp",
+        "bufferqueue/1.0/Conversion.cpp",
+        "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
+        "bufferqueue/1.0/H2BProducerListener.cpp",
+        "bufferqueue/1.0/WProducerListener.cpp",
+        "bufferqueue/2.0/B2HGraphicBufferProducer.cpp",
+        "bufferqueue/2.0/B2HProducerListener.cpp",
+        "bufferqueue/2.0/H2BGraphicBufferProducer.cpp",
+        "bufferqueue/2.0/H2BProducerListener.cpp",
+        "bufferqueue/2.0/types.cpp",
+    ],
+
+    shared_libs: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hidl.token@1.0-utils",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libnativewindow",
+        "libsync",
+        "libui",
+        "libutils",
+        "libvndksupport",
+    ],
+
+    header_libs: [
         "libgui_headers",
         "libnativebase_headers",
-        "libpdx_headers",
     ],
 
     export_shared_lib_headers: [
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d87228f..5fb3f0b 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -59,13 +59,6 @@
     }
 }
 
-void BufferQueue::ProxyConsumerListener::onBufferAllocated(const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != nullptr) {
-        listener->onBufferAllocated(item);
-    }
-}
-
 void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
     sp<ConsumerListener> listener(mConsumerListener.promote());
     if (listener != nullptr) {
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index f2d5c8e..528bfb1 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -58,7 +58,7 @@
     int numDroppedBuffers = 0;
     sp<IProducerListener> listener;
     {
-        Mutex::Autolock lock(mCore->mMutex);
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
 
         // Check that the consumer doesn't currently have the maximum number of
         // buffers acquired. We allow the max buffer count to be exceeded by one
@@ -94,8 +94,6 @@
         // Skip this if we're in shared buffer mode and the queue is empty,
         // since in that case we'll just return the shared buffer.
         if (expectedPresent != 0 && !mCore->mQueue.empty()) {
-            const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
-
             // The 'expectedPresent' argument indicates when the buffer is expected
             // to be presented on-screen. If the buffer's desired present time is
             // earlier (less) than expectedPresent -- meaning it will be displayed
@@ -190,6 +188,7 @@
                         desiredPresent - expectedPresent,
                         systemTime(CLOCK_MONOTONIC),
                         front->mFrameNumber, maxFrameNumber);
+                ATRACE_NAME("PRESENT_LATER");
                 return PRESENT_LATER;
             }
 
@@ -203,7 +202,7 @@
 
         if (sharedBufferAvailable && mCore->mQueue.empty()) {
             // make sure the buffer has finished allocating before acquiring it
-            mCore->waitWhileAllocatingLocked();
+            mCore->waitWhileAllocatingLocked(lock);
 
             slot = mCore->mSharedBufferSlot;
 
@@ -264,7 +263,7 @@
         // We might have freed a slot while dropping old buffers, or the producer
         // may be blocked waiting for the number of buffers in the queue to
         // decrease.
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
 
         ATRACE_INT(mCore->mConsumerName.string(),
                 static_cast<int32_t>(mCore->mQueue.size()));
@@ -286,7 +285,7 @@
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(slot);
     BQ_LOGV("detachBuffer: slot %d", slot);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
@@ -312,7 +311,7 @@
     mCore->mActiveBuffers.erase(slot);
     mCore->mFreeSlots.insert(slot);
     mCore->clearBufferSlotLocked(slot);
-    mCore->mDequeueCondition.broadcast();
+    mCore->mDequeueCondition.notify_all();
     VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
@@ -330,7 +329,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mSharedBufferMode) {
         BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
@@ -422,7 +421,7 @@
 
     sp<IProducerListener> listener;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
+        std::lock_guard<std::mutex> lock(mCore->mMutex);
 
         // If the frame number has changed because the buffer has been reallocated,
         // we can ignore this releaseBuffer for the old buffer.
@@ -461,7 +460,7 @@
         listener = mCore->mConnectedProducerListener;
         BQ_LOGV("releaseBuffer: releasing slot %d", slot);
 
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
         VALIDATE_CONSISTENCY();
     } // Autolock scope
 
@@ -485,7 +484,7 @@
     BQ_LOGV("connect: controlledByApp=%s",
             controlledByApp ? "true" : "false");
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("connect: BufferQueue has been abandoned");
@@ -503,7 +502,7 @@
 
     BQ_LOGV("disconnect");
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mConsumerListener == nullptr) {
         BQ_LOGE("disconnect: no consumer is connected");
@@ -515,7 +514,7 @@
     mCore->mQueue.clear();
     mCore->freeAllBuffersLocked();
     mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
-    mCore->mDequeueCondition.broadcast();
+    mCore->mDequeueCondition.notify_all();
     return NO_ERROR;
 }
 
@@ -527,7 +526,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned");
@@ -569,7 +568,7 @@
 
     BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height);
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mDefaultWidth = width;
     mCore->mDefaultHeight = height;
     return NO_ERROR;
@@ -583,7 +582,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
         BQ_LOGE("setMaxBufferCount: producer is already connected");
@@ -623,8 +622,8 @@
 
     sp<IConsumerListener> listener;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
-        mCore->waitWhileAllocatingLocked();
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked(lock);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("setMaxAcquiredBufferCount: consumer is abandoned");
@@ -684,7 +683,7 @@
 status_t BufferQueueConsumer::setConsumerName(const String8& name) {
     ATRACE_CALL();
     BQ_LOGV("setConsumerName: '%s'", name.string());
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mConsumerName = name;
     mConsumerName = name;
     return NO_ERROR;
@@ -693,7 +692,7 @@
 status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
     ATRACE_CALL();
     BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mDefaultBufferFormat = defaultFormat;
     return NO_ERROR;
 }
@@ -702,7 +701,7 @@
         android_dataspace defaultDataSpace) {
     ATRACE_CALL();
     BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mDefaultBufferDataSpace = defaultDataSpace;
     return NO_ERROR;
 }
@@ -710,7 +709,7 @@
 status_t BufferQueueConsumer::setConsumerUsageBits(uint64_t usage) {
     ATRACE_CALL();
     BQ_LOGV("setConsumerUsageBits: %#" PRIx64, usage);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mConsumerUsageBits = usage;
     return NO_ERROR;
 }
@@ -718,7 +717,7 @@
 status_t BufferQueueConsumer::setConsumerIsProtected(bool isProtected) {
     ATRACE_CALL();
     BQ_LOGV("setConsumerIsProtected: %s", isProtected ? "true" : "false");
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mConsumerIsProtected = isProtected;
     return NO_ERROR;
 }
@@ -726,26 +725,26 @@
 status_t BufferQueueConsumer::setTransformHint(uint32_t hint) {
     ATRACE_CALL();
     BQ_LOGV("setTransformHint: %#x", hint);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mTransformHint = hint;
     return NO_ERROR;
 }
 
 status_t BufferQueueConsumer::getSidebandStream(sp<NativeHandle>* outStream) const {
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     *outStream = mCore->mSidebandStream;
     return NO_ERROR;
 }
 
 status_t BufferQueueConsumer::getOccupancyHistory(bool forceFlush,
         std::vector<OccupancyTracker::Segment>* outHistory) {
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     *outHistory = mCore->mOccupancyTracker.getSegmentHistory(forceFlush);
     return NO_ERROR;
 }
 
 status_t BufferQueueConsumer::discardFreeBuffers() {
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->discardFreeBuffersLocked();
     return NO_ERROR;
 }
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 960b194..b429d38 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -73,6 +73,8 @@
     mActiveBuffers(),
     mDequeueCondition(),
     mDequeueBufferCannotBlock(false),
+    mQueueBufferCanDrop(false),
+    mLegacyBufferDrop(true),
     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
     mDefaultWidth(1),
     mDefaultHeight(1),
@@ -95,7 +97,9 @@
     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
             HAL_DATASPACE_UNKNOWN),
     mLastQueuedSlot(INVALID_BUFFER_SLOT),
-    mUniqueId(getUniqueId())
+    mUniqueId(getUniqueId()),
+    mAutoPrerotation(false),
+    mTransformHintInUse(0)
 {
     int numStartingBuffers = getMaxBufferCountLocked();
     for (int s = 0; s < numStartingBuffers; s++) {
@@ -110,19 +114,23 @@
 BufferQueueCore::~BufferQueueCore() {}
 
 void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
-    Mutex::Autolock lock(mMutex);
+    std::lock_guard<std::mutex> lock(mMutex);
 
     outResult->appendFormat("%s- BufferQueue ", prefix.string());
     outResult->appendFormat("mMaxAcquiredBufferCount=%d mMaxDequeuedBufferCount=%d\n",
                             mMaxAcquiredBufferCount, mMaxDequeuedBufferCount);
     outResult->appendFormat("%s  mDequeueBufferCannotBlock=%d mAsyncMode=%d\n", prefix.string(),
                             mDequeueBufferCannotBlock, mAsyncMode);
+    outResult->appendFormat("%s  mQueueBufferCanDrop=%d mLegacyBufferDrop=%d\n", prefix.string(),
+                            mQueueBufferCanDrop, mLegacyBufferDrop);
     outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
                             mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
-    outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
-                            mFrameCounter);
+    outResult->appendFormat("%s  transform-hint=%02x frame-counter=%" PRIu64 "\n", prefix.string(),
+                            mTransformHint, mFrameCounter);
+    outResult->appendFormat("%s  mTransformHintInUse=%02x mAutoPrerotation=%d\n", prefix.string(),
+                            mTransformHintInUse, mAutoPrerotation);
 
-    outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
+    outResult->appendFormat("%sFIFO(%zu):\n", prefix.string(), mQueue.size());
     Fifo::const_iterator current(mQueue.begin());
     while (current != mQueue.end()) {
         double timestamp = current->mTimestamp / 1e9;
@@ -306,10 +314,10 @@
     return true;
 }
 
-void BufferQueueCore::waitWhileAllocatingLocked() const {
+void BufferQueueCore::waitWhileAllocatingLocked(std::unique_lock<std::mutex>& lock) const {
     ATRACE_CALL();
     while (mIsAllocating) {
-        mIsAllocatingCondition.wait(mMutex);
+        mIsAllocatingCondition.wait(lock);
     }
 }
 
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e657488..d149674 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -59,14 +59,15 @@
     mNextCallbackTicket(0),
     mCurrentCallbackTicket(0),
     mCallbackCondition(),
-    mDequeueTimeout(-1) {}
+    mDequeueTimeout(-1),
+    mDequeueWaitingForAllocation(false) {}
 
 BufferQueueProducer::~BufferQueueProducer() {}
 
 status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
     ATRACE_CALL();
     BQ_LOGV("requestBuffer: slot %d", slot);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
@@ -101,8 +102,8 @@
 
     sp<IConsumerListener> listener;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
-        mCore->waitWhileAllocatingLocked();
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked(lock);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
@@ -163,7 +164,7 @@
         if (delta < 0) {
             listener = mCore->mConsumerListener;
         }
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
     } // Autolock scope
 
     // Call back without lock held
@@ -180,8 +181,8 @@
 
     sp<IConsumerListener> listener;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
-        mCore->waitWhileAllocatingLocked();
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked(lock);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
@@ -215,7 +216,7 @@
         }
         mCore->mAsyncMode = async;
         VALIDATE_CONSISTENCY();
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
         if (delta < 0) {
             listener = mCore->mConsumerListener;
         }
@@ -247,7 +248,7 @@
 }
 
 status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
-        int* found) const {
+        std::unique_lock<std::mutex>& lock, int* found) const {
     auto callerString = (caller == FreeSlotCaller::Dequeue) ?
             "dequeueBuffer" : "attachBuffer";
     bool tryAgain = true;
@@ -273,8 +274,12 @@
         // This check is only done if a buffer has already been queued
         if (mCore->mBufferHasBeenQueued &&
                 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
-            BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
-                    "(%d)", callerString, mCore->mMaxDequeuedBufferCount);
+            // Supress error logs when timeout is non-negative.
+            if (mDequeueTimeout < 0) {
+                BQ_LOGE("%s: attempting to exceed the max dequeued buffer "
+                        "count (%d)", callerString,
+                        mCore->mMaxDequeuedBufferCount);
+            }
             return INVALID_OPERATION;
         }
 
@@ -334,13 +339,13 @@
                 return WOULD_BLOCK;
             }
             if (mDequeueTimeout >= 0) {
-                status_t result = mCore->mDequeueCondition.waitRelative(
-                        mCore->mMutex, mDequeueTimeout);
-                if (result == TIMED_OUT) {
-                    return result;
+                std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
+                        std::chrono::nanoseconds(mDequeueTimeout));
+                if (result == std::cv_status::timeout) {
+                    return TIMED_OUT;
                 }
             } else {
-                mCore->mDequeueCondition.wait(mCore->mMutex);
+                mCore->mDequeueCondition.wait(lock);
             }
         }
     } // while (tryAgain)
@@ -354,7 +359,7 @@
                                             FrameEventHistoryDelta* outTimestamps) {
     ATRACE_CALL();
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
+        std::lock_guard<std::mutex> lock(mCore->mMutex);
         mConsumerName = mCore->mConsumerName;
 
         if (mCore->mIsAbandoned) {
@@ -381,7 +386,16 @@
     bool attachedByConsumer = false;
 
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
+
+        // If we don't have a free buffer, but we are currently allocating, we wait until allocation
+        // is finished such that we don't allocate in parallel.
+        if (mCore->mFreeBuffers.empty() && mCore->mIsAllocating) {
+            mDequeueWaitingForAllocation = true;
+            mCore->waitWhileAllocatingLocked(lock);
+            mDequeueWaitingForAllocation = false;
+            mDequeueWaitingForAllocationCondition.notify_all();
+        }
 
         if (format == 0) {
             format = mCore->mDefaultBufferFormat;
@@ -394,12 +408,15 @@
         if (useDefaultSize) {
             width = mCore->mDefaultWidth;
             height = mCore->mDefaultHeight;
+            if (mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(width, height);
+            }
         }
 
         int found = BufferItem::INVALID_BUFFER_SLOT;
         while (found == BufferItem::INVALID_BUFFER_SLOT) {
-            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
-                    &found);
+            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
             if (status != NO_ERROR) {
                 return status;
             }
@@ -506,7 +523,7 @@
         status_t error = graphicBuffer->initCheck();
 
         { // Autolock scope
-            Mutex::Autolock lock(mCore->mMutex);
+            std::lock_guard<std::mutex> lock(mCore->mMutex);
 
             if (error == NO_ERROR && !mCore->mIsAbandoned) {
                 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
@@ -514,7 +531,7 @@
             }
 
             mCore->mIsAllocating = false;
-            mCore->mIsAllocatingCondition.broadcast();
+            mCore->mIsAllocatingCondition.notify_all();
 
             if (error != NO_ERROR) {
                 mCore->mFreeSlots.insert(*outSlot);
@@ -530,13 +547,6 @@
                 return NO_INIT;
             }
 
-            if (mCore->mConsumerListener != nullptr) {
-                BufferItem item;
-                item.mGraphicBuffer = graphicBuffer;
-                item.mSlot = *outSlot;
-                mCore->mConsumerListener->onBufferAllocated(item);
-            }
-
             VALIDATE_CONSISTENCY();
         } // Autolock scope
     }
@@ -580,7 +590,7 @@
 
     sp<IConsumerListener> listener;
     {
-        Mutex::Autolock lock(mCore->mMutex);
+        std::lock_guard<std::mutex> lock(mCore->mMutex);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
@@ -615,7 +625,7 @@
         mCore->mActiveBuffers.erase(slot);
         mCore->mFreeSlots.insert(slot);
         mCore->clearBufferSlotLocked(slot);
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
         VALIDATE_CONSISTENCY();
         listener = mCore->mConsumerListener;
     }
@@ -641,7 +651,7 @@
 
     sp<IConsumerListener> listener;
     {
-        Mutex::Autolock lock(mCore->mMutex);
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
@@ -659,7 +669,7 @@
             return BAD_VALUE;
         }
 
-        mCore->waitWhileAllocatingLocked();
+        mCore->waitWhileAllocatingLocked(lock);
 
         if (mCore->mFreeBuffers.empty()) {
             return NO_MEMORY;
@@ -697,7 +707,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::unique_lock<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
@@ -721,11 +731,11 @@
         return BAD_VALUE;
     }
 
-    mCore->waitWhileAllocatingLocked();
+    mCore->waitWhileAllocatingLocked(lock);
 
     status_t returnFlags = NO_ERROR;
     int found;
-    status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, &found);
+    status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, lock, &found);
     if (status != NO_ERROR) {
         return status;
     }
@@ -798,7 +808,7 @@
     uint64_t currentFrameNumber = 0;
     BufferItem item;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
+        std::lock_guard<std::mutex> lock(mCore->mMutex);
 
         if (mCore->mIsAbandoned) {
             BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
@@ -880,7 +890,8 @@
         item.mFence = acquireFence;
         item.mFenceTime = acquireFenceTime;
         item.mIsDroppable = mCore->mAsyncMode ||
-                mCore->mDequeueBufferCannotBlock ||
+                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
+                (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
         item.mSurfaceDamage = surfaceDamage;
         item.mQueuedBuffer = true;
@@ -929,6 +940,15 @@
                     }
                 }
 
+                // Make sure to merge the damage rect from the frame we're about
+                // to drop into the new frame's damage rect.
+                if (last.mSurfaceDamage.bounds() == Rect::INVALID_RECT ||
+                    item.mSurfaceDamage.bounds() == Rect::INVALID_RECT) {
+                    item.mSurfaceDamage = Region::INVALID_REGION;
+                } else {
+                    item.mSurfaceDamage |= last.mSurfaceDamage;
+                }
+
                 // Overwrite the droppable buffer with the incoming one
                 mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                 frameReplacedListener = mCore->mConsumerListener;
@@ -939,12 +959,12 @@
         }
 
         mCore->mBufferHasBeenQueued = true;
-        mCore->mDequeueCondition.broadcast();
+        mCore->mDequeueCondition.notify_all();
         mCore->mLastQueuedSlot = slot;
 
         output->width = mCore->mDefaultWidth;
         output->height = mCore->mDefaultHeight;
-        output->transformHint = mCore->mTransformHint;
+        output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
         output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
         output->nextFrameNumber = mCore->mFrameCounter + 1;
 
@@ -965,9 +985,6 @@
         item.mGraphicBuffer.clear();
     }
 
-    // Don't send the slot number through the callback since the consumer shouldn't need it
-    item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
-
     // Call back without the main BufferQueue lock held, but with the callback
     // lock held so we can ensure that callbacks occur in order
 
@@ -975,9 +992,9 @@
     sp<Fence> lastQueuedFence;
 
     { // scope for the lock
-        Mutex::Autolock lock(mCallbackMutex);
+        std::unique_lock<std::mutex> lock(mCallbackMutex);
         while (callbackTicket != mCurrentCallbackTicket) {
-            mCallbackCondition.wait(mCallbackMutex);
+            mCallbackCondition.wait(lock);
         }
 
         if (frameAvailableListener != nullptr) {
@@ -994,15 +1011,7 @@
         mLastQueuedTransform = item.mTransform;
 
         ++mCurrentCallbackTicket;
-        mCallbackCondition.broadcast();
-    }
-
-    // Wait without lock held
-    if (connectedApi == NATIVE_WINDOW_API_EGL) {
-        // Waiting here allows for two full buffers to be queued but not a
-        // third. In the event that frames take varying time, this makes a
-        // small trade-off in favor of latency rather than throughput.
-        lastQueuedFence->waitForever("Throttling EGL Production");
+        mCallbackCondition.notify_all();
     }
 
     // Update and get FrameEventHistory.
@@ -1016,13 +1025,21 @@
     addAndGetFrameTimestamps(&newFrameEventsEntry,
             getFrameTimestamps ? &output->frameTimestamps : nullptr);
 
+    // Wait without lock held
+    if (connectedApi == NATIVE_WINDOW_API_EGL) {
+        // Waiting here allows for two full buffers to be queued but not a
+        // third. In the event that frames take varying time, this makes a
+        // small trade-off in favor of latency rather than throughput.
+        lastQueuedFence->waitForever("Throttling EGL Production");
+    }
+
     return NO_ERROR;
 }
 
 status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
     ATRACE_CALL();
     BQ_LOGV("cancelBuffer: slot %d", slot);
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
@@ -1067,7 +1084,7 @@
     }
 
     mSlots[slot].mFence = fence;
-    mCore->mDequeueCondition.broadcast();
+    mCore->mDequeueCondition.notify_all();
     VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
@@ -1075,7 +1092,7 @@
 
 int BufferQueueProducer::query(int what, int *outValue) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     if (outValue == nullptr) {
         BQ_LOGE("query: outValue was NULL");
@@ -1128,9 +1145,6 @@
         case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
             value = static_cast<int32_t>(mCore->mConsumerIsProtected);
             break;
-        case NATIVE_WINDOW_MAX_BUFFER_COUNT:
-            value = static_cast<int32_t>(mCore->mMaxBufferCount);
-            break;
         default:
             return BAD_VALUE;
     }
@@ -1143,7 +1157,7 @@
 status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
         int api, bool producerControlledByApp, QueueBufferOutput *output) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mConsumerName = mCore->mConsumerName;
     BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
             producerControlledByApp ? "true" : "false");
@@ -1190,11 +1204,12 @@
 
             output->width = mCore->mDefaultWidth;
             output->height = mCore->mDefaultHeight;
-            output->transformHint = mCore->mTransformHint;
+            output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
             output->numPendingBuffers =
                     static_cast<uint32_t>(mCore->mQueue.size());
             output->nextFrameNumber = mCore->mFrameCounter + 1;
             output->bufferReplaced = false;
+            output->maxBufferCount = mCore->mMaxBufferCount;
 
             if (listener != nullptr) {
                 // Set up a death notification so that we can disconnect
@@ -1221,9 +1236,11 @@
     mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
     mCore->mBufferHasBeenQueued = false;
     mCore->mDequeueBufferCannotBlock = false;
-    if (mDequeueTimeout < 0) {
-        mCore->mDequeueBufferCannotBlock =
-                mCore->mConsumerControlledByApp && producerControlledByApp;
+    mCore->mQueueBufferCanDrop = false;
+    mCore->mLegacyBufferDrop = true;
+    if (mCore->mConsumerControlledByApp && producerControlledByApp) {
+        mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
+        mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
     }
 
     mCore->mAllowAllocation = true;
@@ -1238,7 +1255,7 @@
     int status = NO_ERROR;
     sp<IConsumerListener> listener;
     { // Autolock scope
-        Mutex::Autolock lock(mCore->mMutex);
+        std::unique_lock<std::mutex> lock(mCore->mMutex);
 
         if (mode == DisconnectMode::AllLocal) {
             if (BufferQueueThreadState::getCallingPid() != mCore->mConnectedPid) {
@@ -1247,7 +1264,7 @@
             api = BufferQueueCore::CURRENTLY_CONNECTED_API;
         }
 
-        mCore->waitWhileAllocatingLocked();
+        mCore->waitWhileAllocatingLocked(lock);
 
         if (mCore->mIsAbandoned) {
             // It's not really an error to disconnect after the surface has
@@ -1291,7 +1308,8 @@
                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
                     mCore->mConnectedPid = -1;
                     mCore->mSidebandStream.clear();
-                    mCore->mDequeueCondition.broadcast();
+                    mCore->mDequeueCondition.notify_all();
+                    mCore->mAutoPrerotation = false;
                     listener = mCore->mConsumerListener;
                 } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
                     BQ_LOGE("disconnect: not connected (req=%d)", api);
@@ -1321,7 +1339,7 @@
 status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
     sp<IConsumerListener> listener;
     { // Autolock scope
-        Mutex::Autolock _l(mCore->mMutex);
+        std::lock_guard<std::mutex> _l(mCore->mMutex);
         mCore->mSidebandStream = stream;
         listener = mCore->mConsumerListener;
     } // Autolock scope
@@ -1335,6 +1353,8 @@
 void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
         PixelFormat format, uint64_t usage) {
     ATRACE_CALL();
+
+    const bool useDefaultSize = !width && !height;
     while (true) {
         size_t newBufferCount = 0;
         uint32_t allocWidth = 0;
@@ -1343,8 +1363,8 @@
         uint64_t allocUsage = 0;
         std::string allocName;
         { // Autolock scope
-            Mutex::Autolock lock(mCore->mMutex);
-            mCore->waitWhileAllocatingLocked();
+            std::unique_lock<std::mutex> lock(mCore->mMutex);
+            mCore->waitWhileAllocatingLocked(lock);
 
             if (!mCore->mAllowAllocation) {
                 BQ_LOGE("allocateBuffers: allocation is not allowed for this "
@@ -1361,6 +1381,11 @@
 
             allocWidth = width > 0 ? width : mCore->mDefaultWidth;
             allocHeight = height > 0 ? height : mCore->mDefaultHeight;
+            if (useDefaultSize && mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(allocWidth, allocHeight);
+            }
+
             allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
             allocUsage = usage | mCore->mConsumerUsageBits;
             allocName.assign(mCore->mConsumerName.string(), mCore->mConsumerName.size());
@@ -1379,18 +1404,23 @@
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                         " %u, usage %#" PRIx64 ")", width, height, format, usage);
-                Mutex::Autolock lock(mCore->mMutex);
+                std::lock_guard<std::mutex> lock(mCore->mMutex);
                 mCore->mIsAllocating = false;
-                mCore->mIsAllocatingCondition.broadcast();
+                mCore->mIsAllocatingCondition.notify_all();
                 return;
             }
             buffers.push_back(graphicBuffer);
         }
 
         { // Autolock scope
-            Mutex::Autolock lock(mCore->mMutex);
+            std::unique_lock<std::mutex> lock(mCore->mMutex);
             uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
             uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
+            if (useDefaultSize && mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(checkWidth, checkHeight);
+            }
+
             PixelFormat checkFormat = format != 0 ?
                     format : mCore->mDefaultBufferFormat;
             uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
@@ -1399,7 +1429,7 @@
                 // Something changed while we released the lock. Retry.
                 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
                 mCore->mIsAllocating = false;
-                mCore->mIsAllocatingCondition.broadcast();
+                mCore->mIsAllocatingCondition.notify_all();
                 continue;
             }
 
@@ -1421,21 +1451,20 @@
                 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
                         *slot);
 
-                if (mCore->mConsumerListener != nullptr) {
-                    BufferItem item;
-                    item.mGraphicBuffer = buffers[i];
-                    item.mSlot = *slot;
-                    mCore->mConsumerListener->onBufferAllocated(item);
-                }
-
                 // Make sure the erase is done after all uses of the slot
                 // iterator since it will be invalid after this point.
                 mCore->mFreeSlots.erase(slot);
             }
 
             mCore->mIsAllocating = false;
-            mCore->mIsAllocatingCondition.broadcast();
+            mCore->mIsAllocatingCondition.notify_all();
             VALIDATE_CONSISTENCY();
+
+            // If dequeue is waiting for to allocate a buffer, release the lock until it's not
+            // waiting anymore so it can use the buffer we just allocated.
+            while (mDequeueWaitingForAllocation) {
+                mDequeueWaitingForAllocationCondition.wait(lock);
+            }
         } // Autolock scope
     }
 }
@@ -1444,7 +1473,7 @@
     ATRACE_CALL();
     BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mAllowAllocation = allow;
     return NO_ERROR;
 }
@@ -1453,14 +1482,14 @@
     ATRACE_CALL();
     BQ_LOGV("setGenerationNumber: %u", generationNumber);
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     mCore->mGenerationNumber = generationNumber;
     return NO_ERROR;
 }
 
 String8 BufferQueueProducer::getConsumerName() const {
     ATRACE_CALL();
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     BQ_LOGV("getConsumerName: %s", mConsumerName.string());
     return mConsumerName;
 }
@@ -1469,7 +1498,7 @@
     ATRACE_CALL();
     BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     if (!sharedBufferMode) {
         mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
     }
@@ -1481,7 +1510,7 @@
     ATRACE_CALL();
     BQ_LOGV("setAutoRefresh: %d", autoRefresh);
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
 
     mCore->mAutoRefresh = autoRefresh;
     return NO_ERROR;
@@ -1491,8 +1520,10 @@
     ATRACE_CALL();
     BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
 
-    Mutex::Autolock lock(mCore->mMutex);
-    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+    bool dequeueBufferCannotBlock =
+            timeout >= 0 ? false : mCore->mDequeueBufferCannotBlock;
+    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, dequeueBufferCannotBlock,
             mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
     if (!mCore->adjustAvailableSlotsLocked(delta)) {
         BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
@@ -1501,18 +1532,30 @@
     }
 
     mDequeueTimeout = timeout;
-    mCore->mDequeueBufferCannotBlock = false;
+    mCore->mDequeueBufferCannotBlock = dequeueBufferCannotBlock;
+    if (timeout > 0) {
+        mCore->mQueueBufferCanDrop = false;
+    }
 
     VALIDATE_CONSISTENCY();
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::setLegacyBufferDrop(bool drop) {
+    ATRACE_CALL();
+    BQ_LOGV("setLegacyBufferDrop: drop = %d", drop);
+
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+    mCore->mLegacyBufferDrop = drop;
+    return NO_ERROR;
+}
+
 status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
         sp<Fence>* outFence, float outTransformMatrix[16]) {
     ATRACE_CALL();
     BQ_LOGV("getLastQueuedBuffer");
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
         *outBuffer = nullptr;
         *outFence = Fence::NO_FENCE;
@@ -1548,7 +1591,7 @@
     BQ_LOGV("addAndGetFrameTimestamps");
     sp<IConsumerListener> listener;
     {
-        Mutex::Autolock lock(mCore->mMutex);
+        std::lock_guard<std::mutex> lock(mCore->mMutex);
         listener = mCore->mConsumerListener;
     }
     if (listener != nullptr) {
@@ -1575,9 +1618,19 @@
 status_t BufferQueueProducer::getConsumerUsage(uint64_t* outUsage) const {
     BQ_LOGV("getConsumerUsage");
 
-    Mutex::Autolock lock(mCore->mMutex);
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
     *outUsage = mCore->mConsumerUsageBits;
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) {
+    ATRACE_CALL();
+    BQ_LOGV("setAutoPrerotation: %d", autoPrerotation);
+
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+    mCore->mAutoPrerotation = autoPrerotation;
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 1e94cc1..abd9921 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -131,8 +131,6 @@
     }
 }
 
-void ConsumerBase::onBufferAllocated(const BufferItem& /*item*/) {}
-
 void ConsumerBase::onBuffersReleased() {
     Mutex::Autolock lock(mMutex);
 
diff --git a/libs/gui/DebugEGLImageTracker.cpp b/libs/gui/DebugEGLImageTracker.cpp
new file mode 100644
index 0000000..ab6f364
--- /dev/null
+++ b/libs/gui/DebugEGLImageTracker.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 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 <cutils/properties.h>
+#include <gui/DebugEGLImageTracker.h>
+
+#include <cinttypes>
+#include <unordered_map>
+
+using android::base::StringAppendF;
+
+std::mutex DebugEGLImageTracker::mInstanceLock;
+std::atomic<DebugEGLImageTracker *> DebugEGLImageTracker::mInstance;
+
+class DebugEGLImageTrackerNoOp : public DebugEGLImageTracker {
+public:
+    DebugEGLImageTrackerNoOp() = default;
+    ~DebugEGLImageTrackerNoOp() override = default;
+    void create(const char * /*from*/) override {}
+    void destroy(const char * /*from*/) override {}
+
+    void dump(std::string & /*result*/) override {}
+};
+
+class DebugEGLImageTrackerImpl : public DebugEGLImageTracker {
+public:
+    DebugEGLImageTrackerImpl() = default;
+    ~DebugEGLImageTrackerImpl() override = default;
+    void create(const char * /*from*/) override;
+    void destroy(const char * /*from*/) override;
+
+    void dump(std::string & /*result*/) override;
+
+private:
+    std::mutex mLock;
+    std::unordered_map<std::string, int64_t> mCreateTracker;
+    std::unordered_map<std::string, int64_t> mDestroyTracker;
+
+    int64_t mTotalCreated = 0;
+    int64_t mTotalDestroyed = 0;
+};
+
+DebugEGLImageTracker *DebugEGLImageTracker::getInstance() {
+    std::lock_guard lock(mInstanceLock);
+    if (mInstance == nullptr) {
+        char value[PROPERTY_VALUE_MAX];
+        property_get("debug.sf.enable_egl_image_tracker", value, "0");
+        const bool enabled = static_cast<bool>(atoi(value));
+
+        if (enabled) {
+            mInstance = new DebugEGLImageTrackerImpl();
+        } else {
+            mInstance = new DebugEGLImageTrackerNoOp();
+        }
+    }
+
+    return mInstance;
+}
+
+void DebugEGLImageTrackerImpl::create(const char *from) {
+    std::lock_guard lock(mLock);
+    mCreateTracker[from]++;
+    mTotalCreated++;
+}
+
+void DebugEGLImageTrackerImpl::destroy(const char *from) {
+    std::lock_guard lock(mLock);
+    mDestroyTracker[from]++;
+    mTotalDestroyed++;
+}
+
+void DebugEGLImageTrackerImpl::dump(std::string &result) {
+    std::lock_guard lock(mLock);
+    StringAppendF(&result, "Live EGL Image objects: %" PRIi64 "\n",
+                  mTotalCreated - mTotalDestroyed);
+    StringAppendF(&result, "Total EGL Image created: %" PRIi64 "\n", mTotalCreated);
+    for (const auto &[from, count] : mCreateTracker) {
+        StringAppendF(&result, "\t%s: %" PRIi64 "\n", from.c_str(), count);
+    }
+    StringAppendF(&result, "Total EGL Image destroyed: %" PRIi64 "\n", mTotalDestroyed);
+    for (const auto &[from, count] : mDestroyTracker) {
+        StringAppendF(&result, "\t%s: %" PRIi64 "\n", from.c_str(), count);
+    }
+}
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f5cf1c4..b8faa2d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -32,10 +32,11 @@
 
 // ---------------------------------------------------------------------------
 
-DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
+DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
+                                           ISurfaceComposer::ConfigChanged configChanged) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     if (sf != nullptr) {
-        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
+        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
         if (mEventConnection != nullptr) {
             mDataChannel = std::make_unique<gui::BitTube>();
             mEventConnection->stealReceiveChannel(mDataChannel.get());
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index faf02f3..8199c98 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -34,6 +34,7 @@
 #include <math/mat4.h>
 
 #include <gui/BufferItem.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <gui/GLConsumer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
@@ -745,104 +746,6 @@
         mCurrentTransform, mFilteringEnabled);
 }
 
-void GLConsumer::computeTransformMatrix(float outTransform[16],
-        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
-        bool filtering) {
-    // Transform matrices
-    static const mat4 mtxFlipH(
-        -1, 0, 0, 0,
-        0, 1, 0, 0,
-        0, 0, 1, 0,
-        1, 0, 0, 1
-    );
-    static const mat4 mtxFlipV(
-        1, 0, 0, 0,
-        0, -1, 0, 0,
-        0, 0, 1, 0,
-        0, 1, 0, 1
-    );
-    static const mat4 mtxRot90(
-        0, 1, 0, 0,
-        -1, 0, 0, 0,
-        0, 0, 1, 0,
-        1, 0, 0, 1
-    );
-
-    mat4 xform;
-    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
-        xform *= mtxFlipH;
-    }
-    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
-        xform *= mtxFlipV;
-    }
-    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-        xform *= mtxRot90;
-    }
-
-    if (!cropRect.isEmpty()) {
-        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
-        float bufferWidth = buf->getWidth();
-        float bufferHeight = buf->getHeight();
-        float shrinkAmount = 0.0f;
-        if (filtering) {
-            // In order to prevent bilinear sampling beyond the edge of the
-            // crop rectangle we may need to shrink it by 2 texels in each
-            // dimension.  Normally this would just need to take 1/2 a texel
-            // off each end, but because the chroma channels of YUV420 images
-            // are subsampled we may need to shrink the crop region by a whole
-            // texel on each side.
-            switch (buf->getPixelFormat()) {
-                case PIXEL_FORMAT_RGBA_8888:
-                case PIXEL_FORMAT_RGBX_8888:
-                case PIXEL_FORMAT_RGBA_FP16:
-                case PIXEL_FORMAT_RGBA_1010102:
-                case PIXEL_FORMAT_RGB_888:
-                case PIXEL_FORMAT_RGB_565:
-                case PIXEL_FORMAT_BGRA_8888:
-                    // We know there's no subsampling of any channels, so we
-                    // only need to shrink by a half a pixel.
-                    shrinkAmount = 0.5;
-                    break;
-
-                default:
-                    // If we don't recognize the format, we must assume the
-                    // worst case (that we care about), which is YUV420.
-                    shrinkAmount = 1.0;
-                    break;
-            }
-        }
-
-        // Only shrink the dimensions that are not the size of the buffer.
-        if (cropRect.width() < bufferWidth) {
-            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
-            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
-                    bufferWidth;
-        }
-        if (cropRect.height() < bufferHeight) {
-            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
-                    bufferHeight;
-            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
-                    bufferHeight;
-        }
-
-        mat4 crop(
-            sx, 0, 0, 0,
-            0, sy, 0, 0,
-            0, 0, 1, 0,
-            tx, ty, 0, 1
-        );
-        xform = crop * xform;
-    }
-
-    // GLConsumer uses the GL convention where (0, 0) is the bottom-left
-    // corner and (1, 1) is the top-right corner.  Add an additional vertical
-    // flip after all other transforms to map from GL convention to buffer
-    // queue memory layout, where (0, 0) is the top-left corner.
-    xform = mtxFlipV * xform;
-
-    memcpy(outTransform, xform.asArray(), sizeof(xform));
-}
-
 Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
     Rect outCrop = crop;
 
@@ -1042,6 +945,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("~EglImage: eglDestroyImageKHR failed");
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         eglTerminate(mEglDisplay);
     }
 }
@@ -1055,6 +959,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         eglTerminate(mEglDisplay);
         mEglImage = EGL_NO_IMAGE_KHR;
         mEglDisplay = EGL_NO_DISPLAY;
@@ -1104,7 +1009,10 @@
         EGLint error = eglGetError();
         ALOGE("error creating EGLImage: %#x", error);
         eglTerminate(dpy);
+    } else {
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
     }
+
     return image;
 }
 
diff --git a/libs/gui/GLConsumerUtils.cpp b/libs/gui/GLConsumerUtils.cpp
new file mode 100644
index 0000000..7a06c3d
--- /dev/null
+++ b/libs/gui/GLConsumerUtils.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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 LOG_TAG "GLConsumerUtils"
+//#define LOG_NDEBUG 0
+
+#include <gui/GLConsumer.h>
+#include <math/mat4.h>
+#include <system/window.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void GLConsumer::computeTransformMatrix(float outTransform[16],
+        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
+        bool filtering) {
+    // Transform matrices
+    static const mat4 mtxFlipH(
+        -1, 0, 0, 0,
+        0, 1, 0, 0,
+        0, 0, 1, 0,
+        1, 0, 0, 1
+    );
+    static const mat4 mtxFlipV(
+        1, 0, 0, 0,
+        0, -1, 0, 0,
+        0, 0, 1, 0,
+        0, 1, 0, 1
+    );
+    static const mat4 mtxRot90(
+        0, 1, 0, 0,
+        -1, 0, 0, 0,
+        0, 0, 1, 0,
+        1, 0, 0, 1
+    );
+
+    mat4 xform;
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+        xform *= mtxFlipH;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+        xform *= mtxFlipV;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        xform *= mtxRot90;
+    }
+
+    if (!cropRect.isEmpty()) {
+        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
+        float bufferWidth = buf->getWidth();
+        float bufferHeight = buf->getHeight();
+        float shrinkAmount = 0.0f;
+        if (filtering) {
+            // In order to prevent bilinear sampling beyond the edge of the
+            // crop rectangle we may need to shrink it by 2 texels in each
+            // dimension.  Normally this would just need to take 1/2 a texel
+            // off each end, but because the chroma channels of YUV420 images
+            // are subsampled we may need to shrink the crop region by a whole
+            // texel on each side.
+            switch (buf->getPixelFormat()) {
+                case PIXEL_FORMAT_RGBA_8888:
+                case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGBA_FP16:
+                case PIXEL_FORMAT_RGBA_1010102:
+                case PIXEL_FORMAT_RGB_888:
+                case PIXEL_FORMAT_RGB_565:
+                case PIXEL_FORMAT_BGRA_8888:
+                    // We know there's no subsampling of any channels, so we
+                    // only need to shrink by a half a pixel.
+                    shrinkAmount = 0.5;
+                    break;
+
+                default:
+                    // If we don't recognize the format, we must assume the
+                    // worst case (that we care about), which is YUV420.
+                    shrinkAmount = 1.0;
+                    break;
+            }
+        }
+
+        // Only shrink the dimensions that are not the size of the buffer.
+        if (cropRect.width() < bufferWidth) {
+            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
+                    bufferWidth;
+        }
+        if (cropRect.height() < bufferHeight) {
+            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
+                    bufferHeight;
+            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
+                    bufferHeight;
+        }
+
+        mat4 crop(
+            sx, 0, 0, 0,
+            0, sy, 0, 0,
+            0, 0, 1, 0,
+            tx, ty, 0, 1
+        );
+        xform = crop * xform;
+    }
+
+    // GLConsumer uses the GL convention where (0, 0) is the bottom-left
+    // corner and (1, 1) is the top-right corner.  Add an additional vertical
+    // flip after all other transforms to map from GL convention to buffer
+    // queue memory layout, where (0, 0) is the top-left corner.
+    xform = mtxFlipV * xform;
+
+    memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+}; // namespace android
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index ea9045c..85ac304 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -28,8 +28,7 @@
     ON_FRAME_REPLACED,
     ON_BUFFERS_RELEASED,
     ON_SIDEBAND_STREAM_CHANGED,
-    ON_BUFFER_ALLOCATED,
-    LAST = ON_BUFFER_ALLOCATED,
+    LAST = ON_SIDEBAND_STREAM_CHANGED,
 };
 
 } // Anonymous namespace
@@ -55,11 +54,6 @@
                                                                        item);
     }
 
-    void onBufferAllocated(const BufferItem& item) override {
-        callRemoteAsync<decltype(&IConsumerListener::onBufferAllocated)>(Tag::ON_BUFFER_ALLOCATED,
-                                                                         item);
-    }
-
     void onBuffersReleased() override {
         callRemoteAsync<decltype(&IConsumerListener::onBuffersReleased)>(Tag::ON_BUFFERS_RELEASED);
     }
@@ -95,8 +89,6 @@
             return callLocalAsync(data, reply, &IConsumerListener::onFrameAvailable);
         case Tag::ON_FRAME_REPLACED:
             return callLocalAsync(data, reply, &IConsumerListener::onFrameReplaced);
-        case Tag::ON_BUFFER_ALLOCATED:
-            return callLocalAsync(data, reply, &IConsumerListener::onBufferAllocated);
         case Tag::ON_BUFFERS_RELEASED:
             return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased);
         case Tag::ON_SIDEBAND_STREAM_CHANGED:
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 14eca43..0009a57 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -72,6 +72,8 @@
     GET_FRAME_TIMESTAMPS,
     GET_UNIQUE_ID,
     GET_CONSUMER_USAGE,
+    SET_LEGACY_BUFFER_DROP,
+    SET_AUTO_PREROTATION,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -360,7 +362,7 @@
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
         data.writeUint64(usage);
-        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, TF_ONE_WAY);
+        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, IBinder::FLAG_ONEWAY);
         if (result != NO_ERROR) {
             ALOGE("allocateBuffers failed to transact: %d", result);
         }
@@ -437,6 +439,20 @@
         return reply.readInt32();
     }
 
+    virtual status_t setLegacyBufferDrop(bool drop) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(drop);
+        status_t result = remote()->transact(SET_LEGACY_BUFFER_DROP,
+                data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
+    }
+
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) override {
         Parcel data, reply;
@@ -532,6 +548,17 @@
         }
         return actualResult;
     }
+
+    virtual status_t setAutoPrerotation(bool autoPrerotation) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeBool(autoPrerotation);
+        status_t result = remote()->transact(SET_AUTO_PREROTATION, data, &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -637,6 +664,10 @@
         return mBase->setDequeueTimeout(timeout);
     }
 
+    status_t setLegacyBufferDrop(bool drop) override {
+        return mBase->setLegacyBufferDrop(drop);
+    }
+
     status_t getLastQueuedBuffer(
             sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence,
@@ -656,6 +687,10 @@
     status_t getConsumerUsage(uint64_t* outUsage) const override {
         return mBase->getConsumerUsage(outUsage);
     }
+
+    status_t setAutoPrerotation(bool autoPrerotation) override {
+        return mBase->setAutoPrerotation(autoPrerotation);
+    }
 };
 
 IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
@@ -663,6 +698,18 @@
 
 // ----------------------------------------------------------------------
 
+status_t IGraphicBufferProducer::setLegacyBufferDrop(bool drop) {
+    // No-op for IGBP other than BufferQueue.
+    (void) drop;
+    return INVALID_OPERATION;
+}
+
+status_t IGraphicBufferProducer::setAutoPrerotation(bool autoPrerotation) {
+    // No-op for IGBP other than BufferQueue.
+    (void)autoPrerotation;
+    return INVALID_OPERATION;
+}
+
 status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
     status_t res = OK;
     res = parcel->writeUint32(USE_BUFFER_QUEUE);
@@ -1018,6 +1065,20 @@
             }
             return NO_ERROR;
         }
+        case SET_LEGACY_BUFFER_DROP: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool drop = data.readInt32();
+            int result = setLegacyBufferDrop(drop);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_AUTO_PREROTATION: {
+            CHECK_INTERFACE(IGraphicBuffer, data, reply);
+            bool autoPrerotation = data.readBool();
+            status_t result = setAutoPrerotation(autoPrerotation);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
@@ -1109,12 +1170,8 @@
 
 // ----------------------------------------------------------------------------
 constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
-    return sizeof(width) +
-            sizeof(height) +
-            sizeof(transformHint) +
-            sizeof(numPendingBuffers) +
-            sizeof(nextFrameNumber) +
-            sizeof(bufferReplaced);
+    return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) +
+            sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount);
 }
 
 size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
@@ -1138,6 +1195,7 @@
     FlattenableUtils::write(buffer, size, numPendingBuffers);
     FlattenableUtils::write(buffer, size, nextFrameNumber);
     FlattenableUtils::write(buffer, size, bufferReplaced);
+    FlattenableUtils::write(buffer, size, maxBufferCount);
 
     return frameTimestamps.flatten(buffer, size, fds, count);
 }
@@ -1155,6 +1213,7 @@
     FlattenableUtils::read(buffer, size, numPendingBuffers);
     FlattenableUtils::read(buffer, size, nextFrameNumber);
     FlattenableUtils::read(buffer, size, bufferReplaced);
+    FlattenableUtils::read(buffer, size, maxBufferCount);
 
     return frameTimestamps.unflatten(buffer, size, fds, count);
 }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index b74d675..12deaf0 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -69,7 +69,7 @@
                                      const sp<IBinder>& applyToken,
                                      const InputWindowCommands& commands,
                                      int64_t desiredPresentTime,
-                                     const cached_buffer_t& uncacheBuffer,
+                                     const client_cache_t& uncacheBuffer,
                                      const std::vector<ListenerCallbacks>& listenerCallbacks) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -88,8 +88,8 @@
         data.writeStrongBinder(applyToken);
         commands.write(data);
         data.writeInt64(desiredPresentTime);
-        data.writeStrongBinder(uncacheBuffer.token);
-        data.writeUint64(uncacheBuffer.cacheId);
+        data.writeStrongBinder(uncacheBuffer.token.promote());
+        data.writeUint64(uncacheBuffer.id);
 
         if (data.writeVectorSize(listenerCallbacks) == NO_ERROR) {
             for (const auto& [listener, callbackIds] : listenerCallbacks) {
@@ -109,7 +109,7 @@
     }
 
     virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
+                                   bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace,
                                    const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                    uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
                                    ISurfaceComposer::Rotation rotation, bool captureSecureLayers) {
@@ -137,20 +137,49 @@
 
         *outBuffer = new GraphicBuffer();
         reply.read(**outBuffer);
+        outCapturedSecureLayers = reply.readBool();
 
         return result;
     }
 
-    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
-                                   sp<GraphicBuffer>* outBuffer, const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
-                                   float frameScale, bool childrenOnly) {
+    virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeUint64(displayOrLayerStack);
+        status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_BY_ID, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("captureScreen failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result != NO_ERROR) {
+            ALOGE("captureScreen failed to readInt32: %d", result);
+            return result;
+        }
+
+        *outDataspace = static_cast<ui::Dataspace>(reply.readInt32());
+        *outBuffer = new GraphicBuffer();
+        reply.read(**outBuffer);
+        return result;
+    }
+
+    virtual status_t captureLayers(
+            const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
+            const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+            const Rect& sourceCrop,
+            const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& excludeLayers, float frameScale,
+            bool childrenOnly) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(layerHandleBinder);
         data.writeInt32(static_cast<int32_t>(reqDataspace));
         data.writeInt32(static_cast<int32_t>(reqPixelFormat));
         data.write(sourceCrop);
+        data.writeInt32(excludeLayers.size());
+        for (auto el : excludeLayers) {
+            data.writeStrongBinder(el);
+        }
         data.writeFloat(frameScale);
         data.writeBool(childrenOnly);
         status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
@@ -249,8 +278,8 @@
         return NO_ERROR;
     }
 
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource)
-    {
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
+                                                                     ConfigChanged configChanged) {
         Parcel data, reply;
         sp<IDisplayEventConnection> result;
         int err = data.writeInterfaceToken(
@@ -259,6 +288,7 @@
             return result;
         }
         data.writeInt32(static_cast<int32_t>(vsyncSource));
+        data.writeInt32(static_cast<int32_t>(configChanged));
         err = remote()->transact(
                 BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
                 data, &reply);
@@ -551,8 +581,8 @@
             ALOGE("enableVSyncInjections failed to writeBool: %d", result);
             return result;
         }
-        result = remote()->transact(BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS,
-                data, &reply, TF_ONE_WAY);
+        result = remote()->transact(BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS, data, &reply,
+                                    IBinder::FLAG_ONEWAY);
         if (result != NO_ERROR) {
             ALOGE("enableVSyncInjections failed to transact: %d", result);
             return result;
@@ -572,7 +602,8 @@
             ALOGE("injectVSync failed to writeInt64: %d", result);
             return result;
         }
-        result = remote()->transact(BnSurfaceComposer::INJECT_VSYNC, data, &reply, TF_ONE_WAY);
+        result = remote()->transact(BnSurfaceComposer::INJECT_VSYNC, data, &reply,
+                                    IBinder::FLAG_ONEWAY);
         if (result != NO_ERROR) {
             ALOGE("injectVSync failed to transact: %d", result);
             return result;
@@ -925,6 +956,27 @@
         }
         return NO_ERROR;
     }
+
+    virtual status_t notifyPowerHint(int32_t hintId) {
+        Parcel data, reply;
+        status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (error != NO_ERROR) {
+            ALOGE("notifyPowerHint: failed to write interface token: %d", error);
+            return error;
+        }
+        error = data.writeInt32(hintId);
+        if (error != NO_ERROR) {
+            ALOGE("notifyPowerHint: failed to write hintId: %d", error);
+            return error;
+        }
+        error = remote()->transact(BnSurfaceComposer::NOTIFY_POWER_HINT, data, &reply,
+                                   IBinder::FLAG_ONEWAY);
+        if (error != NO_ERROR) {
+            ALOGE("notifyPowerHint: failed to transact: %d", error);
+            return error;
+        }
+        return NO_ERROR;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -983,9 +1035,9 @@
 
             int64_t desiredPresentTime = data.readInt64();
 
-            cached_buffer_t uncachedBuffer;
+            client_cache_t uncachedBuffer;
             uncachedBuffer.token = data.readStrongBinder();
-            uncachedBuffer.cacheId = data.readUint64();
+            uncachedBuffer.id = data.readUint64();
 
             std::vector<ListenerCallbacks> listenerCallbacks;
             int32_t listenersSize = data.readInt32();
@@ -1020,12 +1072,30 @@
             int32_t rotation = data.readInt32();
             bool captureSecureLayers = static_cast<bool>(data.readInt32());
 
-            status_t res = captureScreen(display, &outBuffer, reqDataspace, reqPixelFormat,
-                                         sourceCrop, reqWidth, reqHeight, useIdentityTransform,
-                                         static_cast<ISurfaceComposer::Rotation>(rotation), captureSecureLayers);
+            bool capturedSecureLayers = false;
+            status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace,
+                                         reqPixelFormat, sourceCrop, reqWidth, reqHeight,
+                                         useIdentityTransform,
+                                         static_cast<ISurfaceComposer::Rotation>(rotation),
+                                         captureSecureLayers);
+
             reply->writeInt32(res);
             if (res == NO_ERROR) {
                 reply->write(*outBuffer);
+                reply->writeBool(capturedSecureLayers);
+            }
+            return NO_ERROR;
+        }
+        case CAPTURE_SCREEN_BY_ID: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            uint64_t displayOrLayerStack = data.readUint64();
+            ui::Dataspace outDataspace = ui::Dataspace::V0_SRGB;
+            sp<GraphicBuffer> outBuffer;
+            status_t res = captureScreen(displayOrLayerStack, &outDataspace, &outBuffer);
+            reply->writeInt32(res);
+            if (res == NO_ERROR) {
+                reply->writeInt32(static_cast<int32_t>(outDataspace));
+                reply->write(*outBuffer);
             }
             return NO_ERROR;
         }
@@ -1037,11 +1107,20 @@
             sp<GraphicBuffer> outBuffer;
             Rect sourceCrop(Rect::EMPTY_RECT);
             data.read(sourceCrop);
+
+            std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles;
+            int numExcludeHandles = data.readInt32();
+            excludeHandles.reserve(numExcludeHandles);
+            for (int i = 0; i < numExcludeHandles; i++) {
+                excludeHandles.emplace(data.readStrongBinder());
+            }
+
             float frameScale = data.readFloat();
             bool childrenOnly = data.readBool();
 
-            status_t res = captureLayers(layerHandleBinder, &outBuffer, reqDataspace,
-                                         reqPixelFormat, sourceCrop, frameScale, childrenOnly);
+            status_t res =
+                    captureLayers(layerHandleBinder, &outBuffer, reqDataspace, reqPixelFormat,
+                                  sourceCrop, excludeHandles, frameScale, childrenOnly);
             reply->writeInt32(res);
             if (res == NO_ERROR) {
                 reply->write(*outBuffer);
@@ -1077,8 +1156,11 @@
         }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IDisplayEventConnection> connection(createDisplayEventConnection(
-                    static_cast<ISurfaceComposer::VsyncSource>(data.readInt32())));
+            auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
+            auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
+
+            sp<IDisplayEventConnection> connection(
+                    createDisplayEventConnection(vsyncSource, configChanged));
             reply->writeStrongBinder(IInterface::asBinder(connection));
             return NO_ERROR;
         }
@@ -1499,6 +1581,16 @@
             }
             return setDisplayBrightness(displayToken, brightness);
         }
+        case NOTIFY_POWER_HINT: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int32_t hintId;
+            status_t error = data.readInt32(&hintId);
+            if (error != NO_ERROR) {
+                ALOGE("notifyPowerHint: failed to read hintId: %d", error);
+                return error;
+            }
+            return notifyPowerHint(hintId);
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 3077b21..bf7991a 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -87,8 +87,8 @@
            colorTransform.asArray(), 16 * sizeof(float));
     output.writeFloat(cornerRadius);
     output.writeBool(hasListenerCallbacks);
-    output.writeStrongBinder(cachedBuffer.token);
-    output.writeUint64(cachedBuffer.cacheId);
+    output.writeStrongBinder(cachedBuffer.token.promote());
+    output.writeUint64(cachedBuffer.id);
     output.writeParcelable(metadata);
 
     output.writeFloat(bgColorAlpha);
@@ -158,7 +158,7 @@
     cornerRadius = input.readFloat();
     hasListenerCallbacks = input.readBool();
     cachedBuffer.token = input.readStrongBinder();
-    cachedBuffer.cacheId = input.readUint64();
+    cachedBuffer.id = input.readUint64();
     input.readParcelable(&metadata);
 
     bgColorAlpha = input.readFloat();
@@ -245,6 +245,7 @@
     }
     if (other.what & eLayerChanged) {
         what |= eLayerChanged;
+        what &= ~eRelativeLayerChanged;
         z = other.z;
     }
     if (other.what & eSizeChanged) {
@@ -266,8 +267,9 @@
     }
     if (other.what & eFlagsChanged) {
         what |= eFlagsChanged;
-        flags = other.flags;
-        mask = other.mask;
+        flags &= ~other.mask;
+        flags |= (other.flags & other.mask);
+        mask |= other.mask;
     }
     if (other.what & eLayerStackChanged) {
         what |= eLayerStackChanged;
@@ -303,6 +305,7 @@
     }
     if (other.what & eRelativeLayerChanged) {
         what |= eRelativeLayerChanged;
+        what &= ~eLayerChanged;
         z = other.z;
         relativeLayerHandle = other.relativeLayerHandle;
     }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 93b4191..4e6a4e7 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -96,6 +96,7 @@
     mConnectedToCpu = false;
     mProducerControlledByApp = controlledByApp;
     mSwapIntervalZero = false;
+    mMaxBufferCount = 0;
 }
 
 Surface::~Surface() {
@@ -829,8 +830,9 @@
     mDefaultHeight = output.height;
     mNextFrameNumber = output.nextFrameNumber;
 
-    // Disable transform hint if sticky transform is set.
-    if (mStickyTransform == 0) {
+    // Ignore transform hint if sticky transform is set or transform to display inverse flag is
+    // set.
+    if (mStickyTransform == 0 && !transformToDisplayInverse()) {
         mTransformHint = output.transformHint;
     }
 
@@ -960,6 +962,10 @@
                 *value = static_cast<int>(mDataSpace);
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_MAX_BUFFER_COUNT: {
+                *value = mMaxBufferCount;
+                return NO_ERROR;
+            }
         }
     }
     return mGraphicBufferProducer->query(what, value);
@@ -1071,6 +1077,9 @@
     case NATIVE_WINDOW_GET_CONSUMER_USAGE64:
         res = dispatchGetConsumerUsage64(args);
         break;
+    case NATIVE_WINDOW_SET_AUTO_PREROTATION:
+        res = dispatchSetAutoPrerotation(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1271,6 +1280,16 @@
     return getConsumerUsage(usage);
 }
 
+int Surface::dispatchSetAutoPrerotation(va_list args) {
+    bool autoPrerotation = va_arg(args, int);
+    return setAutoPrerotation(autoPrerotation);
+}
+
+bool Surface::transformToDisplayInverse() {
+    return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
+            NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+}
+
 int Surface::connect(int api) {
     static sp<IProducerListener> listener = new DummyProducerListener();
     return connect(api, listener);
@@ -1292,9 +1311,12 @@
         mDefaultWidth = output.width;
         mDefaultHeight = output.height;
         mNextFrameNumber = output.nextFrameNumber;
+        mMaxBufferCount = output.maxBufferCount;
 
-        // Disable transform hint if sticky transform is set.
-        if (mStickyTransform == 0) {
+        // Ignore transform hint if sticky transform is set or transform to display inverse flag is
+        // set. Transform hint should be ignored if the client is expected to always submit buffers
+        // in the same orientation.
+        if (mStickyTransform == 0 && !transformToDisplayInverse()) {
             mTransformHint = output.transformHint;
         }
 
@@ -1331,6 +1353,7 @@
         mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
         mTransform = 0;
         mStickyTransform = 0;
+        mAutoPrerotation = false;
 
         if (api == NATIVE_WINDOW_API_CPU) {
             mConnectedToCpu = false;
@@ -1591,6 +1614,13 @@
     ATRACE_CALL();
     ALOGV("Surface::setBuffersTransform");
     Mutex::Autolock lock(mMutex);
+    // Ensure NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY is sticky. If the client sets the flag, do not
+    // override it until the surface is disconnected. This is a temporary workaround for camera
+    // until they switch to using Buffer State Layers. Currently if client sets the buffer transform
+    // it may be overriden by the buffer producer when the producer sets the buffer transform.
+    if (transformToDisplayInverse()) {
+        transform |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+    }
     mTransform = transform;
     return NO_ERROR;
 }
@@ -1905,7 +1935,8 @@
     return OK;
 }
 
-status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
+status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer,
+                                                    Dataspace dataspace) {
     if (buffer == nullptr) {
         return BAD_VALUE;
     }
@@ -1914,6 +1945,11 @@
     if (err != OK) {
         return err;
     }
+    ui::Dataspace tmpDataspace = surface->getBuffersDataSpace();
+    err = surface->setBuffersDataSpace(dataspace);
+    if (err != OK) {
+        return err;
+    }
     err = surface->attachBuffer(buffer->getNativeBuffer());
     if (err != OK) {
         return err;
@@ -1922,8 +1958,30 @@
     if (err != OK) {
         return err;
     }
+    err = surface->setBuffersDataSpace(tmpDataspace);
+    if (err != OK) {
+        return err;
+    }
     err = surface->disconnect(NATIVE_WINDOW_API_CPU);
     return err;
 }
 
+int Surface::setAutoPrerotation(bool autoPrerotation) {
+    ATRACE_CALL();
+    ALOGV("Surface::setAutoPrerotation (%d)", autoPrerotation);
+    Mutex::Autolock lock(mMutex);
+
+    if (mAutoPrerotation == autoPrerotation) {
+        return OK;
+    }
+
+    status_t err = mGraphicBufferProducer->setAutoPrerotation(autoPrerotation);
+    if (err == NO_ERROR) {
+        mAutoPrerotation = autoPrerotation;
+    }
+    ALOGE_IF(err, "IGraphicBufferProducer::setAutoPrerotation(%d) returned %s", autoPrerotation,
+             strerror(-err));
+    return err;
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 83cf40c..16a4b35 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -322,10 +322,99 @@
         mTransactionNestCount(other.mTransactionNestCount),
         mAnimation(other.mAnimation),
         mEarlyWakeup(other.mEarlyWakeup),
+        mContainsBuffer(other.mContainsBuffer),
         mDesiredPresentTime(other.mDesiredPresentTime) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
     mInputWindowCommands = other.mInputWindowCommands;
+    mListenerCallbacks = other.mListenerCallbacks;
+}
+
+std::unique_ptr<SurfaceComposerClient::Transaction>
+SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) {
+    auto transaction = std::make_unique<Transaction>();
+    if (transaction->readFromParcel(parcel) == NO_ERROR) {
+        return transaction;
+    }
+    return nullptr;
+}
+
+status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
+    const uint32_t forceSynchronous = parcel->readUint32();
+    const uint32_t transactionNestCount = parcel->readUint32();
+    const bool animation = parcel->readBool();
+    const bool earlyWakeup = parcel->readBool();
+    const bool containsBuffer = parcel->readBool();
+    const int64_t desiredPresentTime = parcel->readInt64();
+
+    size_t count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    SortedVector<DisplayState> displayStates;
+    displayStates.setCapacity(count);
+    for (size_t i = 0; i < count; i++) {
+        DisplayState displayState;
+        if (displayState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        displayStates.add(displayState);
+    }
+
+    count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> composerStates;
+    composerStates.reserve(count);
+    for (size_t i = 0; i < count; i++) {
+        sp<SurfaceControl> surfaceControl = SurfaceControl::readFromParcel(parcel);
+
+        ComposerState composerState;
+        if (composerState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        composerStates[surfaceControl] = composerState;
+    }
+
+    InputWindowCommands inputWindowCommands;
+    inputWindowCommands.read(*parcel);
+
+    // Parsing was successful. Update the object.
+    mForceSynchronous = forceSynchronous;
+    mTransactionNestCount = transactionNestCount;
+    mAnimation = animation;
+    mEarlyWakeup = earlyWakeup;
+    mContainsBuffer = containsBuffer;
+    mDesiredPresentTime = desiredPresentTime;
+    mDisplayStates = displayStates;
+    mComposerStates = composerStates;
+    mInputWindowCommands = inputWindowCommands;
+    // listener callbacks contain function pointer addresses and may not be safe to parcel.
+    mListenerCallbacks.clear();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const {
+    parcel->writeUint32(mForceSynchronous);
+    parcel->writeUint32(mTransactionNestCount);
+    parcel->writeBool(mAnimation);
+    parcel->writeBool(mEarlyWakeup);
+    parcel->writeBool(mContainsBuffer);
+    parcel->writeInt64(mDesiredPresentTime);
+    parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
+    for (auto const& displayState : mDisplayStates) {
+        displayState.write(*parcel);
+    }
+
+    parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size()));
+    for (auto const& [surfaceControl, composerState] : mComposerStates) {
+        surfaceControl->writeToParcel(parcel);
+        composerState.write(*parcel);
+    }
+
+    mInputWindowCommands.write(*parcel);
+    return NO_ERROR;
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
@@ -336,7 +425,6 @@
             mComposerStates[kv.first].state.merge(kv.second.state);
         }
     }
-    other.mComposerStates.clear();
 
     for (auto const& state : other.mDisplayStates) {
         ssize_t index = mDisplayStates.indexOf(state);
@@ -346,7 +434,6 @@
             mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
         }
     }
-    other.mDisplayStates.clear();
 
     for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) {
         auto& [callbackIds, surfaceControls] = callbackInfo;
@@ -357,17 +444,28 @@
                 .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()),
                                         std::make_move_iterator(surfaceControls.end()));
     }
-    other.mListenerCallbacks.clear();
 
     mInputWindowCommands.merge(other.mInputWindowCommands);
-    other.mInputWindowCommands.clear();
 
     mContainsBuffer = other.mContainsBuffer;
-    other.mContainsBuffer = false;
-
+    mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup;
+    other.clear();
     return *this;
 }
 
+void SurfaceComposerClient::Transaction::clear() {
+    mComposerStates.clear();
+    mDisplayStates.clear();
+    mListenerCallbacks.clear();
+    mInputWindowCommands.clear();
+    mContainsBuffer = false;
+    mForceSynchronous = 0;
+    mTransactionNestCount = 0;
+    mAnimation = false;
+    mEarlyWakeup = false;
+    mDesiredPresentTime = -1;
+}
+
 void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle,
         const sp<ISurfaceComposerClient>& client) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
@@ -381,17 +479,19 @@
     s.state.parentHandleForChild = nullptr;
 
     composerStates.add(s);
-    sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {}, {});
+    sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    sf->setTransactionState(composerStates, displayStates, 0, applyToken, {}, -1, {}, {});
 }
 
 void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
 
-    cached_buffer_t uncacheBuffer;
+    client_cache_t uncacheBuffer;
     uncacheBuffer.token = BufferCache::getInstance().getToken();
-    uncacheBuffer.cacheId = cacheId;
+    uncacheBuffer.id = cacheId;
 
-    sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer, {});
+    sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    sf->setTransactionState({}, {}, 0, applyToken, {}, -1, uncacheBuffer, {});
 }
 
 void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -422,7 +522,7 @@
         }
         s->what |= layer_state_t::eCachedBufferChanged;
         s->cachedBuffer.token = BufferCache::getInstance().getToken();
-        s->cachedBuffer.cacheId = cacheId;
+        s->cachedBuffer.id = cacheId;
 
         // If we have more buffers than the size of the cache, we should stop caching so we don't
         // evict other buffers in this transaction
@@ -609,6 +709,7 @@
         return *this;
     }
     s->what |= layer_state_t::eLayerChanged;
+    s->what &= ~layer_state_t::eRelativeLayerChanged;
     s->z = z;
 
     registerSurfaceControlForCallback(sc);
@@ -620,8 +721,10 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eRelativeLayerChanged;
+    s->what &= ~layer_state_t::eLayerChanged;
     s->relativeLayerHandle = relativeTo;
     s->z = z;
 
@@ -1048,6 +1151,7 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eDetachChildren;
 
@@ -1147,8 +1251,12 @@
 
     int x = dst.left;
     int y = dst.top;
-    float xScale = dst.getWidth() / static_cast<float>(source.getWidth());
-    float yScale = dst.getHeight() / static_cast<float>(source.getHeight());
+
+    float sourceWidth = source.getWidth();
+    float sourceHeight = source.getHeight();
+
+    float xScale = sourceWidth < 0 ? 1.0f : dst.getWidth() / sourceWidth;
+    float yScale = sourceHeight < 0 ? 1.0f : dst.getHeight() / sourceHeight;
     float matrix[4] = {1, 0, 0, 1};
 
     switch (transform) {
@@ -1537,18 +1645,24 @@
     return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness);
 }
 
+status_t SurfaceComposerClient::notifyPowerHint(int32_t hintId) {
+    return ComposerService::getComposerService()->notifyPowerHint(hintId);
+}
+
 // ----------------------------------------------------------------------------
 
 status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
                                    const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                    uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
-                                   uint32_t rotation, bool captureSecureLayers, sp<GraphicBuffer>* outBuffer) {
+                                   uint32_t rotation, bool captureSecureLayers,
+                                   sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == nullptr) return NO_INIT;
-    status_t ret = s->captureScreen(display, outBuffer, reqDataSpace, reqPixelFormat, sourceCrop,
-            reqWidth, reqHeight, useIdentityTransform,
-            static_cast<ISurfaceComposer::Rotation>(rotation),
-            captureSecureLayers);
+    status_t ret =
+            s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace,
+                             reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform,
+                             static_cast<ISurfaceComposer::Rotation>(rotation),
+                             captureSecureLayers);
     if (ret != NO_ERROR) {
         return ret;
     }
@@ -1559,8 +1673,16 @@
                                    const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                    uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
                                    uint32_t rotation, sp<GraphicBuffer>* outBuffer) {
-    return capture(display, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth,
-            reqHeight, useIdentityTransform, rotation, false, outBuffer);
+    bool ignored;
+    return capture(display, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight,
+                   useIdentityTransform, rotation, false, outBuffer, ignored);
+}
+
+status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (s == nullptr) return NO_INIT;
+    return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer);
 }
 
 status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
@@ -1570,18 +1692,20 @@
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == nullptr) return NO_INIT;
     status_t ret = s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat,
-                                    sourceCrop, frameScale, false /* childrenOnly */);
+                                    sourceCrop, {}, frameScale, false /* childrenOnly */);
     return ret;
 }
 
-status_t ScreenshotClient::captureChildLayers(const sp<IBinder>& layerHandle,
-                                              const ui::Dataspace reqDataSpace,
-                                              const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
-                                              float frameScale, sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::captureChildLayers(
+        const sp<IBinder>& layerHandle, const ui::Dataspace reqDataSpace,
+        const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
+        const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& excludeHandles,
+        float frameScale, sp<GraphicBuffer>* outBuffer) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == nullptr) return NO_INIT;
-    status_t ret = s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat,
-                                    sourceCrop, frameScale, true /* childrenOnly */);
+    status_t ret =
+            s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat, sourceCrop,
+                             excludeHandles, frameScale, true /* childrenOnly */);
     return ret;
 }
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 55488da..b9defdd 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -71,14 +71,6 @@
     release();
 }
 
-void SurfaceControl::destroy()
-{
-    if (isValid()) {
-        SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
-    }
-    release();
-}
-
 void SurfaceControl::release()
 {
     // Trigger an IPC now, to make sure things
@@ -186,8 +178,7 @@
     parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer));
 }
 
-sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
-{
+sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) {
     sp<IBinder> client = parcel->readStrongBinder();
     sp<IBinder> handle = parcel->readStrongBinder();
     if (client == nullptr || handle == nullptr)
diff --git a/libs/gui/bufferqueue/1.0/Conversion.cpp b/libs/gui/bufferqueue/1.0/Conversion.cpp
new file mode 100644
index 0000000..5cb3593
--- /dev/null
+++ b/libs/gui/bufferqueue/1.0/Conversion.cpp
@@ -0,0 +1,1542 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/bufferqueue/1.0/Conversion.h>
+
+namespace android {
+namespace conversion {
+
+// native_handle_t helper functions.
+
+/**
+ * \brief Take an fd and create a native handle containing only the given fd.
+ * The created handle will need to be deleted manually with
+ * `native_handle_delete()`.
+ *
+ * \param[in] fd The source file descriptor (of type `int`).
+ * \return The create `native_handle_t*` that contains the given \p fd. If the
+ * supplied \p fd is negative, the created native handle will contain no file
+ * descriptors.
+ *
+ * If the native handle cannot be created, the return value will be
+ * `nullptr`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+native_handle_t* native_handle_create_from_fd(int fd) {
+    if (fd < 2) {
+        return native_handle_create(0, 0);
+    }
+    native_handle_t* nh = native_handle_create(1, 0);
+    if (nh == nullptr) {
+        return nullptr;
+    }
+    nh->data[0] = fd;
+    return nh;
+}
+
+/**
+ * \brief Extract a file descriptor from a native handle.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \param[in] index The index of the file descriptor in \p nh to read from. This
+ * input has the default value of `0`.
+ * \return The `index`-th file descriptor in \p nh. If \p nh does not have
+ * enough file descriptors, the returned value will be `-1`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+int native_handle_read_fd(native_handle_t const* nh, int index) {
+    return ((nh == nullptr) || (nh->numFds == 0) ||
+            (nh->numFds <= index) || (index < 0)) ?
+            -1 : nh->data[index];
+}
+
+/**
+ * Conversion functions
+ * ====================
+ *
+ * There are two main directions of conversion:
+ * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
+ *   input. The wrapper has type `TargetType`.
+ * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
+ *   corresponds to the input. The lifetime of the output does not depend on the
+ *   lifetime of the input.
+ * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
+ *   that cannot be copied and/or moved efficiently, or when there are multiple
+ *   output arguments.
+ * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
+ *   `TargetType` that cannot be copied and/or moved efficiently, or when there
+ *   are multiple output arguments.
+ *
+ * `wrapIn()` and `convertTo()` functions will take output arguments before
+ * input arguments. Some of these functions might return a value to indicate
+ * success or error.
+ *
+ * In converting or wrapping something as a Treble type that contains a
+ * `hidl_handle`, `native_handle_t*` will need to be created and returned as
+ * an additional output argument, hence only `wrapIn()` or `convertTo()` would
+ * be available. The caller must call `native_handle_delete()` to deallocate the
+ * returned native handle when it is no longer needed.
+ *
+ * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
+ * not perform duplication of file descriptors, while `toTargetType()` and
+ * `convertTo()` do.
+ */
+
+/**
+ * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `status_t`.
+ */
+// convert: Return<void> -> status_t
+status_t toStatusT(Return<void> const& t) {
+    return t.isOk() ? OK : (t.isDeadObject() ? DEAD_OBJECT : UNKNOWN_ERROR);
+}
+
+/**
+ * \brief Convert `Return<void>` to `binder::Status`.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: Return<void> -> ::android::binder::Status
+::android::binder::Status toBinderStatus(
+        Return<void> const& t) {
+    return ::android::binder::Status::fromExceptionCode(
+            toStatusT(t),
+            t.description().c_str());
+}
+
+/**
+ * \brief Wrap `native_handle_t*` in `hidl_handle`.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \return The `hidl_handle` that points to \p nh.
+ */
+// wrap: native_handle_t* -> hidl_handle
+hidl_handle inHidlHandle(native_handle_t const* nh) {
+    return hidl_handle(nh);
+}
+
+/**
+ * \brief Convert `int32_t` to `Dataspace`.
+ *
+ * \param[in] l The source `int32_t`.
+ * \result The corresponding `Dataspace`.
+ */
+// convert: int32_t -> Dataspace
+Dataspace toHardwareDataspace(int32_t l) {
+    return static_cast<Dataspace>(l);
+}
+
+/**
+ * \brief Convert `Dataspace` to `int32_t`.
+ *
+ * \param[in] t The source `Dataspace`.
+ * \result The corresponding `int32_t`.
+ */
+// convert: Dataspace -> int32_t
+int32_t toRawDataspace(Dataspace const& t) {
+    return static_cast<int32_t>(t);
+}
+
+/**
+ * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that points to the buffer.
+ */
+// wrap: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
+    hidl_vec<uint8_t> t;
+    t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
+    return t;
+}
+
+/**
+ * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
+ */
+// convert: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
+    hidl_vec<uint8_t> t;
+    t.resize(size);
+    uint8_t const* src = static_cast<uint8_t const*>(l);
+    std::copy(src, src + size, t.data());
+    return t;
+}
+
+/**
+ * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
+ *
+ * \param[out] t The wrapper of type `AnwBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: GraphicBuffer -> AnwBuffer
+void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
+    t->attr.width = l.getWidth();
+    t->attr.height = l.getHeight();
+    t->attr.stride = l.getStride();
+    t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
+    t->attr.layerCount = l.getLayerCount();
+    t->attr.usage = static_cast<uint32_t>(l.getUsage());
+    t->attr.id = l.getId();
+    t->attr.generationNumber = l.getGenerationNumber();
+    t->nativeHandle = hidl_handle(l.handle);
+}
+
+/**
+ * \brief Convert `AnwBuffer` to `GraphicBuffer`.
+ *
+ * \param[out] l The destination `GraphicBuffer`.
+ * \param[in] t The source `AnwBuffer`.
+ *
+ * This function will duplicate all file descriptors in \p t.
+ */
+// convert: AnwBuffer -> GraphicBuffer
+// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
+bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
+    native_handle_t* handle = t.nativeHandle == nullptr ?
+            nullptr : native_handle_clone(t.nativeHandle);
+
+    size_t const numInts = 12 + static_cast<size_t>(handle ? handle->numInts : 0);
+    int32_t* ints = new int32_t[numInts];
+
+    size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
+    int* fds = new int[numFds];
+
+    ints[0] = 'GBFR';
+    ints[1] = static_cast<int32_t>(t.attr.width);
+    ints[2] = static_cast<int32_t>(t.attr.height);
+    ints[3] = static_cast<int32_t>(t.attr.stride);
+    ints[4] = static_cast<int32_t>(t.attr.format);
+    ints[5] = static_cast<int32_t>(t.attr.layerCount);
+    ints[6] = static_cast<int32_t>(t.attr.usage);
+    ints[7] = static_cast<int32_t>(t.attr.id >> 32);
+    ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
+    ints[9] = static_cast<int32_t>(t.attr.generationNumber);
+    ints[10] = 0;
+    ints[11] = 0;
+    if (handle) {
+        ints[10] = static_cast<int32_t>(handle->numFds);
+        ints[11] = static_cast<int32_t>(handle->numInts);
+        int* intsStart = handle->data + handle->numFds;
+        std::copy(handle->data, intsStart, fds);
+        std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
+    }
+
+    void const* constBuffer = static_cast<void const*>(ints);
+    size_t size = numInts * sizeof(int32_t);
+    int const* constFds = static_cast<int const*>(fds);
+    status_t status = l->unflatten(constBuffer, size, constFds, numFds);
+
+    delete [] fds;
+    delete [] ints;
+    native_handle_delete(handle);
+    return status == NO_ERROR;
+}
+
+/**
+ * Conversion functions for types outside media
+ * ============================================
+ *
+ * Some objects in libui and libgui that were made to go through binder calls do
+ * not expose ways to read or write their fields to the public. To pass an
+ * object of this kind through the HIDL boundary, translation functions need to
+ * work around the access restriction by using the publicly available
+ * `flatten()` and `unflatten()` functions.
+ *
+ * All `flatten()` and `unflatten()` overloads follow the same convention as
+ * follows:
+ *
+ *     status_t flatten(ObjectType const& object,
+ *                      [OtherType const& other, ...]
+ *                      void*& buffer, size_t& size,
+ *                      int*& fds, size_t& numFds)
+ *
+ *     status_t unflatten(ObjectType* object,
+ *                        [OtherType* other, ...,]
+ *                        void*& buffer, size_t& size,
+ *                        int*& fds, size_t& numFds)
+ *
+ * The number of `other` parameters varies depending on the `ObjectType`. For
+ * example, in the process of unflattening an object that contains
+ * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
+ * be created.
+ *
+ * The last four parameters always work the same way in all overloads of
+ * `flatten()` and `unflatten()`:
+ * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
+ *   `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
+ *   `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
+ *   size (in ints) of the fd buffer pointed to by `fds`.
+ * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
+ *   from, `size` is the size (in bytes) of the non-fd buffer pointed to by
+ *   `buffer`, `fds` is the pointer to the fd buffer to be read from, and
+ *   `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
+ * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
+ *   will be advanced, while `size` and `numFds` will be decreased to reflect
+ *   how much storage/data of the two buffers (fd and non-fd) have been used.
+ * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
+ *   `numFds` are invalid.
+ *
+ * The return value of a successful `flatten()` or `unflatten()` call will be
+ * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
+ *
+ * For each object type that supports flattening, there will be two accompanying
+ * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
+ * return the size of the non-fd buffer that the object will need for
+ * flattening. `getFdCount()` will return the size of the fd buffer that the
+ * object will need for flattening.
+ *
+ * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
+ * `flatten()` and `unflatten()`, are similar to functions of the same name in
+ * the abstract class `Flattenable`. The only difference is that functions in
+ * this file are not member functions of the object type. For example, we write
+ *
+ *     flatten(x, buffer, size, fds, numFds)
+ *
+ * instead of
+ *
+ *     x.flatten(buffer, size, fds, numFds)
+ *
+ * because we cannot modify the type of `x`.
+ *
+ * There is one exception to the naming convention: `hidl_handle` that
+ * represents a fence. The four functions for this "Fence" type have the word
+ * "Fence" attched to their names because the object type, which is
+ * `hidl_handle`, does not carry the special meaning that the object itself can
+ * only contain zero or one file descriptor.
+ */
+
+// Ref: frameworks/native/libs/ui/Fence.cpp
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return The required size of the flat buffer.
+ *
+ * The current version of this function always returns 4, which is the number of
+ * bytes required to store the number of file descriptors contained in the fd
+ * part of the flat buffer.
+ */
+size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
+    return 4;
+};
+
+/**
+ * \brief Return the number of file descriptors contained in a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return `0` if \p fence does not contain a valid file descriptor, or `1`
+ * otherwise.
+ */
+size_t getFenceFdCount(hidl_handle const& fence) {
+    return native_handle_read_fd(fence) == -1 ? 0 : 1;
+}
+
+/**
+ * \brief Unflatten `Fence` to `hidl_handle`.
+ *
+ * \param[out] fence The destination `hidl_handle`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will point to a newly created
+ * native handle, which needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+    if (size < 4) {
+        return NO_MEMORY;
+    }
+
+    uint32_t numFdsInHandle;
+    FlattenableUtils::read(buffer, size, numFdsInHandle);
+
+    if (numFdsInHandle > 1) {
+        return BAD_VALUE;
+    }
+
+    if (numFds < numFdsInHandle) {
+        return NO_MEMORY;
+    }
+
+    if (numFdsInHandle) {
+        *nh = native_handle_create_from_fd(*fds);
+        if (*nh == nullptr) {
+            return NO_MEMORY;
+        }
+        *fence = *nh;
+        ++fds;
+        --numFds;
+    } else {
+        *nh = nullptr;
+        *fence = hidl_handle();
+    }
+
+    return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `hidl_handle` as `Fence`.
+ *
+ * \param[in] t The source `hidl_handle`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flattenFence(hidl_handle const& fence,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+    if (size < getFenceFlattenedSize(fence) ||
+            numFds < getFenceFdCount(fence)) {
+        return NO_MEMORY;
+    }
+    // Cast to uint32_t since the size of a size_t can vary between 32- and
+    // 64-bit processes
+    FlattenableUtils::write(buffer, size,
+            static_cast<uint32_t>(getFenceFdCount(fence)));
+    int fd = native_handle_read_fd(fence);
+    if (fd != -1) {
+        *fds = fd;
+        ++fds;
+        --numFds;
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Wrap `Fence` in `hidl_handle`.
+ *
+ * \param[out] t The wrapper of type `hidl_handle`.
+ * \param[out] nh The native handle pointed to by \p t.
+ * \param[in] l The source `Fence`.
+ *
+ * On success, \p nh will hold a newly created native handle, which must be
+ * deleted manually with `native_handle_delete()` afterwards.
+ */
+// wrap: Fence -> hidl_handle
+bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
+    size_t const baseSize = l.getFlattenedSize();
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    size_t const baseNumFds = l.getFdCount();
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = static_cast<int*>(baseFds.get());
+    size_t numFds = baseNumFds;
+    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
+            != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * \brief Convert `hidl_handle` to `Fence`.
+ *
+ * \param[out] l The destination `Fence`. `l` must not have been used
+ * (`l->isValid()` must return `false`) before this function is called.
+ * \param[in] t The source `hidl_handle`.
+ *
+ * If \p t contains a valid file descriptor, it will be duplicated.
+ */
+// convert: hidl_handle -> Fence
+bool convertTo(Fence* l, hidl_handle const& t) {
+    int fd = native_handle_read_fd(t);
+    if (fd != -1) {
+        fd = dup(fd);
+        if (fd == -1) {
+            return false;
+        }
+    }
+    native_handle_t* nh = native_handle_create_from_fd(fd);
+    if (nh == nullptr) {
+        if (fd != -1) {
+            close(fd);
+        }
+        return false;
+    }
+
+    size_t const baseSize = getFenceFlattenedSize(t);
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        native_handle_delete(nh);
+        return false;
+    }
+
+    size_t const baseNumFds = getFenceFdCount(t);
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        native_handle_delete(nh);
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = static_cast<int*>(baseFds.get());
+    size_t numFds = baseNumFds;
+    if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
+        native_handle_delete(nh);
+        return false;
+    }
+    native_handle_delete(nh);
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+        HGraphicBufferProducer::FenceTimeSnapshot const& t) {
+    constexpr size_t min = sizeof(t.state);
+    switch (t.state) {
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
+            return min;
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
+            return min + getFenceFlattenedSize(t.fence);
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
+            return min + sizeof(
+                    ::android::FenceTime::Snapshot::signalTime);
+    }
+    return 0;
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The number of file descriptors contained in \p snapshot.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::FenceTimeSnapshot const& t) {
+    return t.state ==
+            HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
+            getFenceFdCount(t.fence) : 0;
+}
+
+/**
+ * \brief Flatten `FenceTimeSnapshot`.
+ *
+ * \param[in] t The source `FenceTimeSnapshot`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence` if `t.state ==
+ * FENCE`.
+ */
+status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+    if (size < getFlattenedSize(t)) {
+        return NO_MEMORY;
+    }
+
+    switch (t.state) {
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
+            FlattenableUtils::write(buffer, size,
+                    ::android::FenceTime::Snapshot::State::EMPTY);
+            return NO_ERROR;
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
+            FlattenableUtils::write(buffer, size,
+                    ::android::FenceTime::Snapshot::State::FENCE);
+            return flattenFence(t.fence, buffer, size, fds, numFds);
+        case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
+            FlattenableUtils::write(buffer, size,
+                    ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
+            FlattenableUtils::write(buffer, size, t.signalTimeNs);
+            return NO_ERROR;
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Unflatten `FenceTimeSnapshot`.
+ *
+ * \param[out] t The destination `FenceTimeSnapshot`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and the constructed snapshot contains a
+ * file descriptor, \p nh will be created to hold that file descriptor. In this
+ * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+    if (size < sizeof(t->state)) {
+        return NO_MEMORY;
+    }
+
+    *nh = nullptr;
+    ::android::FenceTime::Snapshot::State state;
+    FlattenableUtils::read(buffer, size, state);
+    switch (state) {
+        case ::android::FenceTime::Snapshot::State::EMPTY:
+            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
+            return NO_ERROR;
+        case ::android::FenceTime::Snapshot::State::FENCE:
+            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
+            return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
+        case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
+            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
+            if (size < sizeof(t->signalTimeNs)) {
+                return NO_MEMORY;
+            }
+            FlattenableUtils::read(buffer, size, t->signalTimeNs);
+            return NO_ERROR;
+    }
+    return NO_ERROR;
+}
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
+
+/**
+ * \brief Return a lower bound on the size of the non-fd buffer required to
+ * flatten `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return A lower bound on the size of the flat buffer.
+ */
+constexpr size_t minFlattenedSize(
+        HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
+    return sizeof(uint64_t) + // mFrameNumber
+            sizeof(uint8_t) + // mIndex
+            sizeof(uint8_t) + // mAddPostCompositeCalled
+            sizeof(uint8_t) + // mAddRetireCalled
+            sizeof(uint8_t) + // mAddReleaseCalled
+            sizeof(nsecs_t) + // mPostedTime
+            sizeof(nsecs_t) + // mRequestedPresentTime
+            sizeof(nsecs_t) + // mLatchTime
+            sizeof(nsecs_t) + // mFirstRefreshStartTime
+            sizeof(nsecs_t); // mLastRefreshStartTime
+}
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+        HGraphicBufferProducer::FrameEventsDelta const& t) {
+    return minFlattenedSize(t) +
+            getFlattenedSize(t.gpuCompositionDoneFence) +
+            getFlattenedSize(t.displayPresentFence) +
+            getFlattenedSize(t.displayRetireFence) +
+            getFlattenedSize(t.releaseFence);
+};
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::FrameEventsDelta const& t) {
+    return getFdCount(t.gpuCompositionDoneFence) +
+            getFdCount(t.displayPresentFence) +
+            getFdCount(t.displayRetireFence) +
+            getFdCount(t.releaseFence);
+};
+
+/**
+ * \brief Unflatten `FrameEventsDelta`.
+ *
+ * \param[out] t The destination `FrameEventsDelta`.
+ * \param[out] nh The underlying array of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
+ * populated with `nullptr` or newly created handles. Each non-null slot in \p
+ * nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
+        std::vector<native_handle_t*>* nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+    if (size < minFlattenedSize(*t)) {
+        return NO_MEMORY;
+    }
+    FlattenableUtils::read(buffer, size, t->frameNumber);
+
+    // These were written as uint8_t for alignment.
+    uint8_t temp = 0;
+    FlattenableUtils::read(buffer, size, temp);
+    size_t index = static_cast<size_t>(temp);
+    if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+        return BAD_VALUE;
+    }
+    t->index = static_cast<uint32_t>(index);
+
+    FlattenableUtils::read(buffer, size, temp);
+    t->addPostCompositeCalled = static_cast<bool>(temp);
+    FlattenableUtils::read(buffer, size, temp);
+    t->addRetireCalled = static_cast<bool>(temp);
+    FlattenableUtils::read(buffer, size, temp);
+    t->addReleaseCalled = static_cast<bool>(temp);
+
+    FlattenableUtils::read(buffer, size, t->postedTimeNs);
+    FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
+    FlattenableUtils::read(buffer, size, t->latchTimeNs);
+    FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
+    FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
+    FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
+
+    // Fences
+    HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
+    tSnapshot[0] = &t->gpuCompositionDoneFence;
+    tSnapshot[1] = &t->displayPresentFence;
+    tSnapshot[2] = &t->displayRetireFence;
+    tSnapshot[3] = &t->releaseFence;
+    nh->resize(4);
+    for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
+        status_t status = unflatten(
+                tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
+                buffer, size, fds, numFds);
+        if (status != NO_ERROR) {
+            while (snapshotIndex > 0) {
+                --snapshotIndex;
+                if ((*nh)[snapshotIndex] != nullptr) {
+                    native_handle_delete((*nh)[snapshotIndex]);
+                }
+            }
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `FrameEventsDelta`.
+ *
+ * \param[in] t The source `FrameEventsDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
+//      FrameEventsDelta::flatten
+status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
+        void*& buffer, size_t& size, int*& fds, size_t numFds) {
+    // Check that t.index is within a valid range.
+    if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
+            || t.index > std::numeric_limits<uint8_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    FlattenableUtils::write(buffer, size, t.frameNumber);
+
+    // These are static_cast to uint8_t for alignment.
+    FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
+    FlattenableUtils::write(
+            buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
+    FlattenableUtils::write(
+            buffer, size, static_cast<uint8_t>(t.addRetireCalled));
+    FlattenableUtils::write(
+            buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
+
+    FlattenableUtils::write(buffer, size, t.postedTimeNs);
+    FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
+    FlattenableUtils::write(buffer, size, t.latchTimeNs);
+    FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
+    FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
+    FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
+
+    // Fences
+    HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
+    tSnapshot[0] = &t.gpuCompositionDoneFence;
+    tSnapshot[1] = &t.displayPresentFence;
+    tSnapshot[2] = &t.displayRetireFence;
+    tSnapshot[3] = &t.releaseFence;
+    for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
+        status_t status = flatten(
+                *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+    size_t size = 4 + // mDeltas.size()
+            sizeof(t.compositorTiming);
+    for (size_t i = 0; i < t.deltas.size(); ++i) {
+        size += getFlattenedSize(t.deltas[i]);
+    }
+    return size;
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+    size_t numFds = 0;
+    for (size_t i = 0; i < t.deltas.size(); ++i) {
+        numFds += getFdCount(t.deltas[i]);
+    }
+    return numFds;
+}
+
+/**
+ * \brief Unflatten `FrameEventHistoryDelta`.
+ *
+ * \param[out] t The destination `FrameEventHistoryDelta`.
+ * \param[out] nh The underlying array of arrays of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
+ * newly created handles. The second dimension of \p nh will be 4. Each non-null
+ * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::FrameEventHistoryDelta* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+    if (size < 4) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::read(buffer, size, t->compositorTiming);
+
+    uint32_t deltaCount = 0;
+    FlattenableUtils::read(buffer, size, deltaCount);
+    if (static_cast<size_t>(deltaCount) >
+            ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+        return BAD_VALUE;
+    }
+    t->deltas.resize(deltaCount);
+    nh->resize(deltaCount);
+    for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
+        status_t status = unflatten(
+                &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
+                buffer, size, fds, numFds);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `FrameEventHistoryDelta`.
+ *
+ * \param[in] t The source `FrameEventHistoryDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+status_t flatten(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+    if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+        return BAD_VALUE;
+    }
+    if (size < getFlattenedSize(t)) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, t.compositorTiming);
+
+    FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
+    for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
+        status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Wrap `::android::FrameEventHistoryData` in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `::android::FrameEventHistoryDelta`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        ::android::FrameEventHistoryDelta const& l) {
+
+    size_t const baseSize = l.getFlattenedSize();
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    size_t const baseNumFds = l.getFdCount();
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = baseFds.get();
+    size_t numFds = baseNumFds;
+    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
+ * `::android::FrameEventHistoryDelta`.
+ *
+ * \param[out] l The destination `::android::FrameEventHistoryDelta`.
+ * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+bool convertTo(
+        ::android::FrameEventHistoryDelta* l,
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
+
+    size_t const baseSize = getFlattenedSize(t);
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    size_t const baseNumFds = getFdCount(t);
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = static_cast<int*>(baseFds.get());
+    size_t numFds = baseNumFds;
+    if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+// Ref: frameworks/native/libs/ui/Region.cpp
+
+/**
+ * \brief Return the size of the buffer required to flatten `Region`.
+ *
+ * \param[in] t The input `Region`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(Region const& t) {
+    return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
+}
+
+/**
+ * \brief Unflatten `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t unflatten(Region* t, void const*& buffer, size_t& size) {
+    if (size < sizeof(uint32_t)) {
+        return NO_MEMORY;
+    }
+
+    uint32_t numRects = 0;
+    FlattenableUtils::read(buffer, size, numRects);
+    if (size < numRects * sizeof(Rect)) {
+        return NO_MEMORY;
+    }
+    if (numRects > (UINT32_MAX / sizeof(Rect))) {
+        return NO_MEMORY;
+    }
+
+    t->resize(numRects);
+    for (size_t r = 0; r < numRects; ++r) {
+        ::android::Rect rect(::android::Rect::EMPTY_RECT);
+        status_t status = rect.unflatten(buffer, size);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        FlattenableUtils::advance(buffer, size, sizeof(rect));
+        (*t)[r] = Rect{
+                static_cast<int32_t>(rect.left),
+                static_cast<int32_t>(rect.top),
+                static_cast<int32_t>(rect.right),
+                static_cast<int32_t>(rect.bottom)};
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Flatten `Region`.
+ *
+ * \param[in] t The source `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flatten(Region const& t, void*& buffer, size_t& size) {
+    if (size < getFlattenedSize(t)) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
+    for (size_t r = 0; r < t.size(); ++r) {
+        ::android::Rect rect(
+                static_cast<int32_t>(t[r].left),
+                static_cast<int32_t>(t[r].top),
+                static_cast<int32_t>(t[r].right),
+                static_cast<int32_t>(t[r].bottom));
+        status_t status = rect.flatten(buffer, size);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        FlattenableUtils::advance(buffer, size, sizeof(rect));
+    }
+    return NO_ERROR;
+}
+
+/**
+ * \brief Convert `::android::Region` to `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in] l The source `::android::Region`.
+ */
+// convert: ::android::Region -> Region
+bool convertTo(Region* t, ::android::Region const& l) {
+    size_t const baseSize = l.getFlattenedSize();
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    if (l.flatten(buffer, size) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    if (unflatten(t, constBuffer, size) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * \brief Convert `Region` to `::android::Region`.
+ *
+ * \param[out] l The destination `::android::Region`.
+ * \param[in] t The source `Region`.
+ */
+// convert: Region -> ::android::Region
+bool convertTo(::android::Region* l, Region const& t) {
+    size_t const baseSize = getFlattenedSize(t);
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    if (flatten(t, buffer, size) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    if (l->unflatten(constBuffer, size) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+//      BGraphicBufferProducer::QueueBufferInput
+
+/**
+ * \brief Return a lower bound on the size of the buffer required to flatten
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return A lower bound on the size of the flat buffer.
+ */
+constexpr size_t minFlattenedSize(
+        HGraphicBufferProducer::QueueBufferInput const& /* t */) {
+    return sizeof(int64_t) + // timestamp
+            sizeof(int) + // isAutoTimestamp
+            sizeof(android_dataspace) + // dataSpace
+            sizeof(::android::Rect) + // crop
+            sizeof(int) + // scalingMode
+            sizeof(uint32_t) + // transform
+            sizeof(uint32_t) + // stickyTransform
+            sizeof(bool); // getFrameTimestamps
+}
+
+/**
+ * \brief Return the size of the buffer required to flatten
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
+    return minFlattenedSize(t) +
+            getFenceFlattenedSize(t.fence) +
+            getFlattenedSize(t.surfaceDamage) +
+            sizeof(HdrMetadata::validTypes);
+}
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::QueueBufferInput const& t) {
+    return getFenceFdCount(t.fence);
+}
+
+/**
+ * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The native handle cloned from `t.fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence`. */
+status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
+        native_handle_t** nh,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
+    if (size < getFlattenedSize(t)) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, t.timestamp);
+    FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
+    FlattenableUtils::write(buffer, size,
+            static_cast<android_dataspace_t>(t.dataSpace));
+    FlattenableUtils::write(buffer, size, ::android::Rect(
+            static_cast<int32_t>(t.crop.left),
+            static_cast<int32_t>(t.crop.top),
+            static_cast<int32_t>(t.crop.right),
+            static_cast<int32_t>(t.crop.bottom)));
+    FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
+    FlattenableUtils::write(buffer, size, t.transform);
+    FlattenableUtils::write(buffer, size, t.stickyTransform);
+    FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
+
+    *nh = t.fence.getNativeHandle() == nullptr ?
+            nullptr : native_handle_clone(t.fence);
+    status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    status = flatten(t.surfaceDamage, buffer, size);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
+    return NO_ERROR;
+}
+
+/**
+ * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
+    if (size < minFlattenedSize(*t)) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::read(buffer, size, t->timestamp);
+    int lIsAutoTimestamp;
+    FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
+    t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
+    android_dataspace_t lDataSpace;
+    FlattenableUtils::read(buffer, size, lDataSpace);
+    t->dataSpace = static_cast<Dataspace>(lDataSpace);
+    Rect lCrop;
+    FlattenableUtils::read(buffer, size, lCrop);
+    t->crop = Rect{
+            static_cast<int32_t>(lCrop.left),
+            static_cast<int32_t>(lCrop.top),
+            static_cast<int32_t>(lCrop.right),
+            static_cast<int32_t>(lCrop.bottom)};
+    int lScalingMode;
+    FlattenableUtils::read(buffer, size, lScalingMode);
+    t->scalingMode = static_cast<int32_t>(lScalingMode);
+    FlattenableUtils::read(buffer, size, t->transform);
+    FlattenableUtils::read(buffer, size, t->stickyTransform);
+    FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
+
+    status_t status = unflattenFence(&(t->fence), nh,
+            buffer, size, fds, numFds);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    // HdrMetadata ignored
+    return unflatten(&(t->surfaceDamage), buffer, size);
+}
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If the return value is `true` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+bool wrapAs(
+        HGraphicBufferProducer::QueueBufferInput* t,
+        native_handle_t** nh,
+        BGraphicBufferProducer::QueueBufferInput const& l) {
+
+    size_t const baseSize = l.getFlattenedSize();
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    size_t const baseNumFds = l.getFdCount();
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = baseFds.get();
+    size_t numFds = baseNumFds;
+    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
+ * `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If `t.fence` has a valid file descriptor, it will be duplicated.
+ */
+bool convertTo(
+        BGraphicBufferProducer::QueueBufferInput* l,
+        HGraphicBufferProducer::QueueBufferInput const& t) {
+
+    size_t const baseSize = getFlattenedSize(t);
+    std::unique_ptr<uint8_t[]> baseBuffer(
+            new (std::nothrow) uint8_t[baseSize]);
+    if (!baseBuffer) {
+        return false;
+    }
+
+    size_t const baseNumFds = getFdCount(t);
+    std::unique_ptr<int[]> baseFds(
+            new (std::nothrow) int[baseNumFds]);
+    if (!baseFds) {
+        return false;
+    }
+
+    void* buffer = static_cast<void*>(baseBuffer.get());
+    size_t size = baseSize;
+    int* fds = baseFds.get();
+    size_t numFds = baseNumFds;
+    native_handle_t* nh;
+    if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
+        return false;
+    }
+
+    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
+    size = baseSize;
+    int const* constFds = static_cast<int const*>(baseFds.get());
+    numFds = baseNumFds;
+    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
+        if (nh != nullptr) {
+            native_handle_close(nh);
+            native_handle_delete(nh);
+        }
+        return false;
+    }
+
+    native_handle_delete(nh);
+    return true;
+}
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+//      BGraphicBufferProducer::QueueBufferOutput
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+// wrap: BGraphicBufferProducer::QueueBufferOutput ->
+// HGraphicBufferProducer::QueueBufferOutput
+bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        BGraphicBufferProducer::QueueBufferOutput const& l) {
+    if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
+        return false;
+    }
+    t->width = l.width;
+    t->height = l.height;
+    t->transformHint = l.transformHint;
+    t->numPendingBuffers = l.numPendingBuffers;
+    t->nextFrameNumber = l.nextFrameNumber;
+    t->bufferReplaced = l.bufferReplaced;
+    return true;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
+ * `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+// convert: HGraphicBufferProducer::QueueBufferOutput ->
+// BGraphicBufferProducer::QueueBufferOutput
+bool convertTo(
+        BGraphicBufferProducer::QueueBufferOutput* l,
+        HGraphicBufferProducer::QueueBufferOutput const& t) {
+    if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
+        return false;
+    }
+    l->width = t.width;
+    l->height = t.height;
+    l->transformHint = t.transformHint;
+    l->numPendingBuffers = t.numPendingBuffers;
+    l->nextFrameNumber = t.nextFrameNumber;
+    l->bufferReplaced = t.bufferReplaced;
+    return true;
+}
+
+/**
+ * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
+ * `HGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
+ */
+HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
+        BGraphicBufferProducer::DisconnectMode l) {
+    switch (l) {
+        case BGraphicBufferProducer::DisconnectMode::Api:
+            return HGraphicBufferProducer::DisconnectMode::API;
+        case BGraphicBufferProducer::DisconnectMode::AllLocal:
+            return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
+    }
+    return HGraphicBufferProducer::DisconnectMode::API;
+}
+
+/**
+ * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
+ * `BGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
+ */
+BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
+        HGraphicBufferProducer::DisconnectMode t) {
+    switch (t) {
+        case HGraphicBufferProducer::DisconnectMode::API:
+            return BGraphicBufferProducer::DisconnectMode::Api;
+        case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
+            return BGraphicBufferProducer::DisconnectMode::AllLocal;
+    }
+    return BGraphicBufferProducer::DisconnectMode::Api;
+}
+
+}  // namespace conversion
+}  // namespace android
+
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index e64ba9b..cee1b81 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -1061,7 +1061,7 @@
 
 status_t H2BGraphicBufferProducer::attachBuffer(
         int* outSlot, const sp<GraphicBuffer>& buffer) {
-    AnwBuffer tBuffer;
+    AnwBuffer tBuffer{};
     wrapAs(&tBuffer, *buffer);
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->attachBuffer(tBuffer,
@@ -1076,7 +1076,7 @@
         int slot,
         const QueueBufferInput& input,
         QueueBufferOutput* output) {
-    HGraphicBufferProducer::QueueBufferInput tInput;
+    HGraphicBufferProducer::QueueBufferInput tInput{};
     native_handle_t* nh;
     if (!wrapAs(&tInput, &nh, input)) {
         ALOGE("H2BGraphicBufferProducer::queueBuffer - "
diff --git a/libs/gui/bufferqueue/1.0/WProducerListener.cpp b/libs/gui/bufferqueue/1.0/WProducerListener.cpp
new file mode 100644
index 0000000..78dc4e8
--- /dev/null
+++ b/libs/gui/bufferqueue/1.0/WProducerListener.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/bufferqueue/1.0/WProducerListener.h>
+
+namespace android {
+
+// TWProducerListener
+TWProducerListener::TWProducerListener(
+        sp<BProducerListener> const& base):
+    mBase(base) {
+}
+
+Return<void> TWProducerListener::onBufferReleased() {
+    mBase->onBufferReleased();
+    return Void();
+}
+
+Return<bool> TWProducerListener::needsReleaseNotify() {
+    return mBase->needsReleaseNotify();
+}
+
+// LWProducerListener
+LWProducerListener::LWProducerListener(
+        sp<HProducerListener> const& base):
+    mBase(base) {
+}
+
+void LWProducerListener::onBufferReleased() {
+    mBase->onBufferReleased();
+}
+
+bool LWProducerListener::needsReleaseNotify() {
+    return static_cast<bool>(mBase->needsReleaseNotify());
+}
+
+}  // namespace android
diff --git a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
index e039593..e891ec5 100644
--- a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "H2BGraphicBufferProducer@2.0"
+#define LOG_TAG "B2HGraphicBufferProducer@2.0"
 
 #include <android-base/logging.h>
 
@@ -30,13 +30,38 @@
 #include <vndk/hardware_buffer.h>
 
 namespace android {
-
 namespace hardware {
 namespace graphics {
 namespace bufferqueue {
 namespace V2_0 {
 namespace utils {
 
+namespace /* unnamed */ {
+
+using BQueueBufferInput = ::android::
+        IGraphicBufferProducer::QueueBufferInput;
+using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferInput;
+using BQueueBufferOutput = ::android::
+        IGraphicBufferProducer::QueueBufferOutput;
+using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferOutput;
+
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
+
+bool b2h(BQueueBufferOutput const& from, HQueueBufferOutput* to) {
+    to->width = from.width;
+    to->height = from.height;
+    to->transformHint = static_cast<int32_t>(from.transformHint);
+    to->numPendingBuffers = from.numPendingBuffers;
+    to->nextFrameNumber = from.nextFrameNumber;
+    to->bufferReplaced = from.bufferReplaced;
+    return true;
+}
+
+} // unnamed namespace
+
 // B2HGraphicBufferProducer
 // ========================
 
@@ -161,11 +186,7 @@
         int32_t slot,
         QueueBufferInput const& hInput,
         queueBuffer_cb _hidl_cb) {
-    using HOutput = QueueBufferOutput;
-    using BInput = BGraphicBufferProducer::QueueBufferInput;
-    using BOutput = BGraphicBufferProducer::QueueBufferOutput;
-
-    BInput bInput{
+    BQueueBufferInput bInput{
             hInput.timestamp,
             hInput.isAutoTimestamp,
             static_cast<android_dataspace>(hInput.dataSpace),
@@ -178,35 +199,32 @@
 
     // Convert crop.
     if (!h2b(hInput.crop, &bInput.crop)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
     // Convert surfaceDamage.
     if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
     // Convert fence.
     if (!h2b(hInput.fence, &bInput.fence)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
 
-    BOutput bOutput{};
+    BQueueBufferOutput bOutput{};
     HStatus hStatus{};
-    bool converted = b2h(
-            mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
-            &hStatus);
+    QueueBufferOutput hOutput{};
+    bool converted =
+            b2h(
+                mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
+                &hStatus) &&
+            b2h(bOutput, &hOutput);
 
-    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
-             HOutput{bOutput.width,
-                     bOutput.height,
-                     static_cast<int32_t>(bOutput.transformHint),
-                     bOutput.numPendingBuffers,
-                     bOutput.nextFrameNumber,
-                     bOutput.bufferReplaced});
+    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
     return {};
 }
 
@@ -236,33 +254,23 @@
         HConnectionType hConnectionType,
         bool producerControlledByApp,
         connect_cb _hidl_cb) {
-    using BOutput = BGraphicBufferProducer::QueueBufferOutput;
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     sp<BProducerListener> bListener = new H2BProducerListener(hListener);
-    if (!bListener) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
+    int bConnectionType{};
+    if (!bListener || !h2b(hConnectionType, &bConnectionType)) {
+        _hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
         return {};
     }
-    int bConnectionType;
-    if (!h2b(hConnectionType, &bConnectionType)) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, HOutput{});
-        return {};
-    }
-    BOutput bOutput{};
+    BQueueBufferOutput bOutput{};
     HStatus hStatus{};
-    bool converted = b2h(
-            mBase->connect(bListener,
-                           bConnectionType,
-                           producerControlledByApp,
-                           &bOutput),
-            &hStatus);
-    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
-             HOutput{bOutput.width,
-                     bOutput.height,
-                     static_cast<int32_t>(bOutput.transformHint),
-                     bOutput.numPendingBuffers,
-                     bOutput.nextFrameNumber,
-                     bOutput.bufferReplaced});
+    QueueBufferOutput hOutput{};
+    bool converted =
+            b2h(mBase->connect(bListener,
+                               bConnectionType,
+                               producerControlledByApp,
+                               &bOutput),
+                &hStatus) &&
+            b2h(bOutput, &hOutput);
+    _hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
     return {};
 }
 
diff --git a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
index 1023ef1..2f5b73c 100644
--- a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
@@ -29,13 +29,54 @@
 #include <vndk/hardware_buffer.h>
 
 namespace android {
-
 namespace hardware {
 namespace graphics {
 namespace bufferqueue {
 namespace V2_0 {
 namespace utils {
 
+namespace /* unnamed */ {
+
+using BQueueBufferInput = ::android::
+        IGraphicBufferProducer::QueueBufferInput;
+using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferInput;
+using BQueueBufferOutput = ::android::
+        IGraphicBufferProducer::QueueBufferOutput;
+using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
+        IGraphicBufferProducer::QueueBufferOutput;
+
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
+
+bool b2h(BQueueBufferInput const& from, HQueueBufferInput* to,
+         HFenceWrapper* hFenceWrapper) {
+    to->timestamp = from.timestamp;
+    to->isAutoTimestamp = static_cast<bool>(from.isAutoTimestamp);
+    to->dataSpace = static_cast<int32_t>(from.dataSpace);
+    to->transform = static_cast<int32_t>(from.transform);
+    to->stickyTransform = static_cast<int32_t>(from.stickyTransform);
+    if (!b2h(from.crop, &to->crop) ||
+            !b2h(from.surfaceDamage, &to->surfaceDamage) ||
+            !b2h(from.fence, hFenceWrapper)) {
+        return false;
+    }
+    to->fence = hFenceWrapper->getHandle();
+    return true;
+}
+
+bool h2b(HQueueBufferOutput const& from, BQueueBufferOutput* to) {
+    to->width = from.width;
+    to->height = from.height;
+    to->transformHint = static_cast<uint32_t>(from.transformHint);
+    to->numPendingBuffers = from.numPendingBuffers;
+    to->nextFrameNumber = from.nextFrameNumber;
+    to->bufferReplaced = from.bufferReplaced;
+    return true;
+}
+
+} // unnamed namespace
+
 // H2BGraphicBufferProducer
 // ========================
 
@@ -209,47 +250,13 @@
         int slot,
         QueueBufferInput const& input,
         QueueBufferOutput* output) {
-    HRect hCrop{};
-    (void)b2h(input.crop, &hCrop);
-
-    using HInput = HGraphicBufferProducer::QueueBufferInput;
-    HInput hInput{
-            input.timestamp,
-            static_cast<bool>(input.isAutoTimestamp),
-            static_cast<int32_t>(input.dataSpace),
-            {}, // crop
-            static_cast<int32_t>(input.transform),
-            static_cast<int32_t>(input.stickyTransform),
-            {}, // fence
-            {}  // surfaceDamage
-            };
-
-    // Convert crop.
-    if (!b2h(input.crop, &hInput.crop)) {
-        LOG(ERROR) << "queueBuffer: corrupted input crop rectangle.";
-        return UNKNOWN_ERROR;
-    }
-
-    // Convert surfaceDamage.
-    size_t numRects;
-    Rect const* rectArray = input.surfaceDamage.getArray(&numRects);
-    hInput.surfaceDamage.resize(numRects);
-    for (size_t i = 0; i < numRects; ++i) {
-        if (!b2h(rectArray[i], &hInput.surfaceDamage[i])) {
-            LOG(ERROR) << "queueBuffer: corrupted input surface damage.";
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    // Convert fence.
+    HQueueBufferInput hInput{};
     HFenceWrapper hFenceWrapper;
-    if (!b2h(input.fence, &hFenceWrapper)) {
-        LOG(ERROR) << "queueBuffer: corrupted input fence.";
+    if (!b2h(input, &hInput, &hFenceWrapper)) {
+        LOG(ERROR) << "queueBuffer: corrupted input.";
         return UNKNOWN_ERROR;
     }
-    hInput.fence = hFenceWrapper.getHandle();
 
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     bool converted{};
     status_t bStatus{};
     Return<void> transResult = mBase->queueBuffer(
@@ -257,15 +264,8 @@
             hInput,
             [&converted, &bStatus, output](
                     HStatus hStatus,
-                    HOutput const& hOutput) {
-                converted = h2b(hStatus, &bStatus);
-                output->width = hOutput.width;
-                output->height = hOutput.height;
-                output->transformHint =
-                        static_cast<uint32_t>(hOutput.transformHint);
-                output->numPendingBuffers = hOutput.numPendingBuffers;
-                output->nextFrameNumber = hOutput.nextFrameNumber;
-                output->bufferReplaced = hOutput.bufferReplaced;
+                    HQueueBufferOutput const& hOutput) {
+                converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
             });
 
     if (!transResult.isOk()) {
@@ -332,7 +332,6 @@
         }
     }
 
-    using HOutput = HGraphicBufferProducer::QueueBufferOutput;
     bool converted{};
     status_t bStatus{};
     Return<void> transResult = mBase->connect(
@@ -341,15 +340,8 @@
             producerControlledByApp,
             [&converted, &bStatus, output](
                     HStatus hStatus,
-                    HOutput hOutput) {
-                converted = h2b(hStatus, &bStatus);
-                output->width = hOutput.width;
-                output->height = hOutput.height;
-                output->transformHint =
-                        static_cast<uint32_t>(hOutput.transformHint);
-                output->numPendingBuffers = hOutput.numPendingBuffers;
-                output->nextFrameNumber = hOutput.nextFrameNumber;
-                output->bufferReplaced = hOutput.bufferReplaced;
+                    HQueueBufferOutput const& hOutput) {
+                converted = h2b(hStatus, &bStatus) && h2b(hOutput, output);
             });
     if (!transResult.isOk()) {
         LOG(ERROR) << "connect: transaction failed.";
diff --git a/libs/gui/bufferqueue/2.0/types.cpp b/libs/gui/bufferqueue/2.0/types.cpp
index a110517..cbd6cad 100644
--- a/libs/gui/bufferqueue/2.0/types.cpp
+++ b/libs/gui/bufferqueue/2.0/types.cpp
@@ -289,6 +289,7 @@
         return false;
     }
     *to = GraphicBuffer::fromAHardwareBuffer(hwBuffer);
+    AHardwareBuffer_release(hwBuffer);
     return true;
 }
 
diff --git a/libs/gui/bufferqueue/OWNERS b/libs/gui/bufferqueue/OWNERS
new file mode 100644
index 0000000..cbe9317
--- /dev/null
+++ b/libs/gui/bufferqueue/OWNERS
@@ -0,0 +1,5 @@
+chz@google.com
+lajos@google.com
+pawin@google.com
+taklee@google.com
+wonsik@google.com
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index 721427b..da95274 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -61,7 +61,6 @@
         void onDisconnect() override;
         void onFrameAvailable(const BufferItem& item) override;
         void onFrameReplaced(const BufferItem& item) override;
-        void onBufferAllocated(const BufferItem& item) override;
         void onBuffersReleased() override;
         void onSidebandStreamChanged() override;
         void addAndGetFrameTimestamps(
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index aa13c0c..7db69ec 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -171,6 +171,9 @@
 
     // End functions required for backwards compatibility
 
+    // Value used to determine if present time is valid.
+    constexpr static int MAX_REASONABLE_NSEC = 1'000'000'000ULL; // 1 second
+
 private:
     sp<BufferQueueCore> mCore;
 
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index b377a41..205e79c 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -22,8 +22,6 @@
 #include <gui/BufferSlot.h>
 #include <gui/OccupancyTracker.h>
 
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
 #include <utils/NativeHandle.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
@@ -33,6 +31,8 @@
 
 #include <list>
 #include <set>
+#include <mutex>
+#include <condition_variable>
 
 #define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
 #define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
@@ -134,7 +134,7 @@
     bool adjustAvailableSlotsLocked(int delta);
 
     // waitWhileAllocatingLocked blocks until mIsAllocating is false.
-    void waitWhileAllocatingLocked() const;
+    void waitWhileAllocatingLocked(std::unique_lock<std::mutex>& lock) const;
 
 #if DEBUG_ONLY_CODE
     // validateConsistencyLocked ensures that the free lists are in sync with
@@ -145,7 +145,7 @@
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of BufferQueueCore objects. It must be locked whenever any
     // member variable is accessed.
-    mutable Mutex mMutex;
+    mutable std::mutex mMutex;
 
     // mIsAbandoned indicates that the BufferQueue will no longer be used to
     // consume image buffers pushed to it using the IGraphicBufferProducer
@@ -219,13 +219,24 @@
 
     // mDequeueCondition is a condition variable used for dequeueBuffer in
     // synchronous mode.
-    mutable Condition mDequeueCondition;
+    mutable std::condition_variable mDequeueCondition;
 
     // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
     // block. This flag is set during connect when both the producer and
     // consumer are controlled by the application.
     bool mDequeueBufferCannotBlock;
 
+    // mQueueBufferCanDrop indicates whether queueBuffer is allowed to drop
+    // buffers in non-async mode. This flag is set during connect when both the
+    // producer and consumer are controlled by application.
+    bool mQueueBufferCanDrop;
+
+    // mLegacyBufferDrop indicates whether mQueueBufferCanDrop is in effect.
+    // If this flag is set mQueueBufferCanDrop is working as explained. If not
+    // queueBuffer will not drop buffers unless consumer is SurfaceFlinger and
+    // mQueueBufferCanDrop is set.
+    bool mLegacyBufferDrop;
+
     // mDefaultBufferFormat can be set so it will override the buffer format
     // when it isn't specified in dequeueBuffer.
     PixelFormat mDefaultBufferFormat;
@@ -282,7 +293,7 @@
 
     // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
     // becomes false.
-    mutable Condition mIsAllocatingCondition;
+    mutable std::condition_variable mIsAllocatingCondition;
 
     // mAllowAllocation determines whether dequeueBuffer is allowed to allocate
     // new buffers
@@ -337,6 +348,14 @@
 
     const uint64_t mUniqueId;
 
+    // When buffer size is driven by the consumer and mTransformHint specifies
+    // a 90 or 270 degree rotation, this indicates whether the width and height
+    // used by dequeueBuffer will be additionally swapped.
+    bool mAutoPrerotation;
+
+    // mTransformHintInUse is to cache the mTransformHint used by the producer.
+    uint32_t mTransformHintInUse;
+
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 73bc5dd..9ad92a6 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -174,6 +174,9 @@
     // See IGraphicBufferProducer::setDequeueTimeout
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
 
+    // see IGraphicBufferProducer::setLegacyBufferDrop
+    virtual status_t setLegacyBufferDrop(bool drop);
+
     // See IGraphicBufferProducer::getLastQueuedBuffer
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
@@ -187,6 +190,9 @@
     // See IGraphicBufferProducer::getConsumerUsage
     virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
 
+    // See IGraphicBufferProducer::setAutoPrerotation
+    virtual status_t setAutoPrerotation(bool autoPrerotation);
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
@@ -211,7 +217,8 @@
         Dequeue,
         Attach,
     };
-    status_t waitForFreeSlotThenRelock(FreeSlotCaller caller, int* found) const;
+    status_t waitForFreeSlotThenRelock(FreeSlotCaller caller, std::unique_lock<std::mutex>& lock,
+            int* found) const;
 
     sp<BufferQueueCore> mCore;
 
@@ -243,15 +250,22 @@
     // (mCore->mMutex) is held, a ticket is retained by the producer. After
     // dropping the BufferQueue lock, the producer must wait on the condition
     // variable until the current callback ticket matches its retained ticket.
-    Mutex mCallbackMutex;
+    std::mutex mCallbackMutex;
     int mNextCallbackTicket; // Protected by mCore->mMutex
     int mCurrentCallbackTicket; // Protected by mCallbackMutex
-    Condition mCallbackCondition;
+    std::condition_variable mCallbackCondition;
 
     // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
     // slot is not yet available.
     nsecs_t mDequeueTimeout;
 
+    // If set to true, dequeueBuffer() is currently waiting for buffer allocation to complete.
+    bool mDequeueWaitingForAllocation;
+
+    // Condition variable to signal allocateBuffers() that dequeueBuffer() is no longer waiting for
+    // allocation to complete.
+    std::condition_variable mDequeueWaitingForAllocationCondition;
+
 }; // class BufferQueueProducer
 
 } // namespace android
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 7c26482..366ced3 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -141,7 +141,6 @@
     // classes if they want the notification.
     virtual void onFrameAvailable(const BufferItem& item) override;
     virtual void onFrameReplaced(const BufferItem& item) override;
-    virtual void onBufferAllocated(const BufferItem& item) override;
     virtual void onBuffersReleased() override;
     virtual void onSidebandStreamChanged() override;
 
diff --git a/libs/gui/include/gui/DebugEGLImageTracker.h b/libs/gui/include/gui/DebugEGLImageTracker.h
new file mode 100644
index 0000000..5d369c9
--- /dev/null
+++ b/libs/gui/include/gui/DebugEGLImageTracker.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 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 <atomic>
+#include <mutex>
+#include <string>
+
+class DebugEGLImageTracker {
+public:
+    static DebugEGLImageTracker *getInstance();
+
+    virtual void create(const char *from) = 0;
+    virtual void destroy(const char *from) = 0;
+
+    virtual void dump(std::string &result) = 0;
+
+protected:
+    DebugEGLImageTracker() = default;
+    virtual ~DebugEGLImageTracker() = default;
+    DebugEGLImageTracker(const DebugEGLImageTracker &) = delete;
+
+    static std::mutex mInstanceLock;
+    static std::atomic<DebugEGLImageTracker *> mInstance;
+};
+
+#define DEBUG_EGL_IMAGE_TRACKER_CREATE() \
+    (DebugEGLImageTracker::getInstance()->create(__PRETTY_FUNCTION__))
+#define DEBUG_EGL_IMAGE_TRACKER_DESTROY() \
+    (DebugEGLImageTracker::getInstance()->destroy(__PRETTY_FUNCTION__))
\ No newline at end of file
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 22de751..a558cf9 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -88,10 +88,13 @@
      * DisplayEventReceiver creates and registers an event connection with
      * SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
      * or requestNextVsync to receive them.
+     * To receive Config Changed events specify this in the constructor.
      * Other events start being delivered immediately.
      */
     explicit DisplayEventReceiver(
-            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
+            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress);
 
     /*
      * ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
index 03fefbe..c082882 100644
--- a/libs/gui/include/gui/IConsumerListener.h
+++ b/libs/gui/include/gui/IConsumerListener.h
@@ -61,13 +61,6 @@
     // This is called without any lock held and can be called concurrently by multiple threads.
     virtual void onFrameReplaced(const BufferItem& /* item */) {} /* Asynchronous */
 
-    // onBufferAllocated is called to notify the buffer consumer that the BufferQueue has allocated
-    // a GraphicBuffer for a particular slot. Only the GraphicBuffer pointer and the slot ID will
-    // be populated.
-    //
-    // This is called without any lock held and can be called concurrently by multiple threads.
-    virtual void onBufferAllocated(const BufferItem& /* item */) {} /* Asynchronous */
-
     // onBuffersReleased is called to notify the buffer consumer that the BufferQueue has released
     // its references to one or more GraphicBuffers contained in its slots. The buffer consumer
     // should then call BufferQueue::getReleasedBuffers to retrieve the list of buffers.
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 2f538ad..abe1e3f 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -25,6 +25,7 @@
 
 #include <binder/IInterface.h>
 
+#include <ui/BufferQueueDefs.h>
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
@@ -75,10 +76,10 @@
     enum {
         // A flag returned by dequeueBuffer when the client needs to call
         // requestBuffer immediately thereafter.
-        BUFFER_NEEDS_REALLOCATION = 0x1,
+        BUFFER_NEEDS_REALLOCATION = BufferQueueDefs::BUFFER_NEEDS_REALLOCATION,
         // A flag returned by dequeueBuffer when all mirrored slots should be
         // released by the client. This flag should always be processed first.
-        RELEASE_ALL_BUFFERS       = 0x2,
+        RELEASE_ALL_BUFFERS       = BufferQueueDefs::RELEASE_ALL_BUFFERS,
     };
 
     enum {
@@ -411,6 +412,7 @@
         uint64_t nextFrameNumber{0};
         FrameEventHistoryDelta frameTimestamps;
         bool bufferReplaced{false};
+        int maxBufferCount{0};
     };
 
     virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
@@ -591,12 +593,20 @@
     // non-blocking mode and its corresponding spare buffer (which is used to
     // ensure a buffer is always available).
     //
+    // Note well: queueBuffer will stop buffer dropping behavior if timeout is
+    // strictly positive. If timeout is zero or negative, previous buffer
+    // dropping behavior will not be changed.
+    //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * BAD_VALUE - Failure to adjust the number of available slots. This can
     //               happen because of trying to allocate/deallocate the async
     //               buffer.
     virtual status_t setDequeueTimeout(nsecs_t timeout) = 0;
 
+    // Used to enable/disable buffer drop behavior of queueBuffer.
+    // If it's not used, legacy drop behavior will be retained.
+    virtual status_t setLegacyBufferDrop(bool drop);
+
     // Returns the last queued buffer along with a fence which must signal
     // before the contents of the buffer are read. If there are no buffers in
     // the queue, outBuffer will be populated with nullptr and outFence will be
@@ -620,6 +630,14 @@
     // NATIVE_WINDOW_CONSUMER_USAGE_BITS attribute.
     virtual status_t getConsumerUsage(uint64_t* outUsage) const = 0;
 
+    // Enable/disable the auto prerotation at buffer allocation when the buffer
+    // size is driven by the consumer.
+    //
+    // When buffer size is driven by the consumer and the transform hint
+    // specifies a 90 or 270 degree rotation, if auto prerotation is enabled,
+    // the width and height used for dequeueBuffer will be additionally swapped.
+    virtual status_t setAutoPrerotation(bool autoPrerotation);
+
     // Static method exports any IGraphicBufferProducer object to a parcel. It
     // handles null producer as well.
     static status_t exportToParcel(const sp<IGraphicBufferProducer>& producer,
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index fe85fdf..c84910b 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <binder/IBinder.h>
 #include <binder/IInterface.h>
 
 #include <gui/ITransactionCompletedListener.h>
@@ -37,12 +38,13 @@
 #include <utils/Vector.h>
 
 #include <optional>
+#include <unordered_set>
 #include <vector>
 
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct cached_buffer_t;
+struct client_cache_t;
 struct ComposerState;
 struct DisplayState;
 struct DisplayInfo;
@@ -88,6 +90,8 @@
         eVsyncSourceSurfaceFlinger = 1
     };
 
+    enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };
+
     /*
      * Create a connection with SurfaceFlinger.
      */
@@ -95,7 +99,8 @@
 
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            VsyncSource vsyncSource = eVsyncSourceApp) = 0;
+            VsyncSource vsyncSource = eVsyncSourceApp,
+            ConfigChanged configChanged = eConfigChangedSuppress) = 0;
 
     /* create a virtual display
      * requires ACCESS_SURFACE_FLINGER permission.
@@ -135,7 +140,7 @@
                                      const sp<IBinder>& applyToken,
                                      const InputWindowCommands& inputWindowCommands,
                                      int64_t desiredPresentTime,
-                                     const cached_buffer_t& uncacheBuffer,
+                                     const client_cache_t& uncacheBuffer,
                                      const std::vector<ListenerCallbacks>& listenerCallbacks) = 0;
 
     /* signal that we're done booting.
@@ -210,7 +215,7 @@
      * it) around its center.
      */
     virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
+                                   bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace,
                                    const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                    uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
                                    Rotation rotation = eRotateNone,
@@ -239,10 +244,20 @@
     virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
                                    Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
                                    bool useIdentityTransform, Rotation rotation = eRotateNone) {
-        return captureScreen(display, outBuffer, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
-                             sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation);
+        bool outIgnored;
+        return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB,
+                             ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight,
+                             useIdentityTransform, rotation);
     }
 
+    virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                                   sp<GraphicBuffer>* outBuffer) = 0;
+
+    template <class AA>
+    struct SpHash {
+        size_t operator()(const sp<AA>& k) const { return std::hash<AA*>()(k.get()); }
+    };
+
     /**
      * Capture a subtree of the layer hierarchy, potentially ignoring the root node.
      *
@@ -250,10 +265,12 @@
      * of the buffer. The caller should pick the data space and pixel format
      * that it can consume.
      */
-    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
-                                   sp<GraphicBuffer>* outBuffer, const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
-                                   float frameScale = 1.0, bool childrenOnly = false) = 0;
+    virtual status_t captureLayers(
+            const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
+            const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+            const Rect& sourceCrop,
+            const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& excludeHandles,
+            float frameScale = 1.0, bool childrenOnly = false) = 0;
 
     /**
      * Capture a subtree of the layer hierarchy into an sRGB buffer with RGBA_8888 pixel format,
@@ -263,7 +280,7 @@
                            const Rect& sourceCrop, float frameScale = 1.0,
                            bool childrenOnly = false) {
         return captureLayers(layerHandleBinder, outBuffer, ui::Dataspace::V0_SRGB,
-                             ui::PixelFormat::RGBA_8888, sourceCrop, frameScale, childrenOnly);
+                             ui::PixelFormat::RGBA_8888, sourceCrop, {}, frameScale, childrenOnly);
     }
 
     /* Clears the frame statistics for animations.
@@ -411,6 +428,16 @@
      */
     virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken,
                                           float brightness) const = 0;
+
+    /*
+     * Sends a power hint to the composer. This function is asynchronous.
+     *
+     * hintId
+     *      hint id according to android::hardware::power::V1_0::PowerHint
+     *
+     * Returns NO_ERROR upon success.
+     */
+    virtual status_t notifyPowerHint(int32_t hintId) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -462,6 +489,8 @@
         GET_ALLOWED_DISPLAY_CONFIGS,
         GET_DISPLAY_BRIGHTNESS_SUPPORT,
         SET_DISPLAY_BRIGHTNESS,
+        CAPTURE_SCREEN_BY_ID,
+        NOTIFY_POWER_HINT,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 774ad46..cbfd365 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -106,6 +106,16 @@
                       const std::vector<CallbackId>& ids)
           : transactionCompletedListener(listener), callbackIds(ids) {}
 
+    bool operator==(const ListenerCallbacks& rhs) const {
+        if (transactionCompletedListener != rhs.transactionCompletedListener) {
+            return false;
+        }
+        if (callbackIds.empty()) {
+            return rhs.callbackIds.empty();
+        }
+        return callbackIds.front() == rhs.callbackIds.front();
+    }
+
     sp<ITransactionCompletedListener> transactionCompletedListener;
     std::vector<CallbackId> callbackIds;
 };
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 2256497..f438eb3 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -40,9 +40,13 @@
 class Parcel;
 class ISurfaceComposerClient;
 
-struct cached_buffer_t {
-    sp<IBinder> token = nullptr;
-    uint64_t cacheId;
+struct client_cache_t {
+    wp<IBinder> token = nullptr;
+    uint64_t id;
+
+    bool operator==(const client_cache_t& other) const { return id == other.id; }
+
+    bool isValid() const { return token != nullptr; }
 };
 
 /*
@@ -187,7 +191,7 @@
     InputWindowInfo inputInfo;
 #endif
 
-    cached_buffer_t cachedBuffer;
+    client_cache_t cachedBuffer;
 
     LayerMetadata metadata;
 
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 248e105..fe528b3 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -230,6 +230,8 @@
     int dispatchGetWideColorSupport(va_list args);
     int dispatchGetHdrSupport(va_list args);
     int dispatchGetConsumerUsage64(va_list args);
+    int dispatchSetAutoPrerotation(va_list args);
+    bool transformToDisplayInverse();
 
 protected:
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
@@ -264,6 +266,7 @@
     virtual int setAsyncMode(bool async);
     virtual int setSharedBufferMode(bool sharedBufferMode);
     virtual int setAutoRefresh(bool autoRefresh);
+    virtual int setAutoPrerotation(bool autoPrerotation);
     virtual int setBuffersDimensions(uint32_t width, uint32_t height);
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
@@ -291,7 +294,8 @@
 
     ui::Dataspace getBuffersDataSpace();
 
-    static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
+    static status_t attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer,
+                                                      ui::Dataspace dataspace);
 
 protected:
     enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
@@ -432,6 +436,7 @@
     // Caches the values that have been passed to the producer.
     bool mSharedBufferMode;
     bool mAutoRefresh;
+    bool mAutoPrerotation;
 
     // If in shared buffer mode and auto refresh is enabled, store the shared
     // buffer slot and return it for all calls to queue/dequeue without going
@@ -464,6 +469,7 @@
 
     bool mReportRemovedBuffers = false;
     std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+    int mMaxBufferCount;
 };
 
 } // namespace android
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 593a5e7..4dda97f 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -37,6 +37,7 @@
 #include <ui/PixelFormat.h>
 
 #include <gui/CpuConsumer.h>
+#include <gui/ISurfaceComposer.h>
 #include <gui/ITransactionCompletedListener.h>
 #include <gui/LayerState.h>
 #include <gui/SurfaceControl.h>
@@ -200,6 +201,16 @@
      */
     static status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness);
 
+    /*
+     * Sends a power hint to the composer. This function is asynchronous.
+     *
+     * hintId
+     *      hint id according to android::hardware::power::V1_0::PowerHint
+     *
+     * Returns NO_ERROR upon success.
+     */
+    static status_t notifyPowerHint(int32_t hintId);
+
     // ------------------------------------------------------------------------
     // surface creation / destruction
 
@@ -274,7 +285,7 @@
         std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls;
     };
 
-    class Transaction {
+    class Transaction : Parcelable {
         std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates;
         SortedVector<DisplayState > mDisplayStates;
         std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
@@ -314,6 +325,15 @@
         virtual ~Transaction() = default;
         Transaction(Transaction const& other);
 
+        // Factory method that creates a new Transaction instance from the parcel.
+        static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel);
+
+        status_t writeToParcel(Parcel* parcel) const override;
+        status_t readFromParcel(const Parcel* parcel) override;
+
+        // Clears the contents of the transaction without applying it.
+        void clear();
+
         status_t apply(bool synchronous = false);
         // Merge another transaction in to this one, clearing other
         // as if it had been applied.
@@ -508,18 +528,23 @@
     static status_t capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
                             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                             uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
-                            uint32_t rotation, bool captureSecureLayers, sp<GraphicBuffer>* outBuffer);
+                            uint32_t rotation, bool captureSecureLayers,
+                            sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers);
     static status_t capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
                             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                             uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
                             uint32_t rotation, sp<GraphicBuffer>* outBuffer);
+    static status_t capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                            sp<GraphicBuffer>* outBuffer);
     static status_t captureLayers(const sp<IBinder>& layerHandle, const ui::Dataspace reqDataSpace,
                                   const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                   float frameScale, sp<GraphicBuffer>* outBuffer);
-    static status_t captureChildLayers(const sp<IBinder>& layerHandle,
-                                       const ui::Dataspace reqDataSpace,
-                                       const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
-                                       float frameScale, sp<GraphicBuffer>* outBuffer);
+    static status_t captureChildLayers(
+            const sp<IBinder>& layerHandle, const ui::Dataspace reqDataSpace,
+            const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
+            const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>&
+                    excludeHandles,
+            float frameScale, sp<GraphicBuffer>* outBuffer);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 55efcbf..ae4a146 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -44,7 +44,7 @@
 class SurfaceControl : public RefBase
 {
 public:
-    static sp<SurfaceControl> readFromParcel(Parcel* parcel);
+    static sp<SurfaceControl> readFromParcel(const Parcel* parcel);
     void writeToParcel(Parcel* parcel);
 
     static bool isValid(const sp<SurfaceControl>& surface) {
@@ -81,9 +81,12 @@
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
     sp<SurfaceComposerClient> getClient() const;
-    
+
     explicit SurfaceControl(const sp<SurfaceControl>& other);
 
+    SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
+                   const sp<IGraphicBufferProducer>& gbp, bool owned);
+
 private:
     // can't be copied
     SurfaceControl& operator = (SurfaceControl& rhs);
@@ -92,12 +95,6 @@
     friend class SurfaceComposerClient;
     friend class Surface;
 
-    SurfaceControl(
-            const sp<SurfaceComposerClient>& client,
-            const sp<IBinder>& handle,
-            const sp<IGraphicBufferProducer>& gbp,
-            bool owned);
-
     ~SurfaceControl();
 
     sp<Surface> generateSurfaceLocked() const;
diff --git a/libs/gui/include/gui/bufferqueue/1.0/Conversion.h b/libs/gui/include/gui/bufferqueue/1.0/Conversion.h
new file mode 100644
index 0000000..627845c
--- /dev/null
+++ b/libs/gui/include/gui/bufferqueue/1.0/Conversion.h
@@ -0,0 +1,765 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_CONVERSION_H_
+#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_CONVERSION_H_
+
+#include <vector>
+#include <list>
+
+#include <unistd.h>
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <binder/Binder.h>
+#include <binder/Status.h>
+#include <ui/FenceTime.h>
+#include <cutils/native_handle.h>
+#include <gui/IGraphicBufferProducer.h>
+
+#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
+
+namespace android {
+namespace conversion {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::status_t;
+
+using ::android::String8;
+
+using ::android::hardware::media::V1_0::Rect;
+using ::android::hardware::media::V1_0::Region;
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+
+using ::android::hardware::media::V1_0::AnwBuffer;
+using ::android::GraphicBuffer;
+
+typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
+        HGraphicBufferProducer;
+typedef ::android::IGraphicBufferProducer
+        BGraphicBufferProducer;
+
+// native_handle_t helper functions.
+
+/**
+ * \brief Take an fd and create a native handle containing only the given fd.
+ * The created handle will need to be deleted manually with
+ * `native_handle_delete()`.
+ *
+ * \param[in] fd The source file descriptor (of type `int`).
+ * \return The create `native_handle_t*` that contains the given \p fd. If the
+ * supplied \p fd is negative, the created native handle will contain no file
+ * descriptors.
+ *
+ * If the native handle cannot be created, the return value will be
+ * `nullptr`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+native_handle_t* native_handle_create_from_fd(int fd);
+
+/**
+ * \brief Extract a file descriptor from a native handle.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \param[in] index The index of the file descriptor in \p nh to read from. This
+ * input has the default value of `0`.
+ * \return The `index`-th file descriptor in \p nh. If \p nh does not have
+ * enough file descriptors, the returned value will be `-1`.
+ *
+ * This function does not duplicate the file descriptor.
+ */
+int native_handle_read_fd(native_handle_t const* nh, int index = 0);
+
+/**
+ * Conversion functions
+ * ====================
+ *
+ * There are two main directions of conversion:
+ * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
+ *   input. The wrapper has type `TargetType`.
+ * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
+ *   corresponds to the input. The lifetime of the output does not depend on the
+ *   lifetime of the input.
+ * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
+ *   that cannot be copied and/or moved efficiently, or when there are multiple
+ *   output arguments.
+ * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
+ *   `TargetType` that cannot be copied and/or moved efficiently, or when there
+ *   are multiple output arguments.
+ *
+ * `wrapIn()` and `convertTo()` functions will take output arguments before
+ * input arguments. Some of these functions might return a value to indicate
+ * success or error.
+ *
+ * In converting or wrapping something as a Treble type that contains a
+ * `hidl_handle`, `native_handle_t*` will need to be created and returned as
+ * an additional output argument, hence only `wrapIn()` or `convertTo()` would
+ * be available. The caller must call `native_handle_delete()` to deallocate the
+ * returned native handle when it is no longer needed.
+ *
+ * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
+ * not perform duplication of file descriptors, while `toTargetType()` and
+ * `convertTo()` do.
+ */
+
+/**
+ * \brief Convert `Return<void>` to `binder::Status`.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: Return<void> -> ::android::binder::Status
+::android::binder::Status toBinderStatus(Return<void> const& t);
+
+/**
+ * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `status_t`.
+ */
+// convert: Return<void> -> status_t
+status_t toStatusT(Return<void> const& t);
+
+/**
+ * \brief Wrap `native_handle_t*` in `hidl_handle`.
+ *
+ * \param[in] nh The source `native_handle_t*`.
+ * \return The `hidl_handle` that points to \p nh.
+ */
+// wrap: native_handle_t* -> hidl_handle
+hidl_handle inHidlHandle(native_handle_t const* nh);
+
+/**
+ * \brief Convert `int32_t` to `Dataspace`.
+ *
+ * \param[in] l The source `int32_t`.
+ * \result The corresponding `Dataspace`.
+ */
+// convert: int32_t -> Dataspace
+Dataspace toHardwareDataspace(int32_t l);
+
+/**
+ * \brief Convert `Dataspace` to `int32_t`.
+ *
+ * \param[in] t The source `Dataspace`.
+ * \result The corresponding `int32_t`.
+ */
+// convert: Dataspace -> int32_t
+int32_t toRawDataspace(Dataspace const& t);
+
+/**
+ * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that points to the buffer.
+ */
+// wrap: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size);
+
+/**
+ * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
+ *
+ * \param[in] l The pointer to the beginning of the opaque buffer.
+ * \param[in] size The size of the buffer.
+ * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
+ */
+// convert: void*, size_t -> hidl_vec<uint8_t>
+hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size);
+
+/**
+ * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
+ *
+ * \param[out] t The wrapper of type `AnwBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: GraphicBuffer -> AnwBuffer
+void wrapAs(AnwBuffer* t, GraphicBuffer const& l);
+
+/**
+ * \brief Convert `AnwBuffer` to `GraphicBuffer`.
+ *
+ * \param[out] l The destination `GraphicBuffer`.
+ * \param[in] t The source `AnwBuffer`.
+ *
+ * This function will duplicate all file descriptors in \p t.
+ */
+// convert: AnwBuffer -> GraphicBuffer
+// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
+bool convertTo(GraphicBuffer* l, AnwBuffer const& t);
+
+/**
+ * Conversion functions for types outside media
+ * ============================================
+ *
+ * Some objects in libui and libgui that were made to go through binder calls do
+ * not expose ways to read or write their fields to the public. To pass an
+ * object of this kind through the HIDL boundary, translation functions need to
+ * work around the access restriction by using the publicly available
+ * `flatten()` and `unflatten()` functions.
+ *
+ * All `flatten()` and `unflatten()` overloads follow the same convention as
+ * follows:
+ *
+ *     status_t flatten(ObjectType const& object,
+ *                      [OtherType const& other, ...]
+ *                      void*& buffer, size_t& size,
+ *                      int*& fds, size_t& numFds)
+ *
+ *     status_t unflatten(ObjectType* object,
+ *                        [OtherType* other, ...,]
+ *                        void*& buffer, size_t& size,
+ *                        int*& fds, size_t& numFds)
+ *
+ * The number of `other` parameters varies depending on the `ObjectType`. For
+ * example, in the process of unflattening an object that contains
+ * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
+ * be created.
+ *
+ * The last four parameters always work the same way in all overloads of
+ * `flatten()` and `unflatten()`:
+ * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
+ *   `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
+ *   `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
+ *   size (in ints) of the fd buffer pointed to by `fds`.
+ * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
+ *   from, `size` is the size (in bytes) of the non-fd buffer pointed to by
+ *   `buffer`, `fds` is the pointer to the fd buffer to be read from, and
+ *   `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
+ * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
+ *   will be advanced, while `size` and `numFds` will be decreased to reflect
+ *   how much storage/data of the two buffers (fd and non-fd) have been used.
+ * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
+ *   `numFds` are invalid.
+ *
+ * The return value of a successful `flatten()` or `unflatten()` call will be
+ * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
+ *
+ * For each object type that supports flattening, there will be two accompanying
+ * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
+ * return the size of the non-fd buffer that the object will need for
+ * flattening. `getFdCount()` will return the size of the fd buffer that the
+ * object will need for flattening.
+ *
+ * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
+ * `flatten()` and `unflatten()`, are similar to functions of the same name in
+ * the abstract class `Flattenable`. The only difference is that functions in
+ * this file are not member functions of the object type. For example, we write
+ *
+ *     flatten(x, buffer, size, fds, numFds)
+ *
+ * instead of
+ *
+ *     x.flatten(buffer, size, fds, numFds)
+ *
+ * because we cannot modify the type of `x`.
+ *
+ * There is one exception to the naming convention: `hidl_handle` that
+ * represents a fence. The four functions for this "Fence" type have the word
+ * "Fence" attched to their names because the object type, which is
+ * `hidl_handle`, does not carry the special meaning that the object itself can
+ * only contain zero or one file descriptor.
+ */
+
+// Ref: frameworks/native/libs/ui/Fence.cpp
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return The required size of the flat buffer.
+ *
+ * The current version of this function always returns 4, which is the number of
+ * bytes required to store the number of file descriptors contained in the fd
+ * part of the flat buffer.
+ */
+size_t getFenceFlattenedSize(hidl_handle const& fence);
+
+/**
+ * \brief Return the number of file descriptors contained in a fence.
+ *
+ * \param[in] fence The input fence of type `hidl_handle`.
+ * \return `0` if \p fence does not contain a valid file descriptor, or `1`
+ * otherwise.
+ */
+size_t getFenceFdCount(hidl_handle const& fence);
+
+/**
+ * \brief Unflatten `Fence` to `hidl_handle`.
+ *
+ * \param[out] fence The destination `hidl_handle`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will point to a newly created
+ * native handle, which needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
+
+/**
+ * \brief Flatten `hidl_handle` as `Fence`.
+ *
+ * \param[in] t The source `hidl_handle`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flattenFence(hidl_handle const& fence,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds);
+
+/**
+ * \brief Wrap `Fence` in `hidl_handle`.
+ *
+ * \param[out] t The wrapper of type `hidl_handle`.
+ * \param[out] nh The native handle pointed to by \p t.
+ * \param[in] l The source `Fence`.
+ *
+ * On success, \p nh will hold a newly created native handle, which must be
+ * deleted manually with `native_handle_delete()` afterwards.
+ */
+// wrap: Fence -> hidl_handle
+bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l);
+
+/**
+ * \brief Convert `hidl_handle` to `Fence`.
+ *
+ * \param[out] l The destination `Fence`. `l` must not have been used
+ * (`l->isValid()` must return `false`) before this function is called.
+ * \param[in] t The source `hidl_handle`.
+ *
+ * If \p t contains a valid file descriptor, it will be duplicated.
+ */
+// convert: hidl_handle -> Fence
+bool convertTo(Fence* l, hidl_handle const& t);
+
+// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(HGraphicBufferProducer::FenceTimeSnapshot const& t);
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FenceTimeSnapshot`.
+ *
+ * \param[in] t The input `FenceTimeSnapshot`.
+ * \return The number of file descriptors contained in \p snapshot.
+ */
+size_t getFdCount(HGraphicBufferProducer::FenceTimeSnapshot const& t);
+
+/**
+ * \brief Flatten `FenceTimeSnapshot`.
+ *
+ * \param[in] t The source `FenceTimeSnapshot`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence` if `t.state ==
+ * FENCE`.
+ */
+status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds);
+
+/**
+ * \brief Unflatten `FenceTimeSnapshot`.
+ *
+ * \param[out] t The destination `FenceTimeSnapshot`.
+ * \param[out] nh The underlying native handle.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and the constructed snapshot contains a
+ * file descriptor, \p nh will be created to hold that file descriptor. In this
+ * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(HGraphicBufferProducer::FrameEventsDelta const& t);
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `FrameEventsDelta`.
+ *
+ * \param[in] t The input `FrameEventsDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(HGraphicBufferProducer::FrameEventsDelta const& t);
+
+/**
+ * \brief Unflatten `FrameEventsDelta`.
+ *
+ * \param[out] t The destination `FrameEventsDelta`.
+ * \param[out] nh The underlying array of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
+ * populated with `nullptr` or newly created handles. Each non-null slot in \p
+ * nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
+        std::vector<native_handle_t*>* nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
+
+/**
+ * \brief Flatten `FrameEventsDelta`.
+ *
+ * \param[in] t The source `FrameEventsDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
+//      FrameEventsDelta::flatten
+status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
+        void*& buffer, size_t& size, int*& fds, size_t numFds);
+
+// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
+
+/**
+ * \brief Return the size of the non-fd buffer required to flatten
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t);
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t);
+
+/**
+ * \brief Unflatten `FrameEventHistoryDelta`.
+ *
+ * \param[out] t The destination `FrameEventHistoryDelta`.
+ * \param[out] nh The underlying array of arrays of native handles.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
+ * newly created handles. The second dimension of \p nh will be 4. Each non-null
+ * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::FrameEventHistoryDelta* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
+
+/**
+ * \brief Flatten `FrameEventHistoryDelta`.
+ *
+ * \param[in] t The source `FrameEventHistoryDelta`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate file descriptors contained in \p t.
+ */
+status_t flatten(
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds);
+
+/**
+ * \brief Wrap `::android::FrameEventHistoryData` in
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `::android::FrameEventHistoryDelta`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        ::android::FrameEventHistoryDelta const& l);
+
+/**
+ * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
+ * `::android::FrameEventHistoryDelta`.
+ *
+ * \param[out] l The destination `::android::FrameEventHistoryDelta`.
+ * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+bool convertTo(
+        ::android::FrameEventHistoryDelta* l,
+        HGraphicBufferProducer::FrameEventHistoryDelta const& t);
+
+// Ref: frameworks/native/libs/ui/Region.cpp
+
+/**
+ * \brief Return the size of the buffer required to flatten `Region`.
+ *
+ * \param[in] t The input `Region`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(Region const& t);
+
+/**
+ * \brief Unflatten `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t unflatten(Region* t, void const*& buffer, size_t& size);
+
+/**
+ * \brief Flatten `Region`.
+ *
+ * \param[in] t The source `Region`.
+ * \param[in,out] buffer The pointer to the flat buffer.
+ * \param[in,out] size The size of the flat buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ */
+status_t flatten(Region const& t, void*& buffer, size_t& size);
+
+/**
+ * \brief Convert `::android::Region` to `Region`.
+ *
+ * \param[out] t The destination `Region`.
+ * \param[in] l The source `::android::Region`.
+ */
+// convert: ::android::Region -> Region
+bool convertTo(Region* t, ::android::Region const& l);
+
+/**
+ * \brief Convert `Region` to `::android::Region`.
+ *
+ * \param[out] l The destination `::android::Region`.
+ * \param[in] t The source `Region`.
+ */
+// convert: Region -> ::android::Region
+bool convertTo(::android::Region* l, Region const& t);
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+//      BGraphicBufferProducer::QueueBufferInput
+
+/**
+ * \brief Return the size of the buffer required to flatten
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The required size of the flat buffer.
+ */
+size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t);
+
+/**
+ * \brief Return the number of file descriptors contained in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
+ * \return The number of file descriptors contained in \p t.
+ */
+size_t getFdCount(
+        HGraphicBufferProducer::QueueBufferInput const& t);
+/**
+ * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The native handle cloned from `t.fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * This function will duplicate the file descriptor in `t.fence`. */
+status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
+        native_handle_t** nh,
+        void*& buffer, size_t& size, int*& fds, size_t& numFds);
+
+/**
+ * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in,out] buffer The pointer to the flat non-fd buffer.
+ * \param[in,out] size The size of the flat non-fd buffer.
+ * \param[in,out] fds The pointer to the flat fd buffer.
+ * \param[in,out] numFds The size of the flat fd buffer.
+ * \return `NO_ERROR` on success; other value on failure.
+ *
+ * If the return value is `NO_ERROR` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+status_t unflatten(
+        HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
+        void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferInput`.
+ * \param[out] nh The underlying native handle for `t->fence`.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If the return value is `true` and `t->fence` contains a valid file
+ * descriptor, \p nh will be a newly created native handle holding that file
+ * descriptor. \p nh needs to be deleted with `native_handle_delete()`
+ * afterwards.
+ */
+bool wrapAs(
+        HGraphicBufferProducer::QueueBufferInput* t,
+        native_handle_t** nh,
+        BGraphicBufferProducer::QueueBufferInput const& l);
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
+ * `BGraphicBufferProducer::QueueBufferInput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
+ *
+ * If `t.fence` has a valid file descriptor, it will be duplicated.
+ */
+bool convertTo(
+        BGraphicBufferProducer::QueueBufferInput* l,
+        HGraphicBufferProducer::QueueBufferInput const& t);
+
+// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
+//      BGraphicBufferProducer::QueueBufferOutput
+
+/**
+ * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] t The wrapper of type
+ * `HGraphicBufferProducer::QueueBufferOutput`.
+ * \param[out] nh The array of array of native handles that are referred to by
+ * members of \p t.
+ * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * On success, each member of \p nh will be either `nullptr` or a newly created
+ * native handle. All the non-`nullptr` elements must be deleted individually
+ * with `native_handle_delete()`.
+ */
+// wrap: BGraphicBufferProducer::QueueBufferOutput ->
+// HGraphicBufferProducer::QueueBufferOutput
+bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
+        std::vector<std::vector<native_handle_t*> >* nh,
+        BGraphicBufferProducer::QueueBufferOutput const& l);
+
+/**
+ * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
+ * `BGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
+ * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
+ *
+ * This function will duplicate all file descriptors contained in \p t.
+ */
+// convert: HGraphicBufferProducer::QueueBufferOutput ->
+// BGraphicBufferProducer::QueueBufferOutput
+bool convertTo(
+        BGraphicBufferProducer::QueueBufferOutput* l,
+        HGraphicBufferProducer::QueueBufferOutput const& t);
+
+/**
+ * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
+ * `HGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
+ */
+HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
+        BGraphicBufferProducer::DisconnectMode l);
+
+/**
+ * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
+ * `BGraphicBufferProducer::DisconnectMode`.
+ *
+ * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
+ * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
+ */
+BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
+        HGraphicBufferProducer::DisconnectMode t);
+
+}  // namespace conversion
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_CONVERSION_H_
diff --git a/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
new file mode 100644
index 0000000..029dcc0
--- /dev/null
+++ b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WGRAPHICBUFFERPRODUCER_H_
+#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WGRAPHICBUFFERPRODUCER_H_
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <binder/Binder.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
+#include <gui/bufferqueue/1.0/Conversion.h>
+#include <gui/bufferqueue/1.0/WProducerListener.h>
+#include <system/window.h>
+
+#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
+
+namespace android {
+
+using ::android::hardware::media::V1_0::AnwBuffer;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+typedef ::android::hardware::graphics::bufferqueue::V1_0::
+        IGraphicBufferProducer HGraphicBufferProducer;
+typedef ::android::hardware::graphics::bufferqueue::V1_0::
+        IProducerListener HProducerListener;
+
+typedef ::android::IGraphicBufferProducer BGraphicBufferProducer;
+typedef ::android::IProducerListener BProducerListener;
+using ::android::BnGraphicBufferProducer;
+
+#ifndef LOG
+struct LOG_dummy {
+    template <typename T>
+    LOG_dummy& operator<< (const T&) { return *this; }
+};
+
+#define LOG(x)  LOG_dummy()
+#endif
+
+// Instantiate only if HGraphicBufferProducer is base of BASE.
+template <typename BASE,
+          typename = typename std::enable_if<std::is_base_of<HGraphicBufferProducer, BASE>::value>::type>
+struct TWGraphicBufferProducer : public BASE {
+    TWGraphicBufferProducer(sp<BGraphicBufferProducer> const& base) : mBase(base) {}
+    Return<void> requestBuffer(int32_t slot, HGraphicBufferProducer::requestBuffer_cb _hidl_cb) override {
+        sp<GraphicBuffer> buf;
+        status_t status = mBase->requestBuffer(slot, &buf);
+        AnwBuffer anwBuffer{};
+        if (buf != nullptr) {
+            ::android::conversion::wrapAs(&anwBuffer, *buf);
+        }
+        _hidl_cb(static_cast<int32_t>(status), anwBuffer);
+        return Void();
+    }
+
+    Return<int32_t> setMaxDequeuedBufferCount(int32_t maxDequeuedBuffers) override {
+        return static_cast<int32_t>(mBase->setMaxDequeuedBufferCount(
+                static_cast<int>(maxDequeuedBuffers)));
+    }
+
+    Return<int32_t> setAsyncMode(bool async) override {
+        return static_cast<int32_t>(mBase->setAsyncMode(async));
+    }
+
+    Return<void> dequeueBuffer(
+            uint32_t width, uint32_t height,
+            ::android::hardware::graphics::common::V1_0::PixelFormat format, uint32_t usage,
+            bool getFrameTimestamps, HGraphicBufferProducer::dequeueBuffer_cb _hidl_cb) override {
+        int slot{};
+        sp<Fence> fence;
+        ::android::FrameEventHistoryDelta outTimestamps;
+        status_t status = mBase->dequeueBuffer(
+            &slot, &fence, width, height,
+            static_cast<::android::PixelFormat>(format), usage, nullptr,
+            getFrameTimestamps ? &outTimestamps : nullptr);
+        hidl_handle tFence{};
+        HGraphicBufferProducer::FrameEventHistoryDelta tOutTimestamps{};
+
+        native_handle_t* nh = nullptr;
+        if ((fence == nullptr) || !::android::conversion::wrapAs(&tFence, &nh, *fence)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::dequeueBuffer - "
+                    "Invalid output fence";
+            _hidl_cb(static_cast<int32_t>(status),
+                     static_cast<int32_t>(slot),
+                     tFence,
+                     tOutTimestamps);
+            return Void();
+        }
+        std::vector<std::vector<native_handle_t*> > nhAA;
+        if (getFrameTimestamps && !::android::conversion::wrapAs(&tOutTimestamps, &nhAA, outTimestamps)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::dequeueBuffer - "
+                    "Invalid output timestamps";
+            _hidl_cb(static_cast<int32_t>(status),
+                     static_cast<int32_t>(slot),
+                     tFence,
+                     tOutTimestamps);
+            native_handle_delete(nh);
+            return Void();
+        }
+
+        _hidl_cb(static_cast<int32_t>(status),
+                static_cast<int32_t>(slot),
+                tFence,
+                tOutTimestamps);
+        native_handle_delete(nh);
+        if (getFrameTimestamps) {
+            for (auto& nhA : nhAA) {
+                for (auto& handle : nhA) {
+                    native_handle_delete(handle);
+                }
+            }
+        }
+        return Void();
+    }
+
+    Return<int32_t> detachBuffer(int32_t slot) override {
+        return static_cast<int32_t>(mBase->detachBuffer(slot));
+    }
+
+    Return<void> detachNextBuffer(HGraphicBufferProducer::detachNextBuffer_cb _hidl_cb) override {
+        sp<GraphicBuffer> outBuffer;
+        sp<Fence> outFence;
+        status_t status = mBase->detachNextBuffer(&outBuffer, &outFence);
+        AnwBuffer tBuffer{};
+        hidl_handle tFence{};
+
+        if (outBuffer == nullptr) {
+            LOG(ERROR) << "TWGraphicBufferProducer::detachNextBuffer - "
+                    "Invalid output buffer";
+            _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
+            return Void();
+        }
+        ::android::conversion::wrapAs(&tBuffer, *outBuffer);
+        native_handle_t* nh = nullptr;
+        if ((outFence != nullptr) && !::android::conversion::wrapAs(&tFence, &nh, *outFence)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::detachNextBuffer - "
+                    "Invalid output fence";
+            _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
+            return Void();
+        }
+
+        _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
+        native_handle_delete(nh);
+        return Void();
+    }
+
+    Return<void> attachBuffer(const AnwBuffer& buffer, HGraphicBufferProducer::attachBuffer_cb _hidl_cb) override {
+        int outSlot;
+        sp<GraphicBuffer> lBuffer = new GraphicBuffer();
+        if (!::android::conversion::convertTo(lBuffer.get(), buffer)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::attachBuffer - "
+                    "Invalid input native window buffer";
+            _hidl_cb(static_cast<int32_t>(BAD_VALUE), -1);
+            return Void();
+        }
+        status_t status = mBase->attachBuffer(&outSlot, lBuffer);
+
+        _hidl_cb(static_cast<int32_t>(status), static_cast<int32_t>(outSlot));
+        return Void();
+    }
+
+    Return<void> queueBuffer(
+            int32_t slot, const HGraphicBufferProducer::QueueBufferInput& input,
+            HGraphicBufferProducer::queueBuffer_cb _hidl_cb) override {
+        HGraphicBufferProducer::QueueBufferOutput tOutput{};
+        BGraphicBufferProducer::QueueBufferInput lInput(
+                0, false, HAL_DATASPACE_UNKNOWN,
+                ::android::Rect(0, 0, 1, 1),
+                NATIVE_WINDOW_SCALING_MODE_FREEZE,
+                0, ::android::Fence::NO_FENCE);
+        if (!::android::conversion::convertTo(&lInput, input)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::queueBuffer - "
+                    "Invalid input";
+            _hidl_cb(static_cast<int32_t>(BAD_VALUE), tOutput);
+            return Void();
+        }
+        BGraphicBufferProducer::QueueBufferOutput lOutput;
+        status_t status = mBase->queueBuffer(
+                static_cast<int>(slot), lInput, &lOutput);
+
+        std::vector<std::vector<native_handle_t*> > nhAA;
+        if (!::android::conversion::wrapAs(&tOutput, &nhAA, lOutput)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::queueBuffer - "
+                    "Invalid output";
+            _hidl_cb(static_cast<int32_t>(BAD_VALUE), tOutput);
+            return Void();
+        }
+
+        _hidl_cb(static_cast<int32_t>(status), tOutput);
+        for (auto& nhA : nhAA) {
+            for (auto& nh : nhA) {
+                native_handle_delete(nh);
+            }
+        }
+        return Void();
+    }
+
+    Return<int32_t> cancelBuffer(int32_t slot, const hidl_handle& fence) override {
+        sp<Fence> lFence = new Fence();
+        if (!::android::conversion::convertTo(lFence.get(), fence)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::cancelBuffer - "
+                    "Invalid input fence";
+            return static_cast<int32_t>(BAD_VALUE);
+        }
+        return static_cast<int32_t>(mBase->cancelBuffer(static_cast<int>(slot), lFence));
+    }
+
+    Return<void> query(int32_t what, HGraphicBufferProducer::query_cb _hidl_cb) override {
+        int lValue;
+        int lReturn = mBase->query(static_cast<int>(what), &lValue);
+        _hidl_cb(static_cast<int32_t>(lReturn), static_cast<int32_t>(lValue));
+        return Void();
+    }
+
+    Return<void> connect(const sp<HProducerListener>& listener,
+            int32_t api, bool producerControlledByApp,
+            HGraphicBufferProducer::connect_cb _hidl_cb) override {
+        sp<BProducerListener> lListener = listener == nullptr ?
+                nullptr : new LWProducerListener(listener);
+        BGraphicBufferProducer::QueueBufferOutput lOutput;
+        status_t status = mBase->connect(lListener,
+                static_cast<int>(api),
+                producerControlledByApp,
+                &lOutput);
+
+        HGraphicBufferProducer::QueueBufferOutput tOutput{};
+        std::vector<std::vector<native_handle_t*> > nhAA;
+        if (!::android::conversion::wrapAs(&tOutput, &nhAA, lOutput)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::connect - "
+                    "Invalid output";
+            _hidl_cb(static_cast<int32_t>(status), tOutput);
+            return Void();
+        }
+
+        _hidl_cb(static_cast<int32_t>(status), tOutput);
+        for (auto& nhA : nhAA) {
+            for (auto& nh : nhA) {
+                native_handle_delete(nh);
+            }
+        }
+        return Void();
+    }
+
+    Return<int32_t> disconnect(
+            int32_t api,
+            HGraphicBufferProducer::DisconnectMode mode) override {
+        return static_cast<int32_t>(mBase->disconnect(
+                static_cast<int>(api),
+                ::android::conversion::toGuiDisconnectMode(mode)));
+    }
+
+    Return<int32_t> setSidebandStream(const hidl_handle& stream) override {
+        return static_cast<int32_t>(mBase->setSidebandStream(NativeHandle::create(
+                stream ? native_handle_clone(stream) : NULL, true)));
+    }
+
+    Return<void> allocateBuffers(
+            uint32_t width, uint32_t height,
+            ::android::hardware::graphics::common::V1_0::PixelFormat format,
+            uint32_t usage) override {
+        mBase->allocateBuffers(
+                width, height,
+                static_cast<::android::PixelFormat>(format),
+                usage);
+        return Void();
+    }
+
+    Return<int32_t> allowAllocation(bool allow) override {
+        return static_cast<int32_t>(mBase->allowAllocation(allow));
+    }
+
+    Return<int32_t> setGenerationNumber(uint32_t generationNumber) override {
+        return static_cast<int32_t>(mBase->setGenerationNumber(generationNumber));
+    }
+
+    Return<void> getConsumerName(HGraphicBufferProducer::getConsumerName_cb _hidl_cb) override {
+        _hidl_cb(mBase->getConsumerName().string());
+        return Void();
+    }
+
+    Return<int32_t> setSharedBufferMode(bool sharedBufferMode) override {
+        return static_cast<int32_t>(mBase->setSharedBufferMode(sharedBufferMode));
+    }
+
+    Return<int32_t> setAutoRefresh(bool autoRefresh) override {
+        return static_cast<int32_t>(mBase->setAutoRefresh(autoRefresh));
+    }
+
+    Return<int32_t> setDequeueTimeout(int64_t timeoutNs) override {
+        return static_cast<int32_t>(mBase->setDequeueTimeout(timeoutNs));
+    }
+
+    Return<void> getLastQueuedBuffer(HGraphicBufferProducer::getLastQueuedBuffer_cb _hidl_cb) override {
+        sp<GraphicBuffer> lOutBuffer = new GraphicBuffer();
+        sp<Fence> lOutFence = new Fence();
+        float lOutTransformMatrix[16];
+        status_t status = mBase->getLastQueuedBuffer(
+                &lOutBuffer, &lOutFence, lOutTransformMatrix);
+
+        AnwBuffer tOutBuffer{};
+        if (lOutBuffer != nullptr) {
+            ::android::conversion::wrapAs(&tOutBuffer, *lOutBuffer);
+        }
+        hidl_handle tOutFence{};
+        native_handle_t* nh = nullptr;
+        if ((lOutFence == nullptr) || !::android::conversion::wrapAs(&tOutFence, &nh, *lOutFence)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::getLastQueuedBuffer - "
+                    "Invalid output fence";
+            _hidl_cb(static_cast<int32_t>(status),
+                    tOutBuffer,
+                    tOutFence,
+                    hidl_array<float, 16>());
+            return Void();
+        }
+        hidl_array<float, 16> tOutTransformMatrix(lOutTransformMatrix);
+
+        _hidl_cb(static_cast<int32_t>(status), tOutBuffer, tOutFence, tOutTransformMatrix);
+        native_handle_delete(nh);
+        return Void();
+    }
+
+    Return<void> getFrameTimestamps(HGraphicBufferProducer::getFrameTimestamps_cb _hidl_cb) override {
+        ::android::FrameEventHistoryDelta lDelta;
+        mBase->getFrameTimestamps(&lDelta);
+
+        HGraphicBufferProducer::FrameEventHistoryDelta tDelta{};
+        std::vector<std::vector<native_handle_t*> > nhAA;
+        if (!::android::conversion::wrapAs(&tDelta, &nhAA, lDelta)) {
+            LOG(ERROR) << "TWGraphicBufferProducer::getFrameTimestamps - "
+                    "Invalid output frame timestamps";
+            _hidl_cb(tDelta);
+            return Void();
+        }
+
+        _hidl_cb(tDelta);
+        for (auto& nhA : nhAA) {
+            for (auto& nh : nhA) {
+                native_handle_delete(nh);
+            }
+        }
+        return Void();
+    }
+
+    Return<void> getUniqueId(HGraphicBufferProducer::getUniqueId_cb _hidl_cb) override {
+        uint64_t outId{};
+        status_t status = mBase->getUniqueId(&outId);
+        _hidl_cb(static_cast<int32_t>(status), outId);
+        return Void();
+    }
+
+private:
+    sp<BGraphicBufferProducer> mBase;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WGRAPHICBUFFERPRODUCER_H_
diff --git a/libs/gui/include/gui/bufferqueue/1.0/WProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/WProducerListener.h
new file mode 100644
index 0000000..51dff5b
--- /dev/null
+++ b/libs/gui/include/gui/bufferqueue/1.0/WProducerListener.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WPRODUCERLISTENER_H_
+#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WPRODUCERLISTENER_H_
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <binder/IBinder.h>
+#include <gui/IProducerListener.h>
+
+#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
+
+namespace android {
+
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+typedef ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener
+        HProducerListener;
+typedef ::android::IProducerListener
+        BProducerListener;
+using ::android::BnProducerListener;
+
+struct TWProducerListener : public HProducerListener {
+    sp<BProducerListener> mBase;
+    TWProducerListener(sp<BProducerListener> const& base);
+    Return<void> onBufferReleased() override;
+    Return<bool> needsReleaseNotify() override;
+};
+
+class LWProducerListener : public BnProducerListener {
+public:
+    sp<HProducerListener> mBase;
+    LWProducerListener(sp<HProducerListener> const& base);
+    void onBufferReleased() override;
+    bool needsReleaseNotify() override;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_WPRODUCERLISTENER_H_
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888..98dc1e6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -169,6 +169,18 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
+TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mConsumer->consumerConnect(dc, false);
+    int bufferCount = 50;
+    mConsumer->setMaxBufferCount(bufferCount);
+
+    IGraphicBufferProducer::QueueBufferOutput output;
+    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
+    ASSERT_EQ(output.maxBufferCount, bufferCount);
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
     createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 4a78480..ff1ba0a 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -391,6 +391,25 @@
     parentSurface->expectTap(1, 1);
 }
 
+// Ensure a surface whose insets are scaled, handles the touch offset correctly.
+TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) {
+    std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
+    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+    bgSurface->showAt(100, 100);
+
+    fgSurface->mInputInfo.surfaceInset = 5;
+    fgSurface->showAt(100, 100);
+
+    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });
+
+    // expect = touch / scale - inset
+    injectTap(112, 124);
+    fgSurface->expectTap(1, 1);
+
+    injectTap(101, 101);
+    bgSurface->expectTap(1, 1);
+}
+
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
 TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index d33ecfb..c9de37d 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -297,4 +297,70 @@
     composer->removeRegionSamplingListener(grayListener);
 }
 
+TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    // Invalid input sampleArea
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(Rect::INVALID_RECT, mTopLayer->getHandle(),
+                                                  listener));
+    listener->reset();
+    // Invalid input binder
+    EXPECT_EQ(NO_ERROR, composer->addRegionSamplingListener(sampleArea, NULL, listener));
+    // Invalid input listener
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), NULL));
+    EXPECT_EQ(BAD_VALUE, composer->removeRegionSamplingListener(NULL));
+    // remove the listener
+    composer->removeRegionSamplingListener(listener);
+}
+
+TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) {
+    fill_render(rgba_green);
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    fill_render(rgba_green);
+
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+
+    listener->reset();
+    composer->removeRegionSamplingListener(listener);
+    fill_render(rgba_green);
+    EXPECT_FALSE(listener->wait_event(100ms))
+            << "callback should stop after remove the region sampling listener";
+}
+
+TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    Rect sampleArea{100, 100, 200, 200};
+
+    // Test: listener in (100, 100). See layer before move, no layer after move.
+    fill_render(rgba_blue);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_blue, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    composer->removeRegionSamplingListener(listener);
+
+    // Test: listener offset to (600, 600). No layer before move, see layer after move.
+    fill_render(rgba_green);
+    sampleArea.offsetTo(600, 600);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+    composer->removeRegionSamplingListener(listener);
+}
+
 } // namespace android::test
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 0ee9bff..7718bc1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -126,7 +126,7 @@
 }
 
 // This test probably doesn't belong here.
-TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
+TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) {
     sp<ANativeWindow> anw(mSurface);
 
     // Verify the screenshot works with no protected buffers.
@@ -136,8 +136,9 @@
     ASSERT_FALSE(display == nullptr);
 
     sp<GraphicBuffer> outBuffer;
+    bool ignored;
     ASSERT_EQ(NO_ERROR,
-              sf->captureScreen(display, &outBuffer, ui::Dataspace::V0_SRGB,
+              sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB,
                                 ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false));
 
     ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -169,7 +170,7 @@
         ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
     }
     ASSERT_EQ(NO_ERROR,
-              sf->captureScreen(display, &outBuffer, ui::Dataspace::V0_SRGB,
+              sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB,
                                 ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false));
 }
 
@@ -547,8 +548,8 @@
     }
 
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
-    sp<IDisplayEventConnection> createDisplayEventConnection(ISurfaceComposer::VsyncSource)
-            override {
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override {
         return nullptr;
     }
     sp<IBinder> createDisplay(const String8& /*displayName*/,
@@ -560,8 +561,7 @@
                              const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
                              const sp<IBinder>& /*applyToken*/,
                              const InputWindowCommands& /*inputWindowCommands*/,
-                             int64_t /*desiredPresentTime*/,
-                             const cached_buffer_t& /*cachedBuffer*/,
+                             int64_t /*desiredPresentTime*/, const client_cache_t& /*cachedBuffer*/,
                              const std::vector<ListenerCallbacks>& /*listenerCallbacks*/) override {
     }
 
@@ -615,6 +615,7 @@
     status_t setActiveColorMode(const sp<IBinder>& /*display*/,
         ColorMode /*colorMode*/) override { return NO_ERROR; }
     status_t captureScreen(const sp<IBinder>& /*display*/, sp<GraphicBuffer>* /*outBuffer*/,
+                           bool& /* outCapturedSecureLayers */,
                            const ui::Dataspace /*reqDataspace*/,
                            const ui::PixelFormat /*reqPixelFormat*/, Rect /*sourceCrop*/,
                            uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
@@ -622,12 +623,17 @@
                            bool /*captureSecureLayers*/) override {
         return NO_ERROR;
     }
-    virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
-                                   sp<GraphicBuffer>* /*outBuffer*/,
-                                   const ui::Dataspace /*reqDataspace*/,
-                                   const ui::PixelFormat /*reqPixelFormat*/,
-                                   const Rect& /*sourceCrop*/, float /*frameScale*/,
-                                   bool /*childrenOnly*/) override {
+    status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/,
+                           sp<GraphicBuffer>* /*outBuffer*/) override {
+        return NO_ERROR;
+    }
+    virtual status_t captureLayers(
+            const sp<IBinder>& /*parentHandle*/, sp<GraphicBuffer>* /*outBuffer*/,
+            const ui::Dataspace /*reqDataspace*/, const ui::PixelFormat /*reqPixelFormat*/,
+            const Rect& /*sourceCrop*/,
+            const std::unordered_set<sp<IBinder>,
+                                     ISurfaceComposer::SpHash<IBinder>>& /*excludeHandles*/,
+            float /*frameScale*/, bool /*childrenOnly*/) override {
         return NO_ERROR;
     }
     status_t clearAnimationFrameStats() override { return NO_ERROR; }
@@ -698,6 +704,7 @@
                                       std::vector<int32_t>* /*outAllowedConfigs*/) override {
         return NO_ERROR;
     }
+    status_t notifyPowerHint(int32_t /*hintId*/) override { return NO_ERROR; }
 
 protected:
     IBinder* onAsBinder() override { return nullptr; }
@@ -1739,4 +1746,74 @@
     EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
+TEST_F(SurfaceTest, DequeueWithConsumerDrivenSize) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setDefaultBufferSize(10, 10);
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+    native_window_set_buffers_dimensions(window.get(), 0, 0);
+
+    int fence;
+    ANativeWindowBuffer* buffer;
+
+    // Buffer size is driven by the consumer
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(10, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Buffer size is driven by the consumer
+    consumer->setDefaultBufferSize(10, 20);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Transform hint isn't synced to producer before queueBuffer or connect
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+
+    // Transform hint is synced to producer but no auto prerotation
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Prerotation is driven by the consumer with the transform hint used by producer
+    native_window_set_auto_prerotation(window.get(), true);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(20, buffer->width);
+    EXPECT_EQ(10, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Turn off auto prerotaton
+    native_window_set_auto_prerotation(window.get(), false);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Test auto prerotation bit is disabled after disconnect
+    native_window_set_auto_prerotation(window.get(), true);
+    native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_CPU);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    native_window_set_buffers_dimensions(window.get(), 0, 0);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+}
+
 } // namespace android
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 9fd25f9..3266b07 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -235,26 +235,14 @@
 
 // --- MotionEvent ---
 
-void MotionEvent::initialize(
-        int32_t deviceId,
-        int32_t source,
-        int32_t displayId,
-        int32_t action,
-        int32_t actionButton,
-        int32_t flags,
-        int32_t edgeFlags,
-        int32_t metaState,
-        int32_t buttonState,
-        MotionClassification classification,
-        float xOffset,
-        float yOffset,
-        float xPrecision,
-        float yPrecision,
-        nsecs_t downTime,
-        nsecs_t eventTime,
-        size_t pointerCount,
-        const PointerProperties* pointerProperties,
-        const PointerCoords* pointerCoords) {
+void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+                             int32_t actionButton, int32_t flags, int32_t edgeFlags,
+                             int32_t metaState, int32_t buttonState,
+                             MotionClassification classification, float xOffset, float yOffset,
+                             float xPrecision, float yPrecision, float xCursorPosition,
+                             float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                             size_t pointerCount, const PointerProperties* pointerProperties,
+                             const PointerCoords* pointerCoords) {
     InputEvent::initialize(deviceId, source, displayId);
     mAction = action;
     mActionButton = actionButton;
@@ -267,6 +255,8 @@
     mYOffset = yOffset;
     mXPrecision = xPrecision;
     mYPrecision = yPrecision;
+    mXCursorPosition = xCursorPosition;
+    mYCursorPosition = yCursorPosition;
     mDownTime = downTime;
     mPointerProperties.clear();
     mPointerProperties.appendArray(pointerProperties, pointerCount);
@@ -288,6 +278,8 @@
     mYOffset = other->mYOffset;
     mXPrecision = other->mXPrecision;
     mYPrecision = other->mYPrecision;
+    mXCursorPosition = other->mXCursorPosition;
+    mYCursorPosition = other->mYCursorPosition;
     mDownTime = other->mDownTime;
     mPointerProperties = other->mPointerProperties;
 
@@ -312,6 +304,16 @@
     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
 }
 
+float MotionEvent::getXCursorPosition() const {
+    const float rawX = getRawXCursorPosition();
+    return rawX + mXOffset;
+}
+
+float MotionEvent::getYCursorPosition() const {
+    const float rawY = getRawYCursorPosition();
+    return rawY + mYOffset;
+}
+
 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
 }
@@ -431,6 +433,15 @@
     float originX, originY;
     transformPoint(matrix, 0, 0, &originX, &originY);
 
+    // Apply the transformation to cursor position.
+    if (!isnan(mXCursorPosition) && !isnan(mYCursorPosition)) {
+        float x = mXCursorPosition + oldXOffset;
+        float y = mYCursorPosition + oldYOffset;
+        transformPoint(matrix, x, y, &x, &y);
+        mXCursorPosition = x - mXOffset;
+        mYCursorPosition = y - mYOffset;
+    }
+
     // Apply the transformation to all samples.
     size_t numSamples = mSamplePointerCoords.size();
     for (size_t i = 0; i < numSamples; i++) {
@@ -470,6 +481,8 @@
     mYOffset = parcel->readFloat();
     mXPrecision = parcel->readFloat();
     mYPrecision = parcel->readFloat();
+    mXCursorPosition = parcel->readFloat();
+    mYCursorPosition = parcel->readFloat();
     mDownTime = parcel->readInt64();
 
     mPointerProperties.clear();
@@ -521,6 +534,8 @@
     parcel->writeFloat(mYOffset);
     parcel->writeFloat(mXPrecision);
     parcel->writeFloat(mYPrecision);
+    parcel->writeFloat(mXCursorPosition);
+    parcel->writeFloat(mYCursorPosition);
     parcel->writeInt64(mDownTime);
 
     for (size_t i = 0; i < pointerCount; i++) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index e13b40e..904a6fe 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -27,12 +27,16 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <android-base/stringprintf.h>
+#include <binder/Parcel.h>
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <utils/Trace.h>
 
-#include <binder/Parcel.h>
 #include <input/InputTransport.h>
 
+using android::base::StringPrintf;
+
 namespace android {
 
 // Socket buffer size.  The default is typically about 128KB, which is much larger than
@@ -80,6 +84,10 @@
     return a + alpha * (b - a);
 }
 
+inline static bool isPointerEvent(int32_t source) {
+    return (source & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
+}
+
 // --- InputMessage ---
 
 bool InputMessage::isValid(size_t actualSize) const {
@@ -183,6 +191,10 @@
             msg->body.motion.xPrecision = body.motion.xPrecision;
             // float yPrecision
             msg->body.motion.yPrecision = body.motion.yPrecision;
+            // float xCursorPosition
+            msg->body.motion.xCursorPosition = body.motion.xCursorPosition;
+            // float yCursorPosition
+            msg->body.motion.yCursorPosition = body.motion.yCursorPosition;
             // uint32_t pointerCount
             msg->body.motion.pointerCount = body.motion.pointerCount;
             //struct Pointer pointers[MAX_POINTERS]
@@ -420,6 +432,11 @@
         int32_t repeatCount,
         nsecs_t downTime,
         nsecs_t eventTime) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")",
+                mChannel->getName().c_str(), keyCode);
+        ATRACE_NAME(message.c_str());
+    }
 #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,"
@@ -452,26 +469,18 @@
 }
 
 status_t InputPublisher::publishMotionEvent(
-        uint32_t seq,
-        int32_t deviceId,
-        int32_t source,
-        int32_t displayId,
-        int32_t action,
-        int32_t actionButton,
-        int32_t flags,
-        int32_t edgeFlags,
-        int32_t metaState,
-        int32_t buttonState,
-        MotionClassification classification,
-        float xOffset,
-        float yOffset,
-        float xPrecision,
-        float yPrecision,
-        nsecs_t downTime,
-        nsecs_t eventTime,
-        uint32_t pointerCount,
-        const PointerProperties* pointerProperties,
-        const PointerCoords* pointerCoords) {
+        uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+        int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
+        int32_t buttonState, MotionClassification classification, float xOffset, float yOffset,
+        float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition,
+        nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
+        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "publishMotionEvent(inputChannel=%s, action=%" PRId32 ")",
+                mChannel->getName().c_str(), action);
+        ATRACE_NAME(message.c_str());
+    }
 #if DEBUG_TRANSPORT_ACTIONS
     ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
             "displayId=%" PRId32 ", "
@@ -513,6 +522,8 @@
     msg.body.motion.yOffset = yOffset;
     msg.body.motion.xPrecision = xPrecision;
     msg.body.motion.yPrecision = yPrecision;
+    msg.body.motion.xCursorPosition = xCursorPosition;
+    msg.body.motion.yCursorPosition = yCursorPosition;
     msg.body.motion.downTime = downTime;
     msg.body.motion.eventTime = eventTime;
     msg.body.motion.pointerCount = pointerCount;
@@ -622,6 +633,16 @@
                             mChannel->getName().c_str());
 #endif
                     break;
+                } else if (isPointerEvent(mMsg.body.motion.source) &&
+                        mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) {
+                    // No need to process events that we are going to cancel anyways
+                    const size_t count = batch.samples.size();
+                    for (size_t i = 0; i < count; i++) {
+                        const InputMessage& msg = batch.samples.itemAt(i);
+                        sendFinishedSignal(msg.body.motion.seq, false);
+                    }
+                    batch.samples.removeItemsAt(0, count);
+                    mBatches.removeAt(batchIndex);
                 } else {
                     // We cannot append to the batch in progress, so we need to consume
                     // the previous batch right now and defer the new message until later.
@@ -744,8 +765,7 @@
 }
 
 void InputConsumer::updateTouchState(InputMessage& msg) {
-    if (!mResampleTouch ||
-            !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+    if (!mResampleTouch || !isPointerEvent(msg.body.motion.source)) {
         return;
     }
 
@@ -857,7 +877,7 @@
 void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
     const InputMessage* next) {
     if (!mResampleTouch
-            || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)
+            || !(isPointerEvent(event->getSource()))
             || event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
         return;
     }
@@ -1107,26 +1127,16 @@
         pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
     }
 
-    event->initialize(
-            msg->body.motion.deviceId,
-            msg->body.motion.source,
-            msg->body.motion.displayId,
-            msg->body.motion.action,
-            msg->body.motion.actionButton,
-            msg->body.motion.flags,
-            msg->body.motion.edgeFlags,
-            msg->body.motion.metaState,
-            msg->body.motion.buttonState,
-            msg->body.motion.classification,
-            msg->body.motion.xOffset,
-            msg->body.motion.yOffset,
-            msg->body.motion.xPrecision,
-            msg->body.motion.yPrecision,
-            msg->body.motion.downTime,
-            msg->body.motion.eventTime,
-            pointerCount,
-            pointerProperties,
-            pointerCoords);
+    event->initialize(msg->body.motion.deviceId, msg->body.motion.source,
+                      msg->body.motion.displayId, msg->body.motion.action,
+                      msg->body.motion.actionButton, msg->body.motion.flags,
+                      msg->body.motion.edgeFlags, msg->body.motion.metaState,
+                      msg->body.motion.buttonState, msg->body.motion.classification,
+                      msg->body.motion.xOffset, msg->body.motion.yOffset,
+                      msg->body.motion.xPrecision, msg->body.motion.yPrecision,
+                      msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,
+                      msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount,
+                      pointerProperties, pointerCoords);
 }
 
 void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 0c22bfe..56900c1 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -38,29 +38,29 @@
 KeyMap::~KeyMap() {
 }
 
-status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
+status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
         const PropertyMap* deviceConfiguration) {
     // Use the configured key layout if available.
     if (deviceConfiguration) {
         String8 keyLayoutName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
                 keyLayoutName)) {
-            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str());
+            status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
                         "it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyLayoutName.string());
             }
         }
 
         String8 keyCharacterMapName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
                 keyCharacterMapName)) {
-            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str());
+            status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
                         "map '%s' but it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyCharacterMapName.string());
             }
         }
 
@@ -70,25 +70,25 @@
     }
 
     // Try searching by device identifier.
-    if (probeKeyMap(deviceIdenfifier, "")) {
+    if (probeKeyMap(deviceIdentifier, "")) {
         return OK;
     }
 
     // Fall back on the Generic key map.
     // TODO Apply some additional heuristics here to figure out what kind of
     //      generic key map to use (US English, etc.) for typical external keyboards.
-    if (probeKeyMap(deviceIdenfifier, "Generic")) {
+    if (probeKeyMap(deviceIdentifier, "Generic")) {
         return OK;
     }
 
     // Try the Virtual key map as a last resort.
-    if (probeKeyMap(deviceIdenfifier, "Virtual")) {
+    if (probeKeyMap(deviceIdentifier, "Virtual")) {
         return OK;
     }
 
     // Give up!
     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
-            deviceIdenfifier.name.c_str());
+            deviceIdentifier.name.c_str());
     return NAME_NOT_FOUND;
 }
 
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 42d774e..c6cc4fc 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -382,7 +382,16 @@
 
 void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
         const VelocityTracker::Position* positions) {
-    if (++mIndex == HISTORY_SIZE) {
+    if (mMovements[mIndex].eventTime != eventTime) {
+        // When ACTION_POINTER_DOWN happens, we will first receive ACTION_MOVE with the coordinates
+        // of the existing pointers, and then ACTION_POINTER_DOWN with the coordinates that include
+        // the new pointer. If the eventtimes for both events are identical, just update the data
+        // for this time.
+        // We only compare against the last value, as it is likely that addMovement is called
+        // in chronological order as events occur.
+        mIndex++;
+    }
+    if (mIndex == HISTORY_SIZE) {
         mIndex = 0;
     }
 
@@ -1017,7 +1026,16 @@
 
 void ImpulseVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
         const VelocityTracker::Position* positions) {
-    if (++mIndex == HISTORY_SIZE) {
+    if (mMovements[mIndex].eventTime != eventTime) {
+        // When ACTION_POINTER_DOWN happens, we will first receive ACTION_MOVE with the coordinates
+        // of the existing pointers, and then ACTION_POINTER_DOWN with the coordinates that include
+        // the new pointer. If the eventtimes for both events are identical, just update the data
+        // for this time.
+        // We only compare against the last value, as it is likely that addMovement is called
+        // in chronological order as events occur.
+        mIndex++;
+    }
+    if (mIndex == HISTORY_SIZE) {
         mIndex = 0;
     }
 
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 2b75c82..ec34f3e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -255,11 +255,11 @@
     pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
     pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
     event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
-            AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
-            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
-            MotionClassification::NONE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
-            ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
-            2, pointerProperties, pointerCoords);
+                      AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP,
+                      AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE,
+                      X_OFFSET, Y_OFFSET, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_DOWN_TIME,
+                      ARBITRARY_EVENT_TIME, 2, pointerProperties, pointerCoords);
 
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -571,10 +571,11 @@
     }
     MotionEvent event;
     event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
-            0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
-            AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
-            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
-            0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
+                     0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                     0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/, 0 /*yOffset*/,
+                     0 /*xPrecision*/, 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/,
+                     2 /*yCursorPosition*/, 0 /*downTime*/, 0 /*eventTime*/, pointerCount,
+                     pointerProperties, pointerCoords);
     float originalRawX = 0 + 3;
     float originalRawY = -RADIUS + 2;
 
@@ -602,6 +603,10 @@
         ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1);
     }
 
+    // Check cursor positions.
+    ASSERT_NEAR(sinf(PI_180 * (90 + ROTATION)) * RADIUS, event.getXCursorPosition(), 0.001);
+    ASSERT_NEAR(-cosf(PI_180 * (90 + ROTATION)) * RADIUS, event.getYCursorPosition(), 0.001);
+
     // Applying the transformation should preserve the raw X and Y of the first point.
     ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
@@ -626,11 +631,34 @@
 
     for (MotionClassification classification : classifications) {
         event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-                AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
-                classification, 0, 0, 0, 0, 0 /*downTime*/, 0 /*eventTime*/,
-                pointerCount, pointerProperties, pointerCoords);
+                         AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                         0, classification, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/,
+                         pointerCount, pointerProperties, pointerCoords);
         ASSERT_EQ(classification, event.getClassification());
     }
 }
 
+TEST_F(MotionEventTest, Initialize_SetsCursorPosition) {
+    MotionEvent event;
+    constexpr size_t pointerCount = 1;
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
+        pointerCoords[i].clear();
+    }
+
+    event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0,
+                     0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE, 0,
+                     0, 0, 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
+                     0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
+    event.offsetLocation(20, 60);
+    ASSERT_EQ(280, event.getRawXCursorPosition());
+    ASSERT_EQ(540, event.getRawYCursorPosition());
+    ASSERT_EQ(300, event.getXCursorPosition());
+    ASSERT_EQ(600, event.getYCursorPosition());
+}
+
 } // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index f2cd1be..a362f32 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -146,6 +146,8 @@
     constexpr float yOffset = -20;
     constexpr float xPrecision = 0.25;
     constexpr float yPrecision = 0.5;
+    constexpr float xCursorPosition = 1.3;
+    constexpr float yCursorPosition = 50.6;
     constexpr nsecs_t downTime = 3;
     constexpr size_t pointerCount = 3;
     constexpr nsecs_t eventTime = 4;
@@ -168,10 +170,12 @@
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
     }
 
-    status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
-            flags, edgeFlags, metaState, buttonState, classification,
-            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount,
-            pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
+                                           flags, edgeFlags, metaState, buttonState, classification,
+                                           xOffset, yOffset, xPrecision, yPrecision,
+                                           xCursorPosition, yCursorPosition, downTime, eventTime,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
 
@@ -199,6 +203,10 @@
     EXPECT_EQ(classification, motionEvent->getClassification());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
+    EXPECT_EQ(xCursorPosition, motionEvent->getRawXCursorPosition());
+    EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());
+    EXPECT_EQ(xCursorPosition + xOffset, motionEvent->getXCursorPosition());
+    EXPECT_EQ(yCursorPosition + yOffset, motionEvent->getYCursorPosition());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
     EXPECT_EQ(eventTime, motionEvent->getEventTime());
     EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
@@ -266,9 +274,11 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -279,9 +289,11 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -297,9 +309,11 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 62023fb..8d8cf06 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -64,8 +64,10 @@
   CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);
   CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 72);
   CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+  CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 80);
+  CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 84);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 88);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 96);
 
   CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
   CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index a106451..968e2fa 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -17,12 +17,14 @@
 #define LOG_TAG "VelocityTracker_test"
 
 #include <array>
+#include <chrono>
 #include <math.h>
 
 #include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 #include <input/VelocityTracker.h>
 
+using namespace std::chrono_literals;
 using android::base::StringPrintf;
 
 namespace android {
@@ -66,60 +68,137 @@
     EXPECT_NEAR_BY_FRACTION(actual, target, COEFFICIENT_TOLERANCE);
 }
 
-static 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;
+
+    /**
+     * If both values are NAN, then this is considered to be an empty entry (no pointer data).
+     * If only one of the values is NAN, this is still a valid entry,
+     * because we may only care about a single axis.
+     */
+    bool isValid() const {
+        return !(isnan(x) && isnan(y));
+    }
 };
 
-static std::unique_ptr<MotionEvent> createSimpleMotionEvent(
-        const std::vector<Position>& positions) {
-    /**
-     * Only populate the basic fields of a MotionEvent, such as time and a single axis
-     * Designed for use with manually-defined tests.
-     */
-    if (positions.empty()) {
-        failWithMessage("Need at least 1 sample to create a MotionEvent. Received empty vector.");
+struct MotionEventEntry {
+    std::chrono::nanoseconds eventTime;
+    std::vector<Position> positions;
+};
+
+static BitSet32 getValidPointers(const std::vector<Position>& positions) {
+    BitSet32 pointers;
+    for (size_t i = 0; i < positions.size(); i++) {
+        if (positions[i].isValid()) {
+            pointers.markBit(i);
+        }
     }
-
-    std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
-
-    constexpr size_t pointerCount = 1;
-    PointerCoords coords[pointerCount];
-    coords[0].clear();
-
-    PointerProperties properties[pointerCount];
-    properties[0].id = DEFAULT_POINTER_ID;
-    properties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-
-    // First sample added separately with initialize
-    coords[0].setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
-    coords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
-    event->initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
-            AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
-            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
-            0 /*downTime*/, positions[0].time, pointerCount, properties, coords);
-
-    for (size_t i = 1; i < positions.size(); i++) {
-        coords[0].setAxisValue(AMOTION_EVENT_AXIS_X, positions[i].x);
-        coords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, positions[i].y);
-        event->addSample(positions[i].time, coords);
-    }
-    return event;
+    return pointers;
 }
 
-static void computeAndCheckVelocity(const std::vector<Position>& positions,
-            int32_t axis, float targetVelocity) {
-    VelocityTracker vt(nullptr);
+static uint32_t getChangingPointerId(BitSet32 pointers, BitSet32 otherPointers) {
+    BitSet32 difference(pointers.value ^ otherPointers.value);
+    uint32_t pointerId = difference.clearFirstMarkedBit();
+    EXPECT_EQ(0U, difference.value) << "Only 1 pointer can enter or leave at a time";
+    return pointerId;
+}
+
+static int32_t resolveAction(const std::vector<Position>& lastPositions,
+        const std::vector<Position>& currentPositions,
+        const std::vector<Position>& nextPositions) {
+    BitSet32 pointers = getValidPointers(currentPositions);
+    const uint32_t pointerCount = pointers.count();
+
+    BitSet32 lastPointers = getValidPointers(lastPositions);
+    const uint32_t lastPointerCount = lastPointers.count();
+    if (lastPointerCount < pointerCount) {
+        // A new pointer is down
+        uint32_t pointerId = getChangingPointerId(pointers, lastPointers);
+        return AMOTION_EVENT_ACTION_POINTER_DOWN |
+                (pointerId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+    }
+
+    BitSet32 nextPointers = getValidPointers(nextPositions);
+    const uint32_t nextPointerCount = nextPointers.count();
+    if (pointerCount > nextPointerCount) {
+        // An existing pointer is leaving
+        uint32_t pointerId = getChangingPointerId(pointers, nextPointers);
+        return AMOTION_EVENT_ACTION_POINTER_UP |
+                (pointerId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+    }
+
+    return AMOTION_EVENT_ACTION_MOVE;
+}
+
+static std::vector<MotionEvent> createMotionEventStream(
+        const std::vector<MotionEventEntry>& motions) {
+    if (motions.empty()) {
+        ADD_FAILURE() << "Need at least 1 sample to create a MotionEvent. Received empty vector.";
+    }
+
+    std::vector<MotionEvent> events;
+    for (size_t i = 0; i < motions.size(); i++) {
+        const MotionEventEntry& entry = motions[i];
+        BitSet32 pointers = getValidPointers(entry.positions);
+        const uint32_t pointerCount = pointers.count();
+
+        int32_t action;
+        if (i == 0) {
+            action = AMOTION_EVENT_ACTION_DOWN;
+            EXPECT_EQ(1U, pointerCount) << "First event should only have 1 pointer";
+        } else if (i == motions.size() - 1) {
+            EXPECT_EQ(1U, pointerCount) << "Last event should only have 1 pointer";
+            action = AMOTION_EVENT_ACTION_UP;
+        } else {
+            const MotionEventEntry& previousEntry = motions[i-1];
+            const MotionEventEntry& nextEntry = motions[i+1];
+            action = resolveAction(previousEntry.positions, entry.positions, nextEntry.positions);
+        }
+
+        PointerCoords coords[pointerCount];
+        PointerProperties properties[pointerCount];
+        uint32_t pointerIndex = 0;
+        while(!pointers.isEmpty()) {
+            uint32_t pointerId = pointers.clearFirstMarkedBit();
+
+            coords[pointerIndex].clear();
+            // We are treating column positions as pointerId
+            EXPECT_TRUE(entry.positions[pointerId].isValid()) <<
+                    "The entry at pointerId must be valid";
+            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_X, entry.positions[pointerId].x);
+            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_Y, entry.positions[pointerId].y);
+
+            properties[pointerIndex].id = pointerId;
+            properties[pointerIndex].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+            pointerIndex++;
+        }
+        EXPECT_EQ(pointerIndex, pointerCount);
+
+        MotionEvent event;
+        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, action,
+                         0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                         0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/,
+                         0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/,
+                         entry.eventTime.count(), pointerCount, properties, coords);
+
+        events.emplace_back(event);
+    }
+
+    return events;
+}
+
+static void computeAndCheckVelocity(const char* strategy,
+        const std::vector<MotionEventEntry>& motions, int32_t axis, float targetVelocity) {
+    VelocityTracker vt(strategy);
     float Vx, Vy;
 
-    std::unique_ptr<MotionEvent> event = createSimpleMotionEvent(positions);
-    vt.addMovement(event.get());
+    std::vector<MotionEvent> events = createMotionEventStream(motions);
+    for (MotionEvent event : events) {
+        vt.addMovement(&event);
+    }
 
     vt.getVelocity(DEFAULT_POINTER_ID, &Vx, &Vy);
 
@@ -135,11 +214,13 @@
     }
 }
 
-static void computeAndCheckQuadraticEstimate(const std::vector<Position>& positions,
+static void computeAndCheckQuadraticEstimate(const std::vector<MotionEventEntry>& motions,
         const std::array<float, 3>& coefficients) {
     VelocityTracker vt("lsq2");
-    std::unique_ptr<MotionEvent> event = createSimpleMotionEvent(positions);
-    vt.addMovement(event.get());
+    std::vector<MotionEvent> events = createMotionEventStream(motions);
+    for (MotionEvent event : events) {
+        vt.addMovement(&event);
+    }
     VelocityTracker::Estimator estimator;
     EXPECT_TRUE(vt.getEstimator(0, &estimator));
     for (size_t i = 0; i< coefficients.size(); i++) {
@@ -151,37 +232,41 @@
 /*
  * ================== VelocityTracker tests generated manually =====================================
  */
- // @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
-TEST_F(VelocityTrackerTest, DISABLED_ThreePointsPositiveVelocityTest) {
+TEST_F(VelocityTrackerTest, 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.
-    std::vector<Position> values = {
-        { 0, 273, NAN },
-        { 12585000, 293, NAN },
-        { 14730000, 293, NAN },
+    std::vector<MotionEventEntry> motions = {
+        {0ms, {{ 273, NAN}}},
+        {12585us, {{293, NAN}}},
+        {14730us, {{293, NAN}}},
+        {14730us, {{293, NAN}}}, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 1600);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 1600);
 }
 
 TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) {
     // Same coordinate is reported 3 times in a row
-    std::vector<Position> values = {
-        { 0, 293, NAN },
-        { 6132000, 293, NAN },
-        { 11283000, 293, NAN },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{293, NAN}} },
+        { 6132us, {{293, NAN}} },
+        { 11283us, {{293, NAN}} },
+        { 11283us, {{293, NAN}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 0);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 0);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 0);
 }
 
 TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) {
     // Fixed velocity at 5 points per 10 milliseconds
-    std::vector<Position> values = {
-        { 0, 0, NAN },
-        { 10000000, 5, NAN },
-        { 20000000, 10, NAN },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{0, NAN}} },
+        { 10ms, {{5, NAN}} },
+        { 20ms, {{10, NAN}} },
+        { 20ms, {{10, NAN}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 500);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 500);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 500);
 }
 
 
@@ -193,23 +278,26 @@
  * 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.
+ *
+ * Another good way to generate this data is to use 'dumpsys input' just after the event has
+ * occurred.
  */
 
 // --------------- Recorded by hand on swordfish ---------------------------------------------------
-// @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
-TEST_F(VelocityTrackerTest, DISABLED_SwordfishFlingDown) {
+TEST_F(VelocityTrackerTest, SwordfishFlingDown) {
     // Recording of a fling on Swordfish that could cause a fling in the wrong direction
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{271, 96}} },
+        { 16071042ns, {{269.786346, 106.922775}} },
+        { 35648403ns, {{267.983063, 156.660034}} },
+        { 52313925ns, {{262.638397, 220.339081}} },
+        { 68976522ns, {{266.138824, 331.581116}} },
+        { 85639375ns, {{274.79245, 428.113159}} },
+        { 96948871ns, {{274.79245, 428.113159}} },
+        { 96948871ns, {{274.79245, 428.113159}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 623.577637);
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 8523.348633);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 623.577637);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 5970.7309);
 }
 
 // --------------- Recorded by hand on sailfish, generated by a script -----------------------------
@@ -231,439 +319,484 @@
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) {
     // Sailfish - fling up - slow - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235089067457000ns, {{528.00, 983.00}} },
+        { 235089084684000ns, {{527.00, 981.00}} },
+        { 235089093349000ns, {{527.00, 977.00}} },
+        { 235089095677625ns, {{527.00, 975.93}} },
+        { 235089101859000ns, {{527.00, 970.00}} },
+        { 235089110378000ns, {{528.00, 960.00}} },
+        { 235089112497111ns, {{528.25, 957.51}} },
+        { 235089118760000ns, {{531.00, 946.00}} },
+        { 235089126686000ns, {{535.00, 931.00}} },
+        { 235089129316820ns, {{536.33, 926.02}} },
+        { 235089135199000ns, {{540.00, 914.00}} },
+        { 235089144297000ns, {{546.00, 896.00}} },
+        { 235089146136443ns, {{547.21, 892.36}} },
+        { 235089152923000ns, {{553.00, 877.00}} },
+        { 235089160784000ns, {{559.00, 851.00}} },
+        { 235089162955851ns, {{560.66, 843.82}} },
+        { 235089162955851ns, {{560.66, 843.82}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 872.794617); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 951.698181); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -3604.819336); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -3044.966064); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 872.794617);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 951.698181);
+    computeAndCheckVelocity("impulse",motions, AMOTION_EVENT_AXIS_Y, -3604.819336);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -3044.966064);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpSlow2) {
     // Sailfish - fling up - slow - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235110560704000ns, {{522.00, 1107.00}} },
+        { 235110575764000ns, {{522.00, 1107.00}} },
+        { 235110584385000ns, {{522.00, 1107.00}} },
+        { 235110588421179ns, {{521.52, 1106.52}} },
+        { 235110592830000ns, {{521.00, 1106.00}} },
+        { 235110601385000ns, {{520.00, 1104.00}} },
+        { 235110605088160ns, {{519.14, 1102.27}} },
+        { 235110609952000ns, {{518.00, 1100.00}} },
+        { 235110618353000ns, {{517.00, 1093.00}} },
+        { 235110621755146ns, {{516.60, 1090.17}} },
+        { 235110627010000ns, {{517.00, 1081.00}} },
+        { 235110634785000ns, {{518.00, 1063.00}} },
+        { 235110638422450ns, {{518.87, 1052.58}} },
+        { 235110643161000ns, {{520.00, 1039.00}} },
+        { 235110651767000ns, {{524.00, 1011.00}} },
+        { 235110655089581ns, {{525.54, 1000.19}} },
+        { 235110660368000ns, {{530.00, 980.00}} },
+        { 235110660368000ns, {{530.00, 980.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -4096.583008); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -3455.094238); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -4096.583008);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -3455.094238);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpSlow3) {
     // Sailfish - fling up - slow - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 792536237000ns, {{580.00, 1317.00}} },
+        { 792541538987ns, {{580.63, 1311.94}} },
+        { 792544613000ns, {{581.00, 1309.00}} },
+        { 792552301000ns, {{583.00, 1295.00}} },
+        { 792558362309ns, {{585.13, 1282.92}} },
+        { 792560828000ns, {{586.00, 1278.00}} },
+        { 792569446000ns, {{589.00, 1256.00}} },
+        { 792575185095ns, {{591.54, 1241.41}} },
+        { 792578491000ns, {{593.00, 1233.00}} },
+        { 792587044000ns, {{597.00, 1211.00}} },
+        { 792592008172ns, {{600.28, 1195.92}} },
+        { 792594616000ns, {{602.00, 1188.00}} },
+        { 792603129000ns, {{607.00, 1167.00}} },
+        { 792608831290ns, {{609.48, 1155.83}} },
+        { 792612321000ns, {{611.00, 1149.00}} },
+        { 792620768000ns, {{615.00, 1131.00}} },
+        { 792625653873ns, {{617.32, 1121.73}} },
+        { 792629200000ns, {{619.00, 1115.00}} },
+        { 792629200000ns, {{619.00, 1115.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 574.33429); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 617.40564); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -2361.982666); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -2500.055664); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 574.33429);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 617.40564);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -2361.982666);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -2500.055664);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFaster1) {
     // Sailfish - fling up - faster - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235160420675000ns, {{610.00, 1042.00}} },
+        { 235160428220000ns, {{609.00, 1026.00}} },
+        { 235160436544000ns, {{609.00, 1024.00}} },
+        { 235160441852394ns, {{609.64, 1020.82}} },
+        { 235160444878000ns, {{610.00, 1019.00}} },
+        { 235160452673000ns, {{613.00, 1006.00}} },
+        { 235160458519743ns, {{617.18, 992.06}} },
+        { 235160461061000ns, {{619.00, 986.00}} },
+        { 235160469798000ns, {{627.00, 960.00}} },
+        { 235160475186713ns, {{632.22, 943.02}} },
+        { 235160478051000ns, {{635.00, 934.00}} },
+        { 235160486489000ns, {{644.00, 906.00}} },
+        { 235160491853697ns, {{649.56, 890.56}} },
+        { 235160495177000ns, {{653.00, 881.00}} },
+        { 235160504148000ns, {{662.00, 858.00}} },
+        { 235160509231495ns, {{666.81, 845.37}} },
+        { 235160512603000ns, {{670.00, 837.00}} },
+        { 235160520366000ns, {{679.00, 814.00}} },
+        { 235160520366000ns, {{679.00, 814.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 1274.141724); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 1438.53186); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -3877.35498); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -3695.859619); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 1274.141724);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 1438.53186);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -3001.4348);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -3695.859619);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFaster2) {
     // Sailfish - fling up - faster - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 847153808000ns, {{576.00, 1264.00}} },
+        { 847171174000ns, {{576.00, 1262.00}} },
+        { 847179640000ns, {{576.00, 1257.00}} },
+        { 847185187540ns, {{577.41, 1249.22}} },
+        { 847187487000ns, {{578.00, 1246.00}} },
+        { 847195710000ns, {{581.00, 1227.00}} },
+        { 847202027059ns, {{583.93, 1209.40}} },
+        { 847204324000ns, {{585.00, 1203.00}} },
+        { 847212672000ns, {{590.00, 1176.00}} },
+        { 847218861395ns, {{594.36, 1157.11}} },
+        { 847221190000ns, {{596.00, 1150.00}} },
+        { 847230484000ns, {{602.00, 1124.00}} },
+        { 847235701400ns, {{607.56, 1103.83}} },
+        { 847237986000ns, {{610.00, 1095.00}} },
+        { 847237986000ns, {{610.00, 1095.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -4280.07959); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -4241.004395); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -4280.07959);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -4241.004395);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFaster3) {
     // Sailfish - fling up - faster - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235200532789000ns, {{507.00, 1084.00}} },
+        { 235200549221000ns, {{507.00, 1083.00}} },
+        { 235200557841000ns, {{507.00, 1081.00}} },
+        { 235200558051189ns, {{507.00, 1080.95}} },
+        { 235200566314000ns, {{507.00, 1078.00}} },
+        { 235200574876586ns, {{508.97, 1070.12}} },
+        { 235200575006000ns, {{509.00, 1070.00}} },
+        { 235200582900000ns, {{514.00, 1054.00}} },
+        { 235200591276000ns, {{525.00, 1023.00}} },
+        { 235200591701829ns, {{525.56, 1021.42}} },
+        { 235200600064000ns, {{542.00, 976.00}} },
+        { 235200608519000ns, {{563.00, 911.00}} },
+        { 235200608527086ns, {{563.02, 910.94}} },
+        { 235200616933000ns, {{590.00, 844.00}} },
+        { 235200616933000ns, {{590.00, 844.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -8715.686523); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -7639.026367); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -8715.686523);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -7639.026367);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFast1) {
     // Sailfish - fling up - fast - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 920922149000ns, {{561.00, 1412.00}} },
+        { 920930185000ns, {{559.00, 1377.00}} },
+        { 920930262463ns, {{558.98, 1376.66}} },
+        { 920938547000ns, {{559.00, 1371.00}} },
+        { 920947096857ns, {{562.91, 1342.68}} },
+        { 920947302000ns, {{563.00, 1342.00}} },
+        { 920955502000ns, {{577.00, 1272.00}} },
+        { 920963931021ns, {{596.87, 1190.54}} },
+        { 920963987000ns, {{597.00, 1190.00}} },
+        { 920972530000ns, {{631.00, 1093.00}} },
+        { 920980765511ns, {{671.31, 994.68}} },
+        { 920980906000ns, {{672.00, 993.00}} },
+        { 920989261000ns, {{715.00, 903.00}} },
+        { 920989261000ns, {{715.00, 903.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 5670.329102); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, 5991.866699); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -13021.101562); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -15093.995117); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 5670.329102);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, 5991.866699);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -13021.101562);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -15093.995117);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFast2) {
     // Sailfish - fling up - fast - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235247153233000ns, {{518.00, 1168.00}} },
+        { 235247170452000ns, {{517.00, 1167.00}} },
+        { 235247178908000ns, {{515.00, 1159.00}} },
+        { 235247179556213ns, {{514.85, 1158.39}} },
+        { 235247186821000ns, {{515.00, 1125.00}} },
+        { 235247195265000ns, {{521.00, 1051.00}} },
+        { 235247196389476ns, {{521.80, 1041.15}} },
+        { 235247203649000ns, {{538.00, 932.00}} },
+        { 235247212253000ns, {{571.00, 794.00}} },
+        { 235247213222491ns, {{574.72, 778.45}} },
+        { 235247220736000ns, {{620.00, 641.00}} },
+        { 235247220736000ns, {{620.00, 641.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -20286.958984); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -20494.587891); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -20286.958984);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -20494.587891);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingUpFast3) {
     // Sailfish - fling up - fast - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235302568736000ns, {{529.00, 1167.00}} },
+        { 235302576644000ns, {{523.00, 1140.00}} },
+        { 235302579395063ns, {{520.91, 1130.61}} },
+        { 235302585140000ns, {{522.00, 1130.00}} },
+        { 235302593615000ns, {{527.00, 1065.00}} },
+        { 235302596207444ns, {{528.53, 1045.12}} },
+        { 235302602102000ns, {{559.00, 872.00}} },
+        { 235302610545000ns, {{652.00, 605.00}} },
+        { 235302613019881ns, {{679.26, 526.73}} },
+        { 235302613019881ns, {{679.26, 526.73}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -39295.941406); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, -36461.421875); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, -39295.941406);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -36461.421875);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownSlow1) {
     // Sailfish - fling down - slow - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235655749552755ns, {{582.00, 432.49}} },
+        { 235655750638000ns, {{582.00, 433.00}} },
+        { 235655758865000ns, {{582.00, 440.00}} },
+        { 235655766221523ns, {{581.16, 448.43}} },
+        { 235655767594000ns, {{581.00, 450.00}} },
+        { 235655776044000ns, {{580.00, 462.00}} },
+        { 235655782890696ns, {{579.18, 474.35}} },
+        { 235655784360000ns, {{579.00, 477.00}} },
+        { 235655792795000ns, {{578.00, 496.00}} },
+        { 235655799559531ns, {{576.27, 515.04}} },
+        { 235655800612000ns, {{576.00, 518.00}} },
+        { 235655809535000ns, {{574.00, 542.00}} },
+        { 235655816988015ns, {{572.17, 564.86}} },
+        { 235655817685000ns, {{572.00, 567.00}} },
+        { 235655825981000ns, {{569.00, 595.00}} },
+        { 235655833808653ns, {{566.26, 620.60}} },
+        { 235655834541000ns, {{566.00, 623.00}} },
+        { 235655842893000ns, {{563.00, 649.00}} },
+        { 235655842893000ns, {{563.00, 649.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -419.749695); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -398.303894); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 3309.016357); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 3969.099854); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, -419.749695);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -398.303894);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 3309.016357);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 3969.099854);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownSlow2) {
     // Sailfish - fling down - slow - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235671152083370ns, {{485.24, 558.28}} },
+        { 235671154126000ns, {{485.00, 559.00}} },
+        { 235671162497000ns, {{484.00, 566.00}} },
+        { 235671168750511ns, {{483.27, 573.29}} },
+        { 235671171071000ns, {{483.00, 576.00}} },
+        { 235671179390000ns, {{482.00, 588.00}} },
+        { 235671185417210ns, {{481.31, 598.98}} },
+        { 235671188173000ns, {{481.00, 604.00}} },
+        { 235671196371000ns, {{480.00, 624.00}} },
+        { 235671202084196ns, {{479.27, 639.98}} },
+        { 235671204235000ns, {{479.00, 646.00}} },
+        { 235671212554000ns, {{478.00, 673.00}} },
+        { 235671219471011ns, {{476.39, 697.12}} },
+        { 235671221159000ns, {{476.00, 703.00}} },
+        { 235671229592000ns, {{474.00, 734.00}} },
+        { 235671236281462ns, {{472.43, 758.38}} },
+        { 235671238098000ns, {{472.00, 765.00}} },
+        { 235671246532000ns, {{470.00, 799.00}} },
+        { 235671246532000ns, {{470.00, 799.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -262.80426); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -243.665344); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4215.682129); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4587.986816); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, -262.80426);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -243.665344);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 4215.682129);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 4587.986816);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownSlow3) {
     // Sailfish - fling down - slow - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 170983201000ns, {{557.00, 533.00}} },
+        { 171000668000ns, {{556.00, 534.00}} },
+        { 171007359750ns, {{554.73, 535.27}} },
+        { 171011197000ns, {{554.00, 536.00}} },
+        { 171017660000ns, {{552.00, 540.00}} },
+        { 171024201831ns, {{549.97, 544.73}} },
+        { 171027333000ns, {{549.00, 547.00}} },
+        { 171034603000ns, {{545.00, 557.00}} },
+        { 171041043371ns, {{541.98, 567.55}} },
+        { 171043147000ns, {{541.00, 571.00}} },
+        { 171051052000ns, {{536.00, 586.00}} },
+        { 171051052000ns, {{536.00, 586.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -723.413513); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -651.038452); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 2091.502441); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 1934.517456); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, -723.413513);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -651.038452);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 2091.502441);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 1934.517456);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFaster1) {
     // Sailfish - fling down - faster - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235695280333000ns, {{558.00, 451.00}} },
+        { 235695283971237ns, {{558.43, 454.45}} },
+        { 235695289038000ns, {{559.00, 462.00}} },
+        { 235695297388000ns, {{561.00, 478.00}} },
+        { 235695300638465ns, {{561.83, 486.25}} },
+        { 235695305265000ns, {{563.00, 498.00}} },
+        { 235695313591000ns, {{564.00, 521.00}} },
+        { 235695317305492ns, {{564.43, 532.68}} },
+        { 235695322181000ns, {{565.00, 548.00}} },
+        { 235695330709000ns, {{565.00, 577.00}} },
+        { 235695333972227ns, {{565.00, 588.10}} },
+        { 235695339250000ns, {{565.00, 609.00}} },
+        { 235695347839000ns, {{565.00, 642.00}} },
+        { 235695351313257ns, {{565.00, 656.18}} },
+        { 235695356412000ns, {{565.00, 677.00}} },
+        { 235695364899000ns, {{563.00, 710.00}} },
+        { 235695368118682ns, {{562.24, 722.52}} },
+        { 235695373403000ns, {{564.00, 744.00}} },
+        { 235695373403000ns, {{564.00, 744.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4254.639648); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4698.415039); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 4254.639648);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 4698.415039);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFaster2) {
     // Sailfish - fling down - faster - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235709624766000ns, {{535.00, 579.00}} },
+        { 235709642256000ns, {{534.00, 580.00}} },
+        { 235709643350278ns, {{533.94, 580.06}} },
+        { 235709650760000ns, {{532.00, 584.00}} },
+        { 235709658615000ns, {{530.00, 593.00}} },
+        { 235709660170495ns, {{529.60, 594.78}} },
+        { 235709667095000ns, {{527.00, 606.00}} },
+        { 235709675616000ns, {{524.00, 628.00}} },
+        { 235709676983261ns, {{523.52, 631.53}} },
+        { 235709684289000ns, {{521.00, 652.00}} },
+        { 235709692763000ns, {{518.00, 682.00}} },
+        { 235709693804993ns, {{517.63, 685.69}} },
+        { 235709701438000ns, {{515.00, 709.00}} },
+        { 235709709830000ns, {{512.00, 739.00}} },
+        { 235709710626776ns, {{511.72, 741.85}} },
+        { 235709710626776ns, {{511.72, 741.85}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -430.440247); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -447.600311); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 3953.859375); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4316.155273); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, -430.440247);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -447.600311);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 3953.859375);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 4316.155273);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFaster3) {
     // Sailfish - fling down - faster - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235727628927000ns, {{540.00, 440.00}} },
+        { 235727636810000ns, {{537.00, 454.00}} },
+        { 235727646176000ns, {{536.00, 454.00}} },
+        { 235727653586628ns, {{535.12, 456.65}} },
+        { 235727654557000ns, {{535.00, 457.00}} },
+        { 235727663024000ns, {{534.00, 465.00}} },
+        { 235727670410103ns, {{533.04, 479.45}} },
+        { 235727670691000ns, {{533.00, 480.00}} },
+        { 235727679255000ns, {{531.00, 501.00}} },
+        { 235727687233704ns, {{529.09, 526.73}} },
+        { 235727687628000ns, {{529.00, 528.00}} },
+        { 235727696113000ns, {{526.00, 558.00}} },
+        { 235727704057546ns, {{523.18, 588.98}} },
+        { 235727704576000ns, {{523.00, 591.00}} },
+        { 235727713099000ns, {{520.00, 626.00}} },
+        { 235727720880776ns, {{516.33, 655.36}} },
+        { 235727721580000ns, {{516.00, 658.00}} },
+        { 235727721580000ns, {{516.00, 658.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4484.617676); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 4927.92627); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 4484.617676);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 4927.92627);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFast1) {
     // Sailfish - fling down - fast - 1
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235762352849000ns, {{467.00, 286.00}} },
+        { 235762360250000ns, {{443.00, 344.00}} },
+        { 235762362787412ns, {{434.77, 363.89}} },
+        { 235762368807000ns, {{438.00, 359.00}} },
+        { 235762377220000ns, {{425.00, 423.00}} },
+        { 235762379608561ns, {{421.31, 441.17}} },
+        { 235762385698000ns, {{412.00, 528.00}} },
+        { 235762394133000ns, {{406.00, 648.00}} },
+        { 235762396429369ns, {{404.37, 680.67}} },
+        { 235762396429369ns, {{404.37, 680.67}} }, //ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 19084.931641); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 16064.685547); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 14227.0224);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 16064.685547);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFast2) {
     // Sailfish - fling down - fast - 2
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 235772487188000ns, {{576.00, 204.00}} },
+        { 235772495159000ns, {{553.00, 236.00}} },
+        { 235772503568000ns, {{551.00, 240.00}} },
+        { 235772508192247ns, {{545.55, 254.17}} },
+        { 235772512051000ns, {{541.00, 266.00}} },
+        { 235772520794000ns, {{520.00, 337.00}} },
+        { 235772525015263ns, {{508.92, 394.43}} },
+        { 235772529174000ns, {{498.00, 451.00}} },
+        { 235772537635000ns, {{484.00, 589.00}} },
+        { 235772537635000ns, {{484.00, 589.00}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 18660.048828); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 16918.439453); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 18660.048828);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 16918.439453);
 }
 
 
 TEST_F(VelocityTrackerTest, SailfishFlingDownFast3) {
     // Sailfish - fling down - fast - 3
-    std::vector<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 },
+    std::vector<MotionEventEntry> motions = {
+        { 507650295000ns, {{628.00, 233.00}} },
+        { 507658234000ns, {{605.00, 269.00}} },
+        { 507666784000ns, {{601.00, 274.00}} },
+        { 507669660483ns, {{599.65, 275.68}} },
+        { 507675427000ns, {{582.00, 308.00}} },
+        { 507683740000ns, {{541.00, 404.00}} },
+        { 507686506238ns, {{527.36, 435.95}} },
+        { 507692220000ns, {{487.00, 581.00}} },
+        { 507700707000ns, {{454.00, 792.00}} },
+        { 507703352649ns, {{443.71, 857.77}} },
+        { 507703352649ns, {{443.71, 857.77}} }, // ACTION_UP
     };
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -6772.508301); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_X, -6388.48877); // lsq2
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 29765.908203); // impulse
-    computeAndCheckVelocity(values, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, -4111.8173);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -6388.48877);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 29765.908203);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, 28354.796875);
 }
 
-/*
+/**
+ * ================== Multiple pointers ============================================================
+ *
+ * Three fingers quickly tap the screen. Since this is a tap, the velocities should be zero.
+ * If the events with POINTER_UP or POINTER_DOWN are not handled correctly (these should not be
+ * part of the fitted data), this can cause large velocity values to be reported instead.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_ThreeFingerTap) {
+    std::vector<MotionEventEntry> motions = {
+        { 0us,      {{1063, 1128}, {NAN, NAN}, {NAN, NAN}} },
+        { 10800us,  {{1063, 1128}, {682, 1318}, {NAN, NAN}} }, // POINTER_DOWN
+        { 10800us,  {{1063, 1128}, {682, 1318}, {397, 1747}} }, // POINTER_DOWN
+        { 267300us, {{1063, 1128}, {682, 1318}, {397, 1747}} }, // POINTER_UP
+        { 267300us, {{1063, 1128}, {NAN, NAN}, {397, 1747}} }, // POINTER_UP
+        { 272700us, {{1063, 1128}, {NAN, NAN}, {NAN, NAN}} },
+    };
+
+    // Velocity should actually be zero, but we expect 0.016 here instead.
+    // This is close enough to zero, and is likely caused by division by a very small number.
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_X, -0.016);
+    computeAndCheckVelocity("lsq2", motions, AMOTION_EVENT_AXIS_Y, -0.016);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_X, 0);
+    computeAndCheckVelocity("impulse", motions, AMOTION_EVENT_AXIS_Y, 0);
+}
+
+/**
+ * ================== Tests for least squares fitting ==============================================
+ *
  * Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
  * getEstimator function. In particular:
  * - inside the function, time gets converted from nanoseconds to seconds
@@ -687,85 +820,90 @@
  * In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
  */
 TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
-    std::vector<Position> values = {
-        { 0000000, 1, 1 }, // 0 s
-        { 1000000, 1, 1 }, // 0.001 s
-        { 2000000, 1, 1 }, // 0.002 s
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{1, 1}} }, // 0 s
+        { 1ms, {{1, 1}} }, // 0.001 s
+        { 2ms, {{1, 1}} }, // 0.002 s
+        { 2ms, {{1, 1}} }, // ACTION_UP
     };
     // The data used for the fit will be as follows:
     // time(s), position
     // -0.002, 1
     // -0.001, 1
-    // -0.000, 1
-    computeAndCheckQuadraticEstimate(values, std::array<float, 3>({1, 0, 0}));
+    // -0.ms, 1
+    computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({1, 0, 0}));
 }
 
 /*
  * Straight line y = x :: the constant and quadratic coefficients are zero.
  */
 TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
-    std::vector<Position> values = {
-        { 0000000, -2, -2 },
-        { 1000000, -1, -1 },
-        { 2000000, -0, -0 },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{-2, -2}} },
+        { 1ms, {{-1, -1}} },
+        { 2ms, {{-0, -0}} },
+        { 2ms, {{-0, -0}} }, // ACTION_UP
     };
     // The data used for the fit will be as follows:
     // time(s), position
     // -0.002, -2
     // -0.001, -1
     // -0.000,  0
-    computeAndCheckQuadraticEstimate(values, std::array<float, 3>({0, 1E3, 0}));
+    computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({0, 1E3, 0}));
 }
 
 /*
  * Parabola
  */
 TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
-    std::vector<Position> values = {
-        { 0000000, 1, 1 },
-        { 1000000, 4, 4 },
-        { 2000000, 8, 8 },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{1, 1}} },
+        { 1ms, {{4, 4}} },
+        { 2ms, {{8, 8}} },
+        { 2ms, {{8, 8}} }, // ACTION_UP
     };
     // The data used for the fit will be as follows:
     // time(s), position
     // -0.002, 1
     // -0.001, 4
     // -0.000, 8
-    computeAndCheckQuadraticEstimate(values, std::array<float, 3>({8, 4.5E3, 0.5E6}));
+    computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({8, 4.5E3, 0.5E6}));
 }
 
 /*
  * Parabola
  */
 TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
-    std::vector<Position> values = {
-        { 0000000, 1, 1 },
-        { 1000000, 4, 4 },
-        { 2000000, 9, 9 },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{1, 1}} },
+        { 1ms, {{4, 4}} },
+        { 2ms, {{9, 9}} },
+        { 2ms, {{9, 9}} }, // ACTION_UP
     };
     // The data used for the fit will be as follows:
     // time(s), position
     // -0.002, 1
     // -0.001, 4
     // -0.000, 9
-    computeAndCheckQuadraticEstimate(values, std::array<float, 3>({9, 6E3, 1E6}));
+    computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({9, 6E3, 1E6}));
 }
 
 /*
  * Parabola :: y = x^2 :: the constant and linear coefficients are zero.
  */
 TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
-    std::vector<Position> values = {
-        { 0000000, 4, 4 },
-        { 1000000, 1, 1 },
-        { 2000000, 0, 0 },
+    std::vector<MotionEventEntry> motions = {
+        { 0ms, {{4, 4}} },
+        { 1ms, {{1, 1}} },
+        { 2ms, {{0, 0}} },
+        { 2ms, {{0, 0}} }, // ACTION_UP
     };
     // The data used for the fit will be as follows:
     // time(s), position
     // -0.002, 4
     // -0.001, 1
     // -0.000, 0
-    computeAndCheckQuadraticEstimate(values, std::array<float, 3>({0, 0E3, 1E6}));
+    computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({0, 0E3, 1E6}));
 }
 
 } // namespace android
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 8435dac..1751443 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -262,3 +262,7 @@
 int ANativeWindow_setAutoRefresh(ANativeWindow* window, bool autoRefresh) {
     return native_window_set_auto_refresh(window, autoRefresh);
 }
+
+int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation) {
+    return native_window_set_auto_prerotation(window, autoPrerotation);
+}
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 61590e0..8cbf0a4 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -203,41 +203,42 @@
  */
 enum {
     // clang-format off
-    NATIVE_WINDOW_SET_USAGE                     =  0,   /* deprecated */
-    NATIVE_WINDOW_CONNECT                       =  1,   /* deprecated */
-    NATIVE_WINDOW_DISCONNECT                    =  2,   /* deprecated */
-    NATIVE_WINDOW_SET_CROP                      =  3,   /* private */
-    NATIVE_WINDOW_SET_BUFFER_COUNT              =  4,
-    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY          =  5,   /* deprecated */
-    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM         =  6,
-    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP         =  7,
-    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS        =  8,
-    NATIVE_WINDOW_SET_BUFFERS_FORMAT            =  9,
-    NATIVE_WINDOW_SET_SCALING_MODE              = 10,   /* private */
-    NATIVE_WINDOW_LOCK                          = 11,   /* private */
-    NATIVE_WINDOW_UNLOCK_AND_POST               = 12,   /* private */
-    NATIVE_WINDOW_API_CONNECT                   = 13,   /* private */
-    NATIVE_WINDOW_API_DISCONNECT                = 14,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS   = 15,   /* private */
-    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP       = 16,   /* deprecated, unimplemented */
-    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM  = 17,   /* private */
-    NATIVE_WINDOW_SET_SIDEBAND_STREAM           = 18,
-    NATIVE_WINDOW_SET_BUFFERS_DATASPACE         = 19,
-    NATIVE_WINDOW_SET_SURFACE_DAMAGE            = 20,   /* private */
-    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE        = 21,
-    NATIVE_WINDOW_SET_AUTO_REFRESH              = 22,
-    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION    = 23,
-    NATIVE_WINDOW_GET_NEXT_FRAME_ID             = 24,
-    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS       = 25,
-    NATIVE_WINDOW_GET_COMPOSITOR_TIMING         = 26,
-    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS          = 27,
-    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT        = 28,
-    NATIVE_WINDOW_GET_HDR_SUPPORT               = 29,
-    NATIVE_WINDOW_SET_USAGE64                   = 30,
-    NATIVE_WINDOW_GET_CONSUMER_USAGE64          = 31,
-    NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
-    NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
+    NATIVE_WINDOW_SET_USAGE                       =  0,   /* deprecated */
+    NATIVE_WINDOW_CONNECT                         =  1,   /* deprecated */
+    NATIVE_WINDOW_DISCONNECT                      =  2,   /* deprecated */
+    NATIVE_WINDOW_SET_CROP                        =  3,   /* private */
+    NATIVE_WINDOW_SET_BUFFER_COUNT                =  4,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY            =  5,   /* deprecated */
+    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM           =  6,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP           =  7,
+    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS          =  8,
+    NATIVE_WINDOW_SET_BUFFERS_FORMAT              =  9,
+    NATIVE_WINDOW_SET_SCALING_MODE                = 10,   /* private */
+    NATIVE_WINDOW_LOCK                            = 11,   /* private */
+    NATIVE_WINDOW_UNLOCK_AND_POST                 = 12,   /* private */
+    NATIVE_WINDOW_API_CONNECT                     = 13,   /* private */
+    NATIVE_WINDOW_API_DISCONNECT                  = 14,   /* private */
+    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS     = 15,   /* private */
+    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP         = 16,   /* deprecated, unimplemented */
+    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM    = 17,   /* private */
+    NATIVE_WINDOW_SET_SIDEBAND_STREAM             = 18,
+    NATIVE_WINDOW_SET_BUFFERS_DATASPACE           = 19,
+    NATIVE_WINDOW_SET_SURFACE_DAMAGE              = 20,   /* private */
+    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE          = 21,
+    NATIVE_WINDOW_SET_AUTO_REFRESH                = 22,
+    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION      = 23,
+    NATIVE_WINDOW_GET_NEXT_FRAME_ID               = 24,
+    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS         = 25,
+    NATIVE_WINDOW_GET_COMPOSITOR_TIMING           = 26,
+    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS            = 27,
+    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT          = 28,
+    NATIVE_WINDOW_GET_HDR_SUPPORT                 = 29,
+    NATIVE_WINDOW_SET_USAGE64                     = 30,
+    NATIVE_WINDOW_GET_CONSUMER_USAGE64            = 31,
+    NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA  = 32,
+    NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA   = 33,
     NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
+    NATIVE_WINDOW_SET_AUTO_PREROTATION            = 35,
     // clang-format on
 };
 
@@ -985,4 +986,18 @@
     return window->perform(window, NATIVE_WINDOW_GET_CONSUMER_USAGE64, outUsage);
 }
 
+/*
+ * native_window_set_auto_prerotation(..., autoPrerotation)
+ * Enable/disable the auto prerotation at buffer allocation when the buffer size
+ * is driven by the consumer.
+ *
+ * When buffer size is driven by the consumer and the transform hint specifies
+ * a 90 or 270 degree rotation, if auto prerotation is enabled, the width and
+ * height used for dequeueBuffer will be additionally swapped.
+ */
+static inline int native_window_set_auto_prerotation(struct ANativeWindow* window,
+                                                     bool autoPrerotation) {
+    return window->perform(window, NATIVE_WINDOW_SET_AUTO_PREROTATION, autoPrerotation);
+}
+
 __END_DECLS
diff --git a/libs/nativewindow/include/vndk/window.h b/libs/nativewindow/include/vndk/window.h
index 995ba44..500052c 100644
--- a/libs/nativewindow/include/vndk/window.h
+++ b/libs/nativewindow/include/vndk/window.h
@@ -316,6 +316,15 @@
  */
 int ANativeWindow_setAutoRefresh(ANativeWindow* window, bool autoRefresh);
 
+/*
+ * Enable/disable the auto prerotation at buffer allocation when the buffer size
+ * is driven by the consumer.
+ *
+ * When buffer size is driven by the consumer and the transform hint specifies
+ * a 90 or 270 degree rotation, if auto prerotation is enabled, the width and
+ * height used for dequeueBuffer will be additionally swapped.
+ */
+int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation);
 
 /*****************************************************************************/
 
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 23a05f3..119a07d 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -8,6 +8,7 @@
     AHardwareBuffer_isSupported; # introduced=29
     AHardwareBuffer_lock;
     AHardwareBuffer_lockAndGetInfo; # introduced=29
+    AHardwareBuffer_lockPlanes; # introduced=29
     AHardwareBuffer_recvHandleFromUnixSocket;
     AHardwareBuffer_release;
     AHardwareBuffer_sendHandleToUnixSocket;
@@ -27,6 +28,7 @@
     ANativeWindow_queryf; # vndk
     ANativeWindow_queueBuffer; # vndk
     ANativeWindow_release;
+    ANativeWindow_setAutoPrerotation; # vndk
     ANativeWindow_setAutoRefresh; # vndk
     ANativeWindow_setBufferCount; # vndk
     ANativeWindow_setBuffersDataSpace; # introduced=28
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index d0127b8..8bfd3dd 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -31,6 +31,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
 #include <renderengine/private/Description.h>
@@ -248,7 +249,8 @@
     bool useContextPriority = extensions.hasContextPriority() &&
             (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
     EGLContext protectedContext = EGL_NO_CONTEXT;
-    if (extensions.hasProtectedContent()) {
+    if ((featureFlags & RenderEngine::ENABLE_PROTECTED_CONTEXT) &&
+        extensions.hasProtectedContent()) {
         protectedContext = createEglContext(display, config, nullptr, useContextPriority,
                                             Protection::PROTECTED);
         ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
@@ -270,13 +272,6 @@
     extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
                                  glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
 
-    // In order to have protected contents in GPU composition, the OpenGL ES extension
-    // GL_EXT_protected_textures must be supported. If it's not supported, reset
-    // protected context to EGL_NO_CONTEXT to indicate that protected contents is not supported.
-    if (!extensions.hasProtectedTexture()) {
-        protectedContext = EGL_NO_CONTEXT;
-    }
-
     EGLSurface protectedDummy = EGL_NO_SURFACE;
     if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
         protectedDummy =
@@ -439,6 +434,7 @@
         EGLImageKHR expired = mFramebufferImageCache.front().second;
         mFramebufferImageCache.pop_front();
         eglDestroyImageKHR(mEGLDisplay, expired);
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
     }
     mImageCache.clear();
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -462,10 +458,6 @@
                                            mFeatureFlags & USE_COLOR_MANAGEMENT);
 }
 
-bool GLESRenderEngine::isCurrent() const {
-    return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
-}
-
 base::unique_fd GLESRenderEngine::flush() {
     ATRACE_CALL();
     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
@@ -539,16 +531,14 @@
         return false;
     }
 
-    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+    // release the fd and transfer the ownership to EGLSync
+    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
     if (sync == EGL_NO_SYNC_KHR) {
         ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
         return false;
     }
 
-    // fenceFd is now owned by EGLSync
-    (void)fenceFd.release();
-
     // XXX: The spec draft is inconsistent as to whether this should return an
     // EGLint or void.  Ignore the return value for now, as it's not strictly
     // needed.
@@ -617,73 +607,34 @@
     const GLenum target = GL_TEXTURE_EXTERNAL_OES;
 
     glBindTexture(target, texName);
-    if (supportsProtectedContent()) {
-        glTexParameteri(target, GL_TEXTURE_PROTECTED_EXT,
-                        glImage.isProtected() ? GL_TRUE : GL_FALSE);
-    }
     if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
         glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
     }
 }
 
-status_t GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    return cacheExternalTextureBufferLocked(buffer);
-}
-
 status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
                                                      const sp<GraphicBuffer>& buffer,
                                                      const sp<Fence>& bufferFence) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    return bindExternalTextureBufferLocked(texName, buffer, bufferFence);
-}
-
-status_t GLESRenderEngine::cacheExternalTextureBufferLocked(const sp<GraphicBuffer>& buffer) {
-    if (buffer == nullptr) {
-        return BAD_VALUE;
-    }
-
     ATRACE_CALL();
-
-    if (mImageCache.count(buffer->getId()) > 0) {
-        return NO_ERROR;
-    }
-
-    std::unique_ptr<Image> newImage = createImage();
-
-    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
-                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-    if (!created) {
-        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
-              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
-              buffer->getPixelFormat());
-        return NO_INIT;
-    }
-    mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
-
-    return NO_ERROR;
-}
-
-status_t GLESRenderEngine::bindExternalTextureBufferLocked(uint32_t texName,
-                                                           const sp<GraphicBuffer>& buffer,
-                                                           const sp<Fence>& bufferFence) {
-    ATRACE_CALL();
-    status_t cacheResult = cacheExternalTextureBufferLocked(buffer);
+    status_t cacheResult = cacheExternalTextureBuffer(buffer);
 
     if (cacheResult != NO_ERROR) {
         return cacheResult;
     }
 
-    auto cachedImage = mImageCache.find(buffer->getId());
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        auto cachedImage = mImageCache.find(buffer->getId());
 
-    if (cachedImage == mImageCache.end()) {
-        // We failed creating the image if we got here, so bail out.
-        bindExternalTextureImage(texName, *createImage());
-        return NO_INIT;
+        if (cachedImage == mImageCache.end()) {
+            // We failed creating the image if we got here, so bail out.
+            bindExternalTextureImage(texName, *createImage());
+            return NO_INIT;
+        }
+
+        bindExternalTextureImage(texName, *cachedImage->second);
     }
 
-    bindExternalTextureImage(texName, *cachedImage->second);
-
     // Wait for the new buffer to be ready.
     if (bufferFence != nullptr && bufferFence->isValid()) {
         if (GLExtensions::getInstance().hasWaitSync()) {
@@ -708,6 +659,45 @@
     return NO_ERROR;
 }
 
+status_t GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
+    if (buffer == nullptr) {
+        return BAD_VALUE;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        if (mImageCache.count(buffer->getId()) > 0) {
+            // If there's already an image then fail fast here.
+            return NO_ERROR;
+        }
+    }
+    ATRACE_CALL();
+
+    // Create the image without holding a lock so that we don't block anything.
+    std::unique_ptr<Image> newImage = createImage();
+
+    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
+                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+    if (!created) {
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+              buffer->getPixelFormat());
+        return NO_INIT;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        if (mImageCache.count(buffer->getId()) > 0) {
+            // In theory it's possible for another thread to recache the image,
+            // so bail out if another thread won.
+            return NO_ERROR;
+        }
+        mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
+    }
+
+    return NO_ERROR;
+}
+
 void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     const auto& cachedImage = mImageCache.find(bufferId);
@@ -743,6 +733,9 @@
     // We separate the layer into 3 parts essentially, such that we only turn on blending for the
     // top rectangle and the bottom rectangle, and turn off blending for the middle rectangle.
     FloatRect bounds = layer.geometry.roundedCornersCrop;
+
+    // Firstly, we need to convert the coordination from layer native coordination space to
+    // device coordination space.
     const auto transformMatrix = display.globalTransform * layer.geometry.positionTransform;
     const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
     const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
@@ -750,8 +743,28 @@
     const vec4 rightBottomCoordinateInBuffer = transformMatrix * rightBottomCoordinate;
     bounds = FloatRect(leftTopCoordinateInBuffer[0], leftTopCoordinateInBuffer[1],
                        rightBottomCoordinateInBuffer[0], rightBottomCoordinateInBuffer[1]);
-    const int32_t radius = ceil(layer.geometry.roundedCornersRadius);
 
+    // Secondly, if the display is rotated, we need to undo the rotation on coordination and
+    // align the (left, top) and (right, bottom) coordination with the device coordination
+    // space.
+    switch (display.orientation) {
+        case ui::Transform::ROT_90:
+            std::swap(bounds.left, bounds.right);
+            break;
+        case ui::Transform::ROT_180:
+            std::swap(bounds.left, bounds.right);
+            std::swap(bounds.top, bounds.bottom);
+            break;
+        case ui::Transform::ROT_270:
+            std::swap(bounds.top, bounds.bottom);
+            break;
+        default:
+            break;
+    }
+
+    // Finally, we cut the layer into 3 parts, with top and bottom parts having rounded corners
+    // and the middle part without rounded corners.
+    const int32_t radius = ceil(layer.geometry.roundedCornersRadius);
     const Rect topRect(bounds.left, bounds.top, bounds.right, bounds.top + radius);
     setScissor(topRect);
     drawMesh(mesh);
@@ -777,10 +790,6 @@
 
     // Bind the texture and turn our EGLImage into a texture
     glBindTexture(GL_TEXTURE_2D, textureName);
-    if (supportsProtectedContent()) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PROTECTED_EXT,
-                        mInProtectedContext ? GL_TRUE : GL_FALSE);
-    }
     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
 
     // Bind the Framebuffer to render into
@@ -788,7 +797,6 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
 
     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
     ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
              glStatus);
 
@@ -835,6 +843,7 @@
                                                              bool useFramebufferCache) {
     sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
     if (useFramebufferCache) {
+        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
         for (const auto& image : mFramebufferImageCache) {
             if (image.first == graphicBuffer->getId()) {
                 return image.second;
@@ -850,14 +859,20 @@
                                           nativeBuffer, attributes);
     if (useFramebufferCache) {
         if (image != EGL_NO_IMAGE_KHR) {
+            std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
             if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
                 EGLImageKHR expired = mFramebufferImageCache.front().second;
                 mFramebufferImageCache.pop_front();
                 eglDestroyImageKHR(mEGLDisplay, expired);
+                DEBUG_EGL_IMAGE_TRACKER_DESTROY();
             }
             mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
         }
     }
+
+    if (image != EGL_NO_IMAGE_KHR) {
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
+    }
     return image;
 }
 
@@ -882,157 +897,126 @@
         return BAD_VALUE;
     }
 
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
+    BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache);
 
-        BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache);
-
-        if (fbo.getStatus() != NO_ERROR) {
-            ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
-                  buffer->handle);
-            checkErrors();
-            return fbo.getStatus();
-        }
-
-        // clear the entire buffer, sometimes when we reuse buffers we'd persist
-        // ghost images otherwise.
-        // we also require a full transparent framebuffer for overlays. This is
-        // probably not quite efficient on all GPUs, since we could filter out
-        // opaque layers.
-        clearWithColor(0.0, 0.0, 0.0, 0.0);
-
-        setViewportAndProjection(display.physicalDisplay, display.clip);
-
-        setOutputDataSpace(display.outputDataspace);
-        setDisplayMaxLuminance(display.maxLuminance);
-
-        mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
-        mState.projectionMatrix = projectionMatrix;
-        if (!display.clearRegion.isEmpty()) {
-            glDisable(GL_BLEND);
-            fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
-        }
-
-        Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
-        for (auto layer : layers) {
-            mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
-
-            const FloatRect bounds = layer.geometry.boundaries;
-            Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-            position[0] = vec2(bounds.left, bounds.top);
-            position[1] = vec2(bounds.left, bounds.bottom);
-            position[2] = vec2(bounds.right, bounds.bottom);
-            position[3] = vec2(bounds.right, bounds.top);
-
-            setupLayerCropping(layer, mesh);
-            setColorTransform(display.colorTransform * layer.colorTransform);
-
-            bool usePremultipliedAlpha = true;
-            bool disableTexture = true;
-            bool isOpaque = false;
-
-            if (layer.source.buffer.buffer != nullptr) {
-                disableTexture = false;
-                isOpaque = layer.source.buffer.isOpaque;
-
-                sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
-                bindExternalTextureBufferLocked(layer.source.buffer.textureName, gBuf,
-                                                layer.source.buffer.fence);
-
-                usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
-                Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
-                mat4 texMatrix = layer.source.buffer.textureTransform;
-
-                texture.setMatrix(texMatrix.asArray());
-                texture.setFiltering(layer.source.buffer.useTextureFiltering);
-
-                texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
-                setSourceY410BT2020(layer.source.buffer.isY410BT2020);
-
-                renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
-                texCoords[0] = vec2(0.0, 0.0);
-                texCoords[1] = vec2(0.0, 1.0);
-                texCoords[2] = vec2(1.0, 1.0);
-                texCoords[3] = vec2(1.0, 0.0);
-                setupLayerTexturing(texture);
-            }
-
-            const half3 solidColor = layer.source.solidColor;
-            const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
-            // Buffer sources will have a black solid color ignored in the shader,
-            // so in that scenario the solid color passed here is arbitrary.
-            setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
-                               layer.geometry.roundedCornersRadius);
-            if (layer.disableBlending) {
-                glDisable(GL_BLEND);
-            }
-            setSourceDataSpace(layer.sourceDataspace);
-
-            // We only want to do a special handling for rounded corners when having rounded corners
-            // is the only reason it needs to turn on blending, otherwise, we handle it like the
-            // usual way since it needs to turn on blending anyway.
-            if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
-                handleRoundedCorners(display, layer, mesh);
-            } else {
-                drawMesh(mesh);
-            }
-
-            // Cleanup if there's a buffer source
-            if (layer.source.buffer.buffer != nullptr) {
-                disableBlending();
-                setSourceY410BT2020(false);
-                disableTexturing();
-            }
-        }
-
-        if (drawFence != nullptr) {
-            *drawFence = flush();
-        }
-        // If flush failed or we don't support native fences, we need to force the
-        // gl command stream to be executed.
-        if (drawFence == nullptr || drawFence->get() < 0) {
-            bool success = finish();
-            if (!success) {
-                ALOGE("Failed to flush RenderEngine commands");
-                checkErrors();
-                // Chances are, something illegal happened (either the caller passed
-                // us bad parameters, or we messed up our shader generation).
-                return INVALID_OPERATION;
-            }
-        }
-
+    if (fbo.getStatus() != NO_ERROR) {
+        ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
+              buffer->handle);
         checkErrors();
+        return fbo.getStatus();
     }
+
+    // clear the entire buffer, sometimes when we reuse buffers we'd persist
+    // ghost images otherwise.
+    // we also require a full transparent framebuffer for overlays. This is
+    // probably not quite efficient on all GPUs, since we could filter out
+    // opaque layers.
+    clearWithColor(0.0, 0.0, 0.0, 0.0);
+
+    setViewportAndProjection(display.physicalDisplay, display.clip);
+
+    setOutputDataSpace(display.outputDataspace);
+    setDisplayMaxLuminance(display.maxLuminance);
+
+    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+    mState.projectionMatrix = projectionMatrix;
+    if (!display.clearRegion.isEmpty()) {
+        glDisable(GL_BLEND);
+        fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
+    }
+
+    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
+    for (auto layer : layers) {
+        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
+
+        const FloatRect bounds = layer.geometry.boundaries;
+        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+        position[0] = vec2(bounds.left, bounds.top);
+        position[1] = vec2(bounds.left, bounds.bottom);
+        position[2] = vec2(bounds.right, bounds.bottom);
+        position[3] = vec2(bounds.right, bounds.top);
+
+        setupLayerCropping(layer, mesh);
+        setColorTransform(display.colorTransform * layer.colorTransform);
+
+        bool usePremultipliedAlpha = true;
+        bool disableTexture = true;
+        bool isOpaque = false;
+
+        if (layer.source.buffer.buffer != nullptr) {
+            disableTexture = false;
+            isOpaque = layer.source.buffer.isOpaque;
+
+            sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
+            bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
+                                      layer.source.buffer.fence);
+
+            usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
+            Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
+            mat4 texMatrix = layer.source.buffer.textureTransform;
+
+            texture.setMatrix(texMatrix.asArray());
+            texture.setFiltering(layer.source.buffer.useTextureFiltering);
+
+            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
+            setSourceY410BT2020(layer.source.buffer.isY410BT2020);
+
+            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+            texCoords[0] = vec2(0.0, 0.0);
+            texCoords[1] = vec2(0.0, 1.0);
+            texCoords[2] = vec2(1.0, 1.0);
+            texCoords[3] = vec2(1.0, 0.0);
+            setupLayerTexturing(texture);
+        }
+
+        const half3 solidColor = layer.source.solidColor;
+        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+        // Buffer sources will have a black solid color ignored in the shader,
+        // so in that scenario the solid color passed here is arbitrary.
+        setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
+                           layer.geometry.roundedCornersRadius);
+        if (layer.disableBlending) {
+            glDisable(GL_BLEND);
+        }
+        setSourceDataSpace(layer.sourceDataspace);
+
+        // We only want to do a special handling for rounded corners when having rounded corners
+        // is the only reason it needs to turn on blending, otherwise, we handle it like the
+        // usual way since it needs to turn on blending anyway.
+        if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
+            handleRoundedCorners(display, layer, mesh);
+        } else {
+            drawMesh(mesh);
+        }
+
+        // Cleanup if there's a buffer source
+        if (layer.source.buffer.buffer != nullptr) {
+            disableBlending();
+            setSourceY410BT2020(false);
+            disableTexturing();
+        }
+    }
+
+    if (drawFence != nullptr) {
+        *drawFence = flush();
+    }
+    // If flush failed or we don't support native fences, we need to force the
+    // gl command stream to be executed.
+    if (drawFence == nullptr || drawFence->get() < 0) {
+        bool success = finish();
+        if (!success) {
+            ALOGE("Failed to flush RenderEngine commands");
+            checkErrors();
+            // Chances are, something illegal happened (either the caller passed
+            // us bad parameters, or we messed up our shader generation).
+            return INVALID_OPERATION;
+        }
+    }
+
+    checkErrors();
     return NO_ERROR;
 }
 
-void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                                ui::Transform::orientation_flags rotation) {
-    setViewportAndProjection(Rect(vpw, vph), sourceCrop);
-
-    if (rotation == ui::Transform::ROT_0) {
-        return;
-    }
-
-    // Apply custom rotation to the projection.
-    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
-    mat4 m = mState.projectionMatrix;
-    switch (rotation) {
-        case ui::Transform::ROT_90:
-            m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_180:
-            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_270:
-            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
-            break;
-        default:
-            break;
-    }
-    mState.projectionMatrix = m;
-}
-
 void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
     ATRACE_CALL();
     mVpWidth = viewport.getWidth();
@@ -1096,14 +1080,6 @@
     mState.textureEnabled = true;
 }
 
-void GLESRenderEngine::setupLayerBlackedOut() {
-    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
-    Texture texture(Texture::TEXTURE_2D, mProtectedTexName);
-    texture.setDimensions(1, 1); // FIXME: we should get that from somewhere
-    mState.texture = texture;
-    mState.textureEnabled = true;
-}
-
 void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
     mState.colorMatrix = colorTransform;
 }
@@ -1289,7 +1265,9 @@
     StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
                   extensions.getVersion());
     StringAppendF(&result, "%s\n", extensions.getExtensions());
-    StringAppendF(&result, "RenderEngine is in protected context : %d\n", mInProtectedContext);
+    StringAppendF(&result, "RenderEngine supports protected context: %d\n",
+                  supportsProtectedContent());
+    StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
     StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n",
                   cache.getSize(mEGLContext));
     StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n",
@@ -1297,6 +1275,23 @@
     StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
                   dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
                   dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        StringAppendF(&result, "RenderEngine image cache size: %zu\n", mImageCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        for (const auto& [id, unused] : mImageCache) {
+            StringAppendF(&result, "0x%" PRIx64 "\n", id);
+        }
+    }
+    {
+        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
+        StringAppendF(&result, "RenderEngine framebuffer image cache size: %zu\n",
+                      mFramebufferImageCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        for (const auto& [id, unused] : mFramebufferImageCache) {
+            StringAppendF(&result, "0x%" PRIx64 "\n", id);
+        }
+    }
 }
 
 GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
@@ -1423,7 +1418,7 @@
 }
 
 bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
+    std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
     return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
                        [=](std::pair<uint64_t, EGLImageKHR> image) {
                            return image.first == bufferId;
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index de793c2..c8b45d2 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -50,7 +50,6 @@
 public:
     static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags,
                                                     uint32_t imageCacheSize);
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
     GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
                      EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
@@ -58,17 +57,7 @@
                      uint32_t imageCacheSize);
     ~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
 
-    std::unique_ptr<Framebuffer> createFramebuffer() override;
-    std::unique_ptr<Image> createImage() override;
-
     void primeCache() const override;
-    bool isCurrent() const override;
-    base::unique_fd flush() override;
-    bool finish() override;
-    bool waitFence(base::unique_fd fenceFd) override;
-    void clearWithColor(float red, float green, float blue, float alpha) override;
-    void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                             float alpha) override;
     void genTextures(size_t count, uint32_t* names) override;
     void deleteTextures(size_t count, uint32_t const* names) override;
     void bindExternalTextureImage(uint32_t texName, const Image& image) override;
@@ -78,53 +67,31 @@
     void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     status_t bindFrameBuffer(Framebuffer* framebuffer) override;
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
-    void checkErrors() const override;
 
     bool isProtected() const override { return mInProtectedContext; }
     bool supportsProtectedContent() const override;
     bool useProtectedContext(bool useProtectedContext) override;
     status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
                         ANativeWindowBuffer* buffer, const bool useFramebufferCache,
-                        base::unique_fd&& bufferFence, base::unique_fd* drawFence)
-            EXCLUDES(mRenderingMutex) override;
+                        base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
 
-    // internal to RenderEngine
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
-    EGLConfig getEGLConfig() const { return mEGLConfig; }
     // Creates an output image for rendering to
     EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                                               bool useFramebufferCache);
+                                               bool useFramebufferCache)
+            EXCLUDES(mFramebufferImageCacheMutex);
 
     // Test-only methods
     // Returns true iff mImageCache contains an image keyed by bufferId
     bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     // Returns true iff mFramebufferImageCache contains an image keyed by bufferId
-    bool isFramebufferImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
+    bool isFramebufferImageCachedForTesting(uint64_t bufferId)
+            EXCLUDES(mFramebufferImageCacheMutex);
 
 protected:
     Framebuffer* getFramebufferForDrawing() override;
-    void dump(std::string& result) override;
-    void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                  ui::Transform::orientation_flags rotation) override;
-    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                            const half4& color, float cornerRadius) override;
-    void setupLayerTexturing(const Texture& texture) override;
-    void setupLayerBlackedOut() override;
-    void setupFillWithColor(float r, float g, float b, float a) override;
-    void setColorTransform(const mat4& colorTransform) override;
-    void disableTexturing() override;
-    void disableBlending() override;
-    void setupCornerRadiusCropSize(float width, float height) override;
-
-    // HDR and color management related functions and state
-    void setSourceY410BT2020(bool enable) override;
-    void setSourceDataSpace(ui::Dataspace source) override;
-    void setOutputDataSpace(ui::Dataspace dataspace) override;
-    void setDisplayMaxLuminance(const float maxLuminance) override;
-
-    // drawing
-    void drawMesh(const Mesh& mesh) override;
-
+    void dump(std::string& result) override EXCLUDES(mRenderingMutex)
+            EXCLUDES(mFramebufferImageCacheMutex);
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
@@ -136,12 +103,16 @@
         GLES_VERSION_3_0 = 0x30000,
     };
 
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
     static GlesVersion parseGlesVersion(const char* str);
     static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                        EGLContext shareContext, bool useContextPriority,
                                        Protection protection);
     static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                    int hwcFormat, Protection protection);
+    std::unique_ptr<Framebuffer> createFramebuffer();
+    std::unique_ptr<Image> createImage();
+    void checkErrors() const;
     void setScissor(const Rect& region);
     void disableScissor();
     bool waitSync(EGLSyncKHR sync, EGLint flags);
@@ -165,6 +136,28 @@
     // blending is an expensive operation, we want to turn off blending when it's not necessary.
     void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer,
                               const Mesh& mesh);
+    base::unique_fd flush();
+    bool finish();
+    bool waitFence(base::unique_fd fenceFd);
+    void clearWithColor(float red, float green, float blue, float alpha);
+    void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha);
+    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                            const half4& color, float cornerRadius);
+    void setupLayerTexturing(const Texture& texture);
+    void setupFillWithColor(float r, float g, float b, float a);
+    void setColorTransform(const mat4& colorTransform);
+    void disableTexturing();
+    void disableBlending();
+    void setupCornerRadiusCropSize(float width, float height);
+
+    // HDR and color management related functions and state
+    void setSourceY410BT2020(bool enable);
+    void setSourceDataSpace(ui::Dataspace source);
+    void setOutputDataSpace(ui::Dataspace dataspace);
+    void setDisplayMaxLuminance(const float maxLuminance);
+
+    // drawing
+    void drawMesh(const Mesh& mesh);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
@@ -200,7 +193,11 @@
     uint32_t mFramebufferImageCacheSize = 0;
 
     // Cache of output images, keyed by corresponding GraphicBuffer ID.
-    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache;
+    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache
+            GUARDED_BY(mFramebufferImageCacheMutex);
+    // The only reason why we have this mutex is so that we don't segfault when
+    // dumping info.
+    std::mutex mFramebufferImageCacheMutex;
 
     // Current dataspace of layer being rendered
     ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
@@ -220,15 +217,6 @@
     // multiple threads is guaranteed thread-safe.
     std::mutex mRenderingMutex;
 
-    // See bindExternalTextureBuffer above, but requiring that mRenderingMutex
-    // is held.
-    status_t bindExternalTextureBufferLocked(uint32_t texName, const sp<GraphicBuffer>& buffer,
-                                             const sp<Fence>& fence) REQUIRES(mRenderingMutex);
-    // See cacheExternalTextureBuffer above, but requiring that mRenderingMutex
-    // is held.
-    status_t cacheExternalTextureBufferLocked(const sp<GraphicBuffer>& buffer)
-            REQUIRES(mRenderingMutex);
-
     std::unique_ptr<Framebuffer> mDrawingBuffer;
 
     class FlushTracer {
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index dacf8d3..5fbb5ba 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -22,6 +22,7 @@
 #include <GLES/glext.h>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <nativebase/nativebase.h>
 #include <utils/Trace.h>
 #include "GLESRenderEngine.h"
@@ -47,6 +48,7 @@
     if (mEGLImage != EGL_NO_IMAGE_KHR) {
         if (!usingFramebufferCache) {
             eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+            DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         }
         mEGLImage = EGL_NO_IMAGE_KHR;
         mBufferWidth = 0;
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
index 77e648e..8497721 100644
--- a/libs/renderengine/gl/GLImage.cpp
+++ b/libs/renderengine/gl/GLImage.cpp
@@ -20,6 +20,7 @@
 
 #include <vector>
 
+#include <gui/DebugEGLImageTracker.h>
 #include <log/log.h>
 #include <utils/Trace.h>
 #include "GLESRenderEngine.h"
@@ -58,6 +59,7 @@
         if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
             ALOGE("failed to destroy image: %#x", eglGetError());
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         mEGLImage = EGL_NO_IMAGE_KHR;
     }
 
@@ -69,6 +71,7 @@
             ALOGE("failed to create EGLImage: %#x", eglGetError());
             return false;
         }
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
         mProtected = isProtected;
     }
 
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index cd1182c..086a324 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -575,7 +575,9 @@
             float applyCornerRadius(vec2 cropCoords)
             {
                 vec2 position = cropCoords - cropCenter;
-                vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
+                // Increase precision here so that a large corner radius doesn't
+                // cause floating point error
+                highp vec2 dist = abs(position) + vec2(cornerRadius) - cropCenter;
                 float plane = length(max(dist, vec2(0.0)));
                 return 1.0 - clamp(plane - cornerRadius, 0.0, 1.0);
             }
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index af8de23..9c9884a 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -20,6 +20,7 @@
 #include <ui/GraphicTypes.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
+#include <ui/Transform.h>
 
 namespace android {
 namespace renderengine {
@@ -56,6 +57,9 @@
     // globalTransform, so that it will be in the same coordinate space as the
     // rendered layers.
     Region clearRegion = Region::INVALID_REGION;
+
+    // The orientation of the physical display.
+    uint32_t orientation = ui::Transform::ROT_0;
 };
 
 } // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index bf614fd..1c480a7 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -63,6 +63,9 @@
     enum FeatureFlag {
         USE_COLOR_MANAGEMENT = 1 << 0,      // Device manages color
         USE_HIGH_PRIORITY_CONTEXT = 1 << 1, // Use high priority context
+
+        // Create a protected context when if possible
+        ENABLE_PROTECTED_CONTEXT = 1 << 2,
     };
 
     static std::unique_ptr<impl::RenderEngine> create(int hwcFormat, uint32_t featureFlags,
@@ -74,10 +77,6 @@
     // This interface, while still in use until a suitable replacement is built,
     // should be considered deprecated, minus some methods which still may be
     // used to support legacy behavior.
-
-    virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
-    virtual std::unique_ptr<Image> createImage() = 0;
-
     virtual void primeCache() const = 0;
 
     // dump the extension strings. always call the base class.
@@ -85,24 +84,6 @@
 
     virtual bool useNativeFenceSync() const = 0;
     virtual bool useWaitSync() const = 0;
-
-    virtual bool isCurrent() const = 0;
-
-    // helpers
-    // flush submits RenderEngine command stream for execution and returns a
-    // native fence fd that is signaled when the execution has completed.  It
-    // returns -1 on errors.
-    virtual base::unique_fd flush() = 0;
-    // finish waits until RenderEngine command stream has been executed.  It
-    // returns false on errors.
-    virtual bool finish() = 0;
-    // waitFence inserts a wait on an external fence fd to RenderEngine
-    // command stream.  It returns false on errors.
-    virtual bool waitFence(base::unique_fd fenceFd) = 0;
-
-    virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
-    virtual void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                                     float alpha) = 0;
     virtual void genTextures(size_t count, uint32_t* names) = 0;
     virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
     virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
@@ -123,40 +104,6 @@
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
     virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
 
-    // set-up
-    virtual void checkErrors() const = 0;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                          ui::Transform::orientation_flags rotation) = 0;
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                                    const half4& color, float cornerRadius) = 0;
-    virtual void setupLayerTexturing(const Texture& texture) = 0;
-    virtual void setupLayerBlackedOut() = 0;
-    virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
-    // Sets up the crop size for corner radius clipping.
-    //
-    // Having corner radius will force GPU composition on the layer and its children, drawing it
-    // with a special shader. The shader will receive the radius and the crop rectangle as input,
-    // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
-    // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
-    // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
-    // in local layer coordinate space, so we have to take the layer transform into account when
-    // walking up the tree.
-    virtual void setupCornerRadiusCropSize(float width, float height) = 0;
-
-    // Set a color transform matrix that is applied in linear space right before OETF.
-    virtual void setColorTransform(const mat4& /* colorTransform */) = 0;
-    virtual void disableTexturing() = 0;
-    virtual void disableBlending() = 0;
-
-    // HDR and color management support
-    virtual void setSourceY410BT2020(bool enable) = 0;
-    virtual void setSourceDataSpace(ui::Dataspace source) = 0;
-    virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0;
-    virtual void setDisplayMaxLuminance(const float maxLuminance) = 0;
-
-    // drawing
-    virtual void drawMesh(const Mesh& mesh) = 0;
-
     // queries
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
@@ -173,6 +120,17 @@
     // should be called for every display that needs to be rendered via the GPU.
     // @param display The display-wide settings that should be applied prior to
     // drawing any layers.
+    //
+    // Assumptions when calling this method:
+    // 1. There is exactly one caller - i.e. multi-threading is not supported.
+    // 2. Additional threads may be calling the {bind,cache}ExternalTexture
+    // methods above. But the main thread is responsible for holding resources
+    // such that Image destruction does not occur while this method is called.
+    //
+    // TODO(b/136806342): This should behavior should ideally be fixed since
+    // the above two assumptions are brittle, as conditional thread safetyness
+    // may be insufficient when maximizing rendering performance in the future.
+    //
     // @param layers The layers to draw onto the display, in Z-order.
     // @param buffer The buffer which will be drawn to. This buffer will be
     // ready once drawFence fires.
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index e33bcfd..f099cd2 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -34,20 +34,12 @@
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
-    MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(std::string&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
-    MOCK_METHOD0(flush, base::unique_fd());
-    MOCK_METHOD0(finish, bool());
-    MOCK_METHOD1(waitFence, bool(base::unique_fd*));
-    bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
-    MOCK_METHOD4(clearWithColor, void(float, float, float, float));
-    MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float));
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
     MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
@@ -55,22 +47,6 @@
     MOCK_METHOD3(bindExternalTextureBuffer,
                  status_t(uint32_t, const sp<GraphicBuffer>&, const sp<Fence>&));
     MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t));
-    MOCK_CONST_METHOD0(checkErrors, void());
-    MOCK_METHOD4(setViewportAndProjection,
-                 void(size_t, size_t, Rect, ui::Transform::orientation_flags));
-    MOCK_METHOD5(setupLayerBlending, void(bool, bool, bool, const half4&, float));
-    MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
-    MOCK_METHOD0(setupLayerBlackedOut, void());
-    MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
-    MOCK_METHOD2(setupCornerRadiusCropSize, void(float, float));
-    MOCK_METHOD1(setColorTransform, void(const mat4&));
-    MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
-    MOCK_METHOD0(disableTexturing, void());
-    MOCK_METHOD0(disableBlending, void());
-    MOCK_METHOD1(setSourceY410BT2020, void(bool));
-    MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
     MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*));
     MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*));
     MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index d9a986e..139987e 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -22,6 +22,13 @@
 #include <binder/IPermissionController.h>
 #include <binder/IServiceManager.h>
 
+/*
+ * The permission to use for activity recognition sensors (like step counter).
+ * See sensor types for more details on what sensors should require this
+ * permission.
+ */
+#define SENSOR_PERMISSION_ACTIVITY_RECOGNITION "android.permission.ACTIVITY_RECOGNITION"
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -116,7 +123,7 @@
         mStringType = SENSOR_STRING_TYPE_HEART_RATE;
         mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
         AppOpsManager appOps;
-        mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
+        mRequiredAppOp = appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         } break;
     case SENSOR_TYPE_LIGHT:
@@ -165,14 +172,22 @@
             mFlags |= SENSOR_FLAG_WAKE_UP;
         }
         break;
-    case SENSOR_TYPE_STEP_COUNTER:
+    case SENSOR_TYPE_STEP_COUNTER: {
         mStringType = SENSOR_STRING_TYPE_STEP_COUNTER;
+        mRequiredPermission = SENSOR_PERMISSION_ACTIVITY_RECOGNITION;
+        AppOpsManager appOps;
+        mRequiredAppOp =
+                appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
-        break;
-    case SENSOR_TYPE_STEP_DETECTOR:
+        } break;
+    case SENSOR_TYPE_STEP_DETECTOR: {
         mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR;
+        mRequiredPermission = SENSOR_PERMISSION_ACTIVITY_RECOGNITION;
+        AppOpsManager appOps;
+        mRequiredAppOp =
+                appOps.permissionToOpCode(String16(mRequiredPermission));
         mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
-        break;
+        } break;
     case SENSOR_TYPE_TEMPERATURE:
         mStringType = SENSOR_STRING_TYPE_TEMPERATURE;
         mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 5840d51..96d5eb9 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -94,7 +94,7 @@
 
 SensorManager::SensorManager(const String16& opPackageName)
     : mSensorList(nullptr), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
-    // okay we're not locked here, but it's not needed during construction
+    Mutex::Autolock _l(mLock);
     assertStateLocked();
 }
 
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index e0e3469..4a606ff 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -28,8 +28,7 @@
     ],
 
     srcs: [
-        "aidl/android/hardware/ISensorPrivacyListener.aidl",
-        "aidl/android/hardware/ISensorPrivacyManager.aidl",
+        ":libsensorprivacy_aidl",
         "SensorPrivacyManager.cpp",
     ],
 
@@ -45,3 +44,12 @@
 
     export_shared_lib_headers: ["libbinder"],
 }
+
+filegroup {
+    name: "libsensorprivacy_aidl",
+    srcs: [
+        "aidl/android/hardware/ISensorPrivacyListener.aidl",
+        "aidl/android/hardware/ISensorPrivacyManager.aidl",
+    ],
+    path: "aidl",
+}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 755418e..2cc6857 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -82,6 +82,9 @@
         "frameworks/native/include",
     ],
 
+    // Uncomment the following line to enable VALIDATE_REGIONS traces
+    //defaults: ["libui-validate-regions-defaults"],
+
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.allocator@2.0",
@@ -92,13 +95,11 @@
         "android.hardware.graphics.mapper@3.0",
         "libbase",
         "libcutils",
-        "libhardware",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
         "libsync",
         "libutils",
-        "libutilscallstack",
         "liblog",
     ],
 
@@ -175,6 +176,13 @@
     ],
 }
 
+// defaults to enable VALIDATE_REGIONS traces
+cc_defaults {
+    name: "libui-validate-regions-defaults",
+    shared_libs: ["libutilscallstack"],
+    cflags: ["-DVALIDATE_REGIONS"],
+}
+
 subdirs = [
     "tests",
     "tools",
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index da91a97..1dfc1e9 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "BufferHubBuffer"
 #include <poll.h>
 
 #include <android-base/unique_fd.h>
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp
index 340231d..bdfe04b 100644
--- a/libs/ui/FenceTime.cpp
+++ b/libs/ui/FenceTime.cpp
@@ -279,8 +279,8 @@
 }
 
 void FenceTimeline::updateSignalTimes() {
+    std::lock_guard<std::mutex> lock(mMutex);
     while (!mQueue.empty()) {
-        std::lock_guard<std::mutex> lock(mMutex);
         std::shared_ptr<FenceTime> fence = mQueue.front().lock();
         if (!fence) {
             // The shared_ptr no longer exists and no one cares about the
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index 7f8e57c..eb43765 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -28,7 +28,7 @@
 #pragma clang diagnostic pop
 
 using android::hardware::graphics::allocator::V3_0::IAllocator;
-using android::hardware::graphics::common::V1_1::BufferUsage;
+using android::hardware::graphics::common::V1_2::BufferUsage;
 using android::hardware::graphics::mapper::V3_0::BufferDescriptor;
 using android::hardware::graphics::mapper::V3_0::Error;
 using android::hardware::graphics::mapper::V3_0::IMapper;
@@ -44,11 +44,7 @@
     static const uint64_t validUsageBits = []() -> uint64_t {
         uint64_t bits = 0;
         for (const auto bit :
-             hardware::hidl_enum_range<hardware::graphics::common::V1_0::BufferUsage>()) {
-            bits = bits | bit;
-        }
-        for (const auto bit :
-             hardware::hidl_enum_range<hardware::graphics::common::V1_1::BufferUsage>()) {
+             hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
             bits = bits | bit;
         }
         return bits;
@@ -71,7 +67,7 @@
     outDescriptorInfo->width = width;
     outDescriptorInfo->height = height;
     outDescriptorInfo->layerCount = layerCount;
-    outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
+    outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
     outDescriptorInfo->usage = usage;
 }
 
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3fc6a2d..579e68e 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -626,7 +626,7 @@
                            bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
                            bufferHubBuffer->desc().stride);
     mBufferId = bufferHubBuffer->id();
-    mBufferHubBuffer.reset(std::move(bufferHubBuffer.get()));
+    mBufferHubBuffer = std::move(bufferHubBuffer);
 
     return NO_ERROR;
 }
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 5a67dc4..9c7d1fd 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -20,6 +20,7 @@
 
 #include <ui/GraphicBufferAllocator.h>
 
+#include <limits.h>
 #include <stdio.h>
 
 #include <grallocusage/GrallocUsageConversion.h>
@@ -60,6 +61,15 @@
 
 GraphicBufferAllocator::~GraphicBufferAllocator() {}
 
+size_t GraphicBufferAllocator::getTotalSize() const {
+    Mutex::Autolock _l(sLock);
+    size_t total = 0;
+    for (size_t i = 0; i < sAllocList.size(); ++i) {
+        total += sAllocList.valueAt(i).size;
+    }
+    return total;
+}
+
 void GraphicBufferAllocator::dump(std::string& result) const {
     Mutex::Autolock _l(sLock);
     KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
@@ -105,6 +115,14 @@
     if (!width || !height)
         width = height = 1;
 
+    const uint32_t bpp = bytesPerPixel(format);
+    if (std::numeric_limits<size_t>::max() / width / height < static_cast<size_t>(bpp)) {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+              "usage %" PRIx64 ": Requesting too large a buffer size",
+              width, height, layerCount, format, usage);
+        return BAD_VALUE;
+    }
+
     // Ensure that layerCount is valid.
     if (layerCount < 1)
         layerCount = 1;
@@ -117,7 +135,6 @@
     if (error == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        uint32_t bpp = bytesPerPixel(format);
         alloc_rec_t rec;
         rec.width = width;
         rec.height = height;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 224dc2c..55e3b99 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -22,7 +22,6 @@
 #include <android-base/stringprintf.h>
 
 #include <utils/Log.h>
-#include <utils/CallStack.h>
 
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -31,10 +30,18 @@
 #include <private/ui/RegionHelper.h>
 
 // ----------------------------------------------------------------------------
-#define VALIDATE_REGIONS        (false)
+
+// ### VALIDATE_REGIONS ###
+// To enable VALIDATE_REGIONS traces, use the "libui-validate-regions-defaults"
+// in Android.bp. Do not #define VALIDATE_REGIONS here as it requires extra libs.
+
 #define VALIDATE_WITH_CORECG    (false)
 // ----------------------------------------------------------------------------
 
+#if defined(VALIDATE_REGIONS)
+#include <utils/CallStack.h>
+#endif
+
 #if VALIDATE_WITH_CORECG
 #include <core/SkRegion.h>
 #endif
@@ -67,7 +74,7 @@
 Region::Region(const Region& rhs)
     : mStorage(rhs.mStorage)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(rhs, "rhs copy-ctor");
 #endif
 }
@@ -203,7 +210,7 @@
             outputRegion.mStorage, direction_LTR);
     outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(outputRegion, "T-Junction free region");
 #endif
 
@@ -212,7 +219,7 @@
 
 Region& Region::operator = (const Region& rhs)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(*this, "this->operator=");
     validate(rhs, "rhs.operator=");
 #endif
@@ -599,10 +606,12 @@
         result = false;
         ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
     }
+#if defined(VALIDATE_REGIONS)
     if (result == false && !silent) {
         reg.dump(name);
         CallStack stack(LOG_TAG);
     }
+#endif
     return result;
 }
 
@@ -610,7 +619,7 @@
         const Region& lhs,
         const Region& rhs, int dx, int dy)
 {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(lhs, "boolean_operation (before): lhs");
     validate(rhs, "boolean_operation (before): rhs");
     validate(dst, "boolean_operation (before): dst");
@@ -630,7 +639,7 @@
         operation(r);
     }
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(lhs, "boolean_operation: lhs");
     validate(rhs, "boolean_operation: rhs");
     validate(dst, "boolean_operation: dst");
@@ -728,7 +737,7 @@
         return;
     }
 
-#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
+#if VALIDATE_WITH_CORECG || defined(VALIDATE_REGIONS)
     boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
 #else
     size_t lhs_count;
@@ -760,7 +769,7 @@
 void Region::translate(Region& reg, int dx, int dy)
 {
     if ((dx || dy) && !reg.isEmpty()) {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
         validate(reg, "translate (before)");
 #endif
         size_t count = reg.mStorage.size();
@@ -770,7 +779,7 @@
             rects++;
             count--;
         }
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
         validate(reg, "translate (after)");
 #endif
     }
@@ -789,7 +798,7 @@
 }
 
 status_t Region::flatten(void* buffer, size_t size) const {
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(*this, "Region::flatten");
 #endif
     if (size < getFlattenedSize()) {
@@ -836,7 +845,7 @@
         result.mStorage.push_back(rect);
     }
 
-#if VALIDATE_REGIONS
+#if defined(VALIDATE_REGIONS)
     validate(result, "Region::unflatten");
 #endif
 
diff --git a/libs/ui/include/ui/BufferQueueDefs.h b/libs/ui/include/ui/BufferQueueDefs.h
index 56de181..0fecda9 100644
--- a/libs/ui/include/ui/BufferQueueDefs.h
+++ b/libs/ui/include/ui/BufferQueueDefs.h
@@ -23,6 +23,16 @@
         // Attempts at runtime to increase the number of buffers past this
         // will fail.
         static constexpr int NUM_BUFFER_SLOTS = 64;
+
+        enum {
+            // A flag returned by dequeueBuffer when the client needs to call
+            // requestBuffer immediately thereafter.
+            BUFFER_NEEDS_REALLOCATION = 0x1,
+            // A flag returned by dequeueBuffer when all mirrored slots should be
+            // released by the client. This flag should always be processed first.
+            RELEASE_ALL_BUFFERS       = 0x2,
+        };
+
     } // namespace BufferQueueDefs
 } // namespace android
 
diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
index a5a1fcb..ecba7f7 100644
--- a/libs/ui/include/ui/FenceTime.h
+++ b/libs/ui/include/ui/FenceTime.h
@@ -19,6 +19,7 @@
 
 #include <ui/Fence.h>
 #include <utils/Flattenable.h>
+#include <utils/Mutex.h>
 #include <utils/Timers.h>
 
 #include <atomic>
@@ -159,7 +160,7 @@
 
 private:
     mutable std::mutex mMutex;
-    std::queue<std::weak_ptr<FenceTime>> mQueue;
+    std::queue<std::weak_ptr<FenceTime>> mQueue GUARDED_BY(mMutex);
 };
 
 // Used by test code to create or get FenceTimes for a given Fence.
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 3a547b6..25d4512 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -49,6 +49,8 @@
 
     status_t free(buffer_handle_t handle);
 
+    size_t getTotalSize() const;
+
     void dump(std::string& res) const;
     static void dumpToSystemLog();
 
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 373fa4f..c5170d0 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -46,6 +46,24 @@
     cflags: ["-Wall", "-Werror"],
 }
 
+// This test has a main method, and requires a separate binary to be built.
+cc_test {
+    name: "GraphicBufferOverBinder_test",
+    srcs: ["GraphicBufferOverBinder_test.cpp"],
+    cflags: ["-Wall", "-Werror"],
+    header_libs: [
+        "libdvr_headers",
+    ],
+    shared_libs: [
+        "android.frameworks.bufferhub@1.0",
+        "libbinder",
+        "libgui",
+        "liblog",
+        "libui",
+        "libutils",
+    ],
+}
+
 cc_test {
     name: "BufferHub_test",
     header_libs: [
diff --git a/libs/ui/tests/GraphicBufferOverBinder_test.cpp b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
new file mode 100644
index 0000000..7c0a44a
--- /dev/null
+++ b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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 "GraphicBufferOverBinder_test"
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <ui/BufferHubBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Log.h>
+
+namespace android {
+
+constexpr uint32_t kTestWidth = 1024;
+constexpr uint32_t kTestHeight = 1;
+constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint32_t kTestLayerCount = 1;
+constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+static const String16 kTestServiceName = String16("GraphicBufferOverBinderTestService");
+enum GraphicBufferOverBinderTestServiceCode {
+    GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER,
+};
+
+class GraphicBufferOverBinderTestService : public BBinder {
+public:
+    GraphicBufferOverBinderTestService() {
+        // GraphicBuffer
+        mGraphicBuffer = new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount,
+                                           kTestUsage);
+        ALOGI("mGraphicBuffer id %" PRIi32, mGraphicBuffer->getBufferId());
+
+        // BufferHub-backed GraphicBuffer
+        std::unique_ptr<BufferHubBuffer> bufferHubBuffer =
+                BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+                                        kTestUsage, /*userMetadataSize=*/0);
+        mBufferhubBackedGraphicBuffer = new GraphicBuffer(std::move(bufferHubBuffer));
+        if (!mBufferhubBackedGraphicBuffer->isBufferHubBuffer()) {
+            ALOGE("Failed to back GraphicBuffer with BufferHub.");
+        }
+        if (bufferHubBuffer != nullptr) {
+            ALOGE("Failed to move BufferHubBuffer to GraphicBuffer");
+        }
+        ALOGI("mBufferhubBackedGraphicBuffer id %" PRIi32,
+              mBufferhubBackedGraphicBuffer->getBufferId());
+    }
+
+    ~GraphicBufferOverBinderTestService() = default;
+
+    virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
+                                uint32_t /*flags*/ = 0) {
+        switch (code) {
+            case GRAPHIC_BUFFER: {
+                return reply->write(*mGraphicBuffer);
+            }
+            case GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER: {
+                return reply->write(*mBufferhubBackedGraphicBuffer);
+            }
+            default:
+                return UNKNOWN_TRANSACTION;
+        };
+    }
+
+protected:
+    sp<GraphicBuffer> mGraphicBuffer;
+    sp<GraphicBuffer> mBufferhubBackedGraphicBuffer;
+};
+
+static int runBinderServer() {
+    ProcessState::self()->startThreadPool();
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<GraphicBufferOverBinderTestService> service = new GraphicBufferOverBinderTestService;
+    sm->addService(kTestServiceName, service, false);
+
+    ALOGI("Binder server running...");
+
+    while (true) {
+        int stat, retval;
+        retval = wait(&stat);
+        if (retval == -1 && errno == ECHILD) {
+            break;
+        }
+    }
+
+    ALOGI("Binder server exiting...");
+    return 0;
+}
+
+class GraphicBufferOverBinderTest : public ::testing::TestWithParam<uint32_t> {
+protected:
+    virtual void SetUp() {
+        mService = defaultServiceManager()->getService(kTestServiceName);
+        if (mService == nullptr) {
+            ALOGE("Failed to connect to the test service.");
+            return;
+        }
+
+        ALOGI("Binder service is ready for client.");
+    }
+
+    status_t GetGraphicBuffer(sp<GraphicBuffer>* outBuf, uint32_t opCode) {
+        Parcel data;
+        Parcel reply;
+        status_t error = mService->transact(opCode, data, &reply);
+        if (error != NO_ERROR) {
+            ALOGE("Failed to get graphic buffer over binder, error=%d.", error);
+            return error;
+        }
+
+        *outBuf = new GraphicBuffer();
+        return reply.read(**outBuf);
+    }
+
+private:
+    sp<IBinder> mService;
+};
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER), OK);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_FALSE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferFromBufferHubBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER), NO_ERROR);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_TRUE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        android::ProcessState::self()->startThreadPool();
+        ::testing::InitGoogleTest(&argc, argv);
+        return RUN_ALL_TESTS();
+
+    } else {
+        ALOGI("Test process pid: %d.", pid);
+        return android::runBinderServer();
+    }
+}
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index a7c248c..127f7ee 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -35,6 +35,22 @@
 
 class GraphicBufferTest : public testing::Test {};
 
+TEST_F(GraphicBufferTest, AllocateNoError) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    sp<GraphicBuffer> gb(new GraphicBuffer(kTestWidth, kTestHeight, format, kTestLayerCount,
+                                           kTestUsage, std::string("test")));
+    ASSERT_EQ(NO_ERROR, gb->initCheck());
+}
+
+TEST_F(GraphicBufferTest, AllocateBadDimensions) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    uint32_t width, height;
+    width = height = std::numeric_limits<uint32_t>::max();
+    sp<GraphicBuffer> gb(new GraphicBuffer(width, height, format, kTestLayerCount, kTestUsage,
+                                           std::string("test")));
+    ASSERT_EQ(BAD_VALUE, gb->initCheck());
+}
+
 TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) {
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 115e866..7823e36 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -52,12 +52,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s Failed to acquire the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to acquire the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again if the buffer is still posted.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientPosted(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -152,12 +146,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to release the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to release the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     // The failure of compare_exchange_weak updates current_buffer_state.
     updated_buffer_state = current_buffer_state & (~client_state_mask());
   }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 3d88ba5..aa9d072 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -96,13 +96,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to post the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to post the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still gained by this client.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientGained(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -186,15 +179,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to gain the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to gain the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still not read by other "
-        "clients.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
-
     if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) ||
         BufferHubDefs::isAnyClientGained(current_buffer_state) ||
         (BufferHubDefs::isAnyClientPosted(
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 9f72c05..77c7911 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -26,10 +26,8 @@
 ]
 
 sharedLibraries = [
-    "libbase",
     "libbinder",
     "libcutils",
-    "libhardware",
     "liblog",
     "libui",
     "libutils",
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c0bace8..8144c8a 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -162,7 +162,7 @@
         "libEGL_getProcAddress",
         "libEGL_blobCache",
     ],
-    ldflags: ["-Wl,--exclude-libs=ALL"],
+    ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"],
     export_include_dirs: ["EGL/include"],
 }
 
@@ -208,6 +208,10 @@
     defaults: ["gles_libs_defaults"],
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv2\""],
+
+    // Bug: http://b/133874658  Disable native_coverage as we investigate a
+    // crash in surfaceflinger on coverage-enabled cuttlefish builds.
+    native_coverage: false,
 }
 
 //##############################################################################
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 259242b..23e11a8 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -39,10 +39,7 @@
 #include "egldefs.h"
 #include <EGL/eglext_angle.h>
 
-// ----------------------------------------------------------------------------
 namespace android {
-// ----------------------------------------------------------------------------
-
 
 /*
  * EGL userspace drivers must be provided either:
@@ -72,41 +69,6 @@
     return loader;
 }
 
-/* This function is called to check whether we run inside the emulator,
- * and if this is the case whether GLES GPU emulation is supported.
- *
- * Returned values are:
- *  -1   -> not running inside the emulator
- *   0   -> running inside the emulator, but GPU emulation not supported
- *   1   -> running inside the emulator, GPU emulation is supported
- *          through the "emulation" host-side OpenGL ES implementation.
- *   2   -> running inside the emulator, GPU emulation is supported
- *          through a guest-side vendor driver's OpenGL ES implementation.
- */
-static int
-checkGlesEmulationStatus(void)
-{
-    /* We're going to check for the following kernel parameters:
-     *
-     *    qemu=1                      -> tells us that we run inside the emulator
-     *    android.qemu.gles=<number>  -> tells us the GLES GPU emulation status
-     *
-     * Note that we will return <number> if we find it. This let us support
-     * more additionnal emulation modes in the future.
-     */
-    char  prop[PROPERTY_VALUE_MAX];
-    int   result = -1;
-
-    /* First, check for qemu=1 */
-    property_get("ro.kernel.qemu",prop,"0");
-    if (atoi(prop) != 1)
-        return -1;
-
-    /* We are in the emulator, get GPU status value */
-    property_get("qemu.gles",prop,"0");
-    return atoi(prop);
-}
-
 static void* do_dlopen(const char* path, int mode) {
     ATRACE_CALL();
     return dlopen(path, mode);
@@ -122,7 +84,10 @@
     return android_load_sphal_library(path, mode);
 }
 
-// ----------------------------------------------------------------------------
+static int do_android_unload_sphal_library(void* dso) {
+    ATRACE_CALL();
+    return android_unload_sphal_library(dso);
+}
 
 Loader::driver_t::driver_t(void* gles)
 {
@@ -159,8 +124,6 @@
     return 0;
 }
 
-// ----------------------------------------------------------------------------
-
 Loader::Loader()
     : getProcAddress(nullptr)
 {
@@ -215,13 +178,87 @@
     }
 }
 
+static const char* DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
+
+static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
+    DRIVER_SUFFIX_PROPERTY,
+    "ro.board.platform",
+};
+
+static bool should_unload_system_driver(egl_connection_t* cnx) {
+    // Return false if the system driver has been unloaded once.
+    if (cnx->systemDriverUnloaded) {
+        return false;
+    }
+
+    // Return true if Angle namespace is set.
+    android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+    if (ns) {
+        return true;
+    }
+
+#ifndef __ANDROID_VNDK__
+    // Return true if updated driver namespace is set.
+    ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+    if (ns) {
+        return true;
+    }
+#endif
+
+    return false;
+}
+
+static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
+    while (*api) {
+        *curr++ = nullptr;
+        api++;
+    }
+}
+
+void Loader::unload_system_driver(egl_connection_t* cnx) {
+    ATRACE_CALL();
+
+    uninit_api(gl_names,
+               (__eglMustCastToProperFunctionPointerType*)&cnx
+                       ->hooks[egl_connection_t::GLESv2_INDEX]
+                       ->gl);
+    uninit_api(gl_names,
+               (__eglMustCastToProperFunctionPointerType*)&cnx
+                       ->hooks[egl_connection_t::GLESv1_INDEX]
+                       ->gl);
+    uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
+
+    if (cnx->dso) {
+        ALOGD("Unload system gl driver.");
+        driver_t* hnd = (driver_t*)cnx->dso;
+        if (hnd->dso[2]) {
+            do_android_unload_sphal_library(hnd->dso[2]);
+        }
+        if (hnd->dso[1]) {
+            do_android_unload_sphal_library(hnd->dso[1]);
+        }
+        if (hnd->dso[0]) {
+            do_android_unload_sphal_library(hnd->dso[0]);
+        }
+        cnx->dso = nullptr;
+    }
+
+    cnx->systemDriverUnloaded = true;
+}
+
 void* Loader::open(egl_connection_t* cnx)
 {
     ATRACE_CALL();
     const nsecs_t openTime = systemTime();
 
-    void* dso;
-    driver_t* hnd = nullptr;
+    if (should_unload_system_driver(cnx)) {
+        unload_system_driver(cnx);
+    }
+
+    // If a driver has been loaded, return the driver directly.
+    if (cnx->dso) {
+        return cnx->dso;
+    }
 
     setEmulatorGlesValue();
 
@@ -232,34 +269,68 @@
         cnx->shouldUseAngle = false;
     }
 
-    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
-    if (dso) {
-        hnd = new driver_t(dso);
-    } else {
-        android::GraphicsEnv::getInstance().clearDriverLoadingInfo(
-                android::GraphicsEnv::Api::API_GL);
-        // Always load EGL first
-        dso = load_driver("EGL", cnx, EGL);
-        if (dso) {
-            hnd = new driver_t(dso);
-            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
-            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );
+    // Firstly, try to load ANGLE driver.
+    driver_t* hnd = attempt_to_load_angle(cnx);
+    if (!hnd) {
+        // Secondly, try to load from driver apk.
+        hnd = attempt_to_load_updated_driver(cnx);
+    }
+
+    bool failToLoadFromDriverSuffixProperty = false;
+    if (!hnd) {
+        // Finally, try to load system driver, start by searching for the library name appended by
+        // the system properties of the GLES userspace driver in both locations.
+        // i.e.:
+        //      libGLES_${prop}.so, or:
+        //      libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+        char prop[PROPERTY_VALUE_MAX + 1];
+        for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+            if (property_get(key, prop, nullptr) <= 0) {
+                continue;
+            }
+            hnd = attempt_to_load_system_driver(cnx, prop, true);
+            if (hnd) {
+                break;
+            } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+                failToLoadFromDriverSuffixProperty = true;
+            }
         }
     }
 
     if (!hnd) {
-        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+        // Can't find graphics driver by appending system properties, now search for the exact name
+        // without any suffix of the GLES userspace driver in both locations.
+        // i.e.:
+        //      libGLES.so, or:
+        //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
+        hnd = attempt_to_load_system_driver(cnx, nullptr, true);
+    }
+
+    if (!hnd && !failToLoadFromDriverSuffixProperty) {
+        hnd = attempt_to_load_system_driver(cnx, nullptr, false);
+    }
+
+    if (!hnd) {
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
                                                             false, systemTime() - openTime);
     }
 
-    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
+    LOG_ALWAYS_FATAL_IF(!hnd,
+                        "couldn't find an OpenGL ES implementation, make sure you set %s or %s",
+                        HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
 
-    cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
-    cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
-    cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+    if (!cnx->libEgl) {
+        cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+    }
+    if (!cnx->libGles1) {
+        cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+    }
+    if (!cnx->libGles2) {
+        cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
+    }
 
     if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
-        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
                                                             false, systemTime() - openTime);
     }
 
@@ -269,7 +340,7 @@
     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
             "couldn't load system OpenGL ES wrapper libraries");
 
-    android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true,
+    android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL, true,
                                                         systemTime() - openTime);
 
     return (void*)hnd;
@@ -360,43 +431,11 @@
     }
 }
 
-static void* load_system_driver(const char* kind) {
+static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
     ATRACE_CALL();
     class MatchFile {
     public:
-        static std::string find(const char* kind) {
-            std::string result;
-            int emulationStatus = checkGlesEmulationStatus();
-            switch (emulationStatus) {
-                case 0:
-#if defined(__LP64__)
-                    result = "/vendor/lib64/egl/libGLES_android.so";
-#else
-                    result = "/vendor/lib/egl/libGLES_android.so";
-#endif
-                    return result;
-                case 1:
-                    // Use host-side OpenGL through the "emulation" library
-#if defined(__LP64__)
-                    result = std::string("/vendor/lib64/egl/lib") + kind + "_emulation.so";
-#else
-                    result = std::string("/vendor/lib/egl/lib") + kind + "_emulation.so";
-#endif
-                    return result;
-                case 2:
-                    // Use guest side swiftshader library
-#if defined(__LP64__)
-                    result = std::string("/vendor/lib64/egl/lib") + kind + "_swiftshader.so";
-#else
-                    result = std::string("/vendor/lib/egl/lib") + kind + "_swiftshader.so";
-#endif
-                    return result;
-                default:
-                    // Not in emulator, or use other guest-side implementation
-                    break;
-            }
-
-            std::string pattern = std::string("lib") + kind;
+        static std::string find(const char* libraryName, const bool exact) {
             const char* const searchPaths[] = {
 #if defined(__LP64__)
                     "/vendor/lib64/egl",
@@ -407,35 +446,16 @@
 #endif
             };
 
-            // first, we search for the exact name of the GLES userspace
-            // driver in both locations.
-            // i.e.:
-            //      libGLES.so, or:
-            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
-
-            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
-                if (find(result, pattern, searchPaths[i], true)) {
-                    return result;
+            for (auto dir : searchPaths) {
+                std::string absolutePath;
+                if (find(absolutePath, libraryName, dir, exact)) {
+                    return absolutePath;
                 }
             }
 
-            // for compatibility with the old "egl.cfg" naming convention
-            // we look for files that match:
-            //      libGLES_*.so, or:
-            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
-
-            pattern.append("_");
-            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
-                if (find(result, pattern, searchPaths[i], false)) {
-                    return result;
-                }
-            }
-
-            // we didn't find the driver. gah.
-            result.clear();
-            return result;
+            // Driver not found. gah.
+            return std::string();
         }
-
     private:
         static bool find(std::string& result,
                 const std::string& pattern, const char* const search, bool exact) {
@@ -473,8 +493,16 @@
         }
     };
 
-
-    std::string absolutePath = MatchFile::find(kind);
+    std::string libraryName = std::string("lib") + kind;
+    if (suffix) {
+        libraryName += std::string("_") + suffix;
+    } else if (!exact) {
+        // Deprecated: we look for files that match
+        //      libGLES_*.so, or:
+        //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+        libraryName += std::string("_");
+    }
+    std::string absolutePath = MatchFile::find(libraryName.c_str(), exact);
     if (absolutePath.empty()) {
         // this happens often, we don't want to log an error
         return nullptr;
@@ -519,11 +547,6 @@
 }
 
 static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) {
-    // Only attempt to load ANGLE libs
-    if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) {
-        return nullptr;
-    }
-
     void* so = nullptr;
 
     if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) {
@@ -561,7 +584,20 @@
         cnx->angleBackend = angleBackendDefault;
         if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
             // Find and load vendor libEGL for ANGLE's GL back-end to use.
-            cnx->vendorEGL = load_system_driver("EGL");
+            char prop[PROPERTY_VALUE_MAX + 1];
+            for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+                if (property_get(key, prop, nullptr) <= 0) {
+                    continue;
+                }
+                void* dso = load_system_driver("EGL", prop, true);
+                if (dso) {
+                    cnx->vendorEGL = dso;
+                    break;
+                }
+            }
+            if (!cnx->vendorEGL) {
+                cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
+            }
         }
     } else {
         ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
@@ -573,11 +609,6 @@
     return so;
 }
 
-static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
-    "ro.hardware.egl",
-    "ro.board.platform",
-};
-
 static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
     ATRACE_CALL();
     const android_dlextinfo dlextinfo = {
@@ -587,45 +618,110 @@
     void* so = nullptr;
     char prop[PROPERTY_VALUE_MAX + 1];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
-        if (property_get(key, prop, nullptr) > 0) {
-            std::string name = std::string("lib") + kind + "_" + prop + ".so";
-            so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-            if (so) {
-                return so;
-            }
+        if (property_get(key, prop, nullptr) <= 0) {
+            continue;
+        }
+        std::string name = std::string("lib") + kind + "_" + prop + ".so";
+        so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+        if (so) {
+            return so;
         }
     }
     return nullptr;
 }
 
-void *Loader::load_driver(const char* kind,
-        egl_connection_t* cnx, uint32_t mask)
-{
+Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
     ATRACE_CALL();
-
-    void* dso = nullptr;
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
-    if (ns) {
-        android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
-        dso = load_angle(kind, ns, cnx);
-    }
-#ifndef __ANDROID_VNDK__
-    if (!dso) {
-        android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
-        if (ns) {
-            android::GraphicsEnv::getInstance().setDriverToLoad(
-                    android::GraphicsEnv::Driver::GL_UPDATED);
-            dso = load_updated_driver(kind, ns);
-        }
-    }
-#endif
-    if (!dso) {
-        android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
-        dso = load_system_driver(kind);
-        if (!dso)
-            return nullptr;
+    if (!ns) {
+        return nullptr;
     }
 
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
+    driver_t* hnd = nullptr;
+
+    // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
+    void* dso = load_angle("EGL", ns, cnx);
+    if (dso) {
+        initialize_api(dso, cnx, EGL);
+        hnd = new driver_t(dso);
+
+        dso = load_angle("GLESv1_CM", ns, cnx);
+        initialize_api(dso, cnx, GLESv1_CM);
+        hnd->set(dso, GLESv1_CM);
+
+        dso = load_angle("GLESv2", ns, cnx);
+        initialize_api(dso, cnx, GLESv2);
+        hnd->set(dso, GLESv2);
+    }
+    return hnd;
+}
+
+Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
+    ATRACE_CALL();
+#ifndef __ANDROID_VNDK__
+    android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+    if (!ns) {
+        return nullptr;
+    }
+
+    ALOGD("Load updated gl driver.");
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL_UPDATED);
+    driver_t* hnd = nullptr;
+    void* dso = load_updated_driver("GLES", ns);
+    if (dso) {
+        initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+        hnd = new driver_t(dso);
+        return hnd;
+    }
+
+    dso = load_updated_driver("EGL", ns);
+    if (dso) {
+        initialize_api(dso, cnx, EGL);
+        hnd = new driver_t(dso);
+
+        dso = load_updated_driver("GLESv1_CM", ns);
+        initialize_api(dso, cnx, GLESv1_CM);
+        hnd->set(dso, GLESv1_CM);
+
+        dso = load_updated_driver("GLESv2", ns);
+        initialize_api(dso, cnx, GLESv2);
+        hnd->set(dso, GLESv2);
+    }
+    return hnd;
+#else
+    return nullptr;
+#endif
+}
+
+Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
+                                                        const bool exact) {
+    ATRACE_CALL();
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+    driver_t* hnd = nullptr;
+    void* dso = load_system_driver("GLES", suffix, exact);
+    if (dso) {
+        initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+        hnd = new driver_t(dso);
+        return hnd;
+    }
+    dso = load_system_driver("EGL", suffix, exact);
+    if (dso) {
+        initialize_api(dso, cnx, EGL);
+        hnd = new driver_t(dso);
+
+        dso = load_system_driver("GLESv1_CM", suffix, exact);
+        initialize_api(dso, cnx, GLESv1_CM);
+        hnd->set(dso, GLESv1_CM);
+
+        dso = load_system_driver("GLESv2", suffix, exact);
+        initialize_api(dso, cnx, GLESv2);
+        hnd->set(dso, GLESv2);
+    }
+    return hnd;
+}
+
+void Loader::initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask) {
     if (mask & EGL) {
         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
 
@@ -665,10 +761,6 @@
                 &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
             getProcAddress);
     }
-
-    return dso;
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
+} // namespace android
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 392887d..6f31ab4 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -55,7 +55,11 @@
 
 private:
     Loader();
-    void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask);
+    driver_t* attempt_to_load_angle(egl_connection_t* cnx);
+    driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
+    driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
+    void unload_system_driver(egl_connection_t* cnx);
+    void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
     void init_api(void* dso,
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 8870d5f..25b1009 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -187,13 +187,9 @@
 
     // dynamically load our EGL implementation
     egl_connection_t* cnx = &gEGLImpl;
-    if (cnx->dso == nullptr) {
-        cnx->hooks[egl_connection_t::GLESv1_INDEX] =
-                &gHooks[egl_connection_t::GLESv1_INDEX];
-        cnx->hooks[egl_connection_t::GLESv2_INDEX] =
-                &gHooks[egl_connection_t::GLESv2_INDEX];
-        cnx->dso = loader.open(cnx);
-    }
+    cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
+    cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
+    cnx->dso = loader.open(cnx);
 
     // Check to see if any layers are enabled and route functions through them
     if (cnx->dso) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 54fa89f..67d69b4 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -71,6 +71,11 @@
     return false;
 }
 
+bool needsAndroidPEglMitigation() {
+    static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+    return vndk_version <= 28;
+}
+
 int egl_get_init_count(EGLDisplay dpy) {
     egl_display_t* eglDisplay = egl_display_t::get(dpy);
     return eglDisplay ? eglDisplay->getRefsCount() : 0;
@@ -212,7 +217,7 @@
     Loader& loader(Loader::getInstance());
 
     egl_connection_t* const cnx = &gEGLImpl;
-    if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
+    if (cnx->dso) {
         EGLDisplay dpy = EGL_NO_DISPLAY;
 
         if (cnx->useAngle) {
@@ -336,45 +341,10 @@
         mVendorString = sVendorString;
         mVersionString.clear();
         cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0);
+        mVersionString = sVersionString14;
         if ((cnx->major == 1) && (cnx->minor == 5)) {
             mVersionString = sVersionString15;
             cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
-        } else if ((cnx->major == 1) && (cnx->minor == 4)) {
-            mVersionString = sVersionString14;
-            // Extensions needed for an EGL 1.4 implementation to be
-            // able to support EGL 1.5 functionality
-            std::vector<const char*> egl15extensions = {
-                    "EGL_EXT_client_extensions",
-                    // "EGL_EXT_platform_base",  // implemented by EGL runtime
-                    "EGL_KHR_image_base",
-                    "EGL_KHR_fence_sync",
-                    "EGL_KHR_wait_sync",
-                    "EGL_KHR_create_context",
-                    "EGL_EXT_create_context_robustness",
-                    "EGL_KHR_gl_colorspace",
-                    "EGL_ANDROID_native_fence_sync",
-            };
-            bool extensionsFound = true;
-            for (const auto& name : egl15extensions) {
-                extensionsFound &= findExtension(disp.queryString.extensions, name);
-                ALOGV("Extension %s: %s", name,
-                      findExtension(disp.queryString.extensions, name) ? "Found" : "Missing");
-            }
-            // NOTE: From the spec:
-            // Creation of fence sync objects requires support from the bound
-            // client API, and will not succeed unless the client API satisfies:
-            // client API is OpenGL ES, and either the OpenGL ES version is 3.0
-            // or greater, or the GL_OES_EGL_sync extension is supported.
-            // We don't have a way to check the GL_EXTENSIONS string at this
-            // point in the code, assume that GL_OES_EGL_sync is supported
-            // because EGL_KHR_fence_sync is supported (as verified above).
-            if (extensionsFound) {
-                // Have everything needed to emulate EGL 1.5 so report EGL 1.5
-                // to the application.
-                mVersionString = sVersionString15;
-                cnx->major = 1;
-                cnx->minor = 5;
-            }
         }
         if (mVersionString.empty()) {
             ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor);
@@ -419,6 +389,13 @@
             if (len) {
                 // NOTE: we could avoid the copy if we had strnstr.
                 const std::string ext(start, len);
+                // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
+                // some Android P vendor partitions this extension under the draft KHR name,
+                // but during Khronos review it was decided to demote it to EXT.
+                if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
+                    findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
+                    mExtensionString.append("EGL_EXT_image_gl_colorspace ");
+                }
                 if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
                     mExtensionString.append(ext + " ");
                 }
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 36856b7..e117314 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -43,6 +43,7 @@
 struct egl_connection_t;
 
 bool findExtension(const char* exts, const char* name, size_t nameLen = 0);
+bool needsAndroidPEglMitigation();
 
 // ----------------------------------------------------------------------------
 
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 34262f3..e996be6 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -1710,6 +1710,26 @@
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_IMAGE_KHR;
 
+    std::vector<AttrType> strippedAttribs;
+    if (needsAndroidPEglMitigation()) {
+        // Mitigation for Android P vendor partitions: eglImageCreateKHR should accept
+        // EGL_GL_COLORSPACE_LINEAR_KHR, EGL_GL_COLORSPACE_SRGB_KHR and
+        // EGL_GL_COLORSPACE_DEFAULT_EXT if EGL_EXT_image_gl_colorspace is supported,
+        // but some drivers don't like the DEFAULT value and generate an error.
+        for (const AttrType *attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
+            if (attr[0] == EGL_GL_COLORSPACE_KHR &&
+                dp->haveExtension("EGL_EXT_image_gl_colorspace")) {
+                if (attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR &&
+                    attr[1] != EGL_GL_COLORSPACE_SRGB_KHR) {
+                    continue;
+                }
+            }
+            strippedAttribs.push_back(attr[0]);
+            strippedAttribs.push_back(attr[1]);
+        }
+        strippedAttribs.push_back(EGL_NONE);
+    }
+
     ContextRef _c(dp.get(), ctx);
     egl_context_t* const c = _c.get();
 
@@ -1717,7 +1737,7 @@
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && eglCreateImageFunc) {
         result = eglCreateImageFunc(dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, target, buffer,
-                                    attrib_list);
+                                    needsAndroidPEglMitigation() ? strippedAttribs.data() : attrib_list);
     }
     return result;
 }
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 9e112cc..7bb9b59 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -44,7 +44,11 @@
         GLESv2_INDEX = 1
     };
 
-    inline egl_connection_t() : dso(nullptr) {
+    inline egl_connection_t() : dso(nullptr),
+                                libEgl(nullptr),
+                                libGles1(nullptr),
+                                libGles2(nullptr),
+                                systemDriverUnloaded(false) {
 
         char const* const* entries = platform_names;
         EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform);
@@ -76,6 +80,7 @@
     void*               libGles1;
     void*               libGles2;
 
+    bool                systemDriverUnloaded;
     bool                shouldUseAngle; // Should we attempt to load ANGLE
     bool                angleDecided;   // Have we tried to load ANGLE
     bool                useAngle;       // Was ANGLE successfully loaded
diff --git a/opengl/libs/ETC1/etc1.cpp b/opengl/libs/ETC1/etc1.cpp
index 97d1085..19d428a 100644
--- a/opengl/libs/ETC1/etc1.cpp
+++ b/opengl/libs/ETC1/etc1.cpp
@@ -378,34 +378,30 @@
         const etc1_byte* pColors, etc_compressed* pCompressed) {
     int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks
     bool differential;
-    {
-        int r51 = convert8To5(pColors[0]);
-        int g51 = convert8To5(pColors[1]);
-        int b51 = convert8To5(pColors[2]);
-        int r52 = convert8To5(pColors[3]);
-        int g52 = convert8To5(pColors[4]);
-        int b52 = convert8To5(pColors[5]);
+    int r51 = convert8To5(pColors[0]);
+    int g51 = convert8To5(pColors[1]);
+    int b51 = convert8To5(pColors[2]);
+    int r52 = convert8To5(pColors[3]);
+    int g52 = convert8To5(pColors[4]);
+    int b52 = convert8To5(pColors[5]);
 
-        r1 = convert5To8(r51);
-        g1 = convert5To8(g51);
-        b1 = convert5To8(b51);
+    r1 = convert5To8(r51);
+    g1 = convert5To8(g51);
+    b1 = convert5To8(b51);
 
-        int dr = r52 - r51;
-        int dg = g52 - g51;
-        int db = b52 - b51;
+    int dr = r52 - r51;
+    int dg = g52 - g51;
+    int db = b52 - b51;
 
-        differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
-                && inRange4bitSigned(db);
-        if (differential) {
-            r2 = convert5To8(r51 + dr);
-            g2 = convert5To8(g51 + dg);
-            b2 = convert5To8(b51 + db);
-            pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
-                    | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
-        }
-    }
-
-    if (!differential) {
+    differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
+            && inRange4bitSigned(db);
+    if (differential) {
+        r2 = convert5To8(r51 + dr);
+        g2 = convert5To8(g51 + dg);
+        b2 = convert5To8(b51 + db);
+        pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
+                | ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
+    } else {
         int r41 = convert8To4(pColors[0]);
         int g41 = convert8To4(pColors[1]);
         int b41 = convert8To4(pColors[2]);
diff --git a/opengl/tools/glgen/specs/egl/EGL15.spec b/opengl/tools/glgen/specs/egl/EGL15.spec
index e0aad30..5c48a15 100644
--- a/opengl/tools/glgen/specs/egl/EGL15.spec
+++ b/opengl/tools/glgen/specs/egl/EGL15.spec
@@ -1,7 +1,8 @@
 EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list )
+// eglGetSyncAttrib pulled in with eglCreateSync stubs
+// EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value )
 EGLBoolean eglDestroySync ( EGLDisplay dpy, EGLSync sync )
 EGLint eglClientWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout )
-EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value )
 // NOTE: native_display isn't actually an EGLAttrib. Using EGLAttrib
 // so that the generate creates mostly correct code (do not want a buffer)
 // have to manually change cast to (void *) in generated code that calls
diff --git a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
index 1c53c9e..34cb3e1 100644
--- a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
@@ -25,6 +25,7 @@
 #include <utils/misc.h>
 
 #include <assert.h>
+#include <vector>
 #include <EGL/egl.h>
 
 #include <ui/ANativeObjectBase.h>
@@ -34,16 +35,6 @@
 static jclass eglsurfaceClass;
 static jclass eglconfigClass;
 static jclass eglcontextClass;
-static jclass bufferClass;
-static jclass nioAccessClass;
-
-static jfieldID positionID;
-static jfieldID limitID;
-static jfieldID elementSizeShiftID;
-
-static jmethodID getBasePointerID;
-static jmethodID getBaseArrayID;
-static jmethodID getBaseArrayOffsetID;
 
 static jmethodID egldisplayGetHandleID;
 static jmethodID eglconfigGetHandleID;
@@ -115,24 +106,6 @@
     _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
 
     // EGL 1.5 init
-    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
-    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
-
-    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
-    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
-
-    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
-            "getBasePointer", "(Ljava/nio/Buffer;)J");
-    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
-    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
-    positionID = _env->GetFieldID(bufferClass, "position", "I");
-    limitID = _env->GetFieldID(bufferClass, "limit", "I");
-    elementSizeShiftID =
-        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
-
     jclass eglimageClassLocal = _env->FindClass("android/opengl/EGLImage");
     eglimageClass = (jclass) _env->NewGlobalRef(eglimageClassLocal);
     jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
@@ -159,23 +132,17 @@
     jint elementSizeShift;
     jlong pointer;
 
-    position = _env->GetIntField(buffer, positionID);
-    limit = _env->GetIntField(buffer, limitID);
-    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
     *remaining = (limit - position) << elementSizeShift;
-    pointer = _env->CallStaticLongMethod(nioAccessClass,
-            getBasePointerID, buffer);
     if (pointer != 0L) {
-        *array = NULL;
+        *array = nullptr;
+        pointer += position << elementSizeShift;
         return reinterpret_cast<void*>(pointer);
     }
 
-    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
-            getBaseArrayID, buffer);
-    *offset = _env->CallStaticIntMethod(nioAccessClass,
-            getBaseArrayOffsetID, buffer);
-
-    return NULL;
+    *array = jniGetNioBufferBaseArray(_env, buffer);
+    *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+    return nullptr;
 }
 
 static void
@@ -206,4 +173,22 @@
     return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
+struct WrappedEGLAttribs {
+private:
+    std::vector<EGLAttrib> backing; // only for 32-bit
+public:
+    EGLAttrib *attribs;
+    WrappedEGLAttribs(): attribs(nullptr) { };
+    void init(jlong *array, jint size) {
+        if (sizeof(EGLAttrib) != sizeof(jlong)) {
+            for (jint i = 0; i < size; ++i) {
+                backing.push_back(array[i]);
+            }
+            attribs = backing.data();
+        } else {
+            attribs = (EGLAttrib*)array;
+        }
+    }
+};
+
 // --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateImage.cpp b/opengl/tools/glgen/stubs/egl/eglCreateImage.cpp
new file mode 100644
index 0000000..f93815c
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.cpp
@@ -0,0 +1,50 @@
+/* EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateImage
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject context, jint target, jlong buffer, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLImage _returnValue = (EGLImage) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLContext context_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, context);
+    jlong *attrib_list_base = (jlong *) 0;
+    jint _remaining;
+    WrappedEGLAttribs attrib_list;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (jlong *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list.init(attrib_list_base + offset, _remaining);
+
+    _returnValue = eglCreateImage(
+        (EGLDisplay)dpy_native,
+        (EGLContext)context_native,
+        (EGLenum)target,
+        (EGLClientBuffer)buffer,
+        attrib_list.attribs
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
+    }
+    return toEGLHandle(_env, eglimageClass, eglimageConstructor, _returnValue);
+}
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateImage.java b/opengl/tools/glgen/stubs/egl/eglCreateImage.java
new file mode 100644
index 0000000..06a04bb
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.java
@@ -0,0 +1,11 @@
+    // C function EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list )
+
+    public static native EGLImage eglCreateImage(
+        EGLDisplay dpy,
+        EGLContext context,
+        int target,
+        long buffer,
+        long[] attrib_list,
+        int offset
+    );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg
new file mode 100644
index 0000000..da5687d
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateImage.nativeReg
@@ -0,0 +1 @@
+{"eglCreateImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;IJ[JI)Landroid/opengl/EGLImage;", (void *) android_eglCreateImage },
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp
new file mode 100644
index 0000000..48dbd35
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.cpp
@@ -0,0 +1,68 @@
+/* EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreatePlatformWindowSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_window_buf, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    jint _native_windowRemaining;
+    void *native_window = (void *) 0;
+    jlong *attrib_list_base = (jlong *) 0;
+    jint _attrib_listRemaining;
+    WrappedEGLAttribs attrib_list;
+
+    if (!native_window_buf) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "native_window == null";
+        goto exit;
+    }
+    native_window = (void *)getPointer(_env, native_window_buf, (jarray*)&_array, &_native_windowRemaining, &_bufferOffset);
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (jlong *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list.init(attrib_list_base + offset, _attrib_listRemaining);
+
+    if (native_window == NULL) {
+        char * _native_windowBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        native_window = (void *) (_native_windowBase + _bufferOffset);
+    }
+    _returnValue = eglCreatePlatformWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (void *)native_window,
+        attrib_list.attribs
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_array) {
+        releasePointer(_env, _array, native_window, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java
new file mode 100644
index 0000000..dda37f8
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.java
@@ -0,0 +1,10 @@
+    // C function EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list )
+
+    public static native EGLSurface eglCreatePlatformWindowSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        java.nio.Buffer native_window,
+        long[] attrib_list,
+        int offset
+    );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg
new file mode 100644
index 0000000..ce464e8
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePlatformWindowSurface.nativeReg
@@ -0,0 +1 @@
+{"eglCreatePlatformWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformWindowSurface },
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp b/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp
new file mode 100644
index 0000000..c53afea
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.cpp
@@ -0,0 +1,101 @@
+/* EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateSync
+  (JNIEnv *_env, jobject _this, jobject dpy, jint type, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLSync _returnValue = (EGLSync) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    jlong *attrib_list_base = (jlong *) 0;
+    jint _remaining;
+    WrappedEGLAttribs attrib_list;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (jlong *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list.init(attrib_list_base + offset, _remaining);
+
+    _returnValue = eglCreateSync(
+        (EGLDisplay)dpy_native,
+        (EGLenum)type,
+        attrib_list.attribs
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
+    }
+    return toEGLHandle(_env, eglsyncClass, eglsyncConstructor, _returnValue);
+}
+
+/* EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value ) */
+static jboolean
+android_eglGetSyncAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint attribute, jlongArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+    jlong *value_base = (jlong *) 0;
+    jint _remaining;
+    EGLAttrib value;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (jlong *)
+        _env->GetLongArrayElements(value_ref, (jboolean *)0);
+
+    _returnValue = eglGetSyncAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLSync)sync_native,
+        (EGLint)attribute,
+        &value
+    );
+
+    if (value_base && _returnValue == EGL_TRUE) {
+        *(value_base + offset) = (jlong) value;
+    }
+
+exit:
+    if (value_base) {
+        _env->ReleaseLongArrayElements(value_ref, (jlong*)value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return JNI_FALSE;
+    }
+    return (jboolean)_returnValue;
+}
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.java b/opengl/tools/glgen/stubs/egl/eglCreateSync.java
new file mode 100644
index 0000000..db8f728
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.java
@@ -0,0 +1,22 @@
+    // C function EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list )
+
+    public static native EGLSync eglCreateSync(
+        EGLDisplay dpy,
+        int type,
+        long[] attrib_list,
+        int offset
+    );
+
+    /**
+    * C function EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute,
+    *                                          EGLAttrib *value )
+    */
+
+    public static native boolean eglGetSyncAttrib(
+            EGLDisplay dpy,
+            EGLSync sync,
+            int attribute,
+            long[] value,
+            int offset
+    );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg
new file mode 100644
index 0000000..c99e7fe
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateSync.nativeReg
@@ -0,0 +1,2 @@
+{"eglCreateSync", "(Landroid/opengl/EGLDisplay;I[JI)Landroid/opengl/EGLSync;", (void *) android_eglCreateSync },
+{"eglGetSyncAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;I[JI)Z", (void *) android_eglGetSyncAttrib },
diff --git a/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp
index 3a6176f..6acb32a 100644
--- a/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglGetPlatformDisplay.cpp
@@ -6,9 +6,9 @@
     const char * _exceptionType = NULL;
     const char * _exceptionMessage = NULL;
     EGLDisplay _returnValue = (EGLDisplay) 0;
-    EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
+    jlong *attrib_list_base = (jlong *) 0;
     jint _remaining;
-    EGLAttrib *attrib_list = (EGLAttrib *) 0;
+    WrappedEGLAttribs attrib_list;
 
     if (!attrib_list_ref) {
         _exception = 1;
@@ -23,14 +23,14 @@
         goto exit;
     }
     _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
-    attrib_list_base = (EGLAttrib *)
+    attrib_list_base = (jlong *)
         _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
-    attrib_list = attrib_list_base + offset;
+    attrib_list.init(attrib_list_base + offset, _remaining);
 
     _returnValue = eglGetPlatformDisplay(
         (EGLenum)platform,
         (void *)native_display,
-        (EGLAttrib *)attrib_list
+        attrib_list.attribs
     );
 
 exit:
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index 51e62ed..e763b4e 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -4,15 +4,6 @@
 #include <utils/misc.h>
 #include <assert.h>
 
-static jclass nioAccessClass;
-static jclass bufferClass;
-static jmethodID getBasePointerID;
-static jmethodID getBaseArrayID;
-static jmethodID getBaseArrayOffsetID;
-static jfieldID positionID;
-static jfieldID limitID;
-static jfieldID elementSizeShiftID;
-
 
 /* special calls implemented in Android's GLES wrapper used to more
  * efficiently bound-check passed arrays */
@@ -47,28 +38,9 @@
 #endif
 }
 
-/* Cache method IDs each time the class is loaded. */
-
 static void
 nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
-    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
-    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
-
-    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
-    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
-
-    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
-            "getBasePointer", "(Ljava/nio/Buffer;)J");
-    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
-    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
-    positionID = _env->GetFieldID(bufferClass, "position", "I");
-    limitID = _env->GetFieldID(bufferClass, "limit", "I");
-    elementSizeShiftID =
-        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
 static void *
@@ -79,23 +51,17 @@
     jint elementSizeShift;
     jlong pointer;
 
-    position = _env->GetIntField(buffer, positionID);
-    limit = _env->GetIntField(buffer, limitID);
-    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
     *remaining = (limit - position) << elementSizeShift;
-    pointer = _env->CallStaticLongMethod(nioAccessClass,
-            getBasePointerID, buffer);
     if (pointer != 0L) {
-        *array = NULL;
+        *array = nullptr;
+        pointer += position << elementSizeShift;
         return reinterpret_cast<void*>(pointer);
     }
 
-    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
-            getBaseArrayID, buffer);
-    *offset = _env->CallStaticIntMethod(nioAccessClass,
-            getBaseArrayOffsetID, buffer);
-
-    return NULL;
+    *array = jniGetNioBufferBaseArray(_env, buffer);
+    *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+    return nullptr;
 }
 
 class ByteArrayGetter {
@@ -217,16 +183,18 @@
 
 static void *
 getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
-    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
-    if (buf) {
-        jint position = _env->GetIntField(buffer, positionID);
-        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
-        buf += position << elementSizeShift;
-    } else {
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+    if (pointer == 0) {
         jniThrowException(_env, "java/lang/IllegalArgumentException",
                           "Must use a native order direct Buffer");
+        return nullptr;
     }
-    return (void*) buf;
+    pointer += position << elementSizeShift;
+    return reinterpret_cast<void*>(pointer);
 }
 
 // --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index c808fe9..c12efc3 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -64,16 +64,7 @@
         GLsizei stride, const GLvoid *pointer, GLsizei count);
 }
 
-static jclass nioAccessClass;
-static jclass bufferClass;
 static jclass G11ImplClass;
-static jmethodID getBasePointerID;
-static jmethodID getBaseArrayID;
-static jmethodID getBaseArrayOffsetID;
-static jmethodID allowIndirectBuffersID;
-static jfieldID positionID;
-static jfieldID limitID;
-static jfieldID elementSizeShiftID;
 static jfieldID haveCheckedExtensionsID;
 static jfieldID have_OES_blend_equation_separateID;
 static jfieldID have_OES_blend_subtractID;
@@ -85,12 +76,6 @@
 static void
 nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
-    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
-    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
-
-    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
-    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
-
     jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
     G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
     haveCheckedExtensionsID =  _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
@@ -98,19 +83,6 @@
     have_OES_blend_subtractID =  _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
     have_OES_framebuffer_objectID =  _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
     have_OES_texture_cube_mapID =  _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
-
-    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
-            "getBasePointer", "(Ljava/nio/Buffer;)J");
-    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
-    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
-            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-    allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
-            "allowIndirectBuffers", "(Ljava/lang/String;)Z");
-    positionID = _env->GetFieldID(bufferClass, "position", "I");
-    limitID = _env->GetFieldID(bufferClass, "limit", "I");
-    elementSizeShiftID =
-        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
 static void *
@@ -121,28 +93,17 @@
     jint elementSizeShift;
     jlong pointer;
 
-    position = _env->GetIntField(buffer, positionID);
-    limit = _env->GetIntField(buffer, limitID);
-    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
     *remaining = (limit - position) << elementSizeShift;
-    pointer = _env->CallStaticLongMethod(nioAccessClass,
-            getBasePointerID, buffer);
     if (pointer != 0L) {
-        *offset = 0;
-        *array = NULL;
-        return reinterpret_cast<void *>(pointer);
+        *array = nullptr;
+        pointer += position << elementSizeShift;
+        return reinterpret_cast<void*>(pointer);
     }
 
-    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
-            getBaseArrayID, buffer);
-    if (*array == NULL) {
-        *offset = 0;
-        return (void*) NULL;
-    }
-    *offset = _env->CallStaticIntMethod(nioAccessClass,
-            getBaseArrayOffsetID, buffer);
-
-    return NULL;
+    *array = jniGetNioBufferBaseArray(_env, buffer);
+    *offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
+    return nullptr;
 }
 
 static void
@@ -156,42 +117,24 @@
 extern char*  __progname;
 }
 
-static bool
-allowIndirectBuffers(JNIEnv *_env) {
-    static jint sIndirectBufferCompatability;
-    if (sIndirectBufferCompatability == 0) {
-        jobject appName = _env->NewStringUTF(::__progname);
-        sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
-    }
-    return sIndirectBufferCompatability == 2;
-}
-
 static void *
 getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
-    if (!buffer) {
-        return NULL;
+    if (buffer == nullptr) {
+        return nullptr;
     }
-    void* buf = _env->GetDirectBufferAddress(buffer);
-    if (buf) {
-        jint position = _env->GetIntField(buffer, positionID);
-        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
-        buf = ((char*) buf) + (position << elementSizeShift);
-    } else {
-        if (allowIndirectBuffers(_env)) {
-            jarray array = 0;
-            jint remaining;
-            jint offset;
-            buf = getPointer(_env, buffer, &array, &remaining, &offset);
-            if (array) {
-                releasePointer(_env, array, buf, 0);
-            }
-            buf = (char*)buf + offset;
-        } else {
-            jniThrowException(_env, "java/lang/IllegalArgumentException",
-                              "Must use a native order direct Buffer");
-        }
+
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+    if (pointer == 0) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
+        return nullptr;
     }
-    return buf;
+    pointer += position << elementSizeShift;
+    return reinterpret_cast<void*>(pointer);
 }
 
 static int
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index b9b0706..6235f06 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -98,6 +98,37 @@
         data.writeInt32((int32_t) piid);
         return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeStrongBinder(recorder);
+        // get new RIId in reply
+        const status_t res = remote()->transact(TRACK_RECORDER, data, &reply, 0);
+        if (res != OK || reply.readExceptionCode() != 0) {
+            ALOGE("trackRecorder() failed, riid is %d", RECORD_RIID_INVALID);
+            return RECORD_RIID_INVALID;
+        } else {
+            const audio_unique_id_t riid = (audio_unique_id_t) reply.readInt32();
+            ALOGV("trackRecorder() returned riid %d", riid);
+            return riid;
+        }
+    }
+
+    virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32((int32_t) riid);
+        data.writeInt32((int32_t) event);
+        return remote()->transact(RECORDER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual status_t releaseRecorder(audio_unique_id_t riid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32((int32_t) riid);
+        return remote()->transact(RELEASE_RECORDER, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index a4b81fe..cd03bc2 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -63,6 +63,7 @@
         "libbufferhubservice",
         "libcrypto",
         "libcutils",
+        "libhidlbase",
         "libhidltransport",
         "libhwbinder",
         "liblog",
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 59fa1c0..e50dfca 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -28,7 +28,12 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
+#include <array>
+#include <fstream>
+#include <sstream>
+#include <sys/types.h>
 #include <vkjson.h>
+#include <unistd.h>
 
 #include "gpustats/GpuStats.h"
 
@@ -40,6 +45,7 @@
 status_t cmdHelp(int out);
 status_t cmdVkjson(int out, int err);
 void dumpGameDriverInfo(std::string* result);
+void dumpMemoryInfo(std::string* result, const GpuMemoryMap& memories, uint32_t pid);
 } // namespace
 
 const String16 sDump("android.permission.DUMP");
@@ -51,26 +57,164 @@
 void GpuService::setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             GraphicsEnv::Driver driver, bool isDriverLoaded,
-                             int64_t driverLoadingTime) {
-    ATRACE_CALL();
-
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) {
     mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
-                      appPackageName, driver, isDriverLoaded, driverLoadingTime);
+                      appPackageName, vulkanVersion, driver, isDriverLoaded, driverLoadingTime);
 }
 
 status_t GpuService::getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullGlobalStats(outStats);
-
     return OK;
 }
 
 status_t GpuService::getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullAppStats(outStats);
+    return OK;
+}
+
+void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value) {
+    mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
+}
+
+bool isExpectedFormat(const char* str) {
+    // Should match in order:
+    // gpuaddr useraddr size id flags type usage sglen mapsize eglsrf eglimg
+    std::istringstream iss;
+    iss.str(str);
+
+    std::string word;
+    iss >> word;
+    if (word != "gpuaddr") { return false; }
+    iss >> word;
+    if (word != "useraddr") { return false; }
+    iss >> word;
+    if (word != "size") { return false; }
+    iss >> word;
+    if (word != "id") { return false; }
+    iss >> word;
+    if (word != "flags") { return false; }
+    iss >> word;
+    if (word != "type") { return false; }
+    iss >> word;
+    if (word != "usage") { return false; }
+    iss >> word;
+    if (word != "sglen") { return false; }
+    iss >> word;
+    if (word != "mapsize") { return false; }
+    iss >> word;
+    if (word != "eglsrf") { return false; }
+    iss >> word;
+    if (word != "eglimg") { return false; }
+    return true;
+}
+
+
+// Queries gpu memory via Qualcomm's /d/kgsl/proc/*/mem interface.
+status_t GpuService::getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const {
+    const std::string kDirectoryPath = "/d/kgsl/proc";
+    DIR* directory = opendir(kDirectoryPath.c_str());
+    if (!directory) { return PERMISSION_DENIED; }
+
+    // File Format:
+    //          gpuaddr         useraddr     size id     flags   type          usage sglen mapsize eglsrf eglimg
+    // 0000000000000000 0000000000000000  8359936 23 --w--pY-- gpumem VK/others( 38)     0       0      0      0
+    // 0000000000000000 0000000000000000 16293888 24 --wL--N--    ion        surface    41       0      0      1
+
+    const bool dumpAll = dumpPid == 0;
+    static constexpr size_t kMaxLineLength = 1024;
+    static char line[kMaxLineLength];
+    while(dirent* subdir = readdir(directory)) {
+        // Skip "." and ".." in directory.
+        if (strcmp(subdir->d_name, ".") == 0 || strcmp(subdir->d_name, "..") == 0 ) { continue; }
+
+        std::string pid_str(subdir->d_name);
+        const uint32_t pid(stoi(pid_str));
+
+        if (!dumpAll && dumpPid != pid) {
+            continue;
+        }
+
+        std::string filepath(kDirectoryPath + "/" + pid_str + "/mem");
+        std::ifstream file(filepath);
+
+        // Check first line
+        file.getline(line, kMaxLineLength);
+        if (!isExpectedFormat(line)) {
+            continue;
+        }
+
+        if (result) {
+            StringAppendF(result, "%d:\n%s\n", pid, line);
+        }
+
+        while( file.getline(line, kMaxLineLength) ) {
+            if (result) {
+                StringAppendF(result, "%s\n", line);
+            }
+
+            std::istringstream iss;
+            iss.str(line);
+
+            // Skip gpuaddr, useraddr.
+            const char delimiter = ' ';
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get size.
+            int64_t memsize;
+            iss >> memsize;
+
+            // Skip id, flags.
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get type, usage.
+            std::string memtype;
+            std::string usage;
+            iss >> memtype >> usage;
+
+            // Adjust for the space in VK/others( #)
+            if (usage == "VK/others(") {
+              std::string vkTypeEnd;
+              iss >> vkTypeEnd;
+              usage.append(vkTypeEnd);
+            }
+
+            // Skip sglen.
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get mapsize.
+            int64_t mapsize;
+            iss >> mapsize;
+
+            if (memsize == 0 && mapsize == 0) {
+                continue;
+            }
+
+            if (memtype == "gpumem") {
+                (*memories)[pid][usage].gpuMemory += memsize;
+            } else {
+                (*memories)[pid][usage].ionMemory += memsize;
+            }
+
+            if (mapsize > 0) {
+                (*memories)[pid][usage].mappedMemory += mapsize;
+            }
+        }
+
+        if (result) {
+            StringAppendF(result, "\n");
+        }
+    }
+
+    closedir(directory);
 
     return OK;
 }
@@ -102,24 +246,44 @@
         StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
     } else {
         bool dumpAll = true;
-        size_t index = 0;
+        bool dumpDriverInfo = false;
+        bool dumpStats = false;
+        bool dumpMemory = false;
         size_t numArgs = args.size();
+        int32_t pid = 0;
 
         if (numArgs) {
-            if ((index < numArgs) && (args[index] == String16("--gpustats"))) {
-                index++;
-                mGpuStats->dump(args, &result);
-                dumpAll = false;
+            dumpAll = false;
+            for (size_t index = 0; index < numArgs; ++index) {
+                if (args[index] == String16("--gpustats")) {
+                    dumpStats = true;
+                } else if (args[index] == String16("--gpudriverinfo")) {
+                    dumpDriverInfo = true;
+                } else if (args[index] == String16("--gpumem")) {
+                    dumpMemory = true;
+                } else if (args[index].compare(String16("--gpumem=")) > 0) {
+                    dumpMemory = true;
+                    pid = atoi(String8(&args[index][9]));
+                }
             }
         }
 
-        if (dumpAll) {
+        if (dumpAll || dumpDriverInfo) {
             dumpGameDriverInfo(&result);
             result.append("\n");
-
+        }
+        if (dumpAll || dumpStats) {
             mGpuStats->dump(Vector<String16>(), &result);
             result.append("\n");
         }
+        if (dumpAll || dumpMemory) {
+            GpuMemoryMap memories;
+            // Currently only queries Qualcomm gpu memory. More will be added later.
+            if (getQCommGpuMemoryInfo(&memories, &result, pid) == OK) {
+                dumpMemoryInfo(&result, memories, pid);
+                result.append("\n");
+            }
+        }
     }
 
     write(fd, result.c_str(), result.size());
@@ -171,6 +335,34 @@
     StringAppendF(result, "Pre-release Game Driver: %s\n", preReleaseGameDriver);
 }
 
+// Read and print all memory info for each process from /d/kgsl/proc/<pid>/mem.
+void dumpMemoryInfo(std::string* result, const GpuMemoryMap& memories, uint32_t pid) {
+    if (!result) return;
+
+    // Write results.
+    StringAppendF(result, "GPU Memory Summary:\n");
+    for(auto& mem : memories) {
+        uint32_t process = mem.first;
+        if (pid != 0 && pid != process) {
+            continue;
+        }
+
+        StringAppendF(result, "%d:\n", process);
+        for(auto& memStruct : mem.second) {
+            StringAppendF(result, "  %s", memStruct.first.c_str());
+
+            if(memStruct.second.gpuMemory > 0)
+                StringAppendF(result, ", GPU memory = %" PRId64, memStruct.second.gpuMemory);
+            if(memStruct.second.mappedMemory > 0)
+                StringAppendF(result, ", Mapped memory = %" PRId64, memStruct.second.mappedMemory);
+            if(memStruct.second.ionMemory > 0)
+                StringAppendF(result, ", Ion memory = %" PRId64, memStruct.second.ionMemory);
+
+            StringAppendF(result, "\n");
+        }
+    }
+}
+
 } // anonymous namespace
 
 } // namespace android
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 7a9b2d4..b3dc2e2 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -25,11 +25,22 @@
 
 #include <mutex>
 #include <vector>
+#include <unordered_map>
 
 namespace android {
 
 class GpuStats;
 
+struct MemoryStruct {
+  int64_t gpuMemory;
+  int64_t mappedMemory;
+  int64_t ionMemory;
+};
+
+// A map that keeps track of how much memory of each type is allocated by every process.
+// Format: map[pid][memoryType] = MemoryStruct()'
+using GpuMemoryMap = std::unordered_map<int32_t, std::unordered_map<std::string, MemoryStruct>>;
+
 class GpuService : public BnGpuService, public PriorityDumper {
 public:
     static const char* const SERVICE_NAME ANDROID_API;
@@ -45,10 +56,13 @@
      */
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
                      uint64_t driverVersionCode, int64_t driverBuildTime,
-                     const std::string& appPackageName, GraphicsEnv::Driver driver,
-                     bool isDriverLoaded, int64_t driverLoadingTime) override;
+                     const std::string& appPackageName, const int32_t vulkanVersion,
+                     GpuStatsInfo::Driver driver, bool isDriverLoaded,
+                     int64_t driverLoadingTime) override;
     status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const override;
     status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const override;
+    void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                        const GpuStatsInfo::Stats stats, const uint64_t value) override;
 
     /*
      * IBinder interface
@@ -68,6 +82,8 @@
 
     status_t doDump(int fd, const Vector<String16>& args, bool asProto);
 
+    status_t getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const;
+
     /*
      * Attributes
      */
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
new file mode 100644
index 0000000..5d02839
--- /dev/null
+++ b/services/gpuservice/OWNERS
@@ -0,0 +1,3 @@
+chrisforbes@google.com
+lpy@google.com
+zzyiwei@google.com
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 6185305..67babd4 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -19,47 +19,55 @@
 
 #include "GpuStats.h"
 
-#include <unordered_set>
-
+#include <cutils/properties.h>
 #include <log/log.h>
 #include <utils/Trace.h>
 
+#include <unordered_set>
+
 namespace android {
 
-static bool addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
+static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
                             GpuStatsGlobalInfo* const outGlobalInfo) {
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
             outGlobalInfo->glLoadingCount++;
             if (!isDriverLoaded) outGlobalInfo->glLoadingFailureCount++;
             break;
-        case GraphicsEnv::Driver::VULKAN:
-        case GraphicsEnv::Driver::VULKAN_UPDATED:
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED:
             outGlobalInfo->vkLoadingCount++;
             if (!isDriverLoaded) outGlobalInfo->vkLoadingFailureCount++;
             break;
+        case GpuStatsInfo::Driver::ANGLE:
+            outGlobalInfo->angleLoadingCount++;
+            if (!isDriverLoaded) outGlobalInfo->angleLoadingFailureCount++;
+            break;
         default:
-            // Currently we don't support GraphicsEnv::Driver::ANGLE because the
-            // basic driver package info only belongs to system or updated driver.
-            return false;
+            break;
     }
-
-    return true;
 }
 
-static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
+static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTime,
                            GpuStatsAppInfo* const outAppInfo) {
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
-            if (outAppInfo->glDriverLoadingTime.size() >= GpuStats::MAX_NUM_LOADING_TIMES) break;
-            outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
+            if (outAppInfo->glDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
+                outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
+            }
             break;
-        case GraphicsEnv::Driver::VULKAN:
-        case GraphicsEnv::Driver::VULKAN_UPDATED:
-            if (outAppInfo->vkDriverLoadingTime.size() >= GpuStats::MAX_NUM_LOADING_TIMES) break;
-            outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED:
+            if (outAppInfo->vkDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
+                outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
+            }
+            break;
+        case GpuStatsInfo::Driver::ANGLE:
+            if (outAppInfo->angleDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
+                outAppInfo->angleDriverLoadingTime.emplace_back(driverLoadingTime);
+            }
             break;
         default:
             break;
@@ -68,8 +76,8 @@
 
 void GpuStats::insert(const std::string& driverPackageName, const std::string& driverVersionName,
                       uint64_t driverVersionCode, int64_t driverBuildTime,
-                      const std::string& appPackageName, GraphicsEnv::Driver driver,
-                      bool isDriverLoaded, int64_t driverLoadingTime) {
+                      const std::string& appPackageName, const int32_t vulkanVersion,
+                      GpuStatsInfo::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mLock);
@@ -79,33 +87,34 @@
           "\tdriverVersionCode[%" PRIu64 "]\n"
           "\tdriverBuildTime[%" PRId64 "]\n"
           "\tappPackageName[%s]\n"
+          "\tvulkanVersion[%d]\n"
           "\tdriver[%d]\n"
           "\tisDriverLoaded[%d]\n"
           "\tdriverLoadingTime[%" PRId64 "]",
           driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
-          appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
+          appPackageName.c_str(), vulkanVersion, static_cast<int32_t>(driver), isDriverLoaded,
+          driverLoadingTime);
 
     if (!mGlobalStats.count(driverVersionCode)) {
         GpuStatsGlobalInfo globalInfo;
-        if (!addLoadingCount(driver, isDriverLoaded, &globalInfo)) {
-            return;
-        }
+        addLoadingCount(driver, isDriverLoaded, &globalInfo);
         globalInfo.driverPackageName = driverPackageName;
         globalInfo.driverVersionName = driverVersionName;
         globalInfo.driverVersionCode = driverVersionCode;
         globalInfo.driverBuildTime = driverBuildTime;
+        globalInfo.vulkanVersion = vulkanVersion;
         mGlobalStats.insert({driverVersionCode, globalInfo});
-    } else if (!addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode])) {
-        return;
-    }
-
-    if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
-        ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
-        return;
+    } else {
+        addLoadingCount(driver, isDriverLoaded, &mGlobalStats[driverVersionCode]);
     }
 
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
     if (!mAppStats.count(appStatsKey)) {
+        if (mAppStats.size() >= MAX_NUM_APP_RECORDS) {
+            ALOGV("GpuStatsAppInfo has reached maximum size. Ignore new stats.");
+            return;
+        }
+
         GpuStatsAppInfo appInfo;
         addLoadingTime(driver, driverLoadingTime, &appInfo);
         appInfo.appPackageName = appPackageName;
@@ -117,6 +126,40 @@
     addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
 }
 
+void GpuStats::insertTargetStats(const std::string& appPackageName,
+                                 const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
+                                 const uint64_t /*value*/) {
+    ATRACE_CALL();
+
+    const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+
+    std::lock_guard<std::mutex> lock(mLock);
+    if (!mAppStats.count(appStatsKey)) {
+        return;
+    }
+
+    switch (stats) {
+        case GpuStatsInfo::Stats::CPU_VULKAN_IN_USE:
+            mAppStats[appStatsKey].cpuVulkanInUse = true;
+            break;
+        case GpuStatsInfo::Stats::FALSE_PREROTATION:
+            mAppStats[appStatsKey].falsePrerotation = true;
+            break;
+        default:
+            break;
+    }
+}
+
+void GpuStats::interceptSystemDriverStatsLocked() {
+    // Append cpuVulkanVersion and glesVersion to system driver stats
+    if (!mGlobalStats.count(0) || mGlobalStats[0].glesVersion) {
+        return;
+    }
+
+    mGlobalStats[0].cpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", 0);
+    mGlobalStats[0].glesVersion = property_get_int32("ro.opengles.version", 0);
+}
+
 void GpuStats::dump(const Vector<String16>& args, std::string* result) {
     ATRACE_CALL();
 
@@ -173,6 +216,8 @@
 }
 
 void GpuStats::dumpGlobalLocked(std::string* result) {
+    interceptSystemDriverStatsLocked();
+
     for (const auto& ele : mGlobalStats) {
         result->append(ele.second.toString());
         result->append("\n");
@@ -193,6 +238,8 @@
     outStats->clear();
     outStats->reserve(mGlobalStats.size());
 
+    interceptSystemDriverStatsLocked();
+
     for (const auto& ele : mGlobalStats) {
         outStats->emplace_back(ele.second);
     }
diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h
index d942154..656b181 100644
--- a/services/gpuservice/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/GpuStats.h
@@ -35,8 +35,11 @@
     // Insert new gpu stats into global stats and app stats.
     void insert(const std::string& driverPackageName, const std::string& driverVersionName,
                 uint64_t driverVersionCode, int64_t driverBuildTime,
-                const std::string& appPackageName, GraphicsEnv::Driver driver, bool isDriverLoaded,
-                int64_t driverLoadingTime);
+                const std::string& appPackageName, const int32_t vulkanVersion,
+                GpuStatsInfo::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
+    // Insert target stats into app stats or potentially global stats as well.
+    void insertTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                           const GpuStatsInfo::Stats stats, const uint64_t value);
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
     // Pull gpu global stats
@@ -52,6 +55,8 @@
     void dumpGlobalLocked(std::string* result);
     // Dump app stats
     void dumpAppLocked(std::string* result);
+    // Append cpuVulkanVersion and glesVersion to system driver stats
+    void interceptSystemDriverStatsLocked();
 
     // Below limits the memory usage of GpuStats to be less than 10KB. This is
     // the preferred number for statsd while maintaining nice data quality.
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 63e759c..8dd4d1d 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -29,6 +29,7 @@
 
     srcs: [
         "InputClassifier.cpp",
+        "InputClassifierConverter.cpp",
         "InputDispatcher.cpp",
         "InputManager.cpp",
     ],
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 0544ec1..af02314 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -28,7 +28,6 @@
 #include <sys/limits.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
-#include <sys/utsname.h>
 #include <unistd.h>
 
 #define LOG_TAG "EventHub"
@@ -94,14 +93,6 @@
     return out;
 }
 
-static void getLinuxRelease(int* major, int* minor) {
-    struct utsname info;
-    if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
-        *major = 0, *minor = 0;
-        ALOGE("Could not get linux version: %s", strerror(errno));
-    }
-}
-
 /**
  * Return true if name matches "v4l-touch*"
  */
@@ -115,8 +106,15 @@
  * The system property ro.input.video_enabled can be used to control whether
  * EventHub scans and opens V4L devices. As V4L does not support multiple
  * clients, EventHub effectively blocks access to these devices when it opens
- * them. This property enables other clients to read these devices for testing
- * and development.
+ * them.
+ *
+ * Setting this to "false" would prevent any video devices from being discovered and
+ * associated with input devices.
+ *
+ * This property can be used as follows:
+ * 1. To turn off features that are dependent on video device presence.
+ * 2. During testing and development, to allow other clients to read video devices
+ * directly from /dev.
  */
 static bool isV4lScanningEnabled() {
   return property_get_bool("ro.input.video_enabled", true /* default_value */);
@@ -285,11 +283,6 @@
     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
             errno);
-
-    int major, minor;
-    getLinuxRelease(&major, &minor);
-    // EPOLLWAKEUP was introduced in kernel 3.5
-    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
 }
 
 EventHub::~EventHub(void) {
@@ -1480,28 +1473,13 @@
         }
     }
 
-    std::string wakeMechanism = "EPOLLWAKEUP";
-    if (!mUsingEpollWakeup) {
-#ifndef EVIOCSSUSPENDBLOCK
-        // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
-        // will use an epoll flag instead, so as long as we want to support
-        // this feature, we need to be prepared to define the ioctl ourselves.
-#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
-#endif
-        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
-            wakeMechanism = "<none>";
-        } else {
-            wakeMechanism = "EVIOCSSUSPENDBLOCK";
-        }
-    }
     // Tell the kernel that we want to use the monotonic clock for reporting timestamps
     // associated with input events.  This is important because the input system
     // uses the timestamps extensively and assumes they were recorded using the monotonic
     // clock.
     int clockId = CLOCK_MONOTONIC;
     bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
-    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
-          toString(usingClockIoctl));
+    ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
 }
 
 void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 63a20ef..eb4e8f2 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -479,8 +479,6 @@
     size_t mPendingEventCount;
     size_t mPendingEventIndex;
     bool mPendingINotify;
-
-    bool mUsingEpollWakeup;
 };
 
 }; // namespace android
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index b4db338..7c061c5 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "InputClassifier"
 
 #include "InputClassifier.h"
+#include "InputClassifierConverter.h"
 
 #include <algorithm>
 #include <android-base/stringprintf.h>
@@ -64,373 +65,6 @@
     return it->second;
 }
 
-static common::V1_0::Source getSource(uint32_t source) {
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) ==
-            common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) ==
-            common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) ==
-            common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) ==
-            common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) ==
-            common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) ==
-            common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) ==
-            common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) ==
-            common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) ==
-            common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) ==
-            common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) ==
-            common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) ==
-            common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) ==
-            common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) ==
-            common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch");
-    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) ==
-            common::V1_0::Source::ANY, "SOURCE_ANY mismatch");
-    return static_cast<common::V1_0::Source>(source);
-}
-
-static common::V1_0::Action getAction(int32_t actionMasked) {
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) ==
-            common::V1_0::Action::DOWN, "ACTION_DOWN mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) ==
-            common::V1_0::Action::UP, "ACTION_UP mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) ==
-            common::V1_0::Action::MOVE, "ACTION_MOVE mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) ==
-            common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) ==
-            common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) ==
-            common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) ==
-            common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch");
-    static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) ==
-            common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) ==
-            common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) ==
-            common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) ==
-            common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) ==
-            common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch");
-    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) ==
-            common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch");
-    return static_cast<common::V1_0::Action>(actionMasked);
-}
-
-static common::V1_0::Button getActionButton(int32_t actionButton) {
-    static_assert(static_cast<common::V1_0::Button>(0) ==
-            common::V1_0::Button::NONE, "BUTTON_NONE mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) ==
-            common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) ==
-            common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) ==
-            common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) ==
-            common::V1_0::Button::BACK, "BUTTON_BACK mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) ==
-            common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) ==
-            common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch");
-    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) ==
-            common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch");
-    return static_cast<common::V1_0::Button>(actionButton);
-}
-
-static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) {
-    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) ==
-            common::V1_0::Flag::WINDOW_IS_OBSCURED);
-    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) ==
-            common::V1_0::Flag::IS_GENERATED_GESTURE);
-    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) ==
-            common::V1_0::Flag::TAINTED);
-    return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) {
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) ==
-            common::V1_0::PolicyFlag::WAKE);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) ==
-            common::V1_0::PolicyFlag::VIRTUAL);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) ==
-            common::V1_0::PolicyFlag::FUNCTION);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) ==
-            common::V1_0::PolicyFlag::GESTURE);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) ==
-            common::V1_0::PolicyFlag::INJECTED);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) ==
-            common::V1_0::PolicyFlag::TRUSTED);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) ==
-            common::V1_0::PolicyFlag::FILTERED);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) ==
-            common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) ==
-            common::V1_0::PolicyFlag::INTERACTIVE);
-    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) ==
-            common::V1_0::PolicyFlag::PASS_TO_USER);
-    return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) {
-    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) ==
-            common::V1_0::EdgeFlag::NONE);
-    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) ==
-            common::V1_0::EdgeFlag::TOP);
-    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) ==
-            common::V1_0::EdgeFlag::BOTTOM);
-    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) ==
-            common::V1_0::EdgeFlag::LEFT);
-    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) ==
-            common::V1_0::EdgeFlag::RIGHT);
-    return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags);
-}
-
-static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) {
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) ==
-            common::V1_0::Meta::NONE);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) ==
-            common::V1_0::Meta::ALT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) ==
-            common::V1_0::Meta::ALT_LEFT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) ==
-            common::V1_0::Meta::ALT_RIGHT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) ==
-            common::V1_0::Meta::SHIFT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) ==
-            common::V1_0::Meta::SHIFT_LEFT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) ==
-            common::V1_0::Meta::SHIFT_RIGHT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) ==
-            common::V1_0::Meta::SYM_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) ==
-            common::V1_0::Meta::FUNCTION_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) ==
-            common::V1_0::Meta::CTRL_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) ==
-            common::V1_0::Meta::CTRL_LEFT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) ==
-            common::V1_0::Meta::CTRL_RIGHT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) ==
-            common::V1_0::Meta::META_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) ==
-            common::V1_0::Meta::META_LEFT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) ==
-            common::V1_0::Meta::META_RIGHT_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) ==
-            common::V1_0::Meta::CAPS_LOCK_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) ==
-            common::V1_0::Meta::NUM_LOCK_ON);
-    static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) ==
-            common::V1_0::Meta::SCROLL_LOCK_ON);
-    return static_cast<hidl_bitfield<common::V1_0::Meta>>(state);
-}
-
-static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) {
-    // No need for static_assert here.
-    // The button values have already been asserted in getActionButton(..) above
-    return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState);
-}
-
-static common::V1_0::ToolType getToolType(int32_t toolType) {
-    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) ==
-            common::V1_0::ToolType::UNKNOWN);
-    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) ==
-            common::V1_0::ToolType::FINGER);
-    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) ==
-            common::V1_0::ToolType::STYLUS);
-    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) ==
-            common::V1_0::ToolType::MOUSE);
-    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) ==
-            common::V1_0::ToolType::ERASER);
-    return static_cast<common::V1_0::ToolType>(toolType);
-}
-
-static common::V1_0::Axis getAxis(uint64_t axis) {
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) ==
-            common::V1_0::Axis::X);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) ==
-            common::V1_0::Axis::Y);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) ==
-            common::V1_0::Axis::PRESSURE);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) ==
-            common::V1_0::Axis::SIZE);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) ==
-            common::V1_0::Axis::TOUCH_MAJOR);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) ==
-            common::V1_0::Axis::TOUCH_MINOR);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) ==
-            common::V1_0::Axis::TOOL_MAJOR);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) ==
-            common::V1_0::Axis::TOOL_MINOR);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) ==
-            common::V1_0::Axis::ORIENTATION);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) ==
-            common::V1_0::Axis::VSCROLL);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) ==
-            common::V1_0::Axis::HSCROLL);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) ==
-            common::V1_0::Axis::Z);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) ==
-            common::V1_0::Axis::RX);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) ==
-            common::V1_0::Axis::RY);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) ==
-            common::V1_0::Axis::RZ);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) ==
-            common::V1_0::Axis::HAT_X);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) ==
-            common::V1_0::Axis::HAT_Y);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) ==
-            common::V1_0::Axis::LTRIGGER);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) ==
-            common::V1_0::Axis::RTRIGGER);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) ==
-            common::V1_0::Axis::THROTTLE);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) ==
-            common::V1_0::Axis::RUDDER);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) ==
-            common::V1_0::Axis::WHEEL);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) ==
-            common::V1_0::Axis::GAS);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) ==
-            common::V1_0::Axis::BRAKE);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) ==
-            common::V1_0::Axis::DISTANCE);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) ==
-            common::V1_0::Axis::TILT);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) ==
-            common::V1_0::Axis::SCROLL);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) ==
-            common::V1_0::Axis::RELATIVE_X);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) ==
-            common::V1_0::Axis::RELATIVE_Y);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) ==
-            common::V1_0::Axis::GENERIC_1);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) ==
-            common::V1_0::Axis::GENERIC_2);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) ==
-            common::V1_0::Axis::GENERIC_3);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) ==
-            common::V1_0::Axis::GENERIC_4);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) ==
-            common::V1_0::Axis::GENERIC_5);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) ==
-            common::V1_0::Axis::GENERIC_6);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) ==
-            common::V1_0::Axis::GENERIC_7);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) ==
-            common::V1_0::Axis::GENERIC_8);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) ==
-            common::V1_0::Axis::GENERIC_9);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) ==
-            common::V1_0::Axis::GENERIC_10);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) ==
-            common::V1_0::Axis::GENERIC_11);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) ==
-            common::V1_0::Axis::GENERIC_12);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) ==
-            common::V1_0::Axis::GENERIC_13);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) ==
-            common::V1_0::Axis::GENERIC_14);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) ==
-            common::V1_0::Axis::GENERIC_15);
-    static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) ==
-            common::V1_0::Axis::GENERIC_16);
-    return static_cast<common::V1_0::Axis>(axis);
-}
-
-static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
-    common::V1_0::VideoFrame out;
-    out.width = frame.getWidth();
-    out.height = frame.getHeight();
-    out.data = frame.getData();
-    struct timeval timestamp = frame.getTimestamp();
-    out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) +
-             microseconds_to_nanoseconds(timestamp.tv_usec);
-    return out;
-}
-
-static std::vector<common::V1_0::VideoFrame> convertVideoFrames(
-        const std::vector<TouchVideoFrame>& frames) {
-    std::vector<common::V1_0::VideoFrame> out;
-    for (const TouchVideoFrame& frame : frames) {
-        out.push_back(getHalVideoFrame(frame));
-    }
-    return out;
-}
-
-static uint8_t getActionIndex(int32_t action) {
-    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
-            AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args,
-        std::vector<common::V1_0::PointerProperties>* outPointerProperties,
-        std::vector<common::V1_0::PointerCoords>* outPointerCoords) {
-    outPointerProperties->reserve(args.pointerCount);
-    outPointerCoords->reserve(args.pointerCount);
-    for (size_t i = 0; i < args.pointerCount; i++) {
-        common::V1_0::PointerProperties properties;
-        properties.id = args.pointerProperties[i].id;
-        properties.toolType = getToolType(args.pointerProperties[i].toolType);
-        outPointerProperties->push_back(properties);
-
-        common::V1_0::PointerCoords coords;
-        BitSet64 bits (args.pointerCoords[i].bits);
-        std::vector<float> values;
-        size_t index = 0;
-        while (!bits.isEmpty()) {
-            uint32_t axis = bits.clearFirstMarkedBit();
-            coords.bits |= 1 << static_cast<uint64_t>(getAxis(axis));
-            float value = args.pointerCoords[i].values[index++];
-            values.push_back(value);
-        }
-        coords.values = values;
-        outPointerCoords->push_back(coords);
-    }
-}
-
-static common::V1_0::MotionEvent getMotionEvent(const NotifyMotionArgs& args) {
-    common::V1_0::MotionEvent event;
-    event.deviceId = args.deviceId;
-    event.source = getSource(args.source);
-    event.displayId = args.displayId;
-    event.downTime = args.downTime;
-    event.eventTime = args.eventTime;
-    event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
-    event.actionIndex = getActionIndex(args.action);
-    event.actionButton = getActionButton(args.actionButton);
-    event.flags = getFlags(args.flags);
-    event.policyFlags = getPolicyFlags(args.policyFlags);
-    event.edgeFlags = getEdgeFlags(args.edgeFlags);
-    event.metaState = getMetastate(args.metaState);
-    event.buttonState = getButtonState(args.buttonState);
-    event.xPrecision = args.xPrecision;
-    event.yPrecision = args.yPrecision;
-
-    std::vector<common::V1_0::PointerProperties> pointerProperties;
-    std::vector<common::V1_0::PointerCoords> pointerCoords;
-    getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords);
-    event.pointerProperties = pointerProperties;
-    event.pointerCoords = pointerCoords;
-
-    event.deviceTimestamp = args.deviceTimestamp;
-    event.frames = convertVideoFrames(args.videoFrames);
-
-    return event;
-}
-
 static MotionClassification getMotionClassification(common::V1_0::Classification classification) {
     static_assert(MotionClassification::NONE ==
             static_cast<MotionClassification>(common::V1_0::Classification::NONE));
@@ -448,7 +82,7 @@
 // Check if the "deep touch" feature is on.
 static bool deepPressEnabled() {
     std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
-            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true");
+            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
     std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
     if (flag_value == "1" || flag_value == "true") {
         ALOGI("Deep press feature enabled.");
@@ -507,19 +141,53 @@
 
 // --- MotionClassifier ---
 
-MotionClassifier::MotionClassifier(
-        sp<android::hardware::input::classifier::V1_0::IInputClassifier> service) :
-        mEvents(MAX_EVENTS), mService(service) {
+MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
+        mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
     mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
 #if defined(__linux__)
     // Set the thread name for debugging
     pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
 #endif
+}
+
+/**
+ * This function may block for some time to initialize the HAL, so it should only be called
+ * from the "InputClassifier HAL" thread.
+ */
+bool MotionClassifier::init() {
+    ensureHalThread(__func__);
+    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
+            classifier::V1_0::IInputClassifier::getService();
+    if (!service) {
+        // Not really an error, maybe the device does not have this HAL,
+        // but somehow the feature flag is flipped
+        ALOGI("Could not obtain InputClassifier HAL");
+        return false;
+    }
+
+    sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
+    if (recipient != nullptr) {
+        const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
+        if (!linked) {
+            ALOGE("Could not link MotionClassifier to the HAL death");
+            return false;
+        }
+    }
+
     // Under normal operation, we do not need to reset the HAL here. But in the case where system
     // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
     // have received events in the past. That means, that HAL could be in an inconsistent state
     // once it receives events from the newly created MotionClassifier.
     mEvents.push(ClassifierEvent::createHalResetEvent());
+
+    {
+        std::scoped_lock lock(mLock);
+        if (mService) {
+            ALOGE("MotionClassifier::%s should only be called once", __func__);
+        }
+        mService = service;
+    }
+    return true;
 }
 
 MotionClassifier::~MotionClassifier() {
@@ -530,7 +198,7 @@
 void MotionClassifier::ensureHalThread(const char* function) {
     if (DEBUG) {
         if (std::this_thread::get_id() != mHalThread.get_id()) {
-            ALOGE("Function %s should only be called from InputClassifier thread", function);
+            LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
         }
     }
 }
@@ -547,13 +215,29 @@
  */
 void MotionClassifier::callInputClassifierHal() {
     ensureHalThread(__func__);
+    const bool initialized = init();
+    if (!initialized) {
+        // MotionClassifier no longer useful.
+        // Deliver death notification from a separate thread
+        // because ~MotionClassifier may be invoked, which calls mHalThread.join()
+        std::thread([deathRecipient = mDeathRecipient](){
+                sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
+                if (recipient != nullptr) {
+                    recipient->serviceDied(0 /*cookie*/, nullptr);
+                }
+        }).detach();
+        return;
+    }
+    // From this point on, mService is guaranteed to be non-null.
+
     while (true) {
         ClassifierEvent event = mEvents.pop();
         bool halResponseOk = true;
         switch (event.type) {
             case ClassifierEventType::MOTION: {
                 NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get());
-                common::V1_0::MotionEvent motionEvent = getMotionEvent(*motionArgs);
+                common::V1_0::MotionEvent motionEvent =
+                        notifyMotionArgsToHalMotionEvent(*motionArgs);
                 Return<common::V1_0::Classification> response = mService->classify(motionEvent);
                 halResponseOk = response.isOk();
                 if (halResponseOk) {
@@ -592,7 +276,7 @@
     bool eventAdded = mEvents.push(std::move(event));
     if (!eventAdded) {
         // If the queue is full, suspect the HAL is slow in processing the events.
-        ALOGE("Dropped event with eventTime %" PRId64, event.args->eventTime);
+        ALOGE("Could not add the event to the queue. Resetting");
         reset();
     }
 }
@@ -666,10 +350,19 @@
     enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
 }
 
+const char* MotionClassifier::getServiceStatus() REQUIRES(mLock) {
+    if (!mService) {
+        return "null";
+    }
+    if (mService->ping().isOk()) {
+        return "running";
+    }
+    return "not responding";
+}
+
 void MotionClassifier::dump(std::string& dump) {
     std::scoped_lock lock(mLock);
-    std::string serviceStatus = mService->ping().isOk() ? "running" : " not responding";
-    dump += StringPrintf(INDENT2 "mService status: %s\n", serviceStatus.c_str());
+    dump += StringPrintf(INDENT2 "mService status: %s\n", getServiceStatus());
     dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
             mEvents.size(), MAX_EVENTS);
     dump += INDENT2 "mClassifications, mLastDownTimes:\n";
@@ -700,28 +393,14 @@
 }
 
 void InputClassifier::onFirstRef() {
-    std::scoped_lock lock(mLock);
     if (!deepPressEnabled()) {
-        // If feature is not enabled, the InputClassifier will just be in passthrough
-        // mode, and will forward all events to the next InputListener, unmodified
+        // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
+        // When MotionClassifier is null, InputClassifier will forward all events
+        // to the next InputListener, unmodified.
         return;
     }
-
-    sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
-            classifier::V1_0::IInputClassifier::getService();
-    if (!service) {
-        // Not really an error, maybe the device does not have this HAL,
-        // but somehow the feature flag is flipped
-        ALOGI("Could not obtain InputClassifier HAL");
-        return;
-    }
-    const bool linked = service->linkToDeath(this, 0 /* cookie */).withDefault(false);
-    if (!linked) {
-        ALOGE("Could not link android::InputClassifier to the HAL death");
-        return;
-    }
-
-    mMotionClassifier = std::make_unique<MotionClassifier>(service);
+    std::scoped_lock lock(mLock);
+    mMotionClassifier = std::make_unique<MotionClassifier>(this);
 }
 
 void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
@@ -786,4 +465,4 @@
     dump += "\n";
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 0b1483f..47e20db 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -114,15 +114,22 @@
 class MotionClassifier final : public MotionClassifierInterface {
 public:
     /**
-     * The provided pointer to the service cannot be null.
+     * The deathRecipient will be subscribed to the HAL death. If the death recipient
+     * owns MotionClassifier and receives HAL death, it should delete its copy of it.
+     * The callback serviceDied will also be sent if the MotionClassifier itself fails
+     * to initialize. If the MotionClassifier fails to initialize, it is not useful, and
+     * should be deleted.
+     * If no death recipient is supplied, then the registration step will be skipped, so there will
+     * be no listeners registered for the HAL death. This is useful for testing
+     * MotionClassifier in isolation.
      */
-    MotionClassifier(sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
+    explicit MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient = nullptr);
     ~MotionClassifier();
+
     /**
      * Classifies events asynchronously; that is, it doesn't block events on a classification,
-     * but instead sends them over to the classifier HAL
-     * and after a classification is determined,
-     * it then marks the next event it sees in the stream with it.
+     * but instead sends them over to the classifier HAL and after a classification is
+     * determined, it then marks the next event it sees in the stream with it.
      *
      * Therefore, it is acceptable to have the classifications be delayed by 1-2 events
      * in a particular gesture.
@@ -134,6 +141,16 @@
     virtual void dump(std::string& dump) override;
 
 private:
+    /**
+     * Initialize MotionClassifier.
+     * Return true if initializaion is successful.
+     */
+    bool init();
+    /**
+     * Entity that will be notified of the HAL death (most likely InputClassifier).
+     */
+    wp<android::hardware::hidl_death_recipient> mDeathRecipient;
+
     // The events that need to be sent to the HAL.
     BlockingQueue<ClassifierEvent> mEvents;
     /**
@@ -148,7 +165,7 @@
     std::thread mHalThread;
     /**
      * Print an error message if the caller is not on the InputClassifier thread.
-     * Caller must supply the name of the calling function as __function__
+     * Caller must supply the name of the calling function as __func__
      */
     void ensureHalThread(const char* function);
     /**
@@ -156,9 +173,14 @@
      */
     void callInputClassifierHal();
     /**
-     * Access to the InputClassifier HAL. Can always be safely dereferenced.
+     * Access to the InputClassifier HAL. May be null if init() hasn't completed yet.
+     * When init() successfully completes, mService is guaranteed to remain non-null and to not
+     * change its value until MotionClassifier is destroyed.
+     * This variable is *not* guarded by mLock in the InputClassifier thread, because
+     * that thread knows exactly when this variable is initialized.
+     * When accessed in any other thread, mService is checked for nullness with a lock.
      */
-    const sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
+    sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
     std::mutex mLock;
     /**
      * Per-device input classifications. Should only be accessed using the
@@ -195,6 +217,10 @@
      * Useful for tests to ensure proper cleanup.
      */
     void requestExit();
+    /**
+     * Return string status of mService
+     */
+    const char* getServiceStatus() REQUIRES(mLock);
 };
 
 
diff --git a/services/inputflinger/InputClassifierConverter.cpp b/services/inputflinger/InputClassifierConverter.cpp
new file mode 100644
index 0000000..fc8c7c3
--- /dev/null
+++ b/services/inputflinger/InputClassifierConverter.cpp
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2019 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 "InputClassifierConverter.h"
+
+using android::hardware::hidl_bitfield;
+using namespace android::hardware::input;
+
+namespace android {
+
+static common::V1_0::Source getSource(uint32_t source) {
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) ==
+            common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) ==
+            common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) ==
+            common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) ==
+            common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) ==
+            common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) ==
+            common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) ==
+            common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) ==
+            common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) ==
+            common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) ==
+            common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) ==
+            common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) ==
+            common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) ==
+            common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) ==
+            common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch");
+    static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) ==
+            common::V1_0::Source::ANY, "SOURCE_ANY mismatch");
+    return static_cast<common::V1_0::Source>(source);
+}
+
+static common::V1_0::Action getAction(int32_t actionMasked) {
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) ==
+            common::V1_0::Action::DOWN, "ACTION_DOWN mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) ==
+            common::V1_0::Action::UP, "ACTION_UP mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) ==
+            common::V1_0::Action::MOVE, "ACTION_MOVE mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) ==
+            common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) ==
+            common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) ==
+            common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) ==
+            common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch");
+    static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) ==
+            common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) ==
+            common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) ==
+            common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) ==
+            common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) ==
+            common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch");
+    static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) ==
+            common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch");
+    return static_cast<common::V1_0::Action>(actionMasked);
+}
+
+static common::V1_0::Button getActionButton(int32_t actionButton) {
+    static_assert(static_cast<common::V1_0::Button>(0) ==
+            common::V1_0::Button::NONE, "BUTTON_NONE mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) ==
+            common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) ==
+            common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) ==
+            common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) ==
+            common::V1_0::Button::BACK, "BUTTON_BACK mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) ==
+            common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) ==
+            common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch");
+    static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) ==
+            common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch");
+    return static_cast<common::V1_0::Button>(actionButton);
+}
+
+static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) {
+    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) ==
+            common::V1_0::Flag::WINDOW_IS_OBSCURED);
+    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) ==
+            common::V1_0::Flag::IS_GENERATED_GESTURE);
+    static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) ==
+            common::V1_0::Flag::TAINTED);
+    return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags);
+}
+
+static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) {
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) ==
+            common::V1_0::PolicyFlag::WAKE);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) ==
+            common::V1_0::PolicyFlag::VIRTUAL);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) ==
+            common::V1_0::PolicyFlag::FUNCTION);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) ==
+            common::V1_0::PolicyFlag::GESTURE);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) ==
+            common::V1_0::PolicyFlag::INJECTED);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) ==
+            common::V1_0::PolicyFlag::TRUSTED);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) ==
+            common::V1_0::PolicyFlag::FILTERED);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) ==
+            common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) ==
+            common::V1_0::PolicyFlag::INTERACTIVE);
+    static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) ==
+            common::V1_0::PolicyFlag::PASS_TO_USER);
+    return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags);
+}
+
+static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) {
+    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) ==
+            common::V1_0::EdgeFlag::NONE);
+    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) ==
+            common::V1_0::EdgeFlag::TOP);
+    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) ==
+            common::V1_0::EdgeFlag::BOTTOM);
+    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) ==
+            common::V1_0::EdgeFlag::LEFT);
+    static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) ==
+            common::V1_0::EdgeFlag::RIGHT);
+    return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags);
+}
+
+static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) {
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) ==
+            common::V1_0::Meta::NONE);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) ==
+            common::V1_0::Meta::ALT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) ==
+            common::V1_0::Meta::ALT_LEFT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) ==
+            common::V1_0::Meta::ALT_RIGHT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) ==
+            common::V1_0::Meta::SHIFT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) ==
+            common::V1_0::Meta::SHIFT_LEFT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) ==
+            common::V1_0::Meta::SHIFT_RIGHT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) ==
+            common::V1_0::Meta::SYM_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) ==
+            common::V1_0::Meta::FUNCTION_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) ==
+            common::V1_0::Meta::CTRL_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) ==
+            common::V1_0::Meta::CTRL_LEFT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) ==
+            common::V1_0::Meta::CTRL_RIGHT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) ==
+            common::V1_0::Meta::META_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) ==
+            common::V1_0::Meta::META_LEFT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) ==
+            common::V1_0::Meta::META_RIGHT_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) ==
+            common::V1_0::Meta::CAPS_LOCK_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) ==
+            common::V1_0::Meta::NUM_LOCK_ON);
+    static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) ==
+            common::V1_0::Meta::SCROLL_LOCK_ON);
+    return static_cast<hidl_bitfield<common::V1_0::Meta>>(state);
+}
+
+static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) {
+    // No need for static_assert here.
+    // The button values have already been asserted in getActionButton(..) above
+    return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState);
+}
+
+static common::V1_0::ToolType getToolType(int32_t toolType) {
+    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) ==
+            common::V1_0::ToolType::UNKNOWN);
+    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) ==
+            common::V1_0::ToolType::FINGER);
+    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) ==
+            common::V1_0::ToolType::STYLUS);
+    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) ==
+            common::V1_0::ToolType::MOUSE);
+    static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) ==
+            common::V1_0::ToolType::ERASER);
+    return static_cast<common::V1_0::ToolType>(toolType);
+}
+
+// MotionEvent axes asserts
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) ==
+        common::V1_0::Axis::X);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) ==
+        common::V1_0::Axis::Y);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) ==
+        common::V1_0::Axis::PRESSURE);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) ==
+        common::V1_0::Axis::SIZE);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) ==
+        common::V1_0::Axis::TOUCH_MAJOR);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) ==
+        common::V1_0::Axis::TOUCH_MINOR);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) ==
+        common::V1_0::Axis::TOOL_MAJOR);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) ==
+        common::V1_0::Axis::TOOL_MINOR);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) ==
+        common::V1_0::Axis::ORIENTATION);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) ==
+        common::V1_0::Axis::VSCROLL);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) ==
+        common::V1_0::Axis::HSCROLL);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) ==
+        common::V1_0::Axis::Z);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) ==
+        common::V1_0::Axis::RX);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) ==
+        common::V1_0::Axis::RY);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) ==
+        common::V1_0::Axis::RZ);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) ==
+        common::V1_0::Axis::HAT_X);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) ==
+        common::V1_0::Axis::HAT_Y);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) ==
+        common::V1_0::Axis::LTRIGGER);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) ==
+        common::V1_0::Axis::RTRIGGER);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) ==
+        common::V1_0::Axis::THROTTLE);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) ==
+        common::V1_0::Axis::RUDDER);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) ==
+        common::V1_0::Axis::WHEEL);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) ==
+        common::V1_0::Axis::GAS);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) ==
+        common::V1_0::Axis::BRAKE);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) ==
+        common::V1_0::Axis::DISTANCE);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) ==
+        common::V1_0::Axis::TILT);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) ==
+        common::V1_0::Axis::SCROLL);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) ==
+        common::V1_0::Axis::RELATIVE_X);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) ==
+        common::V1_0::Axis::RELATIVE_Y);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) ==
+        common::V1_0::Axis::GENERIC_1);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) ==
+        common::V1_0::Axis::GENERIC_2);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) ==
+        common::V1_0::Axis::GENERIC_3);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) ==
+        common::V1_0::Axis::GENERIC_4);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) ==
+        common::V1_0::Axis::GENERIC_5);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) ==
+        common::V1_0::Axis::GENERIC_6);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) ==
+        common::V1_0::Axis::GENERIC_7);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) ==
+        common::V1_0::Axis::GENERIC_8);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) ==
+        common::V1_0::Axis::GENERIC_9);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) ==
+        common::V1_0::Axis::GENERIC_10);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) ==
+        common::V1_0::Axis::GENERIC_11);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) ==
+        common::V1_0::Axis::GENERIC_12);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) ==
+        common::V1_0::Axis::GENERIC_13);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) ==
+        common::V1_0::Axis::GENERIC_14);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) ==
+        common::V1_0::Axis::GENERIC_15);
+static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) ==
+        common::V1_0::Axis::GENERIC_16);
+
+static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
+    common::V1_0::VideoFrame out;
+    out.width = frame.getWidth();
+    out.height = frame.getHeight();
+    out.data = frame.getData();
+    struct timeval timestamp = frame.getTimestamp();
+    out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) +
+             microseconds_to_nanoseconds(timestamp.tv_usec);
+    return out;
+}
+
+static std::vector<common::V1_0::VideoFrame> convertVideoFrames(
+        const std::vector<TouchVideoFrame>& frames) {
+    std::vector<common::V1_0::VideoFrame> out;
+    for (const TouchVideoFrame& frame : frames) {
+        out.push_back(getHalVideoFrame(frame));
+    }
+    return out;
+}
+
+static uint8_t getActionIndex(int32_t action) {
+    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
+            AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+}
+
+static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args,
+        std::vector<common::V1_0::PointerProperties>* outPointerProperties,
+        std::vector<common::V1_0::PointerCoords>* outPointerCoords) {
+    outPointerProperties->reserve(args.pointerCount);
+    outPointerCoords->reserve(args.pointerCount);
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        common::V1_0::PointerProperties properties;
+        properties.id = args.pointerProperties[i].id;
+        properties.toolType = getToolType(args.pointerProperties[i].toolType);
+        outPointerProperties->push_back(properties);
+
+        common::V1_0::PointerCoords coords;
+        // OK to copy bits because we have static_assert for pointerCoords axes
+        coords.bits = args.pointerCoords[i].bits;
+        coords.values = std::vector<float>(
+                args.pointerCoords[i].values,
+                args.pointerCoords[i].values + BitSet64::count(args.pointerCoords[i].bits));
+        outPointerCoords->push_back(coords);
+    }
+}
+
+common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent(const NotifyMotionArgs& args) {
+    common::V1_0::MotionEvent event;
+    event.deviceId = args.deviceId;
+    event.source = getSource(args.source);
+    event.displayId = args.displayId;
+    event.downTime = args.downTime;
+    event.eventTime = args.eventTime;
+    event.deviceTimestamp = 0;
+    event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
+    event.actionIndex = getActionIndex(args.action);
+    event.actionButton = getActionButton(args.actionButton);
+    event.flags = getFlags(args.flags);
+    event.policyFlags = getPolicyFlags(args.policyFlags);
+    event.edgeFlags = getEdgeFlags(args.edgeFlags);
+    event.metaState = getMetastate(args.metaState);
+    event.buttonState = getButtonState(args.buttonState);
+    event.xPrecision = args.xPrecision;
+    event.yPrecision = args.yPrecision;
+
+    std::vector<common::V1_0::PointerProperties> pointerProperties;
+    std::vector<common::V1_0::PointerCoords> pointerCoords;
+    getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords);
+    event.pointerProperties = pointerProperties;
+    event.pointerCoords = pointerCoords;
+
+    event.frames = convertVideoFrames(args.videoFrames);
+
+    return event;
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputClassifierConverter.h b/services/inputflinger/InputClassifierConverter.h
new file mode 100644
index 0000000..5154b0b
--- /dev/null
+++ b/services/inputflinger/InputClassifierConverter.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_CLASSIFIER_CONVERTER_H
+#define _UI_INPUT_CLASSIFIER_CONVERTER_H
+
+#include "InputListener.h"
+#include <android/hardware/input/common/1.0/types.h>
+
+
+namespace android {
+
+/**
+ * Convert from framework's NotifyMotionArgs to hidl's common::V1_0::MotionEvent
+ */
+::android::hardware::input::common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent(
+        const NotifyMotionArgs& args);
+
+} // namespace android
+
+#endif // _UI_INPUT_CLASSIFIER_CONVERTER_H
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 13de53d..3eebd34 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -17,7 +17,7 @@
 #define LOG_TAG "InputDispatcher"
 #define ATRACE_TAG ATRACE_TAG_INPUT
 
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
 
 // Log detailed debug messages about each inbound event notification to the dispatcher.
 #define DEBUG_INBOUND_EVENT_DETAILS 0
@@ -58,7 +58,6 @@
 #include <log/log.h>
 #include <utils/Trace.h>
 #include <powermanager/PowerManager.h>
-#include <ui/Region.h>
 #include <binder/Binder.h>
 
 #define INDENT "  "
@@ -129,7 +128,7 @@
 
 static std::string keyActionToString(int32_t action) {
     // Convert KeyEvent action to string
-    switch(action) {
+    switch (action) {
         case AKEY_EVENT_ACTION_DOWN:
             return "DOWN";
         case AKEY_EVENT_ACTION_UP:
@@ -140,6 +139,24 @@
     return StringPrintf("%" PRId32, action);
 }
 
+static std::string dispatchModeToString(int32_t dispatchMode) {
+    switch (dispatchMode) {
+        case InputTarget::FLAG_DISPATCH_AS_IS:
+            return "DISPATCH_AS_IS";
+        case InputTarget::FLAG_DISPATCH_AS_OUTSIDE:
+            return "DISPATCH_AS_OUTSIDE";
+        case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER:
+            return "DISPATCH_AS_HOVER_ENTER";
+        case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT:
+            return "DISPATCH_AS_HOVER_EXIT";
+        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT:
+            return "DISPATCH_AS_SLIPPERY_EXIT";
+        case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER:
+            return "DISPATCH_AS_SLIPPERY_ENTER";
+    }
+    return StringPrintf("%" PRId32, dispatchMode);
+}
+
 static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
     return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
             >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
@@ -253,14 +270,18 @@
 
 // --- InputDispatcher ---
 
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
-    mPolicy(policy),
-    mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED),
-    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
-    mNextUnblockedEvent(nullptr),
-    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
-    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
+      : mPolicy(policy),
+        mPendingEvent(nullptr),
+        mLastDropReason(DROP_REASON_NOT_DROPPED),
+        mAppSwitchSawKeyDown(false),
+        mAppSwitchDueTime(LONG_LONG_MAX),
+        mNextUnblockedEvent(nullptr),
+        mDispatchEnabled(false),
+        mDispatchFrozen(false),
+        mInputFilterEnabled(false),
+        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
+        mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
     mReporter = createInputReporter();
 
@@ -568,6 +589,32 @@
     return nullptr;
 }
 
+std::vector<InputDispatcher::TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
+        int32_t displayId, const std::vector<sp<InputWindowHandle>>& portalWindows) {
+    std::vector<TouchedMonitor> touchedMonitors;
+
+    std::vector<Monitor> monitors = getValueByKey(mGestureMonitorsByDisplay, displayId);
+    addGestureMonitors(monitors, touchedMonitors);
+    for (const sp<InputWindowHandle>& portalWindow : portalWindows) {
+        const InputWindowInfo* windowInfo = portalWindow->getInfo();
+        monitors = getValueByKey(mGestureMonitorsByDisplay, windowInfo->portalToDisplayId);
+        addGestureMonitors(monitors, touchedMonitors,
+                -windowInfo->frameLeft, -windowInfo->frameTop);
+    }
+    return touchedMonitors;
+}
+
+void InputDispatcher::addGestureMonitors(const std::vector<Monitor>& monitors,
+        std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset, float yOffset) {
+    if (monitors.empty()) {
+        return;
+    }
+    outTouchedMonitors.reserve(monitors.size() + outTouchedMonitors.size());
+    for (const Monitor& monitor : monitors) {
+        outTouchedMonitors.emplace_back(monitor, xOffset, yOffset);
+    }
+}
+
 void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
     const char* reason;
     switch (dropReason) {
@@ -878,7 +925,7 @@
     }
 
     // Add monitor channels from event's or focused display.
-    addMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
 
     // Dispatch the key.
     dispatchEventLocked(currentTime, entry, inputTargets);
@@ -899,6 +946,7 @@
 
 bool InputDispatcher::dispatchMotionLocked(
         nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
+    ATRACE_CALL();
     // Preprocessing.
     if (! entry->dispatchInProgress) {
         entry->dispatchInProgress = true;
@@ -946,7 +994,7 @@
     }
 
     // Add monitor channels from event's or focused display.
-    addMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
 
     if (isPointerEvent) {
         ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(entry->displayId);
@@ -957,7 +1005,7 @@
                 // the corresponding displays as well.
                 for (size_t i = 0; i < state.portalWindows.size(); i++) {
                     const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
-                    addMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
+                    addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
                             -windowInfo->frameLeft, -windowInfo->frameTop);
                 }
             }
@@ -1011,6 +1059,7 @@
 
 void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
         EventEntry* eventEntry, const std::vector<InputTarget>& inputTargets) {
+    ATRACE_CALL();
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("dispatchEventToCurrentInputTargets");
 #endif
@@ -1250,6 +1299,7 @@
 int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
         const MotionEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
         bool* outConflictingPointerActions) {
+    ATRACE_CALL();
     enum InjectionPermission {
         INJECTION_PERMISSION_UNKNOWN,
         INJECTION_PERMISSION_GRANTED,
@@ -1288,6 +1338,7 @@
     bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
             || maskedAction == AMOTION_EVENT_ACTION_SCROLL
             || isHoverAction);
+    const bool isFromMouse = entry->source == AINPUT_SOURCE_MOUSE;
     bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
@@ -1323,19 +1374,30 @@
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
 
+        int32_t x;
+        int32_t y;
         int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t x = int32_t(entry->pointerCoords[pointerIndex].
-                getAxisValue(AMOTION_EVENT_AXIS_X));
-        int32_t y = int32_t(entry->pointerCoords[pointerIndex].
-                getAxisValue(AMOTION_EVENT_AXIS_Y));
+        // Always dispatch mouse events to cursor position.
+        if (isFromMouse) {
+            x = int32_t(entry->xCursorPosition);
+            y = int32_t(entry->yCursorPosition);
+        } else {
+            x = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
+            y = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
+        }
+        bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
         sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(
-                displayId, x, y, maskedAction == AMOTION_EVENT_ACTION_DOWN, true);
+                displayId, x, y, isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
+
+        std::vector<TouchedMonitor> newGestureMonitors = isDown
+                ? findTouchedGestureMonitorsLocked(displayId, mTempTouchState.portalWindows)
+                : std::vector<TouchedMonitor>{};
 
         // Figure out whether splitting will be allowed for this window.
         if (newTouchedWindowHandle != nullptr
                 && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
-            // New window supports splitting.
-            isSplit = true;
+            // New window supports splitting, but we should never split mouse events.
+            isSplit = !isFromMouse;
         } else if (isSplit) {
             // New window does not support splitting but we have already split events.
             // Ignore the new window.
@@ -1346,39 +1408,44 @@
         if (newTouchedWindowHandle == nullptr) {
             // Try to assign the pointer to the first foreground window we find, if there is one.
             newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
-            if (newTouchedWindowHandle == nullptr) {
-                ALOGI("Dropping event because there is no touchable window at (%d, %d) in display "
-                        "%" PRId32 ".", x, y, displayId);
-                injectionResult = INPUT_EVENT_INJECTION_FAILED;
-                goto Failed;
+        }
+
+        if (newTouchedWindowHandle == nullptr && newGestureMonitors.empty()) {
+            ALOGI("Dropping event because there is no touchable window or gesture monitor at "
+                    "(%d, %d) in display %" PRId32 ".", x, y, displayId);
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        if (newTouchedWindowHandle != nullptr) {
+            // Set target flags.
+            int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
+            if (isSplit) {
+                targetFlags |= InputTarget::FLAG_SPLIT;
             }
+            if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
+                targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+            } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
+                targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+            }
+
+            // Update hover state.
+            if (isHoverAction) {
+                newHoverWindowHandle = newTouchedWindowHandle;
+            } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
+                newHoverWindowHandle = mLastHoverWindowHandle;
+            }
+
+            // Update the temporary touch state.
+            BitSet32 pointerIds;
+            if (isSplit) {
+                uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
+                pointerIds.markBit(pointerId);
+            }
+            mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
         }
 
-        // Set target flags.
-        int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
-        if (isSplit) {
-            targetFlags |= InputTarget::FLAG_SPLIT;
-        }
-        if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
-            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-        } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
-            targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
-        }
-
-        // Update hover state.
-        if (isHoverAction) {
-            newHoverWindowHandle = newTouchedWindowHandle;
-        } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
-            newHoverWindowHandle = mLastHoverWindowHandle;
-        }
-
-        // Update the temporary touch state.
-        BitSet32 pointerIds;
-        if (isSplit) {
-            uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
-            pointerIds.markBit(pointerId);
-        }
-        mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
+        mTempTouchState.addGestureMonitors(newGestureMonitors);
     } else {
         /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
 
@@ -1404,6 +1471,7 @@
             sp<InputWindowHandle> newTouchedWindowHandle =
                     findTouchedWindowAtLocked(displayId, x, y);
             if (oldTouchedWindowHandle != newTouchedWindowHandle
+                    && oldTouchedWindowHandle != nullptr
                     && newTouchedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
                 ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
@@ -1475,10 +1543,11 @@
                 }
             }
         }
-        if (! haveForegroundWindow) {
+        bool hasGestureMonitor = !mTempTouchState.gestureMonitors.empty();
+        if (!haveForegroundWindow && !hasGestureMonitor) {
 #if DEBUG_FOCUS
-            ALOGD("Dropping event because there is no touched foreground window in display %" PRId32
-                    " to receive it.", displayId);
+            ALOGD("Dropping event because there is no touched foreground window in display %"
+                    PRId32 " or gesture monitor to receive it.", displayId);
 #endif
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             goto Failed;
@@ -1493,13 +1562,15 @@
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
         sp<InputWindowHandle> foregroundWindowHandle =
                 mTempTouchState.getFirstForegroundWindowHandle();
-        const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
-        for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
-            if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-                sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
-                if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
-                    mTempTouchState.addOrUpdateWindow(inputWindowHandle,
-                            InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
+        if (foregroundWindowHandle) {
+            const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
+            for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
+                if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+                    sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
+                    if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
+                        mTempTouchState.addOrUpdateWindow(inputWindowHandle,
+                                InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
+                    }
                 }
             }
         }
@@ -1528,7 +1599,7 @@
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
         sp<InputWindowHandle> foregroundWindowHandle =
                 mTempTouchState.getFirstForegroundWindowHandle();
-        if (foregroundWindowHandle->getInfo()->hasWallpaper) {
+        if (foregroundWindowHandle && foregroundWindowHandle->getInfo()->hasWallpaper) {
             const std::vector<sp<InputWindowHandle>> windowHandles =
                     getWindowHandlesLocked(displayId);
             for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
@@ -1554,6 +1625,11 @@
                 touchedWindow.pointerIds, inputTargets);
     }
 
+    for (const TouchedMonitor& touchedMonitor : mTempTouchState.gestureMonitors) {
+        addMonitoringTargetLocked(touchedMonitor.monitor, touchedMonitor.xOffset,
+                touchedMonitor.yOffset, inputTargets);
+    }
+
     // Drop the outside or hover touch windows since we will not care about them
     // in the next iteration.
     mTempTouchState.filterNonAsIsTouchWindows();
@@ -1683,31 +1759,32 @@
     inputTargets.push_back(target);
 }
 
-void InputDispatcher::addMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
-        int32_t displayId, float xOffset, float yOffset) {
-    std::unordered_map<int32_t, std::vector<sp<InputChannel>>>::const_iterator it =
-            mMonitoringChannelsByDisplay.find(displayId);
+void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+         int32_t displayId, float xOffset, float yOffset) {
 
-    if (it != mMonitoringChannelsByDisplay.end()) {
-        const std::vector<sp<InputChannel>>& monitoringChannels = it->second;
-        const size_t numChannels = monitoringChannels.size();
-        for (size_t i = 0; i < numChannels; i++) {
-            InputTarget target;
-            target.inputChannel = monitoringChannels[i];
-            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-            target.xOffset = xOffset;
-            target.yOffset = yOffset;
-            target.pointerIds.clear();
-            target.globalScaleFactor = 1.0f;
-            inputTargets.push_back(target);
+    std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
+            mGlobalMonitorsByDisplay.find(displayId);
+
+    if (it != mGlobalMonitorsByDisplay.end()) {
+        const std::vector<Monitor>& monitors = it->second;
+        for (const Monitor& monitor : monitors) {
+            addMonitoringTargetLocked(monitor, xOffset, yOffset, inputTargets);
         }
-    } else {
-        // If there is no monitor channel registered or all monitor channel unregistered,
-        // the display can't detect the extra system gesture by a copy of input events.
-        ALOGW("There is no monitor channel found in display %" PRId32, displayId);
     }
 }
 
+void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor,
+        float xOffset, float yOffset, std::vector<InputTarget>& inputTargets) {
+    InputTarget target;
+    target.inputChannel = monitor.inputChannel;
+    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+    target.xOffset = xOffset;
+    target.yOffset = yOffset;
+    target.pointerIds.clear();
+    target.globalScaleFactor = 1.0f;
+    inputTargets.push_back(target);
+}
+
 bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
         const InjectionState* injectionState) {
     if (injectionState
@@ -1913,6 +1990,12 @@
 
 void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+                connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+        ATRACE_NAME(message.c_str());
+    }
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
             "xOffset=%f, yOffset=%f, globalScaleFactor=%f, "
@@ -1963,6 +2046,13 @@
 
 void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
+                connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+        ATRACE_NAME(message.c_str());
+    }
+
     bool wasEmpty = connection->outboundQueue.isEmpty();
 
     // Enqueue dispatch entries for the requested modes.
@@ -1988,6 +2078,13 @@
 void InputDispatcher::enqueueDispatchEntryLocked(
         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
         int32_t dispatchMode) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf(
+                "enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
+                connection->getInputChannelName().c_str(),
+                dispatchModeToString(dispatchMode).c_str());
+        ATRACE_NAME(message.c_str());
+    }
     int32_t inputTargetFlags = inputTarget->flags;
     if (!(inputTargetFlags & dispatchMode)) {
         return;
@@ -2063,7 +2160,7 @@
             return; // skip the inconsistent event
         }
 
-        dispatchPointerDownOutsideFocusIfNecessary(motionEntry->source,
+        dispatchPointerDownOutsideFocus(motionEntry->source,
                 dispatchEntry->resolvedAction, inputTarget->inputChannel->getToken());
 
         break;
@@ -2081,10 +2178,11 @@
 
 }
 
-void InputDispatcher::dispatchPointerDownOutsideFocusIfNecessary(uint32_t source, int32_t action,
+void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
         const sp<IBinder>& newToken) {
     int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    if (source != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
+    uint32_t maskedSource = source & AINPUT_SOURCE_CLASS_MASK;
+    if (maskedSource != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
         return;
     }
 
@@ -2093,9 +2191,8 @@
         return;
     }
 
-    int32_t displayId = inputWindowHandle->getInfo()->displayId;
     sp<InputWindowHandle> focusedWindowHandle =
-            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+            getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
 
     bool hasFocusChanged = !focusedWindowHandle || focusedWindowHandle->getToken() != newToken;
 
@@ -2103,11 +2200,18 @@
         return;
     }
 
-    // Dispatch onPointerDownOutsideFocus to the policy.
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
+    commandEntry->newToken = newToken;
 }
 
 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
         const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
+                connection->getInputChannelName().c_str());
+        ATRACE_NAME(message.c_str());
+    }
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ startDispatchCycle",
             connection->getInputChannelName().c_str());
@@ -2171,15 +2275,21 @@
             }
 
             // Publish the motion event.
-            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
-                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
-                    dispatchEntry->resolvedAction, motionEntry->actionButton,
-                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
-                    motionEntry->metaState, motionEntry->buttonState, motionEntry->classification,
-                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
-                    motionEntry->downTime, motionEntry->eventTime,
-                    motionEntry->pointerCount, motionEntry->pointerProperties,
-                    usingCoords);
+            status =
+                    connection->inputPublisher
+                            .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
+                                                motionEntry->source, motionEntry->displayId,
+                                                dispatchEntry->resolvedAction,
+                                                motionEntry->actionButton,
+                                                dispatchEntry->resolvedFlags,
+                                                motionEntry->edgeFlags, motionEntry->metaState,
+                                                motionEntry->buttonState,
+                                                motionEntry->classification, xOffset, yOffset,
+                                                motionEntry->xPrecision, motionEntry->yPrecision,
+                                                motionEntry->xCursorPosition,
+                                                motionEntry->yCursorPosition, motionEntry->downTime,
+                                                motionEntry->eventTime, motionEntry->pointerCount,
+                                                motionEntry->pointerProperties, usingCoords);
             break;
         }
 
@@ -2355,11 +2465,17 @@
 
 void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked (
         const CancelationOptions& options) {
-    for (auto& it : mMonitoringChannelsByDisplay) {
-        const std::vector<sp<InputChannel>>& monitoringChannels = it.second;
-        const size_t numChannels = monitoringChannels.size();
-        for (size_t i = 0; i < numChannels; i++) {
-            synthesizeCancelationEventsForInputChannelLocked(monitoringChannels[i], options);
+    synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay);
+    synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay);
+}
+
+void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
+        const CancelationOptions& options,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
+    for (const auto& it : monitorsByDisplay) {
+        const std::vector<Monitor>& monitors = it.second;
+        for (const Monitor& monitor : monitors) {
+            synthesizeCancelationEventsForInputChannelLocked(monitor.inputChannel, options);
         }
     }
 }
@@ -2499,24 +2615,17 @@
         }
     }
 
-    MotionEntry* splitMotionEntry = new MotionEntry(
-            originalMotionEntry->sequenceNum,
-            originalMotionEntry->eventTime,
-            originalMotionEntry->deviceId,
-            originalMotionEntry->source,
-            originalMotionEntry->displayId,
-            originalMotionEntry->policyFlags,
-            action,
-            originalMotionEntry->actionButton,
-            originalMotionEntry->flags,
-            originalMotionEntry->metaState,
-            originalMotionEntry->buttonState,
-            originalMotionEntry->classification,
-            originalMotionEntry->edgeFlags,
-            originalMotionEntry->xPrecision,
-            originalMotionEntry->yPrecision,
-            originalMotionEntry->downTime,
-            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
+    MotionEntry* splitMotionEntry =
+            new MotionEntry(originalMotionEntry->sequenceNum, originalMotionEntry->eventTime,
+                            originalMotionEntry->deviceId, originalMotionEntry->source,
+                            originalMotionEntry->displayId, originalMotionEntry->policyFlags,
+                            action, originalMotionEntry->actionButton, originalMotionEntry->flags,
+                            originalMotionEntry->metaState, originalMotionEntry->buttonState,
+                            originalMotionEntry->classification, originalMotionEntry->edgeFlags,
+                            originalMotionEntry->xPrecision, originalMotionEntry->yPrecision,
+                            originalMotionEntry->xCursorPosition,
+                            originalMotionEntry->yCursorPosition, originalMotionEntry->downTime,
+                            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
 
     if (originalMotionEntry->injectionState) {
         splitMotionEntry->injectionState = originalMotionEntry->injectionState;
@@ -2662,12 +2771,14 @@
 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
-            ", 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=%" PRId64,
-            args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
-            args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
-            args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
+          ", 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, xCursorPosition=%f, "
+          "mYCursorPosition=%f, downTime=%" PRId64,
+          args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+          args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
+          args->edgeFlags, args->xPrecision, args->yPrecision, arg->xCursorPosition,
+          args->yCursorPosition, args->downTime);
     for (uint32_t i = 0; i < args->pointerCount; i++) {
         ALOGD("  Pointer %d: id=%d, toolType=%d, "
                 "x=%f, y=%f, pressure=%f, size=%f, "
@@ -2709,12 +2820,12 @@
             mLock.unlock();
 
             MotionEvent event;
-            event.initialize(args->deviceId, args->source, args->displayId,
-                    args->action, args->actionButton,
-                    args->flags, args->edgeFlags, args->metaState, args->buttonState,
-                    args->classification, 0, 0, args->xPrecision, args->yPrecision,
-                    args->downTime, args->eventTime,
-                    args->pointerCount, args->pointerProperties, args->pointerCoords);
+            event.initialize(args->deviceId, args->source, args->displayId, args->action,
+                             args->actionButton, args->flags, args->edgeFlags, args->metaState,
+                             args->buttonState, args->classification, 0, 0, args->xPrecision,
+                             args->yPrecision, args->xCursorPosition, args->yCursorPosition,
+                             args->downTime, args->eventTime, args->pointerCount,
+                             args->pointerProperties, args->pointerCoords);
 
             policyFlags |= POLICY_FLAG_FILTERED;
             if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -2725,12 +2836,14 @@
         }
 
         // Just enqueue a new motion event.
-        MotionEntry* newEntry = new MotionEntry(args->sequenceNum, args->eventTime,
-                args->deviceId, args->source, args->displayId, policyFlags,
-                args->action, args->actionButton, args->flags,
-                args->metaState, args->buttonState, args->classification,
-                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
-                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
+        MotionEntry* newEntry =
+                new MotionEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
+                                args->displayId, policyFlags, args->action, args->actionButton,
+                                args->flags, args->metaState, args->buttonState,
+                                args->classification, args->edgeFlags, args->xPrecision,
+                                args->yPrecision, args->xCursorPosition, args->yCursorPosition,
+                                args->downTime, args->pointerCount, args->pointerProperties,
+                                args->pointerCoords, 0, 0);
 
         needWake = enqueueInboundEventLocked(newEntry);
         mLock.unlock();
@@ -2861,31 +2974,34 @@
         mLock.lock();
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
         const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        firstInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
-                policyFlags,
-                action, actionButton, motionEvent->getFlags(),
-                motionEvent->getMetaState(), motionEvent->getButtonState(),
-                motionEvent->getClassification(), motionEvent->getEdgeFlags(),
-                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(),
-                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
-                motionEvent->getXOffset(), motionEvent->getYOffset());
+        firstInjectedEntry =
+                new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+                                motionEvent->getDeviceId(), motionEvent->getSource(),
+                                motionEvent->getDisplayId(), policyFlags, action, actionButton,
+                                motionEvent->getFlags(), motionEvent->getMetaState(),
+                                motionEvent->getButtonState(), motionEvent->getClassification(),
+                                motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
+                                motionEvent->getYPrecision(), motionEvent->getRawXCursorPosition(),
+                                motionEvent->getRawYCursorPosition(), motionEvent->getDownTime(),
+                                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                                motionEvent->getXOffset(), motionEvent->getYOffset());
         lastInjectedEntry = firstInjectedEntry;
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
             samplePointerCoords += pointerCount;
-            MotionEntry* nextInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
-                    *sampleEventTimes,
-                    motionEvent->getDeviceId(), motionEvent->getSource(),
-                    motionEvent->getDisplayId(), policyFlags,
-                    action, actionButton, motionEvent->getFlags(),
-                    motionEvent->getMetaState(), motionEvent->getButtonState(),
-                    motionEvent->getClassification(), motionEvent->getEdgeFlags(),
-                    motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                    motionEvent->getDownTime(),
-                    uint32_t(pointerCount), pointerProperties, samplePointerCoords,
-                    motionEvent->getXOffset(), motionEvent->getYOffset());
+            MotionEntry* nextInjectedEntry =
+                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+                                    motionEvent->getDeviceId(), motionEvent->getSource(),
+                                    motionEvent->getDisplayId(), policyFlags, action, actionButton,
+                                    motionEvent->getFlags(), motionEvent->getMetaState(),
+                                    motionEvent->getButtonState(), motionEvent->getClassification(),
+                                    motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
+                                    motionEvent->getYPrecision(),
+                                    motionEvent->getRawXCursorPosition(),
+                                    motionEvent->getRawYCursorPosition(),
+                                    motionEvent->getDownTime(), uint32_t(pointerCount),
+                                    pointerProperties, samplePointerCoords,
+                                    motionEvent->getXOffset(), motionEvent->getYOffset());
             lastInjectedEntry->next = nextInjectedEntry;
             lastInjectedEntry = nextInjectedEntry;
         }
@@ -3309,8 +3425,9 @@
                     getInputChannelLocked(oldFocusedWindowHandle->getToken());
                 if (inputChannel != nullptr) {
                     CancelationOptions options(
-                            CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS,
+                            CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                             "The display which contains this window no longer has focus.");
+                    options.displayId = ADISPLAY_ID_NONE;
                     synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
                 }
             }
@@ -3514,8 +3631,9 @@
 }
 
 void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
-    dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
-    dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
+    dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
+    dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
+    dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
     dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
 
     if (!mFocusedApplicationHandlesByDisplay.empty()) {
@@ -3620,18 +3738,19 @@
         dump += INDENT "Displays: <none>\n";
     }
 
-    if (!mMonitoringChannelsByDisplay.empty()) {
-       for (auto& it : mMonitoringChannelsByDisplay) {
-            const std::vector<sp<InputChannel>>& monitoringChannels = it.second;
-            dump += StringPrintf(INDENT "MonitoringChannels in display %" PRId32 ":\n", it.first);
-            const size_t numChannels = monitoringChannels.size();
-            for (size_t i = 0; i < numChannels; i++) {
-                const sp<InputChannel>& channel = monitoringChannels[i];
-                dump += StringPrintf(INDENT2 "%zu: '%s'\n", i, channel->getName().c_str());
-            }
+    if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) {
+       for (auto& it : mGlobalMonitorsByDisplay) {
+            const std::vector<Monitor>& monitors = it.second;
+            dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first);
+            dumpMonitors(dump, monitors);
+       }
+       for (auto& it : mGestureMonitorsByDisplay) {
+            const std::vector<Monitor>& monitors = it.second;
+            dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first);
+            dumpMonitors(dump, monitors);
        }
     } else {
-        dump += INDENT "MonitoringChannels: <none>\n";
+        dump += INDENT "Monitors: <none>\n";
     }
 
     nsecs_t currentTime = now();
@@ -3746,7 +3865,18 @@
             mConfig.keyRepeatTimeout * 0.000001f);
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, int32_t displayId) {
+void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) {
+    const size_t numMonitors = monitors.size();
+    for (size_t i = 0; i < numMonitors; i++) {
+        const Monitor& monitor = monitors[i];
+        const sp<InputChannel>& channel = monitor.inputChannel;
+        dump += StringPrintf(INDENT2 "%zu: '%s', ", i, channel->getName().c_str());
+        dump += "\n";
+    }
+}
+
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+        int32_t displayId) {
 #if DEBUG_REGISTRATION
     ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
             inputChannel->getName().c_str(), displayId);
@@ -3755,32 +3885,18 @@
     { // acquire lock
         std::scoped_lock _l(mLock);
 
-        // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
-        // treat inputChannel as monitor channel for displayId.
-        bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
-        if (monitor) {
-            inputChannel->setToken(new BBinder());
-        }
-
         if (getConnectionIndexLocked(inputChannel) >= 0) {
             ALOGW("Attempted to register already registered input channel '%s'",
                     inputChannel->getName().c_str());
             return BAD_VALUE;
         }
 
-        sp<Connection> connection = new Connection(inputChannel, monitor);
+        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/);
 
         int fd = inputChannel->getFd();
         mConnectionsByFd.add(fd, connection);
         mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
 
-        // Store monitor channel by displayId.
-        if (monitor) {
-            std::vector<sp<InputChannel>>& monitoringChannels =
-                    mMonitoringChannelsByDisplay[displayId];
-            monitoringChannels.push_back(inputChannel);
-        }
-
         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
     } // release lock
 
@@ -3789,6 +3905,40 @@
     return OK;
 }
 
+status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChannel,
+        int32_t displayId, bool isGestureMonitor) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (displayId < 0) {
+            ALOGW("Attempted to register input monitor without a specified display.");
+            return BAD_VALUE;
+        }
+
+        if (inputChannel->getToken() == nullptr) {
+            ALOGW("Attempted to register input monitor without an identifying token.");
+            return BAD_VALUE;
+        }
+
+        sp<Connection> connection = new Connection(inputChannel, true /*monitor*/);
+
+        const int fd = inputChannel->getFd();
+        mConnectionsByFd.add(fd, connection);
+        mInputChannelsByToken[inputChannel->getToken()] = inputChannel;
+
+        auto& monitorsByDisplay = isGestureMonitor
+                ? mGestureMonitorsByDisplay
+                : mGlobalMonitorsByDisplay;
+        monitorsByDisplay[displayId].emplace_back(inputChannel);
+
+        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+
+    }
+    // Wake the looper because some connections have changed.
+    mLooper->wake();
+    return OK;
+}
+
 status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
 #if DEBUG_REGISTRATION
     ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().c_str());
@@ -3837,24 +3987,89 @@
 }
 
 void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
-    for (auto it = mMonitoringChannelsByDisplay.begin();
-            it != mMonitoringChannelsByDisplay.end(); ) {
-        std::vector<sp<InputChannel>>& monitoringChannels = it->second;
-        const size_t numChannels = monitoringChannels.size();
-        for (size_t i = 0; i < numChannels; i++) {
-             if (monitoringChannels[i] == inputChannel) {
-                 monitoringChannels.erase(monitoringChannels.begin() + i);
+    removeMonitorChannelLocked(inputChannel, mGlobalMonitorsByDisplay);
+    removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay);
+}
+
+void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
+    for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end(); ) {
+        std::vector<Monitor>& monitors = it->second;
+        const size_t numMonitors = monitors.size();
+        for (size_t i = 0; i < numMonitors; i++) {
+             if (monitors[i].inputChannel == inputChannel) {
+                 monitors.erase(monitors.begin() + i);
                  break;
              }
         }
-        if (monitoringChannels.empty()) {
-            it = mMonitoringChannelsByDisplay.erase(it);
+        if (monitors.empty()) {
+            it = monitorsByDisplay.erase(it);
         } else {
             ++it;
         }
     }
 }
 
+status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        std::optional<int32_t> foundDisplayId = findGestureMonitorDisplayByTokenLocked(token);
+
+        if (!foundDisplayId) {
+            ALOGW("Attempted to pilfer pointers from an un-registered monitor or invalid token");
+            return BAD_VALUE;
+        }
+        int32_t displayId = foundDisplayId.value();
+
+        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+        if (stateIndex < 0) {
+            ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId);
+            return BAD_VALUE;
+        }
+
+        TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+        std::optional<int32_t> foundDeviceId;
+        for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) {
+            if (touchedMonitor.monitor.inputChannel->getToken() == token) {
+                foundDeviceId = state.deviceId;
+            }
+        }
+        if (!foundDeviceId || !state.down) {
+            ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams."
+                    " Ignoring.");
+            return BAD_VALUE;
+        }
+        int32_t deviceId = foundDeviceId.value();
+
+        // Send cancel events to all the input channels we're stealing from.
+        CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+                "gesture monitor stole pointer stream");
+        options.deviceId = deviceId;
+        options.displayId = displayId;
+        for (const TouchedWindow& window : state.windows) {
+            sp<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken());
+            synthesizeCancelationEventsForInputChannelLocked(channel, options);
+        }
+        // Then clear the current touch state so we stop dispatching to them as well.
+        state.filterNonMonitors();
+    }
+    return OK;
+}
+
+
+std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked(
+        const sp<IBinder>& token) {
+    for (const auto& it : mGestureMonitorsByDisplay) {
+        const std::vector<Monitor>& monitors = it.second;
+        for (const Monitor& monitor : monitors) {
+            if (monitor.inputChannel->getToken() == token) {
+                return it.first;
+            }
+        }
+    }
+    return std::nullopt;
+}
+
 ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
     if (inputChannel == nullptr) {
         return -1;
@@ -4013,6 +4228,12 @@
     entry->release();
 }
 
+void InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+    mPolicy->onPointerDownOutsideFocus(commandEntry->newToken);
+    mLock.lock();
+}
+
 void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
         CommandEntry* commandEntry) {
     sp<Connection> connection = commandEntry->connection;
@@ -4433,21 +4654,32 @@
 
 // --- InputDispatcher::MotionEntry ---
 
-InputDispatcher::MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
-        uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
-        int32_t actionButton,
+InputDispatcher::MotionEntry::MotionEntry(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+        int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
         int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
-        int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
-        uint32_t pointerCount,
+        int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
+        float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-        float xOffset, float yOffset) :
-        EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
+        float xOffset, float yOffset)
+      : EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
         eventTime(eventTime),
-        deviceId(deviceId), source(source), displayId(displayId), action(action),
-        actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
-        classification(classification), edgeFlags(edgeFlags),
-        xPrecision(xPrecision), yPrecision(yPrecision),
-        downTime(downTime), pointerCount(pointerCount) {
+        deviceId(deviceId),
+        source(source),
+        displayId(displayId),
+        action(action),
+        actionButton(actionButton),
+        flags(flags),
+        metaState(metaState),
+        buttonState(buttonState),
+        classification(classification),
+        edgeFlags(edgeFlags),
+        xPrecision(xPrecision),
+        yPrecision(yPrecision),
+        xCursorPosition(xCursorPosition),
+        yCursorPosition(yCursorPosition),
+        downTime(downTime),
+        pointerCount(pointerCount) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
         this->pointerCoords[i].copyFrom(pointerCoords[i]);
@@ -4462,11 +4694,14 @@
 
 void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
     msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
-            ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
-            "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[",
-            deviceId, source, displayId, motionActionToString(action).c_str(), actionButton, flags,
-            metaState, buttonState, motionClassificationToString(classification), edgeFlags,
-            xPrecision, yPrecision);
+                        ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
+                        "buttonState=0x%08x, "
+                        "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
+                        "xCursorPosition=%0.1f, yCursorPosition=%0.1f, pointers=[",
+                        deviceId, source, displayId, motionActionToString(action).c_str(),
+                        actionButton, flags, metaState, buttonState,
+                        motionClassificationToString(classification), edgeFlags, xPrecision,
+                        yPrecision, xCursorPosition, yCursorPosition);
 
     for (uint32_t i = 0; i < pointerCount; i++) {
         if (i) {
@@ -4736,6 +4971,8 @@
     memento.flags = flags;
     memento.xPrecision = entry->xPrecision;
     memento.yPrecision = entry->yPrecision;
+    memento.xCursorPosition = entry->xCursorPosition;
+    memento.yCursorPosition = entry->yCursorPosition;
     memento.downTime = entry->downTime;
     memento.setPointers(entry);
     memento.hovering = hovering;
@@ -4766,13 +5003,16 @@
         if (shouldCancelMotion(memento, options)) {
             const int32_t action = memento.hovering ?
                     AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
-            outEvents.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
-                    memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
-                    action, 0 /*actionButton*/, memento.flags, AMETA_NONE, 0 /*buttonState*/,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    memento.xPrecision, memento.yPrecision, memento.downTime,
-                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
-                    0 /*xOffset*/, 0 /*yOffset*/));
+            outEvents.push_back(
+                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, memento.deviceId,
+                                    memento.source, memento.displayId, memento.policyFlags, action,
+                                    0 /*actionButton*/, memento.flags, AMETA_NONE,
+                                    0 /*buttonState*/, MotionClassification::NONE,
+                                    AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
+                                    memento.yPrecision, memento.xCursorPosition,
+                                    memento.yCursorPosition, memento.downTime, memento.pointerCount,
+                                    memento.pointerProperties, memento.pointerCoords, 0 /*xOffset*/,
+                                    0 /*yOffset*/));
         }
     }
 }
@@ -4823,11 +5063,15 @@
 
 bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
         const CancelationOptions& options) {
-    if (options.keyCode != -1 && memento.keyCode != options.keyCode) {
+    if (options.keyCode && memento.keyCode != options.keyCode.value()) {
         return false;
     }
 
-    if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
+    if (options.deviceId  && memento.deviceId != options.deviceId.value()) {
+        return false;
+    }
+
+    if (options.displayId && memento.displayId != options.displayId.value()) {
         return false;
     }
 
@@ -4837,8 +5081,6 @@
         return true;
     case CancelationOptions::CANCEL_FALLBACK_EVENTS:
         return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
-    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
-        return memento.displayId == ADISPLAY_ID_NONE;
     default:
         return false;
     }
@@ -4846,7 +5088,11 @@
 
 bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
         const CancelationOptions& options) {
-    if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
+    if (options.deviceId && memento.deviceId != options.deviceId.value()) {
+        return false;
+    }
+
+    if (options.displayId && memento.displayId != options.displayId.value()) {
         return false;
     }
 
@@ -4857,8 +5103,6 @@
         return memento.source & AINPUT_SOURCE_CLASS_POINTER;
     case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
         return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
-    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
-        return memento.displayId == ADISPLAY_ID_NONE;
     default:
         return false;
     }
@@ -4911,9 +5155,14 @@
     return nullptr;
 }
 
+// --- InputDispatcher::Monitor
+InputDispatcher::Monitor::Monitor(const sp<InputChannel>& inputChannel) :
+    inputChannel(inputChannel) {
+}
+
 
 // --- InputDispatcher::CommandEntry ---
-
+//
 InputDispatcher::CommandEntry::CommandEntry(Command command) :
     command(command), eventTime(0), keyEntry(nullptr), userActivityEventType(0),
     seq(0), handled(false) {
@@ -4922,6 +5171,10 @@
 InputDispatcher::CommandEntry::~CommandEntry() {
 }
 
+// --- InputDispatcher::TouchedMonitor ---
+InputDispatcher::TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset,
+        float yOffset) : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {
+}
 
 // --- InputDispatcher::TouchState ---
 
@@ -4940,6 +5193,7 @@
     displayId = ADISPLAY_ID_NONE;
     windows.clear();
     portalWindows.clear();
+    gestureMonitors.clear();
 }
 
 void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
@@ -4950,6 +5204,7 @@
     displayId = other.displayId;
     windows = other.windows;
     portalWindows = other.portalWindows;
+    gestureMonitors = other.gestureMonitors;
 }
 
 void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
@@ -4987,6 +5242,14 @@
     portalWindows.push_back(windowHandle);
 }
 
+void InputDispatcher::TouchState::addGestureMonitors(
+        const std::vector<TouchedMonitor>& newMonitors) {
+    const size_t newSize = gestureMonitors.size() + newMonitors.size();
+    gestureMonitors.reserve(newSize);
+    gestureMonitors.insert(std::end(gestureMonitors),
+            std::begin(newMonitors), std::end(newMonitors));
+}
+
 void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
     for (size_t i = 0; i < windows.size(); i++) {
         if (windows[i].windowHandle == windowHandle) {
@@ -5019,6 +5282,11 @@
     }
 }
 
+void InputDispatcher::TouchState::filterNonMonitors() {
+    windows.clear();
+    portalWindows.clear();
+}
+
 sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
     for (size_t i = 0; i < windows.size(); i++) {
         const TouchedWindow& window = windows[i];
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 183efa9..c30a8d6 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -23,6 +23,8 @@
 #include <input/InputTransport.h>
 #include <input/InputWindow.h>
 #include <input/ISetInputWindowsListener.h>
+#include <optional>
+#include <ui/Region.h>
 #include <utils/threads.h>
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
@@ -272,6 +274,13 @@
      */
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid) = 0;
+
+    /* Notifies the policy that a pointer down event has occurred outside the current focused
+     * window.
+     *
+     * The touchedToken passed as an argument is the window that received the input event.
+     */
+    virtual void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) = 0;
 };
 
 
@@ -351,19 +360,35 @@
     virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
 
     /* Registers input channels that may be used as targets for input events.
-     * If inputWindowHandle is null, and displayId is not ADISPLAY_ID_NONE,
-     * the channel will receive a copy of all input events form the specific displayId.
      *
      * This method may be called on any thread (usually by the input manager).
      */
     virtual status_t registerInputChannel(
             const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
 
+    /* Registers input channels to be used to monitor input events.
+     *
+     * Each monitor must target a specific display and will only receive input events sent to that
+     * display. If the monitor is a gesture monitor, it will only receive pointer events on the
+     * targeted display.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t registerInputMonitor(
+            const sp<InputChannel>& inputChannel, int32_t displayId, bool gestureMonitor) = 0;
+
     /* Unregister input channels that will no longer receive input events.
      *
      * This method may be called on any thread (usually by the input manager).
      */
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+    /* Allows an input monitor steal the current pointer stream away from normal input windows.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t pilferPointers(const sp<IBinder>& token) = 0;
+
 };
 
 /* Dispatches events to input targets.  Some functions of the input dispatcher, such as
@@ -390,35 +415,39 @@
 public:
     explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
 
-    virtual void dump(std::string& dump);
-    virtual void monitor();
+    virtual void dump(std::string& dump) override;
+    virtual void monitor() override;
 
-    virtual void dispatchOnce();
+    virtual void dispatchOnce() override;
 
-    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
-    virtual void notifyKey(const NotifyKeyArgs* args);
-    virtual void notifyMotion(const NotifyMotionArgs* args);
-    virtual void notifySwitch(const NotifySwitchArgs* args);
-    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
+    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+    virtual void notifyKey(const NotifyKeyArgs* args) override;
+    virtual void notifyMotion(const NotifyMotionArgs* args) override;
+    virtual void notifySwitch(const NotifySwitchArgs* args) override;
+    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
 
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
-            uint32_t policyFlags);
+            uint32_t policyFlags) override;
 
     virtual void setInputWindows(const std::vector<sp<InputWindowHandle> >& inputWindowHandles,
             int32_t displayId,
-            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr);
+            const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
     virtual void setFocusedApplication(int32_t displayId,
-            const sp<InputApplicationHandle>& inputApplicationHandle);
-    virtual void setFocusedDisplay(int32_t displayId);
-    virtual void setInputDispatchMode(bool enabled, bool frozen);
-    virtual void setInputFilterEnabled(bool enabled);
+            const sp<InputApplicationHandle>& inputApplicationHandle) override;
+    virtual void setFocusedDisplay(int32_t displayId) override;
+    virtual void setInputDispatchMode(bool enabled, bool frozen) override;
+    virtual void setInputFilterEnabled(bool enabled) override;
 
-    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
+    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken)
+            override;
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            int32_t displayId);
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+            int32_t displayId) override;
+    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel,
+            int32_t displayId, bool isGestureMonitor) override;
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
+    virtual status_t pilferPointers(const sp<IBinder>& token) override;
 
 private:
     template <typename T>
@@ -541,19 +570,21 @@
         int32_t edgeFlags;
         float xPrecision;
         float yPrecision;
+        float xCursorPosition;
+        float yCursorPosition;
         nsecs_t downTime;
         uint32_t pointerCount;
         PointerProperties pointerProperties[MAX_POINTERS];
         PointerCoords pointerCoords[MAX_POINTERS];
 
-        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
-                int32_t action, int32_t actionButton, int32_t flags,
-                int32_t metaState, int32_t buttonState, MotionClassification classification,
-                int32_t edgeFlags, float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
-                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-                float xOffset, float yOffset);
+        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+                    int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+                    int32_t flags, int32_t metaState, int32_t buttonState,
+                    MotionClassification classification, int32_t edgeFlags, float xPrecision,
+                    float yPrecision, float xCursorPosition, float yCursorPosition,
+                    nsecs_t downTime, uint32_t pointerCount,
+                    const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+                    float xOffset, float yOffset);
         virtual void appendDescription(std::string& msg) const;
 
     protected:
@@ -712,10 +743,6 @@
             CANCEL_POINTER_EVENTS = 1,
             CANCEL_NON_POINTER_EVENTS = 2,
             CANCEL_FALLBACK_EVENTS = 3,
-
-            /* Cancel events where the display not specified. These events would go to the focused
-             * display. */
-            CANCEL_DISPLAY_UNSPECIFIED_EVENTS = 4,
         };
 
         // The criterion to use to determine which events should be canceled.
@@ -724,14 +751,16 @@
         // Descriptive reason for the cancelation.
         const char* reason;
 
-        // The specific keycode of the key event to cancel, or -1 to cancel any key event.
-        int32_t keyCode;
+        // The specific keycode of the key event to cancel, or nullopt to cancel any key event.
+        std::optional<int32_t> keyCode = std::nullopt;
 
-        // The specific device id of events to cancel, or -1 to cancel events from any device.
-        int32_t deviceId;
+        // The specific device id of events to cancel, or nullopt to cancel events from any device.
+        std::optional<int32_t> deviceId = std::nullopt;
 
-        CancelationOptions(Mode mode, const char* reason) :
-                mode(mode), reason(reason), keyCode(-1), deviceId(-1) { }
+        // The specific display id of events to cancel, or nullopt to cancel events on any display.
+        std::optional<int32_t> displayId = std::nullopt;
+
+        CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) { }
     };
 
     /* Tracks dispatched key and motion event state so that cancelation events can be
@@ -803,6 +832,8 @@
             int32_t flags;
             float xPrecision;
             float yPrecision;
+            float xCursorPosition;
+            float yCursorPosition;
             nsecs_t downTime;
             uint32_t pointerCount;
             PointerProperties pointerProperties[MAX_POINTERS];
@@ -871,6 +902,12 @@
         DispatchEntry* findWaitQueueEntry(uint32_t seq);
     };
 
+    struct Monitor {
+        sp<InputChannel> inputChannel; // never null
+
+        explicit Monitor(const sp<InputChannel>& inputChannel);
+    };
+
     enum DropReason {
         DROP_REASON_NOT_DROPPED = 0,
         DROP_REASON_POLICY = 1,
@@ -936,12 +973,24 @@
     std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
             GUARDED_BY(mLock);
 
+    // Finds the display ID of the gesture monitor identified by the provided token.
+    std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
+            REQUIRES(mLock);
+
     ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
 
     // Input channels that will receive a copy of all input events sent to the provided display.
-    std::unordered_map<int32_t, std::vector<sp<InputChannel>>> mMonitoringChannelsByDisplay
+    std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay
             GUARDED_BY(mLock);
 
+    // Input channels that will receive pointer events that start within the corresponding display.
+    // These are a bit special when compared to global monitors since they'll cause gesture streams
+    // to continue even when there isn't a touched window,and have the ability to steal the rest of
+    // the pointer stream in order to claim it for a system gesture.
+    std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay
+            GUARDED_BY(mLock);
+
+
     // Event injection and synchronization.
     std::condition_variable mInjectionResultAvailable;
     bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
@@ -1023,6 +1072,16 @@
         int32_t targetFlags;
         BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
     };
+
+    // For tracking the offsets we need to apply when adding gesture monitor targets.
+    struct TouchedMonitor {
+        Monitor monitor;
+        float xOffset = 0.f;
+        float yOffset = 0.f;
+
+        explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
+    };
+
     struct TouchState {
         bool down;
         bool split;
@@ -1036,6 +1095,8 @@
         // monitoring channels of the displays touched.
         std::vector<sp<InputWindowHandle>> portalWindows;
 
+        std::vector<TouchedMonitor> gestureMonitors;
+
         TouchState();
         ~TouchState();
         void reset();
@@ -1043,9 +1104,11 @@
         void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
                 int32_t targetFlags, BitSet32 pointerIds);
         void addPortalWindow(const sp<InputWindowHandle>& windowHandle);
+        void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
         void removeWindow(const sp<InputWindowHandle>& windowHandle);
         void removeWindowByToken(const sp<IBinder>& token);
         void filterNonAsIsTouchWindows();
+        void filterNonMonitors();
         sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
         bool isSlippery() const;
     };
@@ -1115,12 +1178,18 @@
     int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
             std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
             bool* outConflictingPointerActions) REQUIRES(mLock);
+    std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(int32_t displayId,
+            const std::vector<sp<InputWindowHandle>>& portalWindows) REQUIRES(mLock);
+    void addGestureMonitors(const std::vector<Monitor>& monitors,
+            std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0, float yOffset = 0);
 
     void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
             int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets)
             REQUIRES(mLock);
-    void addMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId,
-            float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
+    void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
+            std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
+    void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
+            int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
 
     void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock);
     bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
@@ -1156,13 +1225,15 @@
     void releaseDispatchEntry(DispatchEntry* dispatchEntry);
     static int handleReceiveCallback(int fd, int events, void* data);
     // The action sent should only be of type AMOTION_EVENT_*
-    void dispatchPointerDownOutsideFocusIfNecessary(uint32_t source, int32_t action,
+    void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
             const sp<IBinder>& newToken) REQUIRES(mLock);
 
     void synthesizeCancelationEventsForAllConnectionsLocked(
             const CancelationOptions& options) REQUIRES(mLock);
     void synthesizeCancelationEventsForMonitorsLocked(
             const CancelationOptions& options) REQUIRES(mLock);
+    void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options,
+            std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
     void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
             const CancelationOptions& options) REQUIRES(mLock);
     void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
@@ -1176,10 +1247,14 @@
 
     // Dump state.
     void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock);
+    void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors);
     void logDispatchStateLocked() REQUIRES(mLock);
 
     // Registration.
     void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+    void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel,
+        std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay)
+            REQUIRES(mLock);
     status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
             REQUIRES(mLock);
 
@@ -1211,6 +1286,8 @@
             DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) REQUIRES(mLock);
     void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
     void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
+    void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
 
     // Statistics gathering.
     void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 423b69c..de63977 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -21,6 +21,7 @@
 #include "InputListener.h"
 
 #include <android/log.h>
+#include <math.h>
 
 namespace android {
 
@@ -87,21 +88,32 @@
 
 // --- NotifyMotionArgs ---
 
-NotifyMotionArgs::NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
-        uint32_t source, int32_t displayId, uint32_t policyFlags,
-        int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
-        int32_t buttonState, MotionClassification classification,
-        int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
-        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-        float xPrecision, float yPrecision, nsecs_t downTime,
-        const std::vector<TouchVideoFrame>& videoFrames) :
-        NotifyArgs(sequenceNum, eventTime), deviceId(deviceId), source(source),
-        displayId(displayId), policyFlags(policyFlags),
-        action(action), actionButton(actionButton),
-        flags(flags), metaState(metaState), buttonState(buttonState),
-        classification(classification), edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
+NotifyMotionArgs::NotifyMotionArgs(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+        int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+        int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+        int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
+        const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+        float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+        const std::vector<TouchVideoFrame>& videoFrames)
+      : NotifyArgs(sequenceNum, eventTime),
+        deviceId(deviceId),
+        source(source),
+        displayId(displayId),
+        policyFlags(policyFlags),
+        action(action),
+        actionButton(actionButton),
+        flags(flags),
+        metaState(metaState),
+        buttonState(buttonState),
+        classification(classification),
+        edgeFlags(edgeFlags),
         pointerCount(pointerCount),
-        xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime),
+        xPrecision(xPrecision),
+        yPrecision(yPrecision),
+        xCursorPosition(xCursorPosition),
+        yCursorPosition(yCursorPosition),
+        downTime(downTime),
         videoFrames(videoFrames) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
@@ -109,14 +121,25 @@
     }
 }
 
-NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
-        NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId),
-        source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
-        action(other.action), actionButton(other.actionButton), flags(other.flags),
-        metaState(other.metaState), buttonState(other.buttonState),
-        classification(other.classification), edgeFlags(other.edgeFlags),
-        deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount),
-        xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime),
+NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other)
+      : NotifyArgs(other.sequenceNum, other.eventTime),
+        deviceId(other.deviceId),
+        source(other.source),
+        displayId(other.displayId),
+        policyFlags(other.policyFlags),
+        action(other.action),
+        actionButton(other.actionButton),
+        flags(other.flags),
+        metaState(other.metaState),
+        buttonState(other.buttonState),
+        classification(other.classification),
+        edgeFlags(other.edgeFlags),
+        pointerCount(other.pointerCount),
+        xPrecision(other.xPrecision),
+        yPrecision(other.yPrecision),
+        xCursorPosition(other.xCursorPosition),
+        yCursorPosition(other.yCursorPosition),
+        downTime(other.downTime),
         videoFrames(other.videoFrames) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         pointerProperties[i].copyFrom(other.pointerProperties[i]);
@@ -124,28 +147,23 @@
     }
 }
 
+static inline bool isCursorPositionEqual(float lhs, float rhs) {
+    return (isnan(lhs) && isnan(rhs)) || lhs == rhs;
+}
+
 bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const {
-    bool equal =
-            sequenceNum == rhs.sequenceNum
-            && eventTime == rhs.eventTime
-            && deviceId == rhs.deviceId
-            && source == rhs.source
-            && displayId == rhs.displayId
-            && policyFlags == rhs.policyFlags
-            && action == rhs.action
-            && actionButton == rhs.actionButton
-            && flags == rhs.flags
-            && metaState == rhs.metaState
-            && buttonState == rhs.buttonState
-            && classification == rhs.classification
-            && edgeFlags == rhs.edgeFlags
-            && deviceTimestamp == rhs.deviceTimestamp
-            && pointerCount == rhs.pointerCount
+    bool equal = sequenceNum == rhs.sequenceNum && eventTime == rhs.eventTime &&
+            deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
+            policyFlags == rhs.policyFlags && action == rhs.action &&
+            actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState &&
+            buttonState == rhs.buttonState && classification == rhs.classification &&
+            edgeFlags == rhs.edgeFlags &&
+            pointerCount == rhs.pointerCount
             // PointerProperties and PointerCoords are compared separately below
-            && xPrecision == rhs.xPrecision
-            && yPrecision == rhs.yPrecision
-            && downTime == rhs.downTime
-            && videoFrames == rhs.videoFrames;
+            && xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision &&
+            isCursorPositionEqual(xCursorPosition, rhs.xCursorPosition) &&
+            isCursorPositionEqual(yCursorPosition, rhs.yCursorPosition) &&
+            downTime == rhs.downTime && videoFrames == rhs.videoFrames;
     if (!equal) {
         return false;
     }
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index a45b8a5..2de5ffa 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -559,7 +559,8 @@
     mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
 
     if (changes) {
-        ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
+        ALOGI("Reconfiguring input devices, changes=%s",
+              InputReaderConfiguration::changesToString(changes).c_str());
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
 
         if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
@@ -1093,8 +1094,8 @@
         }
 
         if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
-            ssize_t index = config->disabledDevices.indexOf(mId);
-            bool enabled = index < 0;
+            auto it = config->disabledDevices.find(mId);
+            bool enabled = it == config->disabledDevices.end();
             setEnabled(enabled, when);
         }
 
@@ -1731,10 +1732,12 @@
 
 // --- MultiTouchMotionAccumulator ---
 
-MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
-        mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false),
-        mHaveStylus(false), mDeviceTimestamp(0) {
-}
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
+      : mCurrentSlot(-1),
+        mSlots(nullptr),
+        mSlotCount(0),
+        mUsingSlotsProtocol(false),
+        mHaveStylus(false) {}
 
 MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
     delete[] mSlots;
@@ -1774,7 +1777,6 @@
     } else {
         clearSlots(-1);
     }
-    mDeviceTimestamp = 0;
 }
 
 void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
@@ -1868,8 +1870,6 @@
     } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
         // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
         mCurrentSlot += 1;
-    } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
-        mDeviceTimestamp = rawEvent->value;
     }
 }
 
@@ -2782,6 +2782,8 @@
     mPointerVelocityControl.move(when, &deltaX, &deltaY);
 
     int32_t displayId;
+    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     if (mSource == AINPUT_SOURCE_MOUSE) {
         if (moved || scrolled || buttonsChanged) {
             mPointerController->setPresentation(
@@ -2798,10 +2800,9 @@
             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
         }
 
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
         displayId = mPointerController->getDisplayId();
@@ -2845,21 +2846,23 @@
                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
                 buttonState &= ~actionButton;
                 NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                        mSource, displayId, policyFlags,
-                        AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
-                        metaState, buttonState,
-                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                             mSource, displayId, policyFlags,
+                                             AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+                                             metaState, buttonState, MotionClassification::NONE,
+                                             AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                             &pointerCoords, mXPrecision, mYPrecision,
+                                             xCursorPosition, yCursorPosition, downTime,
+                                             /* videoFrames */ {});
                 getListener()->notifyMotion(&releaseArgs);
             }
         }
 
         NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                              displayId, policyFlags, motionEventAction, 0, 0, metaState,
+                              currentButtonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
+                              mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
 
         if (buttonsPressed) {
@@ -2868,11 +2871,13 @@
                 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
                 buttonState |= actionButton;
                 NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
-                        actionButton, 0, metaState, buttonState,
-                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                           mSource, displayId, policyFlags,
+                                           AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
+                                           metaState, buttonState, MotionClassification::NONE,
+                                           AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                           &pointerCoords, mXPrecision, mYPrecision,
+                                           xCursorPosition, yCursorPosition, downTime,
+                                           /* videoFrames */ {});
                 getListener()->notifyMotion(&pressArgs);
             }
         }
@@ -2882,12 +2887,12 @@
         // Send hover move after UP to tell the application that the mouse is hovering now.
         if (motionEventAction == AMOTION_EVENT_ACTION_UP
                 && (mSource == AINPUT_SOURCE_MOUSE)) {
-            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                    metaState, currentButtonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                       displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+                                       0, metaState, currentButtonState, MotionClassification::NONE,
+                                       AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                       &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
+                                       yCursorPosition, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&hoverArgs);
         }
 
@@ -2897,11 +2902,12 @@
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
             NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                        mSource, displayId, policyFlags,
+                                        AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+                                        currentButtonState, MotionClassification::NONE,
+                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                        &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
+                                        yCursorPosition, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&scrollArgs);
         }
     }
@@ -3041,12 +3047,12 @@
         int32_t metaState = mContext->getGlobalMetaState();
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
 
-        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                0, 0, 0, /* videoFrames */ {});
+        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                    displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
+                                    metaState, /* buttonState */ 0, MotionClassification::NONE,
+                                    AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                    &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                    AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
         getListener()->notifyMotion(&scrollArgs);
     }
 
@@ -4767,7 +4773,6 @@
         int32_t buttonState = mCurrentCookedState.buttonState;
         dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                mCurrentCookedState.deviceTimestamp,
                 mCurrentCookedState.cookedPointerData.pointerProperties,
                 mCurrentCookedState.cookedPointerData.pointerCoords,
                 mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4790,7 +4795,6 @@
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
                     AMOTION_EVENT_EDGE_FLAG_NONE,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4825,7 +4829,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mLastCookedState.cookedPointerData.pointerProperties,
                     mLastCookedState.cookedPointerData.pointerCoords,
                     mLastCookedState.cookedPointerData.idToIndex,
@@ -4840,7 +4843,6 @@
             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4859,7 +4861,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4875,7 +4876,6 @@
         int32_t metaState = getContext()->getGlobalMetaState();
         dispatchMotion(when, policyFlags, mSource,
                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
-                mLastCookedState.deviceTimestamp,
                 mLastCookedState.cookedPointerData.pointerProperties,
                 mLastCookedState.cookedPointerData.pointerCoords,
                 mLastCookedState.cookedPointerData.idToIndex,
@@ -4892,7 +4892,6 @@
         if (!mSentHoverEnter) {
             dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
                     0, 0, metaState, mCurrentRawState.buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4904,7 +4903,6 @@
         dispatchMotion(when, policyFlags, mSource,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
                 mCurrentRawState.buttonState, 0,
-                mCurrentCookedState.deviceTimestamp,
                 mCurrentCookedState.cookedPointerData.pointerProperties,
                 mCurrentCookedState.cookedPointerData.pointerCoords,
                 mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4924,7 +4922,6 @@
         dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
                     0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
@@ -4942,7 +4939,6 @@
         buttonState |= actionButton;
         dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
                     0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
@@ -4961,8 +4957,6 @@
     uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
 
     mCurrentCookedState.cookedPointerData.clear();
-    mCurrentCookedState.deviceTimestamp =
-            mCurrentRawState.deviceTimestamp;
     mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
     mCurrentCookedState.cookedPointerData.hoveringIdBits =
             mCurrentRawState.rawPointerData.hoveringIdBits;
@@ -5354,13 +5348,11 @@
     BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
     if (!dispatchedGestureIdBits.isEmpty()) {
         if (cancelPreviousGesture) {
-            dispatchMotion(when, policyFlags, mSource,
-                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
-                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                    mPointerGesture.lastGestureProperties,
-                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
-                    dispatchedGestureIdBits, -1, 0,
-                    0, mPointerGesture.downTime);
+            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
+                           buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                           mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
+                           mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
+                           mPointerGesture.downTime);
 
             dispatchedGestureIdBits.clear();
         } else {
@@ -5377,7 +5369,6 @@
                 dispatchMotion(when, policyFlags, mSource,
                         AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
                         metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0,
                         mPointerGesture.lastGestureProperties,
                         mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
                         dispatchedGestureIdBits, id,
@@ -5390,13 +5381,12 @@
 
     // Send motion events for all pointers that moved.
     if (moveNeeded) {
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.currentGestureProperties,
-                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
-                dispatchedGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.currentGestureProperties,
+                       mPointerGesture.currentGestureCoords,
+                       mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
+                       mPointerGesture.downTime);
     }
 
     // Send motion events for all pointers that went down.
@@ -5413,7 +5403,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
-                    /* deviceTimestamp */ 0,
                     mPointerGesture.currentGestureProperties,
                     mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
                     dispatchedGestureIdBits, id,
@@ -5423,13 +5412,12 @@
 
     // Send motion events for hover.
     if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.currentGestureProperties,
-                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
-                mPointerGesture.currentGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.currentGestureProperties,
+                       mPointerGesture.currentGestureCoords,
+                       mPointerGesture.currentGestureIdToIndex,
+                       mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
     } else if (dispatchedGestureIdBits.isEmpty()
             && !mPointerGesture.lastGestureIdBits.isEmpty()) {
         // Synthesize a hover move event after all pointers go up to indicate that
@@ -5450,12 +5438,11 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
 
         const int32_t displayId = mPointerController->getDisplayId();
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                0, 0, mPointerGesture.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                              metaState, buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
+                              0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -5482,13 +5469,11 @@
     if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
         int32_t metaState = getContext()->getGlobalMetaState();
         int32_t buttonState = mCurrentRawState.buttonState;
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.lastGestureProperties,
-                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
-                mPointerGesture.lastGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
+                       mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
+                       0, 0, mPointerGesture.downTime);
     }
 
     // Reset the current pointer gesture.
@@ -6360,29 +6345,31 @@
     int32_t metaState = getContext()->getGlobalMetaState();
     int32_t displayId = mViewport.displayId;
 
-    if (mPointerController != nullptr) {
-        if (down || hovering) {
-            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-            mPointerController->clearSpots();
-            mPointerController->setButtonState(mCurrentRawState.buttonState);
-            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
-            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-        }
-        displayId = mPointerController->getDisplayId();
+    if (down || hovering) {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+        mPointerController->clearSpots();
+        mPointerController->setButtonState(mCurrentRawState.buttonState);
+        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+    } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
     }
+    displayId = mPointerController->getDisplayId();
+
+    float xCursorPosition;
+    float yCursorPosition;
+    mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
 
     if (mPointerSimple.down && !down) {
         mPointerSimple.down = false;
 
         // Send up.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
+                              mLastRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+                              &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6390,13 +6377,13 @@
         mPointerSimple.hovering = false;
 
         // Send hover exit.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
+                              metaState, mLastRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+                              &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6406,25 +6393,24 @@
             mPointerSimple.downTime = when;
 
             // Send down.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0,
-                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                    mOrientedXPrecision, mOrientedYPrecision,
-                    mPointerSimple.downTime, /* videoFrames */ {});
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                  displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
+                                  metaState, mCurrentRawState.buttonState,
+                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                                  &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                                  mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+                                  yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&args);
         }
 
         // Send move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+                              mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &mPointerSimple.currentCoords, mOrientedXPrecision,
+                              mOrientedYPrecision, xCursorPosition, yCursorPosition,
+                              mPointerSimple.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6433,26 +6419,24 @@
             mPointerSimple.hovering = true;
 
             // Send hover enter.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
-                    mCurrentRawState.buttonState, MotionClassification::NONE,
-                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                    mOrientedXPrecision, mOrientedYPrecision,
-                    mPointerSimple.downTime, /* videoFrames */ {});
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                  displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
+                                  metaState, mCurrentRawState.buttonState,
+                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                                  &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                                  mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+                                  yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&args);
         }
 
         // Send hover move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
-                mCurrentRawState.buttonState, MotionClassification::NONE,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                              metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &mPointerSimple.currentCoords, mOrientedXPrecision,
+                              mOrientedYPrecision, xCursorPosition, yCursorPosition,
+                              mPointerSimple.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6468,13 +6452,13 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &pointerCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+                              mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6495,11 +6479,12 @@
 }
 
 void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
-        int32_t action, int32_t actionButton, int32_t flags,
-        int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
-        const PointerProperties* properties, const PointerCoords* coords,
-        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
-        float xPrecision, float yPrecision, nsecs_t downTime) {
+                                      int32_t action, int32_t actionButton, int32_t flags,
+                                      int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+                                      const PointerProperties* properties,
+                                      const PointerCoords* coords, const uint32_t* idToIndex,
+                                      BitSet32 idBits, int32_t changedId, float xPrecision,
+                                      float yPrecision, nsecs_t downTime) {
     PointerCoords pointerCoords[MAX_POINTERS];
     PointerProperties pointerProperties[MAX_POINTERS];
     uint32_t pointerCount = 0;
@@ -6531,16 +6516,21 @@
             ALOG_ASSERT(false);
         }
     }
+    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
+        mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
+    }
     const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
     const int32_t deviceId = getDeviceId();
     std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
     std::for_each(frames.begin(), frames.end(),
             [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
-    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
-            source, displayId, policyFlags,
-            action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
-            edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
-            xPrecision, yPrecision, downTime, std::move(frames));
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
+                          policyFlags, action, actionButton, flags, metaState, buttonState,
+                          MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
+                          pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
+                          downTime, std::move(frames));
     getListener()->notifyMotion(&args);
 }
 
@@ -7023,7 +7013,6 @@
         outCount += 1;
     }
 
-    outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
     outState->rawPointerData.pointerCount = outCount;
     mPointerIdBits = newPointerIdBits;
 
@@ -7462,10 +7451,12 @@
     uint32_t policyFlags = 0;
 
     NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-            AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
-            AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-            &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
+                          AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
+                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+                          MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                          &pointerProperties, &pointerCoords, 0, 0,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
     getListener()->notifyMotion(&args);
 }
 
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 9777779..0c08e7d 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -717,7 +717,6 @@
 
     inline size_t getSlotCount() const { return mSlotCount; }
     inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
-    inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
 
 private:
     int32_t mCurrentSlot;
@@ -725,7 +724,6 @@
     size_t mSlotCount;
     bool mUsingSlotsProtocol;
     bool mHaveStylus;
-    uint32_t mDeviceTimestamp;
 
     void clearSlots(int32_t initialSlot);
 };
@@ -1174,7 +1172,6 @@
 
     struct RawState {
         nsecs_t when;
-        uint32_t deviceTimestamp;
 
         // Raw pointer sample data.
         RawPointerData rawPointerData;
@@ -1187,7 +1184,6 @@
 
         void copyFrom(const RawState& other) {
             when = other.when;
-            deviceTimestamp = other.deviceTimestamp;
             rawPointerData.copyFrom(other.rawPointerData);
             buttonState = other.buttonState;
             rawVScroll = other.rawVScroll;
@@ -1196,7 +1192,6 @@
 
         void clear() {
             when = 0;
-            deviceTimestamp = 0;
             rawPointerData.clear();
             buttonState = 0;
             rawVScroll = 0;
@@ -1205,7 +1200,6 @@
     };
 
     struct CookedState {
-        uint32_t deviceTimestamp;
         // Cooked pointer sample data.
         CookedPointerData cookedPointerData;
 
@@ -1217,7 +1211,6 @@
         int32_t buttonState;
 
         void copyFrom(const CookedState& other) {
-            deviceTimestamp = other.deviceTimestamp;
             cookedPointerData.copyFrom(other.cookedPointerData);
             fingerIdBits = other.fingerIdBits;
             stylusIdBits = other.stylusIdBits;
@@ -1226,7 +1219,6 @@
         }
 
         void clear() {
-            deviceTimestamp = 0;
             cookedPointerData.clear();
             fingerIdBits.clear();
             stylusIdBits.clear();
@@ -1634,7 +1626,6 @@
     void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
             int32_t action, int32_t actionButton,
             int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
-            uint32_t deviceTimestamp,
             const PointerProperties* properties, const PointerCoords* coords,
             const uint32_t* idToIndex, BitSet32 idBits,
             int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index f48a645..bc53cf5 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -49,6 +49,44 @@
 
 // --- InputReaderConfiguration ---
 
+std::string InputReaderConfiguration::changesToString(uint32_t changes) {
+    if (changes == 0) {
+        return "<none>";
+    }
+    std::string result;
+    if (changes & CHANGE_POINTER_SPEED) {
+        result += "POINTER_SPEED | ";
+    }
+    if (changes & CHANGE_POINTER_GESTURE_ENABLEMENT) {
+        result += "POINTER_GESTURE_ENABLEMENT | ";
+    }
+    if (changes & CHANGE_DISPLAY_INFO) {
+        result += "DISPLAY_INFO | ";
+    }
+    if (changes & CHANGE_SHOW_TOUCHES) {
+        result += "SHOW_TOUCHES | ";
+    }
+    if (changes & CHANGE_KEYBOARD_LAYOUTS) {
+        result += "KEYBOARD_LAYOUTS | ";
+    }
+    if (changes & CHANGE_DEVICE_ALIAS) {
+        result += "DEVICE_ALIAS | ";
+    }
+    if (changes & CHANGE_TOUCH_AFFINE_TRANSFORMATION) {
+        result += "TOUCH_AFFINE_TRANSFORMATION | ";
+    }
+    if (changes & CHANGE_EXTERNAL_STYLUS_PRESENCE) {
+        result += "EXTERNAL_STYLUS_PRESENCE | ";
+    }
+    if (changes & CHANGE_ENABLED_STATE) {
+        result += "ENABLED_STATE | ";
+    }
+    if (changes & CHANGE_MUST_REOPEN) {
+        result += "MUST_REOPEN | ";
+    }
+    return result;
+}
+
 std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByUniqueId(
         const std::string& uniqueDisplayId) const {
     if (uniqueDisplayId.empty()) {
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index b51dcb6..0dcd2f9 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -107,31 +107,32 @@
      */
     MotionClassification classification;
     int32_t edgeFlags;
-    /**
-     * A timestamp in the input device's time base, not the platform's.
-     * The units are microseconds since the last reset.
-     * This can only be compared to other device timestamps from the same device.
-     * This value will overflow after a little over an hour.
-     */
-    uint32_t deviceTimestamp;
+
     uint32_t pointerCount;
     PointerProperties pointerProperties[MAX_POINTERS];
     PointerCoords pointerCoords[MAX_POINTERS];
     float xPrecision;
     float yPrecision;
+    /**
+     * Mouse cursor position when this event is reported relative to the origin of the specified
+     * display. Only valid if this is a mouse event (originates from a mouse or from a trackpad in
+     * gestures enabled mode.
+     */
+    float xCursorPosition;
+    float yCursorPosition;
     nsecs_t downTime;
     std::vector<TouchVideoFrame> videoFrames;
 
     inline NotifyMotionArgs() { }
 
     NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-            int32_t displayId, uint32_t policyFlags,
-            int32_t action, int32_t actionButton, int32_t flags,
-            int32_t metaState, int32_t buttonState, MotionClassification classification,
-            int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
-            const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime,
-            const std::vector<TouchVideoFrame>& videoFrames);
+                     int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+                     int32_t flags, int32_t metaState, int32_t buttonState,
+                     MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
+                     const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+                     float xPrecision, float yPrecision, float xCursorPosition,
+                     float yCursorPosition, nsecs_t downTime,
+                     const std::vector<TouchVideoFrame>& videoFrames);
 
     NotifyMotionArgs(const NotifyMotionArgs& other);
 
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 8ad5dd0..5d576b9 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -24,14 +24,13 @@
 #include <input/DisplayViewport.h>
 #include <input/VelocityControl.h>
 #include <input/VelocityTracker.h>
-#include <utils/KeyedVector.h>
 #include <utils/Thread.h>
 #include <utils/RefBase.h>
-#include <utils/SortedVector.h>
 
-#include <optional>
 #include <stddef.h>
 #include <unistd.h>
+#include <optional>
+#include <set>
 #include <unordered_map>
 #include <vector>
 
@@ -250,7 +249,7 @@
     bool pointerCapture;
 
     // The set of currently disabled input devices.
-    SortedVector<int32_t> disabledDevices;
+    std::set<int32_t> disabledDevices;
 
     InputReaderConfiguration() :
             virtualKeyQuietTime(0),
@@ -270,6 +269,8 @@
             pointerGestureZoomSpeedRatio(0.3f),
             showTouches(false), pointerCapture(false) { }
 
+    static std::string changesToString(uint32_t changes);
+
     std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
     std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
             const;
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 1835449..9054316 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -6,6 +6,7 @@
         "BlockingQueue_test.cpp",
         "TestInputListener.cpp",
         "InputClassifier_test.cpp",
+        "InputClassifierConverter_test.cpp",
         "InputDispatcher_test.cpp",
         "InputReader_test.cpp",
     ],
diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp
new file mode 100644
index 0000000..f58b628
--- /dev/null
+++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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 "../InputClassifierConverter.h"
+
+#include <gtest/gtest.h>
+#include <utils/BitSet.h>
+
+
+using namespace android::hardware::input;
+
+namespace android {
+
+// --- InputClassifierConverterTest ---
+
+static NotifyMotionArgs generateBasicMotionArgs() {
+    // Create a basic motion event for testing
+    PointerProperties properties;
+    properties.id = 0;
+    properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+    PointerCoords coords;
+    coords.clear();
+    coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
+    coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2);
+    coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.5);
+    static constexpr nsecs_t downTime = 2;
+    NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/,
+                                AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/,
+                                AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/,
+                                AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+                                AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties,
+                                &coords, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+                                {} /*videoFrames*/);
+    return motionArgs;
+}
+
+static float getMotionEventAxis(common::V1_0::PointerCoords coords,
+        common::V1_0::Axis axis) {
+    uint32_t index = BitSet64::getIndexOfBit(static_cast<uint64_t>(coords.bits),
+            static_cast<uint64_t>(axis));
+    return coords.values[index];
+}
+
+/**
+ * Check that coordinates get converted properly from the framework's PointerCoords
+ * to the hidl PointerCoords in input::common.
+ */
+TEST(InputClassifierConverterTest, PointerCoordsAxes) {
+    const NotifyMotionArgs motionArgs = generateBasicMotionArgs();
+    ASSERT_EQ(1, motionArgs.pointerCoords[0].getX());
+    ASSERT_EQ(2, motionArgs.pointerCoords[0].getY());
+    ASSERT_EQ(0.5, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE));
+    ASSERT_EQ(3U, BitSet64::count(motionArgs.pointerCoords[0].bits));
+
+    common::V1_0::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
+
+    ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::X),
+            motionArgs.pointerCoords[0].getX());
+    ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::Y),
+            motionArgs.pointerCoords[0].getY());
+    ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::SIZE),
+            motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE));
+    ASSERT_EQ(BitSet64::count(motionArgs.pointerCoords[0].bits),
+            BitSet64::count(motionEvent.pointerCoords[0].bits));
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 1651057..40086ef 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -38,12 +38,15 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
     coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
     static constexpr nsecs_t downTime = 2;
-    NotifyMotionArgs motionArgs(1/*sequenceNum*/, downTime/*eventTime*/, 3/*deviceId*/,
-            AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4/*policyFlags*/, AMOTION_EVENT_ACTION_DOWN,
-            0/*actionButton*/, 0/*flags*/, AMETA_NONE, 0/*buttonState*/, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, 5/*deviceTimestamp*/,
-            1/*pointerCount*/, &properties, &coords, 0/*xPrecision*/, 0/*yPrecision*/,
-            downTime, {}/*videoFrames*/);
+    NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/,
+                                AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/,
+                                AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/,
+                                AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+                                AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties,
+                                &coords, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+                                {} /*videoFrames*/);
     return motionArgs;
 }
 
@@ -136,11 +139,7 @@
     std::unique_ptr<MotionClassifierInterface> mMotionClassifier;
 
     virtual void SetUp() override {
-        sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
-                classifier::V1_0::IInputClassifier::getService();
-        if (service) {
-            mMotionClassifier = std::make_unique<MotionClassifier>(service);
-        }
+        mMotionClassifier = std::make_unique<MotionClassifier>();
     }
 };
 
@@ -165,9 +164,7 @@
 
     // We are not checking the return value, because we can't be making assumptions
     // about the HAL operation, since it will be highly hardware-dependent
-    if (mMotionClassifier) {
-        ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
-    }
+    ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
 }
 
 /**
@@ -183,9 +180,7 @@
 
     // We are not checking the return value, because we can't be making assumptions
     // about the HAL operation, since it will be highly hardware-dependent
-    if (mMotionClassifier) {
-        ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
-    }
+    ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
 }
 
 /**
@@ -206,18 +201,14 @@
 
     // We are not checking the return value, because we can't be making assumptions
     // about the HAL operation, since it will be highly hardware-dependent
-    if (mMotionClassifier) {
-        ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
-    }
+    ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs));
 }
 
 /**
  * Make sure MotionClassifier does not crash when it is reset.
  */
 TEST_F(MotionClassifierTest, Reset_DoesNotCrash) {
-    if (mMotionClassifier) {
-        ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset());
-    }
+    ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset());
 }
 
 /**
@@ -225,9 +216,7 @@
  */
 TEST_F(MotionClassifierTest, DeviceReset_DoesNotCrash) {
     NotifyDeviceResetArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/);
-    if (mMotionClassifier) {
-        ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset(args));
-    }
+    ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset(args));
 }
 
 } // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 745fac0..a86dcbc 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -52,6 +52,7 @@
         mTime = -1;
         mAction = -1;
         mDisplayId = -1;
+        mOnPointerDownToken.clear();
     }
 
     void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyMotionArgs* args) {
@@ -87,11 +88,18 @@
                 << "Expected filterInputEvent() to not have been called.";
     }
 
+    void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
+        ASSERT_EQ(mOnPointerDownToken, touchedToken)
+                << "Expected token from onPointerDownOutsideFocus was not matched";
+        reset();
+    }
+
 private:
     bool mInputEventFiltered;
     nsecs_t mTime;
     int32_t mAction;
     int32_t mDisplayId;
+    sp<IBinder> mOnPointerDownToken;
 
     virtual void notifyConfigurationChanged(nsecs_t) {
     }
@@ -161,11 +169,16 @@
         return false;
     }
 
+    virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
+        mOnPointerDownToken = newToken;
+    }
+
     void reset() {
         mInputEventFiltered = false;
         mTime = -1;
         mAction = -1;
         mDisplayId = -1;
+        mOnPointerDownToken.clear();
     }
 };
 
@@ -236,8 +249,10 @@
 
     // Rejects undefined motion actions.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -245,18 +260,24 @@
 
     // Rejects pointer down with invalid index.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_DOWN |
+                             (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer down index too large.";
 
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_DOWN |
+                             (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -264,36 +285,45 @@
 
     // Rejects pointer up with invalid index.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_UP |
+                             (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too large.";
 
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_UP |
+                             (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too small.";
 
     // Rejects motion events with invalid number of pointers.
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 0, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with 0 pointers.";
 
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -301,18 +331,22 @@
 
     // Rejects motion events with invalid pointer ids.
     pointerProperties[0].id = -1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer ids less than 0.";
 
     pointerProperties[0].id = MAX_POINTER_ID + 1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -321,9 +355,11 @@
     // Rejects motion events with duplicate pointer ids.
     pointerProperties[0].id = 1;
     pointerProperties[1].id = 1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 2, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -416,7 +452,6 @@
 
         sp<InputDispatcher> mDispatcher;
         sp<InputChannel> mServerChannel, mClientChannel;
-        sp<IBinder> mToken;
         InputConsumer *mConsumer;
         PreallocatedInputEventFactory mEventFactory;
 
@@ -432,10 +467,10 @@
     FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
         const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
             FakeInputReceiver(dispatcher, name, displayId),
-            mFocused(false) {
+            mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
             mServerChannel->setToken(new BBinder());
             mDispatcher->registerInputChannel(mServerChannel, displayId);
- 
+
             inputApplicationHandle->updateInfo();
             mInfo.applicationInfo = *inputApplicationHandle->getInfo();
     }
@@ -443,15 +478,16 @@
     virtual bool updateInfo() {
         mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
         mInfo.name = mName;
-        mInfo.layoutParamsFlags = 0;
+        mInfo.layoutParamsFlags = mLayoutParamFlags;
         mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
         mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
-        mInfo.frameLeft = 0;
-        mInfo.frameTop = 0;
-        mInfo.frameRight = WIDTH;
-        mInfo.frameBottom = HEIGHT;
+        mInfo.frameLeft = mFrame.left;
+        mInfo.frameTop = mFrame.top;
+        mInfo.frameRight = mFrame.right;
+        mInfo.frameBottom = mFrame.bottom;
         mInfo.globalScaleFactor = 1.0;
-        mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
+        mInfo.touchableRegion.clear();
+        mInfo.addTouchableRegion(mFrame);
         mInfo.visible = true;
         mInfo.canReceiveKeys = true;
         mInfo.hasFocus = mFocused;
@@ -470,6 +506,14 @@
         mFocused = true;
     }
 
+    void setFrame(const Rect& frame) {
+        mFrame.set(frame);
+    }
+
+    void setLayoutParamFlags(int32_t flags) {
+        mLayoutParamFlags = flags;
+    }
+
     void releaseChannel() {
         mServerChannel.clear();
         InputWindowHandle::releaseChannel();
@@ -480,6 +524,8 @@
     }
 
     bool mFocused;
+    Rect mFrame;
+    int32_t mLayoutParamFlags;
 };
 
 static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
@@ -499,8 +545,10 @@
             INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
 }
 
-static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
-        int32_t displayId) {
+static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
+                                 int32_t source, int32_t displayId, int32_t x, int32_t y,
+                                 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
     MotionEvent event;
     PointerProperties pointerProperties[1];
     PointerCoords pointerCoords[1];
@@ -510,17 +558,16 @@
     pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
 
     pointerCoords[0].clear();
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
+    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
+    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
 
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid motion down event.
-    event.initialize(DEVICE_ID, source, displayId,
-            AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
-            AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
-            /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
-            /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
-            pointerCoords);
+    event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
+                     /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+                     /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+                     /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
 
     // Inject event until dispatch out.
     return dispatcher->injectInputEvent(
@@ -529,6 +576,11 @@
             INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
 }
 
+static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
+                                int32_t displayId, int32_t x = 100, int32_t y = 200) {
+    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
+}
+
 static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid key event.
@@ -554,11 +606,12 @@
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid motion event.
     NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
-            POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
-            AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1, pointerProperties,
-            pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, currentTime,
-            /* videoFrames */ {});
+                          POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
+                          AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+                          AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords,
+                          /* xPrecision */ 0, /* yPrecision */ 0,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
 
     return args;
 }
@@ -682,6 +735,32 @@
     windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 }
 
+TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+    sp<FakeWindowHandle> windowLeft =
+            new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    windowLeft->setFrame(Rect(0, 0, 600, 800));
+    windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+    sp<FakeWindowHandle> windowRight =
+            new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    windowRight->setFrame(Rect(600, 0, 1200, 800));
+    windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+    std::vector<sp<InputWindowHandle>> inputWindowHandles{windowLeft, windowRight};
+    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+
+    // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
+    // left window. This event should be dispatched to the left window.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
+                                ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
+    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+    windowRight->assertNoEvents();
+}
+
 /* Test InputDispatcher for MultiDisplay */
 class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
 public:
@@ -776,8 +855,10 @@
 class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
 public:
     FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
-            int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
-        mDispatcher->registerInputChannel(mServerChannel, displayId);
+            int32_t displayId, bool isGestureMonitor = false)
+            : FakeInputReceiver(dispatcher, name, displayId) {
+        mServerChannel->setToken(new BBinder());
+        mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
     }
 };
 
@@ -907,4 +988,98 @@
     testNotifyKey(/*expectToBeFiltered*/ false);
 }
 
+class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
+    virtual void SetUp() {
+        InputDispatcherTest::SetUp();
+
+        sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+        mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
+                ADISPLAY_ID_DEFAULT);
+        mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
+        // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
+        // window.
+        mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+        mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
+                ADISPLAY_ID_DEFAULT);
+        mWindowFocused->setFrame(Rect(50, 50, 100, 100));
+        mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+        mWindowFocusedTouchPoint = 60;
+
+        // Set focused application.
+        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+        mWindowFocused->setFocus();
+
+        // Expect one focus window exist in display.
+        std::vector<sp<InputWindowHandle>> inputWindowHandles;
+        inputWindowHandles.push_back(mUnfocusedWindow);
+        inputWindowHandles.push_back(mWindowFocused);
+        mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+    }
+
+    virtual void TearDown() {
+        InputDispatcherTest::TearDown();
+
+        mUnfocusedWindow.clear();
+        mWindowFocused.clear();
+    }
+
+protected:
+    sp<FakeWindowHandle> mUnfocusedWindow;
+    sp<FakeWindowHandle> mWindowFocused;
+    int32_t mWindowFocusedTouchPoint;
+};
+
+// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
+// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
+// the onPointerDownOutsideFocus callback.
+TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    // Call monitor to wait for the command queue to get flushed.
+    mDispatcher->monitor();
+
+    mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
+}
+
+// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
+// DOWN on the window that doesn't have focus. Ensure no window received the
+// onPointerDownOutsideFocus callback.
+TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    // Call monitor to wait for the command queue to get flushed.
+    mDispatcher->monitor();
+
+    mFakePolicy->assertOnPointerDownEquals(nullptr);
+}
+
+// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
+// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
+TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+            << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    // Call monitor to wait for the command queue to get flushed.
+    mDispatcher->monitor();
+
+    mFakePolicy->assertOnPointerDownEquals(nullptr);
+}
+
+// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
+// DOWN on the window that already has focus. Ensure no window received the
+// onPointerDownOutsideFocus callback.
+TEST_F(InputDispatcherOnPointerDownOutsideFocus,
+        OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
+            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
+            mWindowFocusedTouchPoint))
+            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+    // Call monitor to wait for the command queue to get flushed.
+    mDispatcher->monitor();
+
+    mFakePolicy->assertOnPointerDownEquals(nullptr);
+}
+
 } // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index d353028..541de99 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -202,21 +202,9 @@
         mConfig.portAssociations.insert({inputPort, displayPort});
     }
 
-    void addDisabledDevice(int32_t deviceId) {
-        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
-        bool currentlyEnabled = index < 0;
-        if (currentlyEnabled) {
-            mConfig.disabledDevices.add(deviceId);
-        }
-    }
+    void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
 
-    void removeDisabledDevice(int32_t deviceId) {
-        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
-        bool currentlyEnabled = index < 0;
-        if (!currentlyEnabled) {
-            mConfig.disabledDevices.remove(deviceId);
-        }
-    }
+    void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
 
     void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
         mPointerControllers.add(deviceId, controller);
@@ -4688,7 +4676,6 @@
     void processSlot(MultiTouchInputMapper* mapper, int32_t slot);
     void processToolType(MultiTouchInputMapper* mapper, int32_t toolType);
     void processKey(MultiTouchInputMapper* mapper, int32_t code, int32_t value);
-    void processTimestamp(MultiTouchInputMapper* mapper, uint32_t value);
     void processMTSync(MultiTouchInputMapper* mapper);
     void processSync(MultiTouchInputMapper* mapper);
 };
@@ -4804,10 +4791,6 @@
     process(mapper, ARBITRARY_TIME, EV_KEY, code, value);
 }
 
-void MultiTouchInputMapperTest::processTimestamp(MultiTouchInputMapper* mapper, uint32_t value) {
-    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, value);
-}
-
 void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
     process(mapper, ARBITRARY_TIME, EV_SYN, SYN_MT_REPORT, 0);
 }
@@ -6190,64 +6173,6 @@
             toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
 }
 
-TEST_F(MultiTouchInputMapperTest, Process_HandlesTimestamp) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(DISPLAY_ORIENTATION_0);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-    NotifyMotionArgs args;
-
-    // By default, deviceTimestamp should be zero
-    processPosition(mapper, 100, 100);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(0U, args.deviceTimestamp);
-
-    // Now the timestamp of 1000 is reported by evdev and should appear in MotionArgs
-    processPosition(mapper, 0, 0);
-    processTimestamp(mapper, 1000);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1000U, args.deviceTimestamp);
-}
-
-TEST_F(MultiTouchInputMapperTest, WhenMapperIsReset_TimestampIsCleared) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(DISPLAY_ORIENTATION_0);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-    NotifyMotionArgs args;
-
-    // Send a touch event with a timestamp
-    processPosition(mapper, 100, 100);
-    processTimestamp(mapper, 1);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1U, args.deviceTimestamp);
-
-    // Since the data accumulates, and new timestamp has not arrived, deviceTimestamp won't change
-    processPosition(mapper, 100, 200);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1U, args.deviceTimestamp);
-
-    mapper->reset(/* when */ 0);
-    // After the mapper is reset, deviceTimestamp should become zero again
-    processPosition(mapper, 100, 300);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(0U, args.deviceTimestamp);
-}
-
 /**
  * Set the input device port <--> display port associations, and check that the
  * events are routed to the display that matches the display port.
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index a6ed75f..717f317 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -45,7 +45,9 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
 
-static status_t StatusFromResult(Result result) {
+namespace {
+
+status_t statusFromResult(Result result) {
     switch (result) {
         case Result::OK:
             return OK;
@@ -71,6 +73,8 @@
     INTERNAL_WAKE =  1 << 16,
 };
 
+}  // anonymous namespace
+
 void SensorsHalDeathReceivier::serviceDied(
         uint64_t /* cookie */,
         const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
@@ -105,7 +109,7 @@
     initializeSensorList();
 
     mIsDirectReportSupported =
-           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
+            (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
 }
 
 void SensorDevice::initializeSensorList() {
@@ -122,7 +126,7 @@
                     convertToSensor(list[i], &sensor);
                     // Sanity check and clamp power if it is 0 (or close)
                     if (sensor.power < minPowerMa) {
-                        ALOGE("Reported power %f not deemed sane, clamping to %f",
+                        ALOGI("Reported power %f not deemed sane, clamping to %f",
                               sensor.power, minPowerMa);
                         sensor.power = minPowerMa;
                     }
@@ -217,10 +221,10 @@
                 mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
                 mWakeLockQueueFlag != nullptr);
 
-        status_t status = StatusFromResult(checkReturn(mSensors->initialize(
+        status_t status = checkReturnAndGetStatus(mSensors->initialize(
                 *mEventQueue->getDesc(),
                 *mWakeLockQueue->getDesc(),
-                new SensorsCallback())));
+                new SensorsCallback()));
 
         if (status != NO_ERROR) {
             connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
@@ -270,6 +274,8 @@
     bool didChange = false;
 
     if (oldSensorList.size() != newSensorList.size()) {
+        ALOGI("Sensor list size changed from %zu to %zu", oldSensorList.size(),
+              newSensorList.size());
         didChange = true;
     }
 
@@ -281,6 +287,7 @@
             if (prevSensor.handle == newSensor.handle) {
                 found = true;
                 if (!sensorIsEquivalent(prevSensor, newSensor)) {
+                    ALOGI("Sensor %s not equivalent to previous version", newSensor.name);
                     didChange = true;
                 }
             }
@@ -289,6 +296,7 @@
         if (!found) {
             // Could not find the new sensor in the old list of sensors, the lists must
             // have changed.
+            ALOGI("Sensor %s (handle %d) did not exist before", newSensor.name, newSensor.handle);
             didChange = true;
         }
     }
@@ -423,7 +431,7 @@
                         convertToSensorEvents(events, dynamicSensorsAdded, buffer);
                         err = (ssize_t)events.size();
                     } else {
-                        err = StatusFromResult(result);
+                        err = statusFromResult(result);
                     }
                 });
 
@@ -467,11 +475,6 @@
                               asBaseType(INTERNAL_WAKE), &eventFlagState);
         availableEvents = mEventQueue->availableToRead();
 
-        if ((eventFlagState & asBaseType(EventQueueFlagBits::READ_AND_PROCESS)) &&
-                availableEvents == 0) {
-            ALOGW("Event FMQ wake without any events");
-        }
-
         if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
             ALOGD("Event FMQ internal wake, returning from poll with no events");
             return DEAD_OBJECT;
@@ -544,6 +547,9 @@
     }
     Info& info(mActivationCount.editValueAt(activationIndex));
     info.removeBatchParamsForIdent(ident);
+    if (info.numActiveClients() == 0) {
+        info.isActive = false;
+    }
 }
 
 status_t SensorDevice::activate(void* ident, int handle, int enabled) {
@@ -579,10 +585,9 @@
         }
 
         if (info.batchParams.indexOfKey(ident) >= 0) {
-          if (info.numActiveClients() == 1) {
-              // This is the first connection, we need to activate the underlying h/w sensor.
-              actuateHardware = true;
-          }
+            if (info.numActiveClients() > 0 && !info.isActive) {
+                actuateHardware = true;
+            }
         } else {
             // Log error. Every activate call should be preceded by a batch() call.
             ALOGE("\t >>>ERROR: activate called without batch");
@@ -624,13 +629,18 @@
     if (actuateHardware) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                  enabled);
-        err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
+        err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
         ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                  strerror(-err));
 
         if (err != NO_ERROR && enabled) {
             // Failure when enabling the sensor. Clean up on failure.
             info.removeBatchParamsForIdent(ident);
+        } else {
+            // Update the isActive flag if there is no error. If there is an error when disabling a
+            // sensor, still set the flag to false since the batch parameters have already been
+            // removed. This ensures that everything remains in-sync.
+            info.isActive = enabled;
         }
     }
 
@@ -692,9 +702,8 @@
     if (prevBestBatchParams != info.bestBatchParams) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
                  info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
-        err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
+        err = checkReturnAndGetStatus(mSensors->batch(
+                handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
         if (err != NO_ERROR) {
             ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
                   mSensors.get(), handle, info.bestBatchParams.mTSample,
@@ -718,7 +727,7 @@
     if (mSensors == nullptr) return NO_INIT;
     if (isClientDisabled(ident)) return INVALID_OPERATION;
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return StatusFromResult(checkReturn(mSensors->flush(handle)));
+    return checkReturnAndGetStatus(mSensors->flush(handle));
 }
 
 bool SensorDevice::isClientDisabled(void* ident) {
@@ -751,18 +760,20 @@
         const int sensor_handle = mActivationCount.keyAt(i);
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                    sensor_handle);
-        status_t err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    sensor_handle,
-                    info.bestBatchParams.mTSample,
-                    info.bestBatchParams.mTBatch)));
+        status_t err = checkReturnAndGetStatus(mSensors->batch(
+                sensor_handle,
+                info.bestBatchParams.mTSample,
+                info.bestBatchParams.mTBatch));
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
-            err = StatusFromResult(
-                    checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
+            err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
+
+        if (err == NO_ERROR) {
+            info.isActive = true;
+        }
     }
 }
 
@@ -770,7 +781,7 @@
     if (mSensors == nullptr) return;
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i< mActivationCount.size(); ++i) {
-        const Info& info = mActivationCount.valueAt(i);
+        Info& info = mActivationCount.editValueAt(i);
         // Check if this sensor has been activated previously and disable it.
         if (info.batchParams.size() > 0) {
            const int sensor_handle = mActivationCount.keyAt(i);
@@ -784,6 +795,8 @@
                mDisabledClients.add(info.batchParams.keyAt(j));
                ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
            }
+
+           info.isActive = false;
         }
     }
 }
@@ -802,14 +815,13 @@
     Event ev;
     convertFromSensorEvent(*injected_sensor_event, &ev);
 
-    return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
+    return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
     if (mSensors == nullptr) return NO_INIT;
-    return StatusFromResult(
-            checkReturn(mSensors->setOperationMode(
-                    static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
+    return checkReturnAndGetStatus(mSensors->setOperationMode(
+            static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
 }
 
 int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
@@ -847,7 +859,7 @@
                 if (result == Result::OK) {
                     ret = channelHandle;
                 } else {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 }
             }));
     return ret;
@@ -886,12 +898,12 @@
     checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
             [&ret, rate] (auto result, auto token) {
                 if (rate == RateLevel::STOP) {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 } else {
                     if (result == Result::OK) {
                         ret = token;
                     } else {
-                        ret = StatusFromResult(result);
+                        ret = statusFromResult(result);
                     }
                 }
             }));
@@ -1000,7 +1012,7 @@
 }
 
 void SensorDevice::handleHidlDeath(const std::string & detail) {
-    if (!SensorDevice::getInstance().mSensors->supportsMessageQueues()) {
+    if (!mSensors->supportsMessageQueues()) {
         // restart is the only option at present.
         LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
     } else {
@@ -1008,5 +1020,10 @@
     }
 }
 
+status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
+    checkReturn(ret);
+    return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 71b918f..d2c6994 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -165,6 +165,9 @@
         // requested by the client.
         KeyedVector<void*, BatchParams> batchParams;
 
+        // Flag to track if the sensor is active
+        bool isActive = false;
+
         // Sets batch parameters for this ident. Returns error if this ident is not already present
         // in the KeyedVector above.
         status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
@@ -208,14 +211,14 @@
     status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                          int64_t maxBatchReportLatencyNs);
 
-    static void handleHidlDeath(const std::string &detail);
+    void handleHidlDeath(const std::string &detail);
     template<typename T>
-    static Return<T> checkReturn(Return<T> &&ret) {
+    void checkReturn(const Return<T>& ret) {
         if (!ret.isOk()) {
             handleHidlDeath(ret.description());
         }
-        return std::move(ret);
     }
+    status_t checkReturnAndGetStatus(const Return<Result>& ret);
     //TODO(b/67425500): remove waiter after bug is resolved.
     sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
 
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c4cfdc6..0e40940 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -285,8 +285,9 @@
                         scratch[count++] = buffer[i];
                     }
                 } else {
-                    // Regular sensor event, just copy it to the scratch buffer.
-                    if (hasSensorAccess()) {
+                    // Regular sensor event, just copy it to the scratch buffer after checking
+                    // the AppOp.
+                    if (hasSensorAccess() && noteOpIfRequired(buffer[i])) {
                         scratch[count++] = buffer[i];
                     }
                 }
@@ -386,6 +387,16 @@
     return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
 }
 
+bool SensorService::SensorEventConnection::noteOpIfRequired(const sensors_event_t& event) {
+    bool success = true;
+    const auto iter = mHandleToAppOp.find(event.sensor);
+    if (iter != mHandleToAppOp.end()) {
+        int32_t appOpMode = mService->sAppOpsManager.noteOp((*iter).second, mUid, mOpPackageName);
+        success = (appOpMode == AppOpsManager::MODE_ALLOWED);
+    }
+    return success;
+}
+
 void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
                                                                  int count) {
     sensors_event_t *eventCache_new;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 7077880..fd881cb 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <unordered_map>
 
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
@@ -134,6 +135,9 @@
     // privacy not being enabled.
     bool hasSensorAccess();
 
+    // Call noteOp for the sensor if the sensor requires a permission
+    bool noteOpIfRequired(const sensors_event_t& event);
+
     sp<SensorService> const mService;
     sp<BitTube> mChannel;
     uid_t mUid;
@@ -181,6 +185,10 @@
     mutable Mutex mDestroyLock;
     bool mDestroyed;
     bool mHasSensorAccess;
+
+    // Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
+    // valid mapping for sensors that require a permission in order to reduce the lookup time.
+    std::unordered_map<int32_t, int32_t> mHandleToAppOp;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index e3dfde4..c11b88e 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,8 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <android/content/pm/IPackageManagerNative.h>
 #include <binder/ActivityManager.h>
-#include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
@@ -75,6 +75,9 @@
 const char* SensorService::WAKE_LOCK_NAME = "SensorService_wakelock";
 uint8_t SensorService::sHmacGlobalKey[128] = {};
 bool SensorService::sHmacGlobalKeyIsValid = false;
+std::map<String16, int> SensorService::sPackageTargetVersion;
+Mutex SensorService::sPackageTargetVersionLock;
+AppOpsManager SensorService::sAppOpsManager;
 
 #define SENSOR_SERVICE_DIR "/data/system/sensor_service"
 #define SENSOR_SERVICE_HMAC_KEY_FILE  SENSOR_SERVICE_DIR "/hmac_key"
@@ -565,11 +568,11 @@
     if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
         return BAD_VALUE;
     }
-    if (args.size() == 3 && args[0] == String16("set-uid-state")) {
+    if (args[0] == String16("set-uid-state")) {
         return handleSetUidState(args, err);
-    } else if (args.size() == 2 && args[0] == String16("reset-uid-state")) {
+    } else if (args[0] == String16("reset-uid-state")) {
         return handleResetUidState(args, err);
-    } else if (args.size() == 2 && args[0] == String16("get-uid-state")) {
+    } else if (args[0] == String16("get-uid-state")) {
         return handleGetUidState(args, out, err);
     } else if (args.size() == 1 && args[0] == String16("help")) {
         printHelp(out);
@@ -579,14 +582,32 @@
     return BAD_VALUE;
 }
 
-status_t SensorService::handleSetUidState(Vector<String16>& args, int err) {
+static status_t getUidForPackage(String16 packageName, int userId, /*inout*/uid_t& uid, int err) {
     PermissionController pc;
-    int uid = pc.getPackageUid(args[1], 0);
+    uid = pc.getPackageUid(packageName, 0);
     if (uid <= 0) {
-        ALOGE("Unknown package: '%s'", String8(args[1]).string());
-        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+        ALOGE("Unknown package: '%s'", String8(packageName).string());
+        dprintf(err, "Unknown package: '%s'\n", String8(packageName).string());
         return BAD_VALUE;
     }
+
+    if (userId < 0) {
+        ALOGE("Invalid user: %d", userId);
+        dprintf(err, "Invalid user: %d\n", userId);
+        return BAD_VALUE;
+    }
+
+    uid = multiuser_get_uid(userId, uid);
+    return NO_ERROR;
+}
+
+status_t SensorService::handleSetUidState(Vector<String16>& args, int err) {
+    // Valid arg.size() is 3 or 5, args.size() is 5 with --user option.
+    if (!(args.size() == 3 || args.size() == 5)) {
+        printHelp(err);
+        return BAD_VALUE;
+    }
+
     bool active = false;
     if (args[2] == String16("active")) {
         active = true;
@@ -594,30 +615,59 @@
         ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
         return BAD_VALUE;
     }
+
+    int userId = 0;
+    if (args.size() == 5 && args[3] == String16("--user")) {
+        userId = atoi(String8(args[4]));
+    }
+
+    uid_t uid;
+    if (getUidForPackage(args[1], userId, uid, err) != NO_ERROR) {
+        return BAD_VALUE;
+    }
+
     mUidPolicy->addOverrideUid(uid, active);
     return NO_ERROR;
 }
 
 status_t SensorService::handleResetUidState(Vector<String16>& args, int err) {
-    PermissionController pc;
-    int uid = pc.getPackageUid(args[1], 0);
-    if (uid < 0) {
-        ALOGE("Unknown package: '%s'", String8(args[1]).string());
-        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+    // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
+    if (!(args.size() == 2 || args.size() == 4)) {
+        printHelp(err);
         return BAD_VALUE;
     }
+
+    int userId = 0;
+    if (args.size() == 4 && args[2] == String16("--user")) {
+        userId = atoi(String8(args[3]));
+    }
+
+    uid_t uid;
+    if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
+        return BAD_VALUE;
+    }
+
     mUidPolicy->removeOverrideUid(uid);
     return NO_ERROR;
 }
 
 status_t SensorService::handleGetUidState(Vector<String16>& args, int out, int err) {
-    PermissionController pc;
-    int uid = pc.getPackageUid(args[1], 0);
-    if (uid < 0) {
-        ALOGE("Unknown package: '%s'", String8(args[1]).string());
-        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+    // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
+    if (!(args.size() == 2 || args.size() == 4)) {
+        printHelp(err);
         return BAD_VALUE;
     }
+
+    int userId = 0;
+    if (args.size() == 4 && args[2] == String16("--user")) {
+        userId = atoi(String8(args[3]));
+    }
+
+    uid_t uid;
+    if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
+        return BAD_VALUE;
+    }
+
     if (mUidPolicy->isUidActive(uid)) {
         return dprintf(out, "active\n");
     } else {
@@ -627,9 +677,9 @@
 
 status_t SensorService::printHelp(int out) {
     return dprintf(out, "Sensor service commands:\n"
-        "  get-uid-state <PACKAGE> gets the uid state\n"
-        "  set-uid-state <PACKAGE> <active|idle> overrides the uid state\n"
-        "  reset-uid-state <PACKAGE> clears the uid state override\n"
+        "  get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
+        "  set-uid-state <PACKAGE> <active|idle> [--user USER_ID] overrides the uid state\n"
+        "  reset-uid-state <PACKAGE> [--user USER_ID] clears the uid state override\n"
         "  help print this message\n");
 }
 
@@ -1334,15 +1384,6 @@
             ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
             mActiveSensors.removeItemsAt(i, 1);
             mActiveVirtualSensors.erase(handle);
-
-            // If this is the last connection, then mark the RecentEventLogger as stale. This is
-            // critical for on-change events since the previous event is sent to a client if the
-            // sensor is already active. If two clients request the sensor at the same time, one
-            // of the clients would receive a stale event.
-            auto logger = mRecentEvent.find(handle);
-            if (logger != mRecentEvent.end()) {
-                logger->second->setLastEventStale();
-            }
             delete rec;
             size--;
         } else {
@@ -1356,6 +1397,14 @@
         checkWakeLockStateLocked();
     }
 
+    {
+        Mutex::Autolock packageLock(sPackageTargetVersionLock);
+        auto iter = sPackageTargetVersion.find(c->mOpPackageName);
+        if (iter != sPackageTargetVersion.end()) {
+            sPackageTargetVersion.erase(iter);
+        }
+    }
+
     SensorDevice& dev(SensorDevice::getInstance());
     dev.notifyConnectionDestroyed(c);
 }
@@ -1397,6 +1446,20 @@
         if (sensor->isVirtual()) {
             mActiveVirtualSensors.emplace(handle);
         }
+
+        // There was no SensorRecord for this sensor which means it was previously disabled. Mark
+        // the recent event as stale to ensure that the previous event is not sent to a client. This
+        // ensures on-change events that were generated during a previous sensor activation are not
+        // erroneously sent to newly connected clients, especially if a second client registers for
+        // an on-change sensor before the first client receives the updated event. Once an updated
+        // event is received, the recent events will be marked as current, and any new clients will
+        // immediately receive the most recent event.
+        if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
+            auto logger = mRecentEvent.find(handle);
+            if (logger != mRecentEvent.end()) {
+                logger->second->setLastEventStale();
+            }
+        }
     } else {
         if (rec->addConnection(connection)) {
             // this sensor is already activated, but we are adding a connection that uses it.
@@ -1487,6 +1550,11 @@
     if (err == NO_ERROR) {
         connection->updateLooperRegistration(mLooper);
 
+        if (sensor->getSensor().getRequiredPermission().size() > 0 &&
+                sensor->getSensor().getRequiredAppOp() >= 0) {
+            connection->mHandleToAppOp[handle] = sensor->getSensor().getRequiredAppOp();
+        }
+
         mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex) =
                 SensorRegistrationInfo(handle, connection->getPackageName(),
                                        samplingPeriodNs, maxBatchReportLatencyNs, true);
@@ -1611,13 +1679,53 @@
 
 bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
         const String16& opPackageName) {
-    const String8& requiredPermission = sensor.getRequiredPermission();
-
-    if (requiredPermission.length() <= 0) {
+    // Check if a permission is required for this sensor
+    if (sensor.getRequiredPermission().length() <= 0) {
         return true;
     }
 
+    const int32_t opCode = sensor.getRequiredAppOp();
+    const int32_t appOpMode = sAppOpsManager.checkOp(opCode,
+            IPCThreadState::self()->getCallingUid(), opPackageName);
+    bool appOpAllowed = appOpMode == AppOpsManager::MODE_ALLOWED;
+
+    bool canAccess = false;
+    if (hasPermissionForSensor(sensor)) {
+        // Ensure that the AppOp is allowed, or that there is no necessary app op for the sensor
+        if (opCode < 0 || appOpAllowed) {
+            canAccess = true;
+        }
+    } else if (sensor.getType() == SENSOR_TYPE_STEP_COUNTER ||
+            sensor.getType() == SENSOR_TYPE_STEP_DETECTOR) {
+        int targetSdkVersion = getTargetSdkVersion(opPackageName);
+        // Allow access to the sensor if the application targets pre-Q, which is before the
+        // requirement to hold the AR permission to access Step Counter and Step Detector events
+        // was introduced, and the user hasn't revoked the app op.
+        //
+        // Verifying the app op is required to ensure that the user hasn't revoked the necessary
+        // permissions to access the Step Detector and Step Counter when the application targets
+        // pre-Q. Without this check, if the user revokes the pre-Q install-time GMS Core AR
+        // permission, the app would still be able to receive Step Counter and Step Detector events.
+        if (appOpAllowed &&
+                targetSdkVersion > 0 &&
+                targetSdkVersion <= __ANDROID_API_P__) {
+            canAccess = true;
+        }
+    }
+
+    if (canAccess) {
+        sAppOpsManager.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName);
+    } else {
+        ALOGE("%s a sensor (%s) without holding its required permission: %s",
+                operation, sensor.getName().string(), sensor.getRequiredPermission().string());
+    }
+
+    return canAccess;
+}
+
+bool SensorService::hasPermissionForSensor(const Sensor& sensor) {
     bool hasPermission = false;
+    const String8& requiredPermission = sensor.getRequiredPermission();
 
     // Runtime permissions can't use the cache as they may change.
     if (sensor.isRequiredPermissionRuntime()) {
@@ -1626,25 +1734,31 @@
     } else {
         hasPermission = PermissionCache::checkCallingPermission(String16(requiredPermission));
     }
+    return hasPermission;
+}
 
-    if (!hasPermission) {
-        ALOGE("%s a sensor (%s) without holding its required permission: %s",
-                operation, sensor.getName().string(), sensor.getRequiredPermission().string());
-        return false;
-    }
-
-    const int32_t opCode = sensor.getRequiredAppOp();
-    if (opCode >= 0) {
-        AppOpsManager appOps;
-        if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName)
-                        != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("%s a sensor (%s) without enabled required app op: %d",
-                    operation, sensor.getName().string(), opCode);
-            return false;
+int SensorService::getTargetSdkVersion(const String16& opPackageName) {
+    Mutex::Autolock packageLock(sPackageTargetVersionLock);
+    int targetSdkVersion = -1;
+    auto entry = sPackageTargetVersion.find(opPackageName);
+    if (entry != sPackageTargetVersion.end()) {
+        targetSdkVersion = entry->second;
+    } else {
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("package_native"));
+        if (binder != nullptr) {
+            sp<content::pm::IPackageManagerNative> packageManager =
+                    interface_cast<content::pm::IPackageManagerNative>(binder);
+            if (packageManager != nullptr) {
+                binder::Status status = packageManager->getTargetSdkVersionForPackage(
+                        opPackageName, &targetSdkVersion);
+                if (!status.isOk()) {
+                    targetSdkVersion = -1;
+                }
+            }
         }
+        sPackageTargetVersion[opPackageName] = targetSdkVersion;
     }
-
-    return true;
+    return targetSdkVersion;
 }
 
 void SensorService::checkWakeLockState() {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index fbfe05d..e6ec96d 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -20,9 +20,11 @@
 #include "SensorList.h"
 #include "RecentEventLogger.h"
 
+#include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IUidObserver.h>
 #include <cutils/compiler.h>
+#include <cutils/multiuser.h>
 #include <sensor/ISensorServer.h>
 #include <sensor/ISensorEventConnection.h>
 #include <sensor/Sensor.h>
@@ -242,6 +244,8 @@
             sensors_event_t const* buffer, const int count);
     static bool canAccessSensor(const Sensor& sensor, const char* operation,
             const String16& opPackageName);
+    static bool hasPermissionForSensor(const Sensor& sensor);
+    static int getTargetSdkVersion(const String16& opPackageName);
     // SensorService acquires a partial wakelock for delivering events from wake up sensors. This
     // method checks whether all the events from these wake up sensors have been delivered to the
     // corresponding applications, if yes the wakelock is released.
@@ -342,6 +346,10 @@
 
     sp<UidPolicy> mUidPolicy;
     sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
+    static AppOpsManager sAppOpsManager;
+    static std::map<String16, int> sPackageTargetVersion;
+    static Mutex sPackageTargetVersionLock;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/AllowedDisplayConfigs.h b/services/surfaceflinger/AllowedDisplayConfigs.h
deleted file mode 100644
index 7ca62ea..0000000
--- a/services/surfaceflinger/AllowedDisplayConfigs.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2019 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 <log/log.h>
-#include <vector>
-
-/*
- * Used to represent the Display Configurations allowed to be set by SurfaceFlinger
- */
-class AllowedDisplayConfigs {
-private:
-    // Defining ConstructorTag as private to prevent instantiating this class from outside
-    // while still allowing it to be constructed by std::make_unique
-    struct ConstructorTag {};
-
-public:
-    AllowedDisplayConfigs(ConstructorTag) {}
-
-    class Builder {
-    public:
-        Builder()
-              : mAllowedDisplayConfigs(std::make_unique<AllowedDisplayConfigs>(ConstructorTag{})) {}
-
-        std::unique_ptr<const AllowedDisplayConfigs> build() {
-            return std::move(mAllowedDisplayConfigs);
-        }
-
-        // add a config to the allowed config set
-        Builder& addConfig(int32_t config) {
-            mAllowedDisplayConfigs->addConfig(config);
-            return *this;
-        }
-
-    private:
-        std::unique_ptr<AllowedDisplayConfigs> mAllowedDisplayConfigs;
-    };
-
-    bool isConfigAllowed(int32_t config) const {
-        return (std::find(mConfigs.begin(), mConfigs.end(), config) != mConfigs.end());
-    }
-
-    void getAllowedConfigs(std::vector<int32_t>* outConfigs) const {
-        if (outConfigs) {
-            *outConfigs = mConfigs;
-        }
-    }
-
-private:
-    // add a config to the allowed config set
-    void addConfig(int32_t config) { mConfigs.push_back(config); }
-
-    std::vector<int32_t> mConfigs;
-};
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 52c68df..6e953f4 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -100,6 +100,10 @@
     lto: {
         thin: true,
     },
+    // TODO(b/131771163): Fix broken fuzzer support with LTO.
+    sanitize: {
+        fuzzer: false,
+    },
 }
 
 cc_library_headers {
@@ -116,7 +120,7 @@
         "BufferLayerConsumer.cpp",
         "BufferQueueLayer.cpp",
         "BufferStateLayer.cpp",
-        "BufferStateLayerCache.cpp",
+        "ClientCache.cpp",
         "Client.cpp",
         "ColorLayer.cpp",
         "ContainerLayer.cpp",
@@ -145,12 +149,14 @@
         "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
-        "Scheduler/IdleTimer.cpp",
+        "Scheduler/OneShotTimer.cpp",
         "Scheduler/LayerHistory.cpp",
+        "Scheduler/LayerInfo.cpp",
         "Scheduler/MessageQueue.cpp",
+        "Scheduler/PhaseOffsets.cpp",
         "Scheduler/Scheduler.cpp",
         "Scheduler/SchedulerUtils.cpp",
-        "Scheduler/PhaseOffsets.cpp",
+        "Scheduler/VSyncModulator.cpp",
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
         "SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 1b2b180..f51fbb4 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -19,9 +19,7 @@
 #define LOG_TAG "BufferLayer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <cmath>
-#include <cstdlib>
-#include <mutex>
+#include "BufferLayer.h"
 
 #include <compositionengine/CompositionEngine.h>
 #include <compositionengine/Display.h>
@@ -45,11 +43,14 @@
 #include <utils/StopWatch.h>
 #include <utils/Trace.h>
 
-#include "BufferLayer.h"
+#include <cmath>
+#include <cstdlib>
+#include <mutex>
+#include <sstream>
+
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "LayerRejecter.h"
-
 #include "TimeStats/TimeStats.h"
 
 namespace android {
@@ -97,8 +98,11 @@
 }
 
 bool BufferLayer::isVisible() const {
-    return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
+    bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
             (mActiveBuffer != nullptr || mSidebandStream != nullptr);
+    mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible);
+
+    return visible;
 }
 
 bool BufferLayer::isFixedSize() const {
@@ -321,7 +325,10 @@
     }
 
     error = hwcLayer->setColorTransform(getColorTransform());
-    if (error != HWC2::Error::None) {
+    if (error == HWC2::Error::Unsupported) {
+        // If per layer color transform is not supported, we use GPU composition.
+        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CLIENT);
+    } else if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
                 to_string(error).c_str(), static_cast<int32_t>(error));
     }
@@ -413,6 +420,7 @@
     // If the head buffer's acquire fence hasn't signaled yet, return and
     // try again later
     if (!fenceHasSignaled()) {
+        ATRACE_NAME("!fenceHasSignaled()");
         mFlinger->signalLayerUpdate();
         return false;
     }
@@ -423,7 +431,7 @@
     sp<GraphicBuffer> oldBuffer = mActiveBuffer;
 
     if (!allTransactionsSignaled()) {
-        mFlinger->signalLayerUpdate();
+        mFlinger->setTransactionFlags(eTraversalNeeded);
         return false;
     }
 
@@ -518,6 +526,9 @@
             }
 
             if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+                std::stringstream ss;
+                ss << "Dropping sync point " << (*point)->getFrameNumber();
+                ATRACE_NAME(ss.str().c_str());
                 point = mLocalSyncPoints.erase(point);
             } else {
                 ++point;
@@ -530,12 +541,20 @@
 
 // transaction
 void BufferLayer::notifyAvailableFrames() {
-    auto headFrameNumber = getHeadFrameNumber();
-    bool headFenceSignaled = fenceHasSignaled();
+    const auto headFrameNumber = getHeadFrameNumber();
+    const bool headFenceSignaled = fenceHasSignaled();
+    const bool presentTimeIsCurrent = framePresentTimeIsCurrent();
     Mutex::Autolock lock(mLocalSyncPointMutex);
     for (auto& point : mLocalSyncPoints) {
-        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
+        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
+            presentTimeIsCurrent) {
             point->setFrameAvailable();
+            sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer();
+            if (requestedSyncLayer) {
+                // Need to update the transaction flag to ensure the layer's pending transaction
+                // gets applied.
+                requestedSyncLayer->setTransactionFlags(eTransactionNeeded);
+            }
         }
     }
 }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index dc103cb..b679380 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -114,6 +114,7 @@
     // -----------------------------------------------------------------------
 private:
     virtual bool fenceHasSignaled() const = 0;
+    virtual bool framePresentTimeIsCurrent() const = 0;
 
     virtual nsecs_t getDesiredPresentTime() = 0;
     virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index fc98dc8..096cd1a 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -419,30 +419,6 @@
     return mCurrentFenceTime;
 }
 
-status_t BufferLayerConsumer::doFenceWaitLocked() const {
-    if (mCurrentFence->isValid()) {
-        if (mRE.useWaitSync()) {
-            base::unique_fd fenceFd(mCurrentFence->dup());
-            if (fenceFd == -1) {
-                BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
-                return -errno;
-            }
-            if (!mRE.waitFence(std::move(fenceFd))) {
-                BLC_LOGE("doFenceWait: failed to wait on fence fd");
-                return UNKNOWN_ERROR;
-            }
-        } else {
-            status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked");
-            if (err != NO_ERROR) {
-                BLC_LOGE("doFenceWait: error waiting for fence: %d", err);
-                return err;
-            }
-        }
-    }
-
-    return NO_ERROR;
-}
-
 void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
     BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     std::lock_guard<std::mutex> lock(mImagesMutex);
@@ -478,20 +454,15 @@
     }
 }
 
-void BufferLayerConsumer::onBufferAllocated(const BufferItem& item) {
-    if (item.mGraphicBuffer != nullptr) {
-        std::shared_ptr<Image> image = std::make_shared<Image>(item.mGraphicBuffer, mRE);
-        std::shared_ptr<Image> oldImage;
-        {
-            std::lock_guard<std::mutex> lock(mImagesMutex);
-            oldImage = mImages[item.mSlot];
-            if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr ||
-                oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) {
-                mImages[item.mSlot] = std::make_shared<Image>(item.mGraphicBuffer, mRE);
-            }
-            image = mImages[item.mSlot];
+void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) {
+    if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
+        std::lock_guard<std::mutex> lock(mImagesMutex);
+        const std::shared_ptr<Image>& oldImage = mImages[item.mSlot];
+        if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr ||
+            oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) {
+            mImages[item.mSlot] = std::make_shared<Image>(item.mGraphicBuffer, mRE);
+            mRE.cacheExternalTextureBuffer(item.mGraphicBuffer);
         }
-        mRE.cacheExternalTextureBuffer(image->graphicBuffer());
     }
 }
 
@@ -533,5 +504,4 @@
         mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId());
     }
 }
-
 }; // namespace android
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 0f0655d..144686c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -176,6 +176,7 @@
     // setConsumerUsageBits overrides the ConsumerBase method to OR
     // DEFAULT_USAGE_FLAGS to usage.
     status_t setConsumerUsageBits(uint64_t usage);
+    void onBufferAvailable(const BufferItem& item) EXCLUDES(mImagesMutex);
 
 protected:
     // abandonLocked overrides the ConsumerBase method to clear
@@ -241,7 +242,6 @@
 
     // IConsumerListener interface
     void onDisconnect() override;
-    void onBufferAllocated(const BufferItem& item) override EXCLUDES(mImagesMutex);
     void onSidebandStreamChanged() override;
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
                                   FrameEventHistoryDelta* outDelta) override;
@@ -252,11 +252,6 @@
     // mCurrentTextureImage must not be nullptr.
     void computeCurrentTransformMatrixLocked();
 
-    // doFenceWaitLocked inserts a wait command into the RenderEngine command
-    // stream to ensure that it is safe for future RenderEngine commands to
-    // access the current texture buffer.
-    status_t doFenceWaitLocked() const;
-
     // getCurrentCropLocked returns the cropping rectangle of the current buffer.
     Rect getCurrentCropLocked() const;
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d3b36fe..d685366 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -14,15 +14,20 @@
  * limitations under the License.
  */
 
+#undef LOG_TAG
+#define LOG_TAG "BufferQueueLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/LayerCompositionState.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <gui/BufferQueueConsumer.h>
 #include <system/window.h>
 
 #include "BufferQueueLayer.h"
 #include "LayerRejecter.h"
+#include "SurfaceInterceptor.h"
 
 #include "TimeStats/TimeStats.h"
 
@@ -132,6 +137,15 @@
     return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
 }
 
+bool BufferQueueLayer::framePresentTimeIsCurrent() const {
+    if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
+        return true;
+    }
+
+    Mutex::Autolock lock(mQueueItemLock);
+    return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
+}
+
 nsecs_t BufferQueueLayer::getDesiredPresentTime() {
     return mConsumer->getTimestamp();
 }
@@ -184,7 +198,37 @@
 
 uint64_t BufferQueueLayer::getFrameNumber() const {
     Mutex::Autolock lock(mQueueItemLock);
-    return mQueueItems[0].mFrameNumber;
+    uint64_t frameNumber = mQueueItems[0].mFrameNumber;
+
+    // The head of the queue will be dropped if there are signaled and timely frames behind it
+    nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
+
+    if (isRemovedFromCurrentState()) {
+        expectedPresentTime = 0;
+    }
+
+    for (int i = 1; i < mQueueItems.size(); i++) {
+        const bool fenceSignaled =
+                mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+        if (!fenceSignaled) {
+            break;
+        }
+
+        // We don't drop frames without explicit timestamps
+        if (mQueueItems[i].mIsAutoTimestamp) {
+            break;
+        }
+
+        const nsecs_t desiredPresent = mQueueItems[i].mTimestamp;
+        if (desiredPresent < expectedPresentTime - BufferQueueConsumer::MAX_REASONABLE_NSEC ||
+            desiredPresent > expectedPresentTime) {
+            break;
+        }
+
+        frameNumber = mQueueItems[i].mFrameNumber;
+    }
+
+    return frameNumber;
 }
 
 bool BufferQueueLayer::getAutoRefresh() const {
@@ -235,7 +279,7 @@
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
                     getTransformToDisplayInverse(), mFreezeGeometryUpdates);
 
-    nsecs_t expectedPresentTime = mFlinger->mScheduler->expectedPresentTime();
+    nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
 
     if (isRemovedFromCurrentState()) {
         expectedPresentTime = 0;
@@ -394,11 +438,13 @@
 }
 
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
+    ATRACE_CALL();
     // Add this buffer from our internal queue tracker
     { // Autolock scope
         if (mFlinger->mUseSmart90ForVideo) {
-            // Report mApi ID for each layer.
-            mFlinger->mScheduler->addNativeWindowApi(item.mApi);
+            const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
+            mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
+                                                            item.mHdrMetadata.validTypes != 0);
         }
 
         Mutex::Autolock lock(mQueueItemLock);
@@ -434,9 +480,11 @@
     } else {
         mFlinger->signalLayerUpdate();
     }
+    mConsumer->onBufferAvailable(item);
 }
 
 void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
+    ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mQueueItemLock);
 
@@ -458,6 +506,7 @@
         mLastFrameNumberReceived = item.mFrameNumber;
         mQueueItemCondition.broadcast();
     }
+    mConsumer->onBufferAvailable(item);
 }
 
 void BufferQueueLayer::onSidebandStreamChanged() {
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index a2aad17..7def33a 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -61,6 +61,7 @@
     // -----------------------------------------------------------------------
 public:
     bool fenceHasSignaled() const override;
+    bool framePresentTimeIsCurrent() const override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 64dfdc3..4b01301 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -26,6 +26,7 @@
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/LayerCompositionState.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <gui/BufferQueue.h>
 #include <private/gui/SyncFeatures.h>
 #include <renderengine/Image.h>
 
@@ -44,16 +45,11 @@
 };
 // clang-format on
 
-BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {
+BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
+      : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
     mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
     mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
 }
-BufferStateLayer::~BufferStateLayer() {
-    if (mActiveBuffer != nullptr) {
-        auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
-    }
-}
 
 // -----------------------------------------------------------------------
 // Interface implementation for Layer
@@ -89,7 +85,7 @@
 }
 
 void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
-    mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles(
+    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
             mDrawingState.callbackHandles);
 
     mDrawingState.callbackHandles = {};
@@ -209,14 +205,26 @@
     return true;
 }
 
-bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer) {
+bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime,
+                                 nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) {
     if (mCurrentState.buffer) {
         mReleasePreviousBuffer = true;
     }
 
     mCurrentState.buffer = buffer;
+    mCurrentState.clientCacheId = clientCacheId;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
+
+    mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
+    mDesiredPresentTime = desiredPresentTime;
+
+    if (mFlinger->mUseSmart90ForVideo) {
+        const nsecs_t presentTime = (mDesiredPresentTime == -1) ? 0 : mDesiredPresentTime;
+        mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
+                                                        mCurrentState.hdrMetadata.validTypes != 0);
+    }
+
     return true;
 }
 
@@ -302,7 +310,7 @@
 
         } else { // If this layer will NOT need to be relatched and presented this frame
             // Notify the transaction completed thread this handle is done
-            mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle);
+            mFlinger->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle);
         }
     }
 
@@ -348,14 +356,6 @@
     return parentBounds;
 }
 
-void BufferStateLayer::setPostTime(nsecs_t postTime) {
-    mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
-}
-
-void BufferStateLayer::setDesiredPresentTime(nsecs_t desiredPresentTime) {
-    mDesiredPresentTime = desiredPresentTime;
-}
-
 // -----------------------------------------------------------------------
 
 // -----------------------------------------------------------------------
@@ -369,6 +369,14 @@
     return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
 }
 
+bool BufferStateLayer::framePresentTimeIsCurrent() const {
+    if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
+        return true;
+    }
+
+    return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
+}
+
 nsecs_t BufferStateLayer::getDesiredPresentTime() {
     return mDesiredPresentTime;
 }
@@ -557,11 +565,6 @@
         return BAD_VALUE;
     }
 
-    if (mActiveBuffer != nullptr) {
-        // todo: get this to work with BufferStateLayerCache
-        auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
-    }
     mActiveBuffer = s.buffer;
     mActiveBufferFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
@@ -587,8 +590,8 @@
 
     uint32_t hwcSlot;
     sp<GraphicBuffer> buffer;
-    hwcInfo.hwcBufferCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, s.buffer, &hwcSlot,
-                                        &buffer);
+    hwcInfo.hwcBufferCache.getHwcBuffer(mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId),
+                                        s.buffer, &hwcSlot, &buffer);
 
     auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence);
     if (error != HWC2::Error::None) {
@@ -607,4 +610,80 @@
     }
 }
 
+void BufferStateLayer::bufferErased(const client_cache_t& clientCacheId) {
+    mFlinger->getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id);
+}
+
+void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
+    std::lock_guard lock(mMutex);
+    if (!clientCacheId.isValid()) {
+        ALOGE("invalid process, failed to erase buffer");
+        return;
+    }
+    eraseBufferLocked(clientCacheId);
+}
+
+uint32_t BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    auto itr = mCachedBuffers.find(clientCacheId);
+    if (itr == mCachedBuffers.end()) {
+        return addCachedBuffer(clientCacheId);
+    }
+    auto& [hwcCacheSlot, counter] = itr->second;
+    counter = mCounter++;
+    return hwcCacheSlot;
+}
+
+uint32_t BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
+        REQUIRES(mMutex) {
+    if (!clientCacheId.isValid()) {
+        ALOGE("invalid process, returning invalid slot");
+        return BufferQueue::INVALID_BUFFER_SLOT;
+    }
+
+    ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this));
+
+    uint32_t hwcCacheSlot = getFreeHwcCacheSlot();
+    mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++};
+    return hwcCacheSlot;
+}
+
+uint32_t BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
+    if (mFreeHwcCacheSlots.empty()) {
+        evictLeastRecentlyUsed();
+    }
+
+    uint32_t hwcCacheSlot = mFreeHwcCacheSlots.top();
+    mFreeHwcCacheSlots.pop();
+    return hwcCacheSlot;
+}
+
+void BufferStateLayer::HwcSlotGenerator::evictLeastRecentlyUsed() REQUIRES(mMutex) {
+    uint64_t minCounter = UINT_MAX;
+    client_cache_t minClientCacheId = {};
+    for (const auto& [clientCacheId, slotCounter] : mCachedBuffers) {
+        const auto& [hwcCacheSlot, counter] = slotCounter;
+        if (counter < minCounter) {
+            minCounter = counter;
+            minClientCacheId = clientCacheId;
+        }
+    }
+    eraseBufferLocked(minClientCacheId);
+
+    ClientCache::getInstance().unregisterErasedRecipient(minClientCacheId, this);
+}
+
+void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& clientCacheId)
+        REQUIRES(mMutex) {
+    auto itr = mCachedBuffers.find(clientCacheId);
+    if (itr == mCachedBuffers.end()) {
+        return;
+    }
+    auto& [hwcCacheSlot, counter] = itr->second;
+
+    // TODO send to hwc cache and resources
+
+    mFreeHwcCacheSlots.push(hwcCacheSlot);
+    mCachedBuffers.erase(clientCacheId);
+}
 } // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 668830a..db8ae0d 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -25,12 +25,15 @@
 #include <system/window.h>
 #include <utils/String8.h>
 
+#include <stack>
+
 namespace android {
 
+class SlotGenerationTest;
+
 class BufferStateLayer : public BufferLayer {
 public:
     explicit BufferStateLayer(const LayerCreationArgs&);
-    ~BufferStateLayer() override;
 
     // -----------------------------------------------------------------------
     // Interface implementation for Layer
@@ -63,7 +66,8 @@
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
     bool setCrop(const Rect& crop) override;
     bool setFrame(const Rect& frame) override;
-    bool setBuffer(const sp<GraphicBuffer>& buffer) override;
+    bool setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime, nsecs_t desiredPresentTime,
+                   const client_cache_t& clientCacheId) override;
     bool setAcquireFence(const sp<Fence>& fence) override;
     bool setDataspace(ui::Dataspace dataspace) override;
     bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
@@ -90,14 +94,16 @@
     Rect getBufferSize(const State& s) const override;
     FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
 
-    void setPostTime(nsecs_t postTime) override;
-    void setDesiredPresentTime(nsecs_t desiredPresentTime) override;
     // -----------------------------------------------------------------------
 
     // -----------------------------------------------------------------------
     // Interface implementation for BufferLayer
     // -----------------------------------------------------------------------
     bool fenceHasSignaled() const override;
+    bool framePresentTimeIsCurrent() const override;
+
+    // Inherit from ClientCache::ErasedRecipient
+    void bufferErased(const client_cache_t& clientCacheId) override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
@@ -133,6 +139,7 @@
     void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override;
 
 private:
+    friend class SlotGenerationTest;
     void onFirstRef() override;
     bool willPresentCurrentTransaction() const;
 
@@ -155,6 +162,46 @@
     nsecs_t mDesiredPresentTime = -1;
 
     // TODO(marissaw): support sticky transform for LEGACY camera mode
+
+    class HwcSlotGenerator : public ClientCache::ErasedRecipient {
+    public:
+        HwcSlotGenerator() {
+            for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+                mFreeHwcCacheSlots.push(i);
+            }
+        }
+
+        void bufferErased(const client_cache_t& clientCacheId);
+
+        uint32_t getHwcCacheSlot(const client_cache_t& clientCacheId);
+
+    private:
+        friend class SlotGenerationTest;
+        uint32_t addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+        uint32_t getFreeHwcCacheSlot() REQUIRES(mMutex);
+        void evictLeastRecentlyUsed() REQUIRES(mMutex);
+        void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+
+        struct CachedBufferHash {
+            std::size_t operator()(const client_cache_t& clientCacheId) const {
+                return std::hash<uint64_t>{}(clientCacheId.id);
+            }
+        };
+
+        std::mutex mMutex;
+
+        std::unordered_map<client_cache_t,
+                           std::pair<uint32_t /*HwcCacheSlot*/, uint32_t /*counter*/>,
+                           CachedBufferHash>
+                mCachedBuffers GUARDED_BY(mMutex);
+        std::stack<uint32_t /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
+
+        // The cache increments this counter value when a slot is updated or used.
+        // Used to track the least recently-used buffer
+        uint64_t mCounter = 0;
+    };
+
+    sp<HwcSlotGenerator> mHwcSlotGenerator;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp
deleted file mode 100644
index 51ca45c..0000000
--- a/services/surfaceflinger/BufferStateLayerCache.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2019 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 "BufferStateLayerCache"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <cinttypes>
-
-#include "BufferStateLayerCache.h"
-
-namespace android {
-
-ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache);
-
-BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {}
-
-void BufferStateLayerCache::add(const sp<IBinder>& processToken, uint64_t id,
-                                const sp<GraphicBuffer>& buffer) {
-    if (!processToken) {
-        ALOGE("failed to cache buffer: invalid process token");
-        return;
-    }
-
-    if (!buffer) {
-        ALOGE("failed to cache buffer: invalid buffer");
-        return;
-    }
-
-    std::lock_guard lock(mMutex);
-
-    // If this is a new process token, set a death recipient. If the client process dies, we will
-    // get a callback through binderDied.
-    if (mBuffers.find(processToken) == mBuffers.end()) {
-        status_t err = processToken->linkToDeath(mDeathRecipient);
-        if (err != NO_ERROR) {
-            ALOGE("failed to cache buffer: could not link to death");
-            return;
-        }
-    }
-
-    auto& processBuffers = mBuffers[processToken];
-
-    if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
-        ALOGE("failed to cache buffer: cache is full");
-        return;
-    }
-
-    processBuffers[id] = buffer;
-}
-
-void BufferStateLayerCache::erase(const sp<IBinder>& processToken, uint64_t id) {
-    if (!processToken) {
-        ALOGE("failed to uncache buffer: invalid process token");
-        return;
-    }
-
-    std::lock_guard lock(mMutex);
-
-    if (mBuffers.find(processToken) == mBuffers.end()) {
-        ALOGE("failed to uncache buffer: process token not found");
-        return;
-    }
-
-    auto& processBuffers = mBuffers[processToken];
-    processBuffers.erase(id);
-}
-
-sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, uint64_t id) {
-    if (!processToken) {
-        ALOGE("failed to cache buffer: invalid process token");
-        return nullptr;
-    }
-
-    std::lock_guard lock(mMutex);
-    auto itr = mBuffers.find(processToken);
-    if (itr == mBuffers.end()) {
-        ALOGE("failed to get buffer: process token not found");
-        return nullptr;
-    }
-
-    if (itr->second.find(id) == itr->second.end()) {
-        ALOGE("failed to get buffer: buffer not found");
-        return nullptr;
-    }
-
-    return itr->second[id];
-}
-
-void BufferStateLayerCache::removeProcess(const wp<IBinder>& processToken) {
-    std::lock_guard lock(mMutex);
-    mBuffers.erase(processToken);
-}
-
-void BufferStateLayerCache::CacheDeathRecipient::binderDied(const wp<IBinder>& who) {
-    BufferStateLayerCache::getInstance().removeProcess(who);
-}
-
-}; // namespace android
diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h
deleted file mode 100644
index 415c09c..0000000
--- a/services/surfaceflinger/BufferStateLayerCache.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2019 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 <android-base/thread_annotations.h>
-#include <binder/IBinder.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/RefBase.h>
-#include <utils/Singleton.h>
-
-#include <array>
-#include <map>
-#include <mutex>
-
-#define BUFFER_CACHE_MAX_SIZE 64
-
-namespace android {
-
-class BufferStateLayerCache : public Singleton<BufferStateLayerCache> {
-public:
-    BufferStateLayerCache();
-
-    void add(const sp<IBinder>& processToken, uint64_t id, const sp<GraphicBuffer>& buffer);
-    void erase(const sp<IBinder>& processToken, uint64_t id);
-
-    sp<GraphicBuffer> get(const sp<IBinder>& processToken, uint64_t id);
-
-    void removeProcess(const wp<IBinder>& processToken);
-
-private:
-    std::mutex mMutex;
-    std::map<wp<IBinder> /*caching process*/, std::map<uint64_t /*Cache id*/, sp<GraphicBuffer>>>
-            mBuffers GUARDED_BY(mMutex);
-
-    class CacheDeathRecipient : public IBinder::DeathRecipient {
-    public:
-        void binderDied(const wp<IBinder>& who) override;
-    };
-
-    sp<CacheDeathRecipient> mDeathRecipient;
-};
-
-}; // namespace android
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index e54b460..6bfd302 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -76,18 +76,9 @@
                                uint32_t flags, const sp<IBinder>& parentHandle,
                                LayerMetadata metadata, sp<IBinder>* handle,
                                sp<IGraphicBufferProducer>* gbp) {
-    sp<Layer> parent = nullptr;
-    if (parentHandle != nullptr) {
-        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
-        parent = layerHandle->owner.promote();
-        if (parent == nullptr) {
-            return NAME_NOT_FOUND;
-        }
-    }
-
     // We rely on createLayer to check permissions.
     return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
-                                 &parent);
+                                 parentHandle);
 }
 
 status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
@@ -96,17 +87,23 @@
                                          LayerMetadata metadata, sp<IBinder>* handle,
                                          sp<IGraphicBufferProducer>* gbp) {
     if (mFlinger->authenticateSurfaceTexture(parent) == false) {
+        ALOGE("failed to authenticate surface texture");
+        // The extra parent layer check below before returning is to help with debugging
+        // b/134888387. Once the bug is fixed the check can be deleted.
+        if ((static_cast<MonitoredProducer*>(parent.get()))->getLayer() == nullptr) {
+            ALOGE("failed to find parent layer");
+        }
         return BAD_VALUE;
     }
 
     const auto& layer = (static_cast<MonitoredProducer*>(parent.get()))->getLayer();
     if (layer == nullptr) {
+        ALOGE("failed to find parent layer");
         return BAD_VALUE;
     }
 
-    sp<IBinder> parentHandle = layer->getHandle();
-
-    return createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), handle, gbp);
+    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
+                                 nullptr, layer);
 }
 
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
new file mode 100644
index 0000000..77f2f57
--- /dev/null
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2019 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 "ClientCache"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <cinttypes>
+
+#include "ClientCache.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(ClientCache);
+
+ClientCache::ClientCache() : mDeathRecipient(new CacheDeathRecipient) {}
+
+bool ClientCache::getBuffer(const client_cache_t& cacheId,
+                            ClientCacheBuffer** outClientCacheBuffer) {
+    auto& [processToken, id] = cacheId;
+    if (processToken == nullptr) {
+        ALOGE("failed to get buffer, invalid (nullptr) process token");
+        return false;
+    }
+    auto it = mBuffers.find(processToken);
+    if (it == mBuffers.end()) {
+        ALOGE("failed to get buffer, invalid process token");
+        return false;
+    }
+
+    auto& processBuffers = it->second;
+
+    auto bufItr = processBuffers.find(id);
+    if (bufItr == processBuffers.end()) {
+        ALOGE("failed to get buffer, invalid buffer id");
+        return false;
+    }
+
+    ClientCacheBuffer& buf = bufItr->second;
+    *outClientCacheBuffer = &buf;
+    return true;
+}
+
+void ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
+    auto& [processToken, id] = cacheId;
+    if (processToken == nullptr) {
+        ALOGE("failed to cache buffer: invalid process token");
+        return;
+    }
+
+    if (!buffer) {
+        ALOGE("failed to cache buffer: invalid buffer");
+        return;
+    }
+
+    std::lock_guard lock(mMutex);
+    sp<IBinder> token;
+
+    // If this is a new process token, set a death recipient. If the client process dies, we will
+    // get a callback through binderDied.
+    auto it = mBuffers.find(processToken);
+    if (it == mBuffers.end()) {
+        token = processToken.promote();
+        if (!token) {
+            ALOGE("failed to cache buffer: invalid token");
+            return;
+        }
+
+        status_t err = token->linkToDeath(mDeathRecipient);
+        if (err != NO_ERROR) {
+            ALOGE("failed to cache buffer: could not link to death");
+            return;
+        }
+        auto [itr, success] =
+                mBuffers.emplace(processToken, std::unordered_map<uint64_t, ClientCacheBuffer>());
+        LOG_ALWAYS_FATAL_IF(!success, "failed to insert new process into client cache");
+        it = itr;
+    }
+
+    auto& processBuffers = it->second;
+
+    if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
+        ALOGE("failed to cache buffer: cache is full");
+        return;
+    }
+
+    processBuffers[id].buffer = buffer;
+}
+
+void ClientCache::erase(const client_cache_t& cacheId) {
+    auto& [processToken, id] = cacheId;
+    std::vector<sp<ErasedRecipient>> pendingErase;
+    {
+        std::lock_guard lock(mMutex);
+        ClientCacheBuffer* buf = nullptr;
+        if (!getBuffer(cacheId, &buf)) {
+            ALOGE("failed to erase buffer, could not retrieve buffer");
+            return;
+        }
+
+        for (auto& recipient : buf->recipients) {
+            sp<ErasedRecipient> erasedRecipient = recipient.promote();
+            if (erasedRecipient) {
+                pendingErase.push_back(erasedRecipient);
+            }
+        }
+
+        mBuffers[processToken].erase(id);
+    }
+
+    for (auto& recipient : pendingErase) {
+        recipient->bufferErased(cacheId);
+    }
+}
+
+sp<GraphicBuffer> ClientCache::get(const client_cache_t& cacheId) {
+    std::lock_guard lock(mMutex);
+
+    ClientCacheBuffer* buf = nullptr;
+    if (!getBuffer(cacheId, &buf)) {
+        ALOGE("failed to get buffer, could not retrieve buffer");
+        return nullptr;
+    }
+
+    return buf->buffer;
+}
+
+void ClientCache::registerErasedRecipient(const client_cache_t& cacheId,
+                                          const wp<ErasedRecipient>& recipient) {
+    std::lock_guard lock(mMutex);
+
+    ClientCacheBuffer* buf = nullptr;
+    if (!getBuffer(cacheId, &buf)) {
+        ALOGE("failed to register erased recipient, could not retrieve buffer");
+        return;
+    }
+    buf->recipients.insert(recipient);
+}
+
+void ClientCache::unregisterErasedRecipient(const client_cache_t& cacheId,
+                                            const wp<ErasedRecipient>& recipient) {
+    std::lock_guard lock(mMutex);
+
+    ClientCacheBuffer* buf = nullptr;
+    if (!getBuffer(cacheId, &buf)) {
+        ALOGE("failed to unregister erased recipient");
+        return;
+    }
+
+    buf->recipients.erase(recipient);
+}
+
+void ClientCache::removeProcess(const wp<IBinder>& processToken) {
+    std::vector<std::pair<sp<ErasedRecipient>, client_cache_t>> pendingErase;
+    {
+        if (processToken == nullptr) {
+            ALOGE("failed to remove process, invalid (nullptr) process token");
+            return;
+        }
+        std::lock_guard lock(mMutex);
+        auto itr = mBuffers.find(processToken);
+        if (itr == mBuffers.end()) {
+            ALOGE("failed to remove process, could not find process");
+            return;
+        }
+
+        for (auto& [id, clientCacheBuffer] : itr->second) {
+            client_cache_t cacheId = {processToken, id};
+            for (auto& recipient : clientCacheBuffer.recipients) {
+                sp<ErasedRecipient> erasedRecipient = recipient.promote();
+                if (erasedRecipient) {
+                    pendingErase.emplace_back(erasedRecipient, cacheId);
+                }
+            }
+        }
+        mBuffers.erase(itr);
+    }
+
+    for (auto& [recipient, cacheId] : pendingErase) {
+        recipient->bufferErased(cacheId);
+    }
+}
+
+void ClientCache::CacheDeathRecipient::binderDied(const wp<IBinder>& who) {
+    ClientCache::getInstance().removeProcess(who);
+}
+
+}; // namespace android
diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h
new file mode 100644
index 0000000..9f057c4
--- /dev/null
+++ b/services/surfaceflinger/ClientCache.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 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 <android-base/thread_annotations.h>
+#include <binder/IBinder.h>
+#include <gui/LayerState.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+
+#include <map>
+#include <mutex>
+#include <set>
+#include <unordered_map>
+
+#define BUFFER_CACHE_MAX_SIZE 64
+
+namespace android {
+
+class ClientCache : public Singleton<ClientCache> {
+public:
+    ClientCache();
+
+    void add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
+    void erase(const client_cache_t& cacheId);
+
+    sp<GraphicBuffer> get(const client_cache_t& cacheId);
+
+    void removeProcess(const wp<IBinder>& processToken);
+
+    class ErasedRecipient : public virtual RefBase {
+    public:
+        virtual void bufferErased(const client_cache_t& clientCacheId) = 0;
+    };
+
+    void registerErasedRecipient(const client_cache_t& cacheId,
+                                 const wp<ErasedRecipient>& recipient);
+    void unregisterErasedRecipient(const client_cache_t& cacheId,
+                                   const wp<ErasedRecipient>& recipient);
+
+private:
+    std::mutex mMutex;
+
+    struct ClientCacheBuffer {
+        sp<GraphicBuffer> buffer;
+        std::set<wp<ErasedRecipient>> recipients;
+    };
+    std::map<wp<IBinder> /*caching process*/,
+             std::unordered_map<uint64_t /*cache id*/, ClientCacheBuffer>>
+            mBuffers GUARDED_BY(mMutex);
+
+    class CacheDeathRecipient : public IBinder::DeathRecipient {
+    public:
+        void binderDied(const wp<IBinder>& who) override;
+    };
+
+    sp<CacheDeathRecipient> mDeathRecipient;
+
+    bool getBuffer(const client_cache_t& cacheId, ClientCacheBuffer** outClientCacheBuffer)
+            REQUIRES(mMutex);
+};
+
+}; // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index e86d35d..6f076ad 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -68,6 +68,7 @@
         "mock/DisplaySurface.cpp",
         "mock/Layer.cpp",
         "mock/LayerFE.cpp",
+        "mock/NativeWindow.cpp",
         "mock/Output.cpp",
         "mock/OutputLayer.cpp",
         "mock/RenderSurface.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index e69b99f..9bff73e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -50,6 +50,9 @@
     // Returns the bounds of the surface
     virtual const ui::Size& getSize() const = 0;
 
+    // Returns whether the surface is protected.
+    virtual bool isProtected() const = 0;
+
     // Gets the latest fence to pass to the HWC to signal that the surface
     // buffer is done rendering
     virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
@@ -80,10 +83,6 @@
     // Called after the HWC calls are made to present the display
     virtual void onPresentDisplayCompleted() = 0;
 
-    // Called to set the viewport and projection state for rendering into this
-    // surface
-    virtual void setViewportAndProjection() = 0;
-
     // Called after the surface has been rendering to signal the surface should
     // be made ready for displaying
     virtual void flip() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
index 97bdc8f..8eec035 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
@@ -48,20 +48,11 @@
     void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                       sp<GraphicBuffer>* outBuffer);
 
-protected:
-    bool getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot);
-    uint32_t getLeastRecentlyUsedSlot();
-    uint64_t getCounter();
-
 private:
     // an array where the index corresponds to a slot and the value corresponds to a (counter,
     // buffer) pair. "counter" is a unique value that indicates the last time this slot was updated
     // or used and allows us to keep track of the least-recently used buffer.
-    std::pair<uint64_t, wp<GraphicBuffer>> mBuffers[BufferQueue::NUM_BUFFER_SLOTS];
-
-    // The cache increments this counter value when a slot is updated or used.
-    // Used to track the least recently-used buffer
-    uint64_t mCounter = 1;
+    wp<GraphicBuffer> mBuffers[BufferQueue::NUM_BUFFER_SLOTS];
 };
 
 } // namespace compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
index 67bea4b..ab01c20 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h
@@ -33,12 +33,6 @@
 
     LayerFECompositionState frontEnd;
 
-    /*
-     * RE state
-     */
-
-    renderengine::Mesh reMesh{renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2};
-
     // Debugging
     void dump(std::string& result) const;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 024ed45..0c47eb5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -18,6 +18,7 @@
 
 #include <cstdint>
 
+#include <math/mat4.h>
 #include <ui/GraphicTypes.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -78,6 +79,9 @@
     // The color transform to apply
     android_color_transform_t colorTransform{HAL_COLOR_TRANSFORM_IDENTITY};
 
+    // The color transform matrix to apply, corresponding with colorTransform.
+    mat4 colorTransformMat;
+
     // Current active color mode
     ui::ColorMode colorMode{ui::ColorMode::NATIVE};
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 3c79084..e4c9c80 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -45,6 +45,7 @@
     bool isValid() const override;
     void initialize() override;
     const ui::Size& getSize() const override;
+    bool isProtected() const override { return mProtected; }
 
     const sp<Fence>& getClientTargetAcquireFence() const override;
     void setBufferDataspace(ui::Dataspace) override;
@@ -55,7 +56,6 @@
     sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) override;
     void queueBuffer(base::unique_fd&& readyFence) override;
     void onPresentDisplayCompleted() override;
-    void setViewportAndProjection() override;
     void flip() override;
 
     // Debugging
@@ -78,6 +78,7 @@
     sp<GraphicBuffer> mGraphicBuffer;
     const sp<DisplaySurface> mDisplaySurface;
     ui::Size mSize;
+    bool mProtected{false};
     std::uint32_t mPageFlipCount{0};
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/NativeWindow.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/NativeWindow.h
new file mode 100644
index 0000000..714d2f7
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/NativeWindow.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 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 <gmock/gmock.h>
+#include <system/window.h>
+#include <ui/ANativeObjectBase.h>
+#include <ui/GraphicTypes.h>
+#include <ui/PixelFormat.h>
+
+namespace android::compositionengine::mock {
+
+/* ------------------------------------------------------------------------
+ * Mock NativeWindow
+ *
+ * An intentionally simplified Mock which implements a minimal subset of the full
+ * ANativeWindow interface.
+ */
+class NativeWindow : public ANativeObjectBase<ANativeWindow, NativeWindow, RefBase> {
+public:
+    NativeWindow();
+    ~NativeWindow();
+
+    MOCK_METHOD1(setSwapInterval, int(int));
+    MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
+    MOCK_METHOD2(cancelBuffer, int(struct ANativeWindowBuffer*, int));
+    MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));
+    MOCK_CONST_METHOD2(query, int(int, int*));
+    MOCK_METHOD1(connect, int(int));
+    MOCK_METHOD1(disconnect, int(int));
+    MOCK_METHOD1(lockBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
+    MOCK_METHOD1(setBuffersFormat, int(PixelFormat));
+    MOCK_METHOD1(setBuffersDataSpace, int(ui::Dataspace));
+    MOCK_METHOD1(setUsage, int(uint64_t));
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index 1562f58..146a2ea 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -31,6 +31,7 @@
     MOCK_CONST_METHOD0(isValid, bool());
     MOCK_METHOD0(initialize, void());
     MOCK_CONST_METHOD0(getSize, const ui::Size&());
+    MOCK_CONST_METHOD0(isProtected, bool());
     MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
     MOCK_METHOD1(setDisplaySize, void(const ui::Size&));
     MOCK_METHOD1(setProtected, void(bool));
@@ -40,7 +41,6 @@
     MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
     MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
-    MOCK_METHOD0(setViewportAndProjection, void());
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
     MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
diff --git a/services/surfaceflinger/CompositionEngine/mock/NativeWindow.cpp b/services/surfaceflinger/CompositionEngine/mock/NativeWindow.cpp
new file mode 100644
index 0000000..d0cc8ef
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/NativeWindow.cpp
@@ -0,0 +1,121 @@
+
+/*
+ * Copyright 2019 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 "compositionengine/mock/NativeWindow.h"
+#include <log/log.h>
+
+namespace android::compositionengine::mock {
+
+static int forwardSetSwapInterval(ANativeWindow* window, int interval) {
+    return static_cast<NativeWindow*>(window)->setSwapInterval(interval);
+}
+
+static int forwardDequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
+    return static_cast<NativeWindow*>(window)->dequeueBuffer(buffer, fenceFd);
+}
+
+static int forwardCancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
+    return static_cast<NativeWindow*>(window)->cancelBuffer(buffer, fenceFd);
+}
+
+static int forwardQueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
+    return static_cast<NativeWindow*>(window)->queueBuffer(buffer, fenceFd);
+}
+
+static int forwardQuery(const ANativeWindow* window, int what, int* value) {
+    return static_cast<const NativeWindow*>(window)->query(what, value);
+}
+
+static int forwardPerform(ANativeWindow* window, int operation, ...) {
+    va_list args;
+    va_start(args, operation);
+    int result = NO_ERROR;
+    switch (operation) {
+        case NATIVE_WINDOW_API_CONNECT: {
+            int api = va_arg(args, int);
+            result = static_cast<NativeWindow*>(window)->connect(api);
+            break;
+        }
+        case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
+            PixelFormat format = va_arg(args, PixelFormat);
+            result = static_cast<NativeWindow*>(window)->setBuffersFormat(format);
+            break;
+        }
+        case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: {
+            ui::Dataspace dataspace = static_cast<ui::Dataspace>(va_arg(args, int));
+            result = static_cast<NativeWindow*>(window)->setBuffersDataSpace(dataspace);
+            break;
+        }
+        case NATIVE_WINDOW_SET_USAGE: {
+            // Note: Intentionally widens usage from 32 to 64 bits so we
+            // just have one implementation.
+            uint64_t usage = va_arg(args, uint32_t);
+            result = static_cast<NativeWindow*>(window)->setUsage(usage);
+            break;
+        }
+        case NATIVE_WINDOW_SET_USAGE64: {
+            uint64_t usage = va_arg(args, uint64_t);
+            result = static_cast<NativeWindow*>(window)->setUsage(usage);
+            break;
+        }
+        case NATIVE_WINDOW_API_DISCONNECT: {
+            int api = va_arg(args, int);
+            result = static_cast<NativeWindow*>(window)->disconnect(api);
+            break;
+        }
+        default:
+            LOG_ALWAYS_FATAL("Unexpected operation %d", operation);
+            break;
+    }
+
+    va_end(args);
+    return result;
+}
+
+static int forwardDequeueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer** buffer) {
+    int ignoredFenceFd = -1;
+    return static_cast<NativeWindow*>(window)->dequeueBuffer(buffer, &ignoredFenceFd);
+}
+
+static int forwardCancelBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
+    return static_cast<NativeWindow*>(window)->cancelBuffer(buffer, -1);
+}
+
+static int forwardLockBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
+    return static_cast<NativeWindow*>(window)->lockBuffer_DEPRECATED(buffer);
+}
+
+static int forwardQueueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
+    return static_cast<NativeWindow*>(window)->queueBuffer(buffer, -1);
+}
+
+NativeWindow::NativeWindow() {
+    ANativeWindow::setSwapInterval = &forwardSetSwapInterval;
+    ANativeWindow::dequeueBuffer = &forwardDequeueBuffer;
+    ANativeWindow::cancelBuffer = &forwardCancelBuffer;
+    ANativeWindow::queueBuffer = &forwardQueueBuffer;
+    ANativeWindow::query = &forwardQuery;
+    ANativeWindow::perform = &forwardPerform;
+
+    ANativeWindow::dequeueBuffer_DEPRECATED = &forwardDequeueBufferDeprecated;
+    ANativeWindow::cancelBuffer_DEPRECATED = &forwardCancelBufferDeprecated;
+    ANativeWindow::lockBuffer_DEPRECATED = &forwardLockBufferDeprecated;
+    ANativeWindow::queueBuffer_DEPRECATED = &forwardQueueBufferDeprecated;
+}
+NativeWindow::~NativeWindow() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
index a941e09..f72862b 100644
--- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
@@ -21,60 +21,30 @@
 namespace android::compositionengine::impl {
 
 HwcBufferCache::HwcBufferCache() {
-    std::fill(std::begin(mBuffers), std::end(mBuffers),
-              std::pair<uint64_t, wp<GraphicBuffer>>(0, nullptr));
-}
-bool HwcBufferCache::getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot) {
-    // search for cached buffer first
-    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
-        // Weak pointers in the cache may have had their object destroyed.
-        // Comparisons between weak pointers will accurately reflect this case,
-        // but comparisons between weak and strong may not.  Thus, we create a weak
-        // pointer from strong pointer buffer
-        wp<GraphicBuffer> weakCopy(buffer);
-        if (mBuffers[i].second == weakCopy) {
-            *outSlot = i;
-            return true;
-        }
-    }
-
-    // use the least-recently used slot
-    *outSlot = getLeastRecentlyUsedSlot();
-    return false;
-}
-
-uint32_t HwcBufferCache::getLeastRecentlyUsedSlot() {
-    auto iter = std::min_element(std::begin(mBuffers), std::end(mBuffers));
-    return std::distance(std::begin(mBuffers), iter);
+    std::fill(std::begin(mBuffers), std::end(mBuffers), wp<GraphicBuffer>(nullptr));
 }
 
 void HwcBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                                   sp<GraphicBuffer>* outBuffer) {
-    // if this slot corresponds to a BufferStateLayer, generate the slot
-    if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
-        getSlot(buffer, outSlot);
-    } else if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
+    // default is 0
+    if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0 ||
+        slot >= BufferQueue::NUM_BUFFER_SLOTS) {
         *outSlot = 0;
     } else {
         *outSlot = slot;
     }
 
-    auto& [currentCounter, currentBuffer] = mBuffers[*outSlot];
+    auto& currentBuffer = mBuffers[*outSlot];
     wp<GraphicBuffer> weakCopy(buffer);
     if (currentBuffer == weakCopy) {
         // already cached in HWC, skip sending the buffer
         *outBuffer = nullptr;
-        currentCounter = getCounter();
     } else {
         *outBuffer = buffer;
 
         // update cache
         currentBuffer = buffer;
-        currentCounter = getCounter();
     }
 }
 
-uint64_t HwcBufferCache::getCounter() {
-    return mCounter++;
-}
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index d22bdaf..01b5781 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -89,15 +89,16 @@
 }
 
 void Output::setColorTransform(const mat4& transform) {
+    if (mState.colorTransformMat == transform) {
+        return;
+    }
+
     const bool isIdentity = (transform == mat4());
     const auto newColorTransform =
             isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
 
-    if (mState.colorTransform == newColorTransform) {
-        return;
-    }
-
     mState.colorTransform = newColorTransform;
+    mState.colorTransformMat = transform;
 
     dirtyEntireOutput();
 }
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b4dfba1..8a91316 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -52,9 +52,14 @@
         mDisplay(display),
         mNativeWindow(args.nativeWindow),
         mDisplaySurface(args.displaySurface),
-        mSize(args.displayWidth, args.displayHeight) {}
+        mSize(args.displayWidth, args.displayHeight) {
+    LOG_ALWAYS_FATAL_IF(!mNativeWindow);
+}
 
-RenderSurface::~RenderSurface() = default;
+RenderSurface::~RenderSurface() {
+    ANativeWindow* const window = mNativeWindow.get();
+    native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+}
 
 bool RenderSurface::isValid() const {
     return mSize.isValid();
@@ -96,6 +101,9 @@
     }
     const int status = native_window_set_usage(mNativeWindow.get(), usageFlags);
     ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status);
+    if (status == NO_ERROR) {
+        mProtected = useProtected;
+    }
 }
 
 status_t RenderSurface::beginFrame(bool mustRecompose) {
@@ -207,13 +215,6 @@
     mDisplaySurface->onFrameCommitted();
 }
 
-void RenderSurface::setViewportAndProjection() {
-    auto& renderEngine = mCompositionEngine.getRenderEngine();
-    Rect sourceCrop = Rect(mSize);
-    renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop,
-                                          ui::Transform::ROT_0);
-}
-
 void RenderSurface::flip() {
     mPageFlipCount++;
 }
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index cd2d454..33444a5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -22,9 +22,9 @@
 #include <compositionengine/RenderSurfaceCreationArgs.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/mock/CompositionEngine.h>
+#include <compositionengine/mock/NativeWindow.h>
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
-#include <system/window.h>
 
 #include "MockHWComposer.h"
 
@@ -43,6 +43,7 @@
 
     StrictMock<android::mock::HWComposer> mHwComposer;
     StrictMock<mock::CompositionEngine> mCompositionEngine;
+    sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
     impl::Display mDisplay{mCompositionEngine,
                            DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()};
 };
@@ -199,8 +200,9 @@
  */
 
 TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) {
+    EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL)).WillRepeatedly(Return(NO_ERROR));
     EXPECT_TRUE(mDisplay.getRenderSurface() == nullptr);
-    mDisplay.createRenderSurface(RenderSurfaceCreationArgs{640, 480, nullptr, nullptr});
+    mDisplay.createRenderSurface(RenderSurfaceCreationArgs{640, 480, mNativeWindow, nullptr});
     EXPECT_TRUE(mDisplay.getRenderSurface() != nullptr);
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
new file mode 100644
index 0000000..6741cc9
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 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 <string>
+
+#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
+
+namespace {
+
+using android::base::StringAppendF;
+using FloatRect = android::FloatRect;
+
+void dumpFloatRect(const FloatRect& rect, std::string& result, const char* name) {
+    StringAppendF(&result, "%s (%f %f %f %f) ", name, rect.left, rect.top, rect.right, rect.bottom);
+}
+
+// Checks for a region match
+MATCHER_P(FloatRectEq, expected, "") {
+    std::string buf;
+    buf.append("FloatRects are not equal\n");
+    dumpFloatRect(expected, buf, "expected rect");
+    dumpFloatRect(arg, buf, "actual rect");
+    *result_listener << buf;
+
+    const float TOLERANCE = 1e-3f;
+    return (std::fabs(expected.left - arg.left) < TOLERANCE) &&
+            (std::fabs(expected.top - arg.top) < TOLERANCE) &&
+            (std::fabs(expected.right - arg.right) < TOLERANCE) &&
+            (std::fabs(expected.bottom - arg.bottom) < TOLERANCE);
+}
+
+} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
index b261493..00eafb1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
@@ -28,10 +28,6 @@
                       sp<GraphicBuffer>* outBuffer) {
         HwcBufferCache::getHwcBuffer(slot, buffer, outSlot, outBuffer);
     }
-    bool getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot) {
-        return HwcBufferCache::getSlot(buffer, outSlot);
-    }
-    uint32_t getLeastRecentlyUsedSlot() { return HwcBufferCache::getLeastRecentlyUsedSlot(); }
 };
 
 class HwcBufferCacheTest : public testing::Test {
@@ -86,41 +82,5 @@
     testSlot(-123, 0);
 }
 
-TEST_F(HwcBufferCacheTest, cacheGeneratesSlotForInvalidBufferSlot) {
-    uint32_t outSlot;
-    sp<GraphicBuffer> outBuffer;
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
-    EXPECT_EQ(0, outSlot);
-    EXPECT_EQ(mBuffer1, outBuffer);
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
-    EXPECT_EQ(0, outSlot);
-    EXPECT_EQ(nullptr, outBuffer.get());
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
-    EXPECT_EQ(1, outSlot);
-    EXPECT_EQ(mBuffer2, outBuffer);
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
-    EXPECT_EQ(1, outSlot);
-    EXPECT_EQ(nullptr, outBuffer.get());
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, sp<GraphicBuffer>(), &outSlot,
-                        &outBuffer);
-    EXPECT_EQ(2, outSlot);
-    EXPECT_EQ(nullptr, outBuffer.get());
-
-    // note that sending mBuffer1 with explicit slot 1 will overwrite mBuffer2
-    // and also cause mBuffer1 to be stored in two places
-    mCache.getHwcBuffer(1, mBuffer1, &outSlot, &outBuffer);
-    EXPECT_EQ(1, outSlot);
-    EXPECT_EQ(mBuffer1, outBuffer);
-
-    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
-    EXPECT_EQ(3, outSlot);
-    EXPECT_EQ(mBuffer2, outBuffer);
-}
-
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 2060c5a..ae906cd 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -21,6 +21,7 @@
 #include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 
+#include "FloatRectMatcher.h"
 #include "MockHWC2.h"
 #include "MockHWComposer.h"
 #include "RectMatcher.h"
@@ -106,6 +107,114 @@
 }
 
 /*
+ * OutputLayer::calculateOutputSourceCrop()
+ */
+
+struct OutputLayerSourceCropTest : public OutputLayerTest {
+    OutputLayerSourceCropTest() {
+        // Set reasonable default values for a simple case. Each test will
+        // set one specific value to something different.
+        mLayerState.frontEnd.geomUsesSourceCrop = true;
+        mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+        mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
+        mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomBufferTransform = TR_IDENT;
+
+        mOutputState.viewport = Rect{0, 0, 1920, 1080};
+    }
+
+    FloatRect calculateOutputSourceCrop() {
+        mLayerState.frontEnd.geomInverseLayerTransform =
+                mLayerState.frontEnd.geomLayerTransform.inverse();
+
+        return mOutputLayer.calculateOutputSourceCrop();
+    }
+};
+
+TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) {
+    mLayerState.frontEnd.geomUsesSourceCrop = false;
+
+    const FloatRect expected{};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) {
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+    mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
+
+    const FloatRect expected{0.f, 0.f, 1080.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) {
+    struct Entry {
+        uint32_t bufferInvDisplay;
+        uint32_t buffer;
+        uint32_t display;
+        FloatRect expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 12> testData = {
+            // clang-format off
+            //             inv      buffer      display     expected
+            /*  0 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  1 */ Entry{false,   TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  2 */ Entry{false,   TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  3 */ Entry{false,   TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  4 */ Entry{true,    TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  5 */ Entry{true,    TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  6 */ Entry{true,    TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  7 */ Entry{true,    TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  8 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  9 */ Entry{false,   TR_ROT_90,  TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 10 */ Entry{false,   TR_ROT_180, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 11 */ Entry{false,   TR_ROT_270, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay;
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i;
+    }
+}
+
+TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) {
+    mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) {
+    mOutputState.viewport = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+/*
  * OutputLayer::calculateOutputDisplayFrame()
  */
 
@@ -163,7 +272,7 @@
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
 }
 
-TEST_F(OutputLayerDisplayFrameTest, geomLayerSnapToBoundsAffectsFrame) {
+TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) {
     mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f};
     const Rect expected{0, 0, 960, 540};
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
@@ -242,6 +351,159 @@
     }
 }
 
+TEST_F(OutputLayerTest,
+       calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) {
+    mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true;
+
+    struct Entry {
+        uint32_t layer;
+        uint32_t buffer;
+        uint32_t display;
+        uint32_t expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 24> testData = {
+            // clang-format off
+            //             layer       buffer      display     expected
+            /*  0 */ Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /*  1 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /*  2 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /*  3 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /*  4 */ Entry{TR_IDENT,   TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /*  5 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /*  6 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /*  7 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /*  8 */ Entry{TR_IDENT,   TR_FLP_V,   TR_IDENT,   TR_FLP_V},
+            /*  9 */ Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_90,  TR_ROT_90},
+            /* 10 */ Entry{TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_ROT_180},
+            /* 11 */ Entry{TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_ROT_270},
+
+            /* 12 */ Entry{TR_ROT_90,  TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 13 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 14 */ Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /* 15 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /* 16 */ Entry{TR_ROT_180, TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /* 17 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /* 18 */ Entry{TR_ROT_180, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 19 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /* 20 */ Entry{TR_ROT_270, TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 21 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 22 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 23 */ Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT},
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer};
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+        EXPECT_EQ(entry.expected, actual) << "entry " << i;
+    }
+}
+
+/*
+ * OutputLayer::updateCompositionState()
+ */
+
+struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer {
+    OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
+                                                    std::shared_ptr<compositionengine::Layer> layer,
+                                                    sp<compositionengine::LayerFE> layerFE)
+          : impl::OutputLayer(output, layer, layerFE) {}
+    // Mock everything called by updateCompositionState to simplify testing it.
+    MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
+    MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
+    MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+};
+
+struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
+public:
+    OutputLayerUpdateCompositionStateTest() {
+        EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState));
+        EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
+    }
+
+    ~OutputLayerUpdateCompositionStateTest() = default;
+
+    void setupGeometryChildCallValues() {
+        EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
+        EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
+        EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
+                .WillOnce(Return(mBufferTransform));
+    }
+
+    void validateComputedGeometryState() {
+        const auto& state = mOutputLayer.getState();
+        EXPECT_EQ(kSourceCrop, state.sourceCrop);
+        EXPECT_EQ(kDisplayFrame, state.displayFrame);
+        EXPECT_EQ(static_cast<Hwc2::Transform>(mBufferTransform), state.bufferTransform);
+    }
+
+    const FloatRect kSourceCrop{1.f, 2.f, 3.f, 4.f};
+    const Rect kDisplayFrame{11, 12, 13, 14};
+    uint32_t mBufferTransform{21};
+
+    using OutputLayer = OutputLayerPartialMockForUpdateCompositionState;
+    StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE};
+};
+
+TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = false;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfUnsupportedBufferTransform) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    mBufferTransform = ui::Transform::ROT_INVALID;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
 /*
  * OutputLayer::writeStateToHWC()
  */
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index a84af3a..fee0c11 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -172,16 +172,29 @@
     mOutput.setColorTransform(identity);
 
     EXPECT_EQ(HAL_COLOR_TRANSFORM_IDENTITY, mOutput.getState().colorTransform);
+    EXPECT_EQ(identity, mOutput.getState().colorTransformMat);
 
     // Since identity is the default, the dirty region should be unchanged (empty)
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
 
     // Non-identity matrix sets a non-identity state value
-    const mat4 nonIdentity = mat4() * 2;
+    const mat4 nonIdentityHalf = mat4() * 0.5;
 
-    mOutput.setColorTransform(nonIdentity);
+    mOutput.setColorTransform(nonIdentityHalf);
 
     EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
+    EXPECT_EQ(nonIdentityHalf, mOutput.getState().colorTransformMat);
+
+    // Since this is a state change, the entire output should now be dirty.
+    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+
+    // Non-identity matrix sets a non-identity state value
+    const mat4 nonIdentityQuarter = mat4() * 0.25;
+
+    mOutput.setColorTransform(nonIdentityQuarter);
+
+    EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
+    EXPECT_EQ(nonIdentityQuarter, mOutput.getState().colorTransformMat);
 
     // Since this is a state change, the entire output should now be dirty.
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 84af9b9..87419ea 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -22,11 +22,10 @@
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/Display.h>
 #include <compositionengine/mock/DisplaySurface.h>
+#include <compositionengine/mock/NativeWindow.h>
 #include <compositionengine/mock/OutputLayer.h>
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
-#include <system/window.h>
-#include <ui/ANativeObjectBase.h>
 
 #include "MockHWComposer.h"
 
@@ -34,123 +33,6 @@
 namespace {
 
 /* ------------------------------------------------------------------------
- * MockNativeWindow
- *
- * An intentionally simplified Mock which implements a minimal subset of the full
- * ANativeWindow interface.
- */
-
-class MockNativeWindow : public ANativeObjectBase<ANativeWindow, MockNativeWindow, RefBase> {
-public:
-    MockNativeWindow() {
-        ANativeWindow::setSwapInterval = &forwardSetSwapInterval;
-        ANativeWindow::dequeueBuffer = &forwardDequeueBuffer;
-        ANativeWindow::cancelBuffer = &forwardCancelBuffer;
-        ANativeWindow::queueBuffer = &forwardQueueBuffer;
-        ANativeWindow::query = &forwardQuery;
-        ANativeWindow::perform = &forwardPerform;
-
-        ANativeWindow::dequeueBuffer_DEPRECATED = &forwardDequeueBufferDeprecated;
-        ANativeWindow::cancelBuffer_DEPRECATED = &forwardCancelBufferDeprecated;
-        ANativeWindow::lockBuffer_DEPRECATED = &forwardLockBufferDeprecated;
-        ANativeWindow::queueBuffer_DEPRECATED = &forwardQueueBufferDeprecated;
-    }
-
-    MOCK_METHOD1(setSwapInterval, int(int));
-    MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
-    MOCK_METHOD2(cancelBuffer, int(struct ANativeWindowBuffer*, int));
-    MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));
-    MOCK_CONST_METHOD2(query, int(int, int*));
-    MOCK_METHOD1(connect, int(int));
-    MOCK_METHOD1(lockBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
-    MOCK_METHOD1(setBuffersFormat, int(PixelFormat));
-    MOCK_METHOD1(setBuffersDataSpace, int(ui::Dataspace));
-    MOCK_METHOD1(setUsage, int(uint64_t));
-
-    static void unexpectedCall(...) { LOG_ALWAYS_FATAL("Unexpected ANativeWindow API call"); }
-
-    static int forwardSetSwapInterval(ANativeWindow* window, int interval) {
-        return getSelf(window)->setSwapInterval(interval);
-    }
-
-    static int forwardDequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
-                                    int* fenceFd) {
-        return getSelf(window)->dequeueBuffer(buffer, fenceFd);
-    }
-
-    static int forwardCancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
-                                   int fenceFd) {
-        return getSelf(window)->cancelBuffer(buffer, fenceFd);
-    }
-
-    static int forwardQueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
-        return getSelf(window)->queueBuffer(buffer, fenceFd);
-    }
-
-    static int forwardQuery(const ANativeWindow* window, int what, int* value) {
-        return getSelf(window)->query(what, value);
-    }
-
-    static int forwardPerform(ANativeWindow* window, int operation, ...) {
-        va_list args;
-        va_start(args, operation);
-        int result = NO_ERROR;
-        switch (operation) {
-            case NATIVE_WINDOW_API_CONNECT: {
-                int api = va_arg(args, int);
-                result = getSelf(window)->connect(api);
-                break;
-            }
-            case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
-                PixelFormat format = va_arg(args, PixelFormat);
-                result = getSelf(window)->setBuffersFormat(format);
-                break;
-            }
-            case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: {
-                ui::Dataspace dataspace = static_cast<ui::Dataspace>(va_arg(args, int));
-                result = getSelf(window)->setBuffersDataSpace(dataspace);
-                break;
-            }
-            case NATIVE_WINDOW_SET_USAGE: {
-                // Note: Intentionally widens usage from 32 to 64 bits so we
-                // just have one implementation.
-                uint64_t usage = va_arg(args, uint32_t);
-                result = getSelf(window)->setUsage(usage);
-                break;
-            }
-            case NATIVE_WINDOW_SET_USAGE64: {
-                uint64_t usage = va_arg(args, uint64_t);
-                result = getSelf(window)->setUsage(usage);
-                break;
-            }
-            default:
-                LOG_ALWAYS_FATAL("Unexpected operation %d", operation);
-                break;
-        }
-
-        va_end(args);
-        return result;
-    }
-
-    static int forwardDequeueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer** buffer) {
-        int ignoredFenceFd = -1;
-        return getSelf(window)->dequeueBuffer(buffer, &ignoredFenceFd);
-    }
-
-    static int forwardCancelBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
-        return getSelf(window)->cancelBuffer(buffer, -1);
-    }
-
-    static int forwardLockBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
-        return getSelf(window)->lockBuffer_DEPRECATED(buffer);
-    }
-
-    static int forwardQueueBufferDeprecated(ANativeWindow* window, ANativeWindowBuffer* buffer) {
-        return getSelf(window)->queueBuffer(buffer, -1);
-    }
-};
-
-/* ------------------------------------------------------------------------
  * RenderSurfaceTest
  */
 
@@ -175,6 +57,8 @@
         EXPECT_CALL(mDisplay, getName()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_NAME));
         EXPECT_CALL(mCompositionEngine, getHwComposer).WillRepeatedly(ReturnRef(mHwComposer));
         EXPECT_CALL(mCompositionEngine, getRenderEngine).WillRepeatedly(ReturnRef(mRenderEngine));
+        EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL))
+                .WillRepeatedly(Return(NO_ERROR));
     }
     ~RenderSurfaceTest() override = default;
 
@@ -182,7 +66,7 @@
     StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     StrictMock<mock::Display> mDisplay;
-    sp<MockNativeWindow> mNativeWindow = new StrictMock<MockNativeWindow>();
+    sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
     sp<mock::DisplaySurface> mDisplaySurface = new StrictMock<mock::DisplaySurface>();
     impl::RenderSurface mSurface{mCompositionEngine, mDisplay,
                                  RenderSurfaceCreationArgs{DEFAULT_DISPLAY_WIDTH,
@@ -259,16 +143,40 @@
  */
 
 TEST_F(RenderSurfaceTest, setProtectedTrueEnablesProtection) {
+    EXPECT_FALSE(mSurface.isProtected());
     EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
             .WillOnce(Return(NO_ERROR));
 
     mSurface.setProtected(true);
+    EXPECT_TRUE(mSurface.isProtected());
 }
 
 TEST_F(RenderSurfaceTest, setProtectedFalseDisablesProtection) {
+    EXPECT_FALSE(mSurface.isProtected());
     EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR));
 
     mSurface.setProtected(false);
+    EXPECT_FALSE(mSurface.isProtected());
+}
+
+TEST_F(RenderSurfaceTest, setProtectedEnableAndDisable) {
+    EXPECT_FALSE(mSurface.isProtected());
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
+            .WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER)).WillOnce(Return(NO_ERROR));
+
+    mSurface.setProtected(true);
+    EXPECT_TRUE(mSurface.isProtected());
+    mSurface.setProtected(false);
+    EXPECT_FALSE(mSurface.isProtected());
+}
+
+TEST_F(RenderSurfaceTest, setProtectedEnableWithError) {
+    EXPECT_FALSE(mSurface.isProtected());
+    EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_PROTECTED))
+            .WillOnce(Return(INVALID_OPERATION));
+    mSurface.setProtected(true);
+    EXPECT_FALSE(mSurface.isProtected());
 }
 
 /* ------------------------------------------------------------------------
@@ -456,20 +364,6 @@
 }
 
 /* ------------------------------------------------------------------------
- * RenderSurface::setViewportAndProjection()
- */
-
-TEST_F(RenderSurfaceTest, setViewportAndProjectionAppliesChang) {
-    mSurface.setSizeForTest(ui::Size(100, 200));
-
-    EXPECT_CALL(mRenderEngine,
-                setViewportAndProjection(100, 200, Rect(100, 200), ui::Transform::ROT_0))
-            .Times(1);
-
-    mSurface.setViewportAndProjection();
-}
-
-/* ------------------------------------------------------------------------
  * RenderSurface::flip()
  */
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index c80925e..0067b50 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -288,16 +288,21 @@
     }
 
     Rect getSourceCrop() const override {
-        // use the (projected) logical display viewport by default
+        // use the projected display viewport by default.
         if (mSourceCrop.isEmpty()) {
             return mDevice->getScissor();
         }
 
-        const int orientation = mDevice->getInstallOrientation();
-        if (orientation == DisplayState::eOrientationDefault) {
-            return mSourceCrop;
-        }
+        // Recompute the device transformation for the source crop.
+        ui::Transform rotation;
+        ui::Transform translatePhysical;
+        ui::Transform translateLogical;
+        ui::Transform scale;
+        const Rect& viewport = mDevice->getViewport();
+        const Rect& scissor = mDevice->getScissor();
+        const Rect& frame = mDevice->getFrame();
 
+        const int orientation = mDevice->getInstallOrientation();
         // Install orientation is transparent to the callers.  Apply it now.
         uint32_t flags = 0x00;
         switch (orientation) {
@@ -310,10 +315,17 @@
             case DisplayState::eOrientation270:
                 flags = ui::Transform::ROT_270;
                 break;
+            default:
+                break;
         }
-        ui::Transform tr;
-        tr.set(flags, getWidth(), getHeight());
-        return tr.transform(mSourceCrop);
+        rotation.set(flags, getWidth(), getHeight());
+        translateLogical.set(-viewport.left, -viewport.top);
+        translatePhysical.set(scissor.left, scissor.top);
+        scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0,
+                  frame.getHeight() / float(viewport.getHeight()));
+        const ui::Transform finalTransform =
+                rotation * translatePhysical * scale * translateLogical;
+        return finalTransform.transform(mSourceCrop);
     }
 
 private:
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 9cb43bc..7f47a2e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -24,6 +24,7 @@
 
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <gui/BufferQueue.h>
+#include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlTransportUtils.h>
 
 namespace android {
@@ -229,6 +230,7 @@
 
 void Composer::registerCallback(const sp<IComposerCallback>& callback)
 {
+    android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
     auto ret = mClient->registerCallback(callback);
     if (!ret.isOk()) {
         ALOGE("failed to register IComposerCallback");
@@ -1158,23 +1160,6 @@
     return Error::NONE;
 }
 
-Error Composer::getDisplayBrightnessSupport(Display display, bool* outSupport) {
-    if (!mClient_2_3) {
-        return Error::UNSUPPORTED;
-    }
-    Error error = kDefaultError;
-    mClient_2_3->getDisplayBrightnessSupport(display,
-                                             [&](const auto& tmpError, const auto& tmpSupport) {
-                                                 error = tmpError;
-                                                 if (error != Error::NONE) {
-                                                     return;
-                                                 }
-
-                                                 *outSupport = tmpSupport;
-                                             });
-    return error;
-}
-
 Error Composer::setDisplayBrightness(Display display, float brightness) {
     if (!mClient_2_3) {
         return Error::UNSUPPORTED;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index e24db15..c4e952b 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -203,7 +203,6 @@
                                          std::vector<DisplayCapability>* outCapabilities) = 0;
     virtual Error setLayerPerFrameMetadataBlobs(
             Display display, Layer layer, const std::vector<PerFrameMetadataBlob>& metadata) = 0;
-    virtual Error getDisplayBrightnessSupport(Display display, bool* outSupport) = 0;
     virtual Error setDisplayBrightness(Display display, float brightness) = 0;
 };
 
@@ -416,7 +415,6 @@
     Error setLayerPerFrameMetadataBlobs(
             Display display, Layer layer,
             const std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override;
-    Error getDisplayBrightnessSupport(Display display, bool* outSupport) override;
     Error setDisplayBrightness(Display display, float brightness) override;
 
 private:
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 62073b6..c463c4e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -26,7 +26,6 @@
 #include <ui/Fence.h>
 #include <ui/FloatRect.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/Region.h>
 
 #include <android/configuration.h>
 
@@ -262,27 +261,6 @@
         mId(id),
         mIsConnected(false),
         mType(type) {
-    std::vector<Hwc2::DisplayCapability> tmpCapabilities;
-    auto error = static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
-    if (error == Error::None) {
-        for (auto capability : tmpCapabilities) {
-            mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
-        }
-    } else if (error == Error::Unsupported) {
-        if (capabilities.count(Capability::SkipClientColorTransform)) {
-            mDisplayCapabilities.emplace(DisplayCapability::SkipClientColorTransform);
-        }
-        bool dozeSupport = false;
-        error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
-        if (error == Error::None && dozeSupport) {
-            mDisplayCapabilities.emplace(DisplayCapability::Doze);
-        }
-        bool brightnessSupport = false;
-        error = static_cast<Error>(mComposer.getDisplayBrightnessSupport(mId, &brightnessSupport));
-        if (error == Error::None && brightnessSupport) {
-            mDisplayCapabilities.emplace(DisplayCapability::Brightness);
-        }
-    }
     ALOGV("Created display %" PRIu64, id);
 }
 
@@ -666,6 +644,29 @@
 {
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
     auto intError = mComposer.setPowerMode(mId, intMode);
+
+    if (mode == PowerMode::On) {
+        std::call_once(mDisplayCapabilityQueryFlag, [this]() {
+            std::vector<Hwc2::DisplayCapability> tmpCapabilities;
+            auto error =
+                    static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
+            if (error == Error::None) {
+                for (auto capability : tmpCapabilities) {
+                    mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
+                }
+            } else if (error == Error::Unsupported) {
+                if (mCapabilities.count(Capability::SkipClientColorTransform)) {
+                    mDisplayCapabilities.emplace(DisplayCapability::SkipClientColorTransform);
+                }
+                bool dozeSupport = false;
+                error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
+                if (error == Error::None && dozeSupport) {
+                    mDisplayCapabilities.emplace(DisplayCapability::Doze);
+                }
+            }
+        });
+    }
+
     return static_cast<Error>(intError);
 }
 
@@ -826,6 +827,11 @@
 Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
         const sp<Fence>& acquireFence)
 {
+    if (buffer == nullptr && mBufferSlot == slot) {
+        return Error::None;
+    }
+    mBufferSlot = slot;
+
     int32_t fenceFd = acquireFence->dup();
     auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer,
                                              fenceFd);
@@ -834,6 +840,12 @@
 
 Error Layer::setSurfaceDamage(const Region& damage)
 {
+    if (damage.isRect() && mDamageRegion.isRect() &&
+        (damage.getBounds() == mDamageRegion.getBounds())) {
+        return Error::None;
+    }
+    mDamageRegion = damage;
+
     // We encode default full-screen damage as INVALID_RECT upstream, but as 0
     // rects for HWC
     Hwc2::Error intError = Hwc2::Error::NONE;
@@ -988,6 +1000,12 @@
 
 Error Layer::setVisibleRegion(const Region& region)
 {
+    if (region.isRect() && mVisibleRegion.isRect() &&
+        (region.getBounds() == mVisibleRegion.getBounds())) {
+        return Error::None;
+    }
+    mVisibleRegion = region;
+
     size_t rectCount = 0;
     auto rectArray = region.getArray(&rectCount);
 
@@ -1018,9 +1036,13 @@
     if (matrix == mColorMatrix) {
         return Error::None;
     }
-    mColorMatrix = matrix;
     auto intError = mComposer.setLayerColorTransform(mDisplayId, mId, matrix.asArray());
-    return static_cast<Error>(intError);
+    Error error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+    mColorMatrix = matrix;
+    return error;
 }
 
 } // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4209e45..b7cdf7f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -27,6 +27,7 @@
 #include <math/mat4.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
+#include <ui/Region.h>
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
@@ -42,8 +43,6 @@
     class Fence;
     class FloatRect;
     class GraphicBuffer;
-    class Rect;
-    class Region;
     namespace Hwc2 {
         class Composer;
     }
@@ -357,6 +356,7 @@
     DisplayType mType;
     std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
+    std::once_flag mDisplayCapabilityQueryFlag;
     std::unordered_set<DisplayCapability> mDisplayCapabilities;
 };
 } // namespace impl
@@ -438,9 +438,15 @@
 
     hwc2_display_t mDisplayId;
     hwc2_layer_t mId;
+
+    // Cached HWC2 data, to ensure the same commands aren't sent to the HWC
+    // multiple times.
+    android::Region mVisibleRegion = android::Region::INVALID_REGION;
+    android::Region mDamageRegion = android::Region::INVALID_REGION;
     android::ui::Dataspace mDataSpace = android::ui::Dataspace::UNKNOWN;
     android::HdrMetadata mHdrMetadata;
     android::mat4 mColorMatrix;
+    uint32_t mBufferSlot;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7965245..26c61ba 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,12 +19,7 @@
 #define LOG_TAG "Layer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <math.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <algorithm>
-#include <mutex>
+#include "Layer.h"
 
 #include <android-base/stringprintf.h>
 #include <compositionengine/Display.h>
@@ -39,7 +34,11 @@
 #include <gui/BufferItem.h>
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
+#include <math.h>
 #include <renderengine/RenderEngine.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
@@ -49,12 +48,15 @@
 #include <utils/StopWatch.h>
 #include <utils/Trace.h>
 
+#include <algorithm>
+#include <mutex>
+#include <sstream>
+
 #include "BufferLayer.h"
 #include "ColorLayer.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWComposer.h"
-#include "Layer.h"
 #include "LayerProtoHelper.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
@@ -70,7 +72,10 @@
 std::atomic<int32_t> Layer::sSequence{1};
 
 Layer::Layer(const LayerCreationArgs& args)
-      : mFlinger(args.flinger), mName(args.name), mClientRef(args.client) {
+      : mFlinger(args.flinger),
+        mName(args.name),
+        mClientRef(args.client),
+        mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) {
     mCurrentCrop.makeInvalid();
 
     uint32_t layerFlags = 0;
@@ -115,6 +120,8 @@
     mFrameEventHistory.initializeCompositorTiming(compositorTiming);
     mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);
 
+    mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType);
+
     mFlinger->onLayerCreated();
 }
 
@@ -125,8 +132,7 @@
     }
 
     mFrameTracker.logAndResetStats(mName);
-
-    mFlinger->onLayerDestroyed();
+    mFlinger->onLayerDestroyed(this);
 }
 
 // ---------------------------------------------------------------------------
@@ -140,28 +146,47 @@
  */
 void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
 
-void Layer::onRemovedFromCurrentState() {
-    mRemovedFromCurrentState = true;
+void Layer::removeRemoteSyncPoints() {
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    mRemoteSyncPoints.clear();
 
-    // the layer is removed from SF mCurrentState to mLayersPendingRemoval
-    if (mCurrentState.zOrderRelativeOf != nullptr) {
-        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
-        if (strongRelative != nullptr) {
-            strongRelative->removeZOrderRelative(this);
-            mFlinger->setTransactionFlags(eTraversalNeeded);
+    {
+        Mutex::Autolock pendingStateLock(mPendingStateMutex);
+        for (State pendingState : mPendingStates) {
+            pendingState.barrierLayer_legacy = nullptr;
         }
+    }
+}
+
+void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
+    if (mCurrentState.zOrderRelativeOf == nullptr) {
+        return;
+    }
+
+    sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+    if (strongRelative == nullptr) {
+        setZOrderRelativeOf(nullptr);
+        return;
+    }
+
+    if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+        strongRelative->removeZOrderRelative(this);
+        mFlinger->setTransactionFlags(eTraversalNeeded);
         setZOrderRelativeOf(nullptr);
     }
+}
+
+void Layer::removeFromCurrentState() {
+    mRemovedFromCurrentState = true;
 
     // Since we are no longer reachable from CurrentState SurfaceFlinger
     // will no longer invoke doTransaction for us, and so we will
     // never finish applying transactions. We signal the sync point
     // now so that another layer will not become indefinitely
     // blocked.
-    for (auto& point: mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    mRemoteSyncPoints.clear();
+    removeRemoteSyncPoints();
 
     {
     Mutex::Autolock syncLock(mLocalSyncPointMutex);
@@ -171,13 +196,18 @@
     mLocalSyncPoints.clear();
     }
 
-    for (const auto& child : mCurrentChildren) {
-        child->onRemovedFromCurrentState();
-    }
-
     mFlinger->markLayerPendingRemovalLocked(this);
 }
 
+void Layer::onRemovedFromCurrentState() {
+    auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+    std::sort(layersInTree.begin(), layersInTree.end());
+    for (const auto& layer : layersInTree) {
+        layer->removeFromCurrentState();
+        layer->removeRelativeZ(layersInTree);
+    }
+}
+
 void Layer::addToCurrentState() {
     mRemovedFromCurrentState = false;
 
@@ -200,6 +230,11 @@
 
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
+    if (mGetHandleCalled) {
+        ALOGE("Get handle called twice" );
+        return nullptr;
+    }
+    mGetHandleCalled = true;
     return new Handle(mFlinger, this);
 }
 
@@ -377,13 +412,6 @@
     win.right -= roundedCornersCrop.left;
     win.top -= roundedCornersCrop.top;
     win.bottom -= roundedCornersCrop.top;
-
-    renderengine::Mesh::VertexArray<vec2> cropCoords(
-            getCompositionLayer()->editState().reMesh.getCropCoordArray<vec2>());
-    cropCoords[0] = vec2(win.left, win.top);
-    cropCoords[1] = vec2(win.left, win.top + win.getHeight());
-    cropCoords[2] = vec2(win.right, win.top + win.getHeight());
-    cropCoords[3] = vec2(win.right, win.top);
 }
 
 void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const {
@@ -402,7 +430,7 @@
         auto& parentState = parent->getDrawingState();
         const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
         const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0);
-        if (parentType >= 0 || parentAppId >= 0) {
+        if (parentType > 0 && parentAppId > 0) {
             type = parentType;
             appId = parentAppId;
         }
@@ -535,18 +563,6 @@
     return true;
 }
 
-void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
-                            float alpha) const {
-    auto& engine(mFlinger->getRenderEngine());
-    computeGeometry(renderArea, getCompositionLayer()->editState().reMesh, false);
-    engine.setupFillWithColor(red, green, blue, alpha);
-    engine.drawMesh(getCompositionLayer()->getState().reMesh);
-}
-
-void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
-    clearWithOpenGL(renderArea, 0, 0, 0, 0);
-}
-
 void Layer::setCompositionType(const sp<const DisplayDevice>& display,
                                Hwc2::IComposerClient::Composition type) {
     const auto outputLayer = findOutputLayerForDisplay(display);
@@ -603,32 +619,6 @@
 // local state
 // ----------------------------------------------------------------------------
 
-void Layer::computeGeometry(const RenderArea& renderArea,
-                            renderengine::Mesh& mesh,
-                            bool useIdentityTransform) const {
-    const ui::Transform renderAreaTransform(renderArea.getTransform());
-    FloatRect win = getBounds();
-
-    vec2 lt = vec2(win.left, win.top);
-    vec2 lb = vec2(win.left, win.bottom);
-    vec2 rb = vec2(win.right, win.bottom);
-    vec2 rt = vec2(win.right, win.top);
-
-    ui::Transform layerTransform = getTransform();
-    if (!useIdentityTransform) {
-        lt = layerTransform.transform(lt);
-        lb = layerTransform.transform(lb);
-        rb = layerTransform.transform(rb);
-        rt = layerTransform.transform(rt);
-    }
-
-    renderengine::Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    position[0] = renderAreaTransform.transform(lt);
-    position[1] = renderAreaTransform.transform(lb);
-    position[2] = renderAreaTransform.transform(rb);
-    position[3] = renderAreaTransform.transform(rt);
-}
-
 bool Layer::isSecure() const {
     const State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
@@ -663,6 +653,7 @@
     if (!mCurrentState.modified) {
         return;
     }
+    ATRACE_CALL();
 
     // If this transaction is waiting on the receipt of a frame, generate a sync
     // point and send it to the remote layer.
@@ -677,8 +668,11 @@
             // to be applied as per normal (no synchronization).
             mCurrentState.barrierLayer_legacy = nullptr;
         } else {
-            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
+            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this);
             if (barrierLayer->addSyncPoint(syncPoint)) {
+                std::stringstream ss;
+                ss << "Adding sync point " << mCurrentState.frameNumber_legacy;
+                ATRACE_NAME(ss.str().c_str());
                 mRemoteSyncPoints.push_back(std::move(syncPoint));
             } else {
                 // We already missed the frame we're supposed to synchronize
@@ -696,6 +690,7 @@
 }
 
 void Layer::popPendingState(State* stateToCommit) {
+    ATRACE_CALL();
     *stateToCommit = mPendingStates[0];
 
     mPendingStates.removeAt(0);
@@ -727,6 +722,7 @@
             }
 
             if (mRemoteSyncPoints.front()->frameIsAvailable()) {
+                ATRACE_NAME("frameIsAvailable");
                 // Apply the state update
                 popPendingState(stateToCommit);
                 stateUpdateAvailable = true;
@@ -735,6 +731,7 @@
                 mRemoteSyncPoints.front()->setTransactionApplied();
                 mRemoteSyncPoints.pop_front();
             } else {
+                ATRACE_NAME("!frameIsAvailable");
                 break;
             }
         } else {
@@ -1181,6 +1178,7 @@
 }
 
 void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
+    ATRACE_CALL();
     mCurrentState.barrierLayer_legacy = barrierLayer;
     mCurrentState.frameNumber_legacy = frameNumber;
     // We don't set eTransactionNeeded, because just receiving a deferral
@@ -1207,6 +1205,14 @@
     if (parent != nullptr && parent->isHiddenByPolicy()) {
         return true;
     }
+    if (usingRelativeZ(LayerVector::StateSet::Drawing)) {
+        auto zOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote();
+        if (zOrderRelativeOf != nullptr) {
+            if (zOrderRelativeOf->isHiddenByPolicy()) {
+                return true;
+            }
+        }
+    }
     return s.flags & layer_state_t::eLayerHidden;
 }
 
@@ -1225,10 +1231,8 @@
 
 void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
     uint32_t orientation = 0;
-    // Disable setting transform hint if the debug flag is set or if the
-    // getTransformToDisplayInverse flag is set and the client wants to submit buffers
-    // in one orientation.
-    if (!mFlinger->mDebugDisableTransformHint && !getTransformToDisplayInverse()) {
+    // Disable setting transform hint if the debug flag is set.
+    if (!mFlinger->mDebugDisableTransformHint) {
         // The transform hint is used to improve performance, but we can
         // only have a single transform hint, it cannot
         // apply to all displays.
@@ -1298,6 +1302,7 @@
     result.append("-----------------------------\n");
     result.append(" Layer name\n");
     result.append("           Z | ");
+    result.append(" Window Type | ");
     result.append(" Comp Type | ");
     result.append(" Transform | ");
     result.append("  Disp Frame (LTRB) | ");
@@ -1334,6 +1339,7 @@
     } else {
         StringAppendF(&result, "  %10d | ", layerState.z);
     }
+    StringAppendF(&result, "  %10d | ", mWindowType);
     StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
     StringAppendF(&result, "%10s | ",
                   toString(getCompositionLayer() ? compositionState.bufferTransform
@@ -1520,6 +1526,7 @@
         if (client != nullptr && parentClient != client) {
             child->mLayerDetached = true;
             child->detachChildren();
+            child->removeRemoteSyncPoints();
         }
     }
 
@@ -1587,7 +1594,7 @@
     return mDrawingState.z;
 }
 
-bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) {
+bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
     return state.zOrderRelativeOf != nullptr;
@@ -1804,7 +1811,9 @@
         }
     }
     const float radius = getDrawingState().cornerRadius;
-    return radius > 0 ? RoundedCornerState(getBounds(), radius) : RoundedCornerState();
+    return radius > 0 && getCrop(getDrawingState()).isValid()
+            ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius)
+            : RoundedCornerState();
 }
 
 void Layer::commitChildList() {
@@ -1891,6 +1900,7 @@
 
         layerInfo->set_is_opaque(isOpaque(state));
         layerInfo->set_invalidate(contentDirty);
+        layerInfo->set_is_protected(isProtected());
 
         // XXX (b/79210409) mCurrentDataSpace is not protected
         layerInfo->set_dataspace(
@@ -2001,6 +2011,13 @@
     return mRemovedFromCurrentState;
 }
 
+// Debug helper for b/137560795
+#define INT32_MIGHT_OVERFLOW(n) (((n) >= INT32_MAX / 2) || ((n) <= INT32_MIN / 2))
+
+#define RECT_BOUNDS_INVALID(rect)                                               \
+    (INT32_MIGHT_OVERFLOW((rect).left) || INT32_MIGHT_OVERFLOW((rect).right) || \
+     INT32_MIGHT_OVERFLOW((rect).bottom) || INT32_MIGHT_OVERFLOW((rect).top))
+
 InputWindowInfo Layer::fillInputInfo() {
     InputWindowInfo info = mDrawingState.inputInfo;
 
@@ -2011,10 +2028,14 @@
     ui::Transform t = getTransform();
     const float xScale = t.sx();
     const float yScale = t.sy();
+    float xSurfaceInset = info.surfaceInset;
+    float ySurfaceInset = info.surfaceInset;
     if (xScale != 1.0f || yScale != 1.0f) {
         info.windowXScale *= 1.0f / xScale;
         info.windowYScale *= 1.0f / yScale;
         info.touchableRegion.scaleSelf(xScale, yScale);
+        xSurfaceInset *= xScale;
+        ySurfaceInset *= yScale;
     }
 
     // Transform layer size to screen space and inset it by surface insets.
@@ -2026,7 +2047,27 @@
         layerBounds = getCroppedBufferSize(getDrawingState());
     }
     layerBounds = t.transform(layerBounds);
-    layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
+
+    // debug check for b/137560795
+    {
+        if (RECT_BOUNDS_INVALID(layerBounds)) {
+            ALOGE("layer %s bounds are invalid (%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32
+                  ")",
+                  mName.c_str(), layerBounds.left, layerBounds.top, layerBounds.right,
+                  layerBounds.bottom);
+            std::string out;
+            getTransform().dump(out, "Transform");
+            ALOGE("%s", out.c_str());
+            layerBounds.left = layerBounds.top = layerBounds.right = layerBounds.bottom = 0;
+        }
+
+        if (INT32_MIGHT_OVERFLOW(xSurfaceInset) || INT32_MIGHT_OVERFLOW(ySurfaceInset)) {
+            ALOGE("layer %s surface inset are invalid (%" PRIi32 ", %" PRIi32 ")", mName.c_str(),
+                  int32_t(xSurfaceInset), int32_t(ySurfaceInset));
+            xSurfaceInset = ySurfaceInset = 0;
+        }
+    }
+    layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
 
     // Input coordinate should match the layer bounds.
     info.frameLeft = layerBounds.left;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8348ce1..b693a47 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_LAYER_H
 #define ANDROID_LAYER_H
 
-#include <sys/types.h>
-
 #include <compositionengine/LayerFE.h>
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -28,6 +26,7 @@
 #include <math/vec4.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
+#include <sys/types.h>
 #include <ui/FloatRect.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
@@ -44,16 +43,16 @@
 #include <vector>
 
 #include "Client.h"
+#include "ClientCache.h"
+#include "DisplayHardware/ComposerHal.h"
+#include "DisplayHardware/HWComposer.h"
 #include "FrameTracker.h"
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
+#include "RenderArea.h"
 #include "SurfaceFlinger.h"
 #include "TransactionCompletedThread.h"
 
-#include "DisplayHardware/ComposerHal.h"
-#include "DisplayHardware/HWComposer.h"
-#include "RenderArea.h"
-
 using namespace android::surfaceflinger;
 
 namespace android {
@@ -94,7 +93,7 @@
     LayerMetadata metadata;
 };
 
-class Layer : public virtual compositionengine::LayerFE {
+class Layer : public virtual compositionengine::LayerFE, public ClientCache::ErasedRecipient {
     static std::atomic<int32_t> sSequence;
 
 public:
@@ -199,6 +198,7 @@
         Region transparentRegionHint;
 
         sp<GraphicBuffer> buffer;
+        client_cache_t clientCacheId;
         sp<Fence> acquireFence;
         HdrMetadata hdrMetadata;
         Region surfaceDamageRegion;
@@ -311,7 +311,11 @@
     virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
     virtual bool setCrop(const Rect& /*crop*/) { return false; };
     virtual bool setFrame(const Rect& /*frame*/) { return false; };
-    virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) { return false; };
+    virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, nsecs_t /*postTime*/,
+                           nsecs_t /*desiredPresentTime*/,
+                           const client_cache_t& /*clientCacheId*/) {
+        return false;
+    };
     virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
     virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
     virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
@@ -353,8 +357,6 @@
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
-    void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
-                         bool useIdentityTransform) const;
     FloatRect getBounds(const Region& activeTransparentRegion) const;
     FloatRect getBounds() const;
 
@@ -450,9 +452,6 @@
     }
     virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
 
-    virtual void setPostTime(nsecs_t /*postTime*/) {}
-    virtual void setDesiredPresentTime(nsecs_t /*desiredPresentTime*/) {}
-
 protected:
     virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
                                     bool useIdentityTransform, Region& clearRegion,
@@ -569,6 +568,17 @@
     virtual bool isBufferLatched() const { return false; }
 
     /*
+     * Remove relative z for the layer if its relative parent is not part of the
+     * provided layer tree.
+     */
+    void removeRelativeZ(const std::vector<Layer*>& layersInTree);
+
+    /*
+     * Remove from current state and mark for removal.
+     */
+    void removeFromCurrentState();
+
+    /*
      * called with the state lock from a binder thread when the layer is
      * removed from the current list to the pending removal list
      */
@@ -601,9 +611,6 @@
     bool hasHwcLayer(const sp<const DisplayDevice>& displayDevice);
     HWC2::Layer* getHwcLayer(const sp<const DisplayDevice>& displayDevice);
 
-    // -----------------------------------------------------------------------
-    void clearWithOpenGL(const RenderArea& renderArea) const;
-
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
     inline State& getCurrentState() { return mCurrentState; }
@@ -691,6 +698,9 @@
     compositionengine::OutputLayer* findOutputLayerForDisplay(
             const sp<const DisplayDevice>& display) const;
 
+    // Inherit from ClientCache::ErasedRecipient
+    void bufferErased(const client_cache_t& /*clientCacheId*/) override {}
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -727,20 +737,18 @@
      * crop coordinates, transforming them into layer space.
      */
     void setupRoundedCornersCropCoordinates(Rect win, const FloatRect& roundedCornersCrop) const;
-
-    // drawing
-    void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
-                         float alpha) const;
     void setParent(const sp<Layer>& layer);
-
     LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers);
     void addZOrderRelative(const wp<Layer>& relative);
     void removeZOrderRelative(const wp<Layer>& relative);
 
     class SyncPoint {
     public:
-        explicit SyncPoint(uint64_t frameNumber)
-              : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+        explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer)
+              : mFrameNumber(frameNumber),
+                mFrameIsAvailable(false),
+                mTransactionIsApplied(false),
+                mRequestedSyncLayer(requestedSyncLayer) {}
 
         uint64_t getFrameNumber() const { return mFrameNumber; }
 
@@ -752,10 +760,13 @@
 
         void setTransactionApplied() { mTransactionIsApplied = true; }
 
+        sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
+
     private:
         const uint64_t mFrameNumber;
         std::atomic<bool> mFrameIsAvailable;
         std::atomic<bool> mTransactionIsApplied;
+        wp<Layer> mRequestedSyncLayer;
     };
 
     // SyncPoints which will be signaled when the correct frame is at the head
@@ -797,6 +808,8 @@
         wp<Layer> owner;
     };
 
+    // Creates a new handle each time, so we only expect
+    // this to be called once.
     sp<IBinder> getHandle();
     const String8& getName() const;
     virtual void notifyAvailableFrames() {}
@@ -811,7 +824,7 @@
 
 protected:
     // -----------------------------------------------------------------------
-    bool usingRelativeZ(LayerVector::StateSet stateSet);
+    bool usingRelativeZ(LayerVector::StateSet stateSet) const;
 
     bool mPremultipliedAlpha{true};
     String8 mName;
@@ -885,6 +898,12 @@
     // Can only be accessed with the SF state lock held.
     bool mChildrenChanged{false};
 
+    // Window types from WindowManager.LayoutParams
+    const int mWindowType;
+
+    // This is populated if the layer is registered with Scheduler for tracking purposes.
+    std::unique_ptr<scheduler::LayerHistory::LayerHandle> mSchedulerLayerHandle;
+
 private:
     /**
      * Returns an unsorted vector of all layers that are part of this tree.
@@ -924,6 +943,10 @@
     FloatRect mScreenBounds;
 
     void setZOrderRelativeOf(const wp<Layer>& relativeOf);
+
+    bool mGetHandleCalled = false;
+
+    void removeRemoteSyncPoints();
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 06e3d9c..7a959f7 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -132,6 +132,10 @@
     return mProducer->setDequeueTimeout(timeout);
 }
 
+status_t MonitoredProducer::setLegacyBufferDrop(bool drop) {
+    return mProducer->setLegacyBufferDrop(drop);
+}
+
 status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
         sp<Fence>* outFence, float outTransformMatrix[16]) {
     return mProducer->getLastQueuedBuffer(outBuffer, outFence,
@@ -150,6 +154,10 @@
     return mProducer->getConsumerUsage(outUsage);
 }
 
+status_t MonitoredProducer::setAutoPrerotation(bool autoPrerotation) {
+    return mProducer->setAutoPrerotation(autoPrerotation);
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return this;
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 1246d14..788919b 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -61,6 +61,7 @@
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
     virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+    virtual status_t setLegacyBufferDrop(bool drop) override;
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual IBinder* onAsBinder();
@@ -69,6 +70,7 @@
     virtual void getFrameTimestamps(FrameEventHistoryDelta *outDelta) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
     virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
+    virtual status_t setAutoPrerotation(bool autoPrerotation) override;
 
     // The Layer which created this producer, and on which queued Buffer's will be displayed.
     sp<Layer> getLayer() const;
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index ce0611c..69d8c89 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -1,4 +1,6 @@
+adyabr@google.com
 akrulec@google.com
+alecmouri@google.com
 chaviw@google.com
 lpy@google.com
 marissaw@google.com
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index e70bfe4..5b4bec9 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -31,15 +31,22 @@
     const status_t ret =
             mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
                                  PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
-                                 LayerMetadata(), &mIBinder, &mGbp, &mLayer);
+                                 LayerMetadata(), &mIBinder, &mGbp, nullptr);
     if (ret) {
-        ALOGE("failed to color layer");
+        ALOGE("failed to create color layer");
         return false;
     }
 
+    Mutex::Autolock _l(mFlinger.mStateLock);
     mLayer = mClient->getLayerUser(mIBinder);
-    mLayer->setCrop_legacy(Rect(0, 0, 200, 100), true);
-    mLayer->setLayer(INT32_MAX - 2);
+    mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true);
+
+    // setting Layer's Z requires resorting layersSortedByZ
+    ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
+    if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) {
+        mFlinger.mCurrentState.layersSortedByZ.removeAt(idx);
+        mFlinger.mCurrentState.layersSortedByZ.add(mLayer);
+    }
 
     return true;
 }
@@ -47,7 +54,7 @@
 void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) {
     const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED;
     mLayer->setColor(color);
-    mFlinger.setTransactionFlags(eTransactionMask);
+    mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
 }
 
 }; // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 718e996..07fdead 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -26,6 +26,8 @@
 #include <utils/Trace.h>
 #include <string>
 
+#include <compositionengine/Display.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include "DisplayDevice.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
@@ -42,11 +44,14 @@
 enum class samplingStep {
     noWorkNeeded,
     idleTimerWaiting,
+    waitForQuietFrame,
     waitForZeroPhase,
     waitForSamplePhase,
     sample
 };
 
+constexpr auto timeForRegionSampling = 5000000ns;
+constexpr auto maxRegionSamplingSkips = 10;
 constexpr auto defaultRegionSamplingOffset = -3ms;
 constexpr auto defaultRegionSamplingPeriod = 100ms;
 constexpr auto defaultRegionSamplingTimerTimeout = 100ms;
@@ -168,11 +173,8 @@
         mPhaseCallback(std::make_unique<SamplingOffsetCallback>(*this, mScheduler,
                                                                 tunables.mSamplingOffset)),
         lastSampleTime(0ns) {
-    {
-        std::lock_guard threadLock(mThreadMutex);
-        mThread = std::thread([this]() { threadMain(); });
-        pthread_setname_np(mThread.native_handle(), "RegionSamplingThread");
-    }
+    mThread = std::thread([this]() { threadMain(); });
+    pthread_setname_np(mThread.native_handle(), "RegionSamplingThread");
     mIdleTimer.start();
 }
 
@@ -186,12 +188,11 @@
     mIdleTimer.stop();
 
     {
-        std::lock_guard lock(mMutex);
+        std::lock_guard lock(mThreadControlMutex);
         mRunning = false;
         mCondition.notify_one();
     }
 
-    std::lock_guard threadLock(mThreadMutex);
     if (mThread.joinable()) {
         mThread.join();
     }
@@ -205,21 +206,21 @@
 
     sp<IBinder> asBinder = IInterface::asBinder(listener);
     asBinder->linkToDeath(this);
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.emplace(wp<IBinder>(asBinder), Descriptor{samplingArea, stopLayer, listener});
 }
 
 void RegionSamplingThread::removeListener(const sp<IRegionSamplingListener>& listener) {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.erase(wp<IBinder>(IInterface::asBinder(listener)));
 }
 
 void RegionSamplingThread::checkForStaleLuma() {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mThreadControlMutex);
 
-    if (mDiscardedFrames) {
+    if (mDiscardedFrames > 0) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForZeroPhase));
-        mDiscardedFrames = false;
+        mDiscardedFrames = 0;
         mPhaseCallback->startVsyncListener();
     }
 }
@@ -233,17 +234,29 @@
 }
 
 void RegionSamplingThread::doSample() {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mThreadControlMutex);
     auto now = std::chrono::nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     if (lastSampleTime + mTunables.mSamplingPeriod > now) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::idleTimerWaiting));
-        mDiscardedFrames = true;
+        if (mDiscardedFrames == 0) mDiscardedFrames++;
         return;
     }
+    if (mDiscardedFrames < maxRegionSamplingSkips) {
+        // If there is relatively little time left for surfaceflinger
+        // until the next vsync deadline, defer this sampling work
+        // to a later frame, when hopefully there will be more time.
+        DisplayStatInfo stats;
+        mScheduler.getDisplayStatInfo(&stats);
+        if (std::chrono::nanoseconds(stats.vsyncTime) - now < timeForRegionSampling) {
+            ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForQuietFrame));
+            mDiscardedFrames++;
+            return;
+        }
+    }
 
     ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::sample));
 
-    mDiscardedFrames = false;
+    mDiscardedFrames = 0;
     lastSampleTime = now;
 
     mIdleTimer.reset();
@@ -254,20 +267,40 @@
 }
 
 void RegionSamplingThread::binderDied(const wp<IBinder>& who) {
-    std::lock_guard lock(mMutex);
+    std::lock_guard lock(mSamplingMutex);
     mDescriptors.erase(who);
 }
 
 namespace {
 // Using Rec. 709 primaries
-float getLuma(float r, float g, float b) {
+inline float getLuma(float r, float g, float b) {
     constexpr auto rec709_red_primary = 0.2126f;
     constexpr auto rec709_green_primary = 0.7152f;
     constexpr auto rec709_blue_primary = 0.0722f;
     return rec709_red_primary * r + rec709_green_primary * g + rec709_blue_primary * b;
 }
+} // anonymous namespace
 
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+                 uint32_t orientation, const Rect& sample_area) {
+    if (!sample_area.isValid() || (sample_area.getWidth() > width) ||
+        (sample_area.getHeight() > height)) {
+        ALOGE("invalid sampling region requested");
+        return 0.0f;
+    }
+
+    // (b/133849373) ROT_90 screencap images produced upside down
+    auto area = sample_area;
+    if (orientation & ui::Transform::ROT_90) {
+        area.top = height - area.top;
+        area.bottom = height - area.bottom;
+        std::swap(area.top, area.bottom);
+
+        area.left = width - area.left;
+        area.right = width - area.right;
+        std::swap(area.left, area.right);
+    }
+
     std::array<int32_t, 256> brightnessBuckets = {};
     const int32_t majoritySampleNum = area.getWidth() * area.getHeight() / 2;
 
@@ -275,10 +308,10 @@
         const uint32_t* rowBase = data + row * stride;
         for (int32_t column = area.left; column < area.right; ++column) {
             uint32_t pixel = rowBase[column];
-            const float r = (pixel & 0xFF) / 255.0f;
-            const float g = ((pixel >> 8) & 0xFF) / 255.0f;
-            const float b = ((pixel >> 16) & 0xFF) / 255.0f;
-            const uint8_t luma = std::round(getLuma(r, g, b) * 255.0f);
+            const float r = pixel & 0xFF;
+            const float g = (pixel >> 8) & 0xFF;
+            const float b = (pixel >> 16) & 0xFF;
+            const uint8_t luma = std::round(getLuma(r, g, b));
             ++brightnessBuckets[luma];
             if (brightnessBuckets[luma] > majoritySampleNum) return luma / 255.0f;
         }
@@ -286,40 +319,58 @@
 
     int32_t accumulated = 0;
     size_t bucket = 0;
-    while (bucket++ < brightnessBuckets.size()) {
+    for (; bucket < brightnessBuckets.size(); bucket++) {
         accumulated += brightnessBuckets[bucket];
         if (accumulated > majoritySampleNum) break;
     }
 
     return bucket / 255.0f;
 }
-} // anonymous namespace
 
 std::vector<float> RegionSamplingThread::sampleBuffer(
         const sp<GraphicBuffer>& buffer, const Point& leftTop,
-        const std::vector<RegionSamplingThread::Descriptor>& descriptors) {
+        const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation) {
     void* data_raw = nullptr;
     buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &data_raw);
     std::shared_ptr<uint32_t> data(reinterpret_cast<uint32_t*>(data_raw),
                                    [&buffer](auto) { buffer->unlock(); });
     if (!data) return {};
 
+    const int32_t width = buffer->getWidth();
+    const int32_t height = buffer->getHeight();
     const int32_t stride = buffer->getStride();
     std::vector<float> lumas(descriptors.size());
     std::transform(descriptors.begin(), descriptors.end(), lumas.begin(),
                    [&](auto const& descriptor) {
-                       return sampleArea(data.get(), stride, descriptor.area - leftTop);
+                       return sampleArea(data.get(), width, height, stride, orientation,
+                                         descriptor.area - leftTop);
                    });
     return lumas;
 }
 
 void RegionSamplingThread::captureSample() {
     ATRACE_CALL();
+    std::lock_guard lock(mSamplingMutex);
 
     if (mDescriptors.empty()) {
         return;
     }
 
+    const auto device = mFlinger.getDefaultDisplayDevice();
+    const auto orientation = [](uint32_t orientation) {
+        switch (orientation) {
+            default:
+            case DisplayState::eOrientationDefault:
+                return ui::Transform::ROT_0;
+            case DisplayState::eOrientation90:
+                return ui::Transform::ROT_90;
+            case DisplayState::eOrientation180:
+                return ui::Transform::ROT_180;
+            case DisplayState::eOrientation270:
+                return ui::Transform::ROT_270;
+        }
+    }(device->getOrientation());
+
     std::vector<RegionSamplingThread::Descriptor> descriptors;
     Region sampleRegion;
     for (const auto& [listener, descriptor] : mDescriptors) {
@@ -329,10 +380,28 @@
 
     const Rect sampledArea = sampleRegion.bounds();
 
-    sp<const DisplayDevice> device = mFlinger.getDefaultDisplayDevice();
-    DisplayRenderArea renderArea(device, sampledArea, sampledArea.getWidth(),
-                                 sampledArea.getHeight(), ui::Dataspace::V0_SRGB,
-                                 ui::Transform::ROT_0);
+    auto dx = 0;
+    auto dy = 0;
+    switch (orientation) {
+        case ui::Transform::ROT_90:
+            dx = device->getWidth();
+            break;
+        case ui::Transform::ROT_180:
+            dx = device->getWidth();
+            dy = device->getHeight();
+            break;
+        case ui::Transform::ROT_270:
+            dy = device->getHeight();
+            break;
+        default:
+            break;
+    }
+
+    ui::Transform t(orientation);
+    auto screencapRegion = t.transform(sampleRegion);
+    screencapRegion = screencapRegion.translate(dx, dy);
+    DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(),
+                                 sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation);
 
     std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
 
@@ -377,23 +446,18 @@
         mFlinger.traverseLayersInDisplay(device, filterVisitor);
     };
 
-    const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
-    sp<GraphicBuffer> buffer =
-            new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(),
-                              PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+    sp<GraphicBuffer> buffer = nullptr;
+    if (mCachedBuffer && mCachedBuffer->getWidth() == sampledArea.getWidth() &&
+        mCachedBuffer->getHeight() == sampledArea.getHeight()) {
+        buffer = mCachedBuffer;
+    } else {
+        const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
+        buffer = new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(),
+                                   PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+    }
 
-    // When calling into SF, we post a message into the SF message queue (so the
-    // screen capture runs on the main thread). This message blocks until the
-    // screenshot is actually captured, but before the capture occurs, the main
-    // thread may perform a normal refresh cycle. At the end of this cycle, it
-    // can request another sample (because layers changed), which triggers a
-    // call into sampleNow. When sampleNow attempts to grab the mutex, we can
-    // deadlock.
-    //
-    // To avoid this, we drop the mutex while we call into SF.
-    mMutex.unlock();
-    mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false);
-    mMutex.lock();
+    bool ignored;
+    mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false, ignored);
 
     std::vector<Descriptor> activeDescriptors;
     for (const auto& descriptor : descriptors) {
@@ -403,8 +467,8 @@
     }
 
     ALOGV("Sampling %zu descriptors", activeDescriptors.size());
-    std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors);
-
+    std::vector<float> lumas =
+            sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation);
     if (lumas.size() != activeDescriptors.size()) {
         ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(),
               activeDescriptors.size());
@@ -414,18 +478,28 @@
     for (size_t d = 0; d < activeDescriptors.size(); ++d) {
         activeDescriptors[d].listener->onSampleCollected(lumas[d]);
     }
+
+    // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that:
+    // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer
+    // happens in this thread, as opposed to the main thread.
+    // 2) The listener(s) receive their notifications prior to freeing the buffer.
+    mCachedBuffer = buffer;
     ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::noWorkNeeded));
 }
 
-void RegionSamplingThread::threadMain() {
-    std::lock_guard lock(mMutex);
+// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
+void RegionSamplingThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
+    std::unique_lock<std::mutex> lock(mThreadControlMutex);
     while (mRunning) {
         if (mSampleRequested) {
             mSampleRequested = false;
+            lock.unlock();
             captureSample();
+            lock.lock();
         }
-        mCondition.wait(mMutex,
-                        [this]() REQUIRES(mMutex) { return mSampleRequested || !mRunning; });
+        mCondition.wait(lock, [this]() REQUIRES(mThreadControlMutex) {
+            return mSampleRequested || !mRunning;
+        });
     }
 }
 
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index d4e57bf..99c07c2 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -24,19 +24,22 @@
 
 #include <android-base/thread_annotations.h>
 #include <binder/IBinder.h>
+#include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/StrongPointer.h>
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 namespace android {
 
-class GraphicBuffer;
 class IRegionSamplingListener;
 class Layer;
 class Scheduler;
 class SurfaceFlinger;
 struct SamplingOffsetCallback;
 
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+                 uint32_t orientation, const Rect& area);
+
 class RegionSamplingThread : public IBinder::DeathRecipient {
 public:
     struct TimingTunables {
@@ -92,33 +95,34 @@
     };
     std::vector<float> sampleBuffer(
             const sp<GraphicBuffer>& buffer, const Point& leftTop,
-            const std::vector<RegionSamplingThread::Descriptor>& descriptors);
+            const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation);
 
     void doSample();
     void binderDied(const wp<IBinder>& who) override;
     void checkForStaleLuma();
 
-    void captureSample() REQUIRES(mMutex);
+    void captureSample();
     void threadMain();
 
     SurfaceFlinger& mFlinger;
     Scheduler& mScheduler;
     const TimingTunables mTunables;
-    scheduler::IdleTimer mIdleTimer;
+    scheduler::OneShotTimer mIdleTimer;
 
     std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback;
 
-    std::mutex mThreadMutex;
-    std::thread mThread GUARDED_BY(mThreadMutex);
+    std::thread mThread;
 
-    std::mutex mMutex;
+    std::mutex mThreadControlMutex;
     std::condition_variable_any mCondition;
-    bool mRunning GUARDED_BY(mMutex) = true;
-    bool mSampleRequested GUARDED_BY(mMutex) = false;
+    bool mRunning GUARDED_BY(mThreadControlMutex) = true;
+    bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false;
+    uint32_t mDiscardedFrames GUARDED_BY(mThreadControlMutex) = 0;
+    std::chrono::nanoseconds lastSampleTime GUARDED_BY(mThreadControlMutex);
 
-    std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mMutex);
-    std::chrono::nanoseconds lastSampleTime GUARDED_BY(mMutex);
-    bool mDiscardedFrames GUARDED_BY(mMutex) = false;
+    std::mutex mSamplingMutex;
+    std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex);
+    sp<GraphicBuffer> mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index f72aef1..0c94052 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -64,6 +64,7 @@
     DispSyncThread(const char* name, bool showTraceDetailedInfo)
           : mName(name),
             mStop(false),
+            mModelLocked(false),
             mPeriod(0),
             mPhase(0),
             mReferenceTime(0),
@@ -78,6 +79,7 @@
         Mutex::Autolock lock(mMutex);
 
         mPhase = phase;
+        const bool referenceTimeChanged = mReferenceTime != referenceTime;
         mReferenceTime = referenceTime;
         if (mPeriod != 0 && mPeriod != period && mReferenceTime != 0) {
             // Inflate the reference time to be the most recent predicted
@@ -88,6 +90,16 @@
             mReferenceTime = mReferenceTime + (numOldPeriods)*mPeriod;
         }
         mPeriod = period;
+        if (!mModelLocked && referenceTimeChanged) {
+            for (auto& eventListener : mEventListeners) {
+                eventListener.mLastEventTime = mReferenceTime + mPhase + eventListener.mPhase;
+                // If mLastEventTime is after mReferenceTime (can happen when positive phase offsets
+                // are used) we treat it as like it happened in previous period.
+                if (eventListener.mLastEventTime > mReferenceTime) {
+                    eventListener.mLastEventTime -= mPeriod;
+                }
+            }
+        }
         if (mTraceDetailedInfo) {
             ATRACE_INT64("DispSync:Period", mPeriod);
             ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
@@ -106,6 +118,18 @@
         mCond.signal();
     }
 
+    void lockModel() {
+        Mutex::Autolock lock(mMutex);
+        mModelLocked = true;
+        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
+    }
+
+    void unlockModel() {
+        Mutex::Autolock lock(mMutex);
+        mModelLocked = false;
+        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
+    }
+
     virtual bool threadLoop() {
         status_t err;
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -211,14 +235,13 @@
             const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
             const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
             const nsecs_t phaseCorrection = mPhase + listener.mPhase;
-            listener.mLastEventTime = predictedReference + phaseCorrection;
-            // If we're very close in time to the predicted last event time,
-            // then we need to back up the last event time so that we can
-            // attempt to fire an event immediately.
-            //
-            // Otherwise, keep the last event time that we predicted.
-            if (isShorterThanPeriod(now - listener.mLastEventTime)) {
-                listener.mLastEventTime -= mPeriod;
+            const nsecs_t predictedLastEventTime = predictedReference + phaseCorrection;
+            if (predictedLastEventTime >= now) {
+                // Make sure that the last event time does not exceed the current time.
+                // If it would, then back the last event time by a period.
+                listener.mLastEventTime = predictedLastEventTime - mPeriod;
+            } else {
+                listener.mLastEventTime = predictedLastEventTime;
             }
         } else {
             listener.mLastEventTime = now + mPhase - mWakeupLatency;
@@ -269,17 +292,12 @@
                 // new offset to allow for a seamless offset change without double-firing or
                 // skipping.
                 nsecs_t diff = oldPhase - phase;
-                if (diff > mPeriod / 2) {
-                    diff -= mPeriod;
-                } else if (diff < -mPeriod / 2) {
-                    diff += mPeriod;
-                }
                 eventListener.mLastEventTime -= diff;
+                eventListener.mLastCallbackTime -= diff;
                 mCond.signal();
                 return NO_ERROR;
             }
         }
-
         return BAD_VALUE;
     }
 
@@ -315,7 +333,7 @@
 
     // Sanity check that the duration is close enough in length to a period without
     // falling into double-rate vsyncs.
-    bool isShorterThanPeriod(nsecs_t duration) {
+    bool isCloseToPeriod(nsecs_t duration) {
         // Ratio of 3/5 is arbitrary, but it must be greater than 1/2.
         return duration < (3 * mPeriod) / 5;
     }
@@ -331,12 +349,13 @@
             nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo);
 
             if (t < now) {
-                if (isShorterThanPeriod(now - eventListener.mLastCallbackTime)) {
+                if (isCloseToPeriod(now - eventListener.mLastCallbackTime)) {
                     eventListener.mLastEventTime = t;
                     ALOGV("[%s] [%s] Skipping event due to model error", mName,
                           eventListener.mName);
                     continue;
                 }
+
                 CallbackInvocation ci;
                 ci.mCallback = eventListener.mCallback;
                 ci.mEventTime = t;
@@ -391,7 +410,7 @@
 
         // Check that it's been slightly more than half a period since the last
         // event so that we don't accidentally fall into double-rate vsyncs
-        if (isShorterThanPeriod(t - listener.mLastEventTime)) {
+        if (isCloseToPeriod(t - listener.mLastEventTime)) {
             t += mPeriod;
             ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
         }
@@ -412,6 +431,7 @@
     const char* const mName;
 
     bool mStop;
+    bool mModelLocked;
 
     nsecs_t mPeriod;
     nsecs_t mPhase;
@@ -470,7 +490,6 @@
         ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
     }
 
-    reset();
     beginResync();
 
     if (mTraceDetailedInfo && kEnableZeroPhaseTracer) {
@@ -499,6 +518,7 @@
     mNumResyncSamples = 0;
     mFirstResyncSample = 0;
     mNumResyncSamplesSincePresent = 0;
+    mThread->unlockModel();
     resetErrorLocked();
 }
 
@@ -521,25 +541,47 @@
 void DispSync::beginResync() {
     Mutex::Autolock lock(mMutex);
     ALOGV("[%s] beginResync", mName);
-    mModelUpdated = false;
-    mNumResyncSamples = 0;
+    resetLocked();
 }
 
-bool DispSync::addResyncSample(nsecs_t timestamp) {
+bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodFlushed) {
     Mutex::Autolock lock(mMutex);
 
     ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
 
-    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
+    *periodFlushed = false;
+    const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
     mResyncSamples[idx] = timestamp;
     if (mNumResyncSamples == 0) {
         mPhase = 0;
-        mReferenceTime = timestamp;
         ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
               "mReferenceTime = %" PRId64,
-              mName, ns2us(mPeriod), ns2us(mReferenceTime));
-        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+              mName, ns2us(mPeriod), ns2us(timestamp));
+    } else if (mPendingPeriod > 0) {
+        // mNumResyncSamples > 0, so priorIdx won't overflow
+        const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES;
+        const nsecs_t lastTimestamp = mResyncSamples[priorIdx];
+
+        const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp);
+        if (std::abs(observedVsync - mPendingPeriod) <= std::abs(observedVsync - mIntendedPeriod)) {
+            // Either the observed vsync is closer to the pending period, (and
+            // thus we detected a period change), or the period change will
+            // no-op. In either case, reset the model and flush the pending
+            // period.
+            resetLocked();
+            mIntendedPeriod = mPendingPeriod;
+            mPeriod = mPendingPeriod;
+            mPendingPeriod = 0;
+            if (mTraceDetailedInfo) {
+                ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+                ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
+            }
+            *periodFlushed = true;
+        }
     }
+    // Always update the reference time with the most recent timestamp.
+    mReferenceTime = timestamp;
+    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
 
     if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
         mNumResyncSamples++;
@@ -562,12 +604,18 @@
 
     // Check against kErrorThreshold / 2 to add some hysteresis before having to
     // resync again
-    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;
     ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
+    if (modelLocked) {
+        *periodFlushed = true;
+        mThread->lockModel();
+    }
     return !modelLocked;
 }
 
-void DispSync::endResync() {}
+void DispSync::endResync() {
+    mThread->lockModel();
+}
 
 status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback,
                                     nsecs_t lastCallbackTime) {
@@ -594,9 +642,17 @@
 
 void DispSync::setPeriod(nsecs_t period) {
     Mutex::Autolock lock(mMutex);
-    mPeriod = period;
-    mPhase = 0;
-    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+
+    const bool pendingPeriodShouldChange =
+            period != mIntendedPeriod || (period == mIntendedPeriod && mPendingPeriod != 0);
+
+    if (pendingPeriodShouldChange) {
+        mPendingPeriod = period;
+    }
+    if (mTraceDetailedInfo) {
+        ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
+        ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+    }
 }
 
 nsecs_t DispSync::getPeriod() {
@@ -612,7 +668,13 @@
         nsecs_t durationSum = 0;
         nsecs_t minDuration = INT64_MAX;
         nsecs_t maxDuration = 0;
-        for (size_t i = 1; i < mNumResyncSamples; i++) {
+        // We skip the first 2 samples because the first vsync duration on some
+        // devices may be much more inaccurate than on other devices, e.g. due
+        // to delays in ramping up from a power collapse. By doing so this
+        // actually increases the accuracy of the DispSync model even though
+        // we're effectively relying on fewer sample points.
+        static constexpr size_t numSamplesSkipped = 2;
+        for (size_t i = numSamplesSkipped; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
             size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
             nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
@@ -623,15 +685,14 @@
 
         // Exclude the min and max from the average
         durationSum -= minDuration + maxDuration;
-        mPeriod = durationSum / (mNumResyncSamples - 3);
+        mPeriod = durationSum / (mNumResyncSamples - numSamplesSkipped - 2);
 
         ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
 
         double sampleAvgX = 0;
         double sampleAvgY = 0;
         double scale = 2.0 * M_PI / double(mPeriod);
-        // Intentionally skip the first sample
-        for (size_t i = 1; i < mNumResyncSamples; i++) {
+        for (size_t i = numSamplesSkipped; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
             nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
             double samplePhase = double(sample % mPeriod) * scale;
@@ -639,8 +700,8 @@
             sampleAvgY += sin(samplePhase);
         }
 
-        sampleAvgX /= double(mNumResyncSamples - 1);
-        sampleAvgY /= double(mNumResyncSamples - 1);
+        sampleAvgX /= double(mNumResyncSamples - numSamplesSkipped);
+        sampleAvgY /= double(mNumResyncSamples - numSamplesSkipped);
 
         mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
 
@@ -714,6 +775,9 @@
     mPresentSampleOffset = 0;
     mError = 0;
     mZeroErrSamplesCount = 0;
+    if (mTraceDetailedInfo) {
+        ATRACE_INT64("DispSync:Error", mError);
+    }
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
         mPresentFences[i] = FenceTime::NO_FENCE;
     }
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index de2b874..3e33c7e 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -49,7 +49,7 @@
     virtual void reset() = 0;
     virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0;
     virtual void beginResync() = 0;
-    virtual bool addResyncSample(nsecs_t timestamp) = 0;
+    virtual bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) = 0;
     virtual void endResync() = 0;
     virtual void setPeriod(nsecs_t period) = 0;
     virtual nsecs_t getPeriod() = 0;
@@ -119,12 +119,20 @@
     // addPresentFence returns true indicating that the model has drifted away
     // from the hardware vsync events.
     void beginResync() override;
-    bool addResyncSample(nsecs_t timestamp) override;
+    // Adds a vsync sample to the dispsync model. The timestamp is the time
+    // of the vsync event that fired. periodFlushed will return true if the
+    // vsync period was detected to have changed to mPendingPeriod.
+    //
+    // This method will return true if more vsync samples are needed to lock
+    // down the DispSync model, and false otherwise.
+    // periodFlushed will be set to true if mPendingPeriod is flushed to
+    // mIntendedPeriod, and false otherwise.
+    bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) override;
     void endResync() override;
 
     // The setPeriod method sets the vsync event model's period to a specific
-    // value.  This should be used to prime the model when a display is first
-    // turned on.  It should NOT be used after that.
+    // value. This should be used to prime the model when a display is first
+    // turned on, or when a refresh rate change is requested.
     void setPeriod(nsecs_t period) override;
 
     // The getPeriod method returns the current vsync period.
@@ -199,6 +207,17 @@
     // nanoseconds.
     nsecs_t mPeriod;
 
+    // mIntendedPeriod is the intended period of the modeled vsync events in
+    // nanoseconds. Under ideal conditions this should be similar if not the
+    // same as mPeriod, plus or minus an observed error.
+    nsecs_t mIntendedPeriod = 0;
+
+    // mPendingPeriod is the proposed period change in nanoseconds.
+    // If mPendingPeriod differs from mPeriod and is nonzero, it will
+    // be flushed to mPeriod when we detect that the hardware switched
+    // vsync frequency.
+    nsecs_t mPendingPeriod = 0;
+
     // mPhase is the phase offset of the modeled vsync events.  It is the
     // number of nanoseconds from time 0 to the first vsync event.
     nsecs_t mPhase;
@@ -224,8 +243,8 @@
     // process to store information about the hardware vsync event times used
     // to compute the model.
     nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES] = {0};
-    size_t mFirstResyncSample;
-    size_t mNumResyncSamples;
+    size_t mFirstResyncSample = 0;
+    size_t mNumResyncSamples = 0;
     int mNumResyncSamplesSincePresent;
 
     // These member variables store information about the present fences used
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 6e89648..5faf46e 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -27,18 +27,23 @@
 
 namespace android {
 
-DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset,
+                               nsecs_t offsetThresholdForNextVsync, bool traceVsync,
                                const char* name)
       : mName(name),
         mTraceVsync(traceVsync),
         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
         mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
+        mVsyncOffsetLabel(base::StringPrintf("VsyncOffset-%s", name)),
+        mVsyncNegativeOffsetLabel(base::StringPrintf("VsyncNegativeOffset-%s", name)),
         mDispSync(dispSync),
-        mPhaseOffset(phaseOffset) {}
+        mPhaseOffset(phaseOffset),
+        mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
 
 void DispSyncSource::setVSyncEnabled(bool enable) {
     std::lock_guard lock(mVsyncMutex);
     if (enable) {
+        tracePhaseOffset();
         status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                    static_cast<DispSync::Callback*>(this),
                                                    mLastCallbackTime);
@@ -64,16 +69,21 @@
 
 void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
     std::lock_guard 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;
+    const nsecs_t period = mDispSync->getPeriod();
+    // Check if offset should be handled as negative
+    if (phaseOffset >= mOffsetThresholdForNextVsync) {
+        phaseOffset -= period;
     }
+
+    // Normalize phaseOffset to [-period, period)
+    const int numPeriods = phaseOffset / period;
+    phaseOffset -= numPeriods * period;
+    if (mPhaseOffset == phaseOffset) {
+        return;
+    }
+
     mPhaseOffset = phaseOffset;
+    tracePhaseOffset();
 
     // If we're not enabled, we don't need to mess with the listeners
     if (!mEnabled) {
@@ -87,28 +97,16 @@
     }
 }
 
-void DispSyncSource::pauseVsyncCallback(bool pause) {
-    std::lock_guard lock(mVsyncMutex);
-    mCallbackPaused = pause;
-}
-
 void DispSyncSource::onDispSyncEvent(nsecs_t when) {
-    {
-        std::lock_guard lock(mVsyncMutex);
-        if (mCallbackPaused) {
-            return;
-        }
-    }
-
     VSyncSource::Callback* callback;
     {
         std::lock_guard lock(mCallbackMutex);
         callback = mCallback;
+    }
 
-        if (mTraceVsync) {
-            mValue = (mValue + 1) % 2;
-            ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
-        }
+    if (mTraceVsync) {
+        mValue = (mValue + 1) % 2;
+        ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
     }
 
     if (callback != nullptr) {
@@ -116,4 +114,14 @@
     }
 }
 
-} // namespace android
\ No newline at end of file
+void DispSyncSource::tracePhaseOffset() {
+    if (mPhaseOffset > 0) {
+        ATRACE_INT(mVsyncOffsetLabel.c_str(), mPhaseOffset);
+        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), 0);
+    } else {
+        ATRACE_INT(mVsyncOffsetLabel.c_str(), 0);
+        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), -mPhaseOffset);
+    }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 2858678..50560a5 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -25,7 +25,8 @@
 
 class DispSyncSource final : public VSyncSource, private DispSync::Callback {
 public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, nsecs_t offsetThresholdForNextVsync,
+                   bool traceVsync, const char* name);
 
     ~DispSyncSource() override = default;
 
@@ -33,18 +34,21 @@
     void setVSyncEnabled(bool enable) override;
     void setCallback(VSyncSource::Callback* callback) override;
     void setPhaseOffset(nsecs_t phaseOffset) override;
-    void pauseVsyncCallback(bool pause) override;
 
 private:
     // The following method is the implementation of the DispSync::Callback.
     virtual void onDispSyncEvent(nsecs_t when);
 
+    void tracePhaseOffset() REQUIRES(mVsyncMutex);
+
     const char* const mName;
     int mValue = 0;
 
     const bool mTraceVsync;
     const std::string mVsyncOnLabel;
     const std::string mVsyncEventLabel;
+    const std::string mVsyncOffsetLabel;
+    const std::string mVsyncNegativeOffsetLabel;
     nsecs_t mLastCallbackTime GUARDED_BY(mVsyncMutex) = 0;
 
     DispSync* mDispSync;
@@ -54,8 +58,8 @@
 
     std::mutex mVsyncMutex;
     nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+    const nsecs_t mOffsetThresholdForNextVsync;
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
-    bool mCallbackPaused GUARDED_BY(mVsyncMutex) = false;
 };
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index a760079..9d1f777 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -76,6 +76,10 @@
             return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
                                 ", count=%u}",
                                 event.header.displayId, event.vsync.count);
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
+                                ", configId=%u}",
+                                event.header.displayId, event.config.configId);
         default:
             return "Event{}";
     }
@@ -108,9 +112,9 @@
 
 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
                                              ResyncCallback resyncCallback,
-                                             ResetIdleTimerCallback resetIdleTimerCallback)
+                                             ISurfaceComposer::ConfigChanged configChanged)
       : resyncCallback(std::move(resyncCallback)),
-        resetIdleTimerCallback(std::move(resetIdleTimerCallback)),
+        configChanged(configChanged),
         mEventThread(eventThread),
         mChannel(gui::BitTube::DefaultSize) {}
 
@@ -136,12 +140,7 @@
 
 void EventThreadConnection::requestNextVsync() {
     ATRACE_NAME("requestNextVsync");
-    mEventThread->requestNextVsync(this, true);
-}
-
-void EventThreadConnection::requestNextVsyncForHWC() {
-    ATRACE_NAME("requestNextVsyncForHWC");
-    mEventThread->requestNextVsync(this, false);
+    mEventThread->requestNextVsync(this);
 }
 
 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
@@ -210,16 +209,10 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-void EventThread::pauseVsyncCallback(bool pause) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    ATRACE_INT("vsyncPaused", pause);
-    mVSyncSource->pauseVsyncCallback(pause);
-}
-
 sp<EventThreadConnection> EventThread::createEventConnection(
-        ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
+        ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
     return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
-                                     std::move(resetIdleTimerCallback));
+                                     configChanged);
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -261,12 +254,7 @@
     }
 }
 
-void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
-    if (connection->resetIdleTimerCallback && reset) {
-        ATRACE_NAME("resetIdleTimer");
-        connection->resetIdleTimerCallback();
-    }
-
+void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
     if (connection->resyncCallback) {
         connection->resyncCallback();
     }
@@ -418,9 +406,11 @@
                                      const sp<EventThreadConnection>& connection) const {
     switch (event.header.type) {
         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
-        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
             return true;
 
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return connection->configChanged == ISurfaceComposer::eConfigChangedDispatch;
+
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
             switch (connection->vsyncRequest) {
                 case VSyncRequest::None:
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 67e6de9..dd23b88 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -45,7 +45,6 @@
 // ---------------------------------------------------------------------------
 
 using ResyncCallback = std::function<void()>;
-using ResetIdleTimerCallback = std::function<void()>;
 
 enum class VSyncRequest {
     None = -1,
@@ -66,14 +65,12 @@
     virtual void setVSyncEnabled(bool enable) = 0;
     virtual void setCallback(Callback* callback) = 0;
     virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
-
-    // pause/resume vsync callback generation
-    virtual void pauseVsyncCallback(bool pause) = 0;
 };
 
 class EventThreadConnection : public BnDisplayEventConnection {
 public:
-    EventThreadConnection(EventThread*, ResyncCallback, ResetIdleTimerCallback);
+    EventThreadConnection(EventThread*, ResyncCallback,
+                          ISurfaceComposer::ConfigChanged configChanged);
     virtual ~EventThreadConnection();
 
     virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -81,15 +78,12 @@
     status_t stealReceiveChannel(gui::BitTube* outChannel) override;
     status_t setVsyncRate(uint32_t rate) override;
     void requestNextVsync() override; // asynchronous
-    // Requesting Vsync for HWC does not reset the idle timer, since HWC requires a refresh
-    // in order to update the configs.
-    void requestNextVsyncForHWC();
 
     // Called in response to requestNextVsync.
     const ResyncCallback resyncCallback;
-    const ResetIdleTimerCallback resetIdleTimerCallback;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
+    const ISurfaceComposer::ConfigChanged configChanged;
 
 private:
     virtual void onFirstRef();
@@ -101,8 +95,8 @@
 public:
     virtual ~EventThread();
 
-    virtual sp<EventThreadConnection> createEventConnection(ResyncCallback,
-                                                            ResetIdleTimerCallback) const = 0;
+    virtual sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const = 0;
 
     // called before the screen is turned off from main thread
     virtual void onScreenReleased() = 0;
@@ -123,10 +117,7 @@
             const sp<EventThreadConnection>& connection) = 0;
     virtual void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) = 0;
     // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
-    virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
-                                  bool resetIdleTimer) = 0;
-
-    virtual void pauseVsyncCallback(bool pause) = 0;
+    virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
 };
 
 namespace impl {
@@ -140,13 +131,12 @@
     EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
     ~EventThread();
 
-    sp<EventThreadConnection> createEventConnection(ResyncCallback,
-                                                    ResetIdleTimerCallback) const override;
+    sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const override;
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
-    void requestNextVsync(const sp<EventThreadConnection>& connection,
-                          bool resetIdleTimer) override;
+    void requestNextVsync(const sp<EventThreadConnection>& connection) override;
 
     // called before the screen is turned off from main thread
     void onScreenReleased() override;
@@ -162,8 +152,6 @@
 
     void setPhaseOffset(nsecs_t phaseOffset) override;
 
-    void pauseVsyncCallback(bool pause) override;
-
 private:
     friend EventThreadTest;
 
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index d5ccbe1..f80c233 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -14,14 +14,18 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 #include "LayerHistory.h"
 
 #include <cinttypes>
 #include <cstdint>
+#include <limits>
 #include <numeric>
 #include <string>
 #include <unordered_map>
 
+#include <cutils/properties.h>
 #include <utils/Log.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
@@ -29,28 +33,160 @@
 #include "SchedulerUtils.h"
 
 namespace android {
+namespace scheduler {
 
-LayerHistory::LayerHistory() {}
+std::atomic<int64_t> LayerHistory::sNextId = 0;
+
+LayerHistory::LayerHistory() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.layer_history_trace", value, "0");
+    mTraceEnabled = bool(atoi(value));
+}
 
 LayerHistory::~LayerHistory() = default;
 
-void LayerHistory::insert(const std::string layerName, nsecs_t presentTime) {
-    mElements[mCounter].insert(std::make_pair(layerName, presentTime));
+std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
+                                                                     float minRefreshRate,
+                                                                     float maxRefreshRate) {
+    const int64_t id = sNextId++;
+
+    std::lock_guard lock(mLock);
+    mInactiveLayerInfos.emplace(id,
+                                std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate));
+    return std::make_unique<LayerHistory::LayerHandle>(*this, id);
 }
 
-void LayerHistory::incrementCounter() {
-    mCounter++;
-    mCounter = mCounter % scheduler::ARRAY_SIZE;
-    // Clear all the previous data from the history. This is a ring buffer, so we are
-    // reusing memory.
-    mElements[mCounter].clear();
+void LayerHistory::destroyLayer(const int64_t id) {
+    std::lock_guard lock(mLock);
+    auto it = mActiveLayerInfos.find(id);
+    if (it != mActiveLayerInfos.end()) {
+        mActiveLayerInfos.erase(it);
+    }
+
+    it = mInactiveLayerInfos.find(id);
+    if (it != mInactiveLayerInfos.end()) {
+        mInactiveLayerInfos.erase(it);
+    }
 }
 
-const std::unordered_map<std::string, nsecs_t>& LayerHistory::get(size_t index) const {
-    // For the purposes of the layer history, the index = 0 always needs to start at the
-    // current counter, and then decrement to access the layers in correct historical order.
-    return mElements.at((scheduler::ARRAY_SIZE + (mCounter - (index % scheduler::ARRAY_SIZE))) %
-                        scheduler::ARRAY_SIZE);
+void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime,
+                          bool isHdr) {
+    std::shared_ptr<LayerInfo> layerInfo;
+    {
+        std::lock_guard lock(mLock);
+        auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId);
+        if (layerInfoIterator != mInactiveLayerInfos.end()) {
+            layerInfo = layerInfoIterator->second;
+            mInactiveLayerInfos.erase(layerInfoIterator);
+            mActiveLayerInfos.insert({layerHandle->mId, layerInfo});
+        } else {
+            layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId);
+            if (layerInfoIterator != mActiveLayerInfos.end()) {
+                layerInfo = layerInfoIterator->second;
+            } else {
+                ALOGW("Inserting information about layer that is not registered: %" PRId64,
+                      layerHandle->mId);
+                return;
+            }
+        }
+    }
+    layerInfo->setLastPresentTime(presentTime);
+    layerInfo->setHDRContent(isHdr);
 }
 
+void LayerHistory::setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible) {
+    std::shared_ptr<LayerInfo> layerInfo;
+    {
+        std::lock_guard lock(mLock);
+        auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId);
+        if (layerInfoIterator != mInactiveLayerInfos.end()) {
+            layerInfo = layerInfoIterator->second;
+            if (visible) {
+                mInactiveLayerInfos.erase(layerInfoIterator);
+                mActiveLayerInfos.insert({layerHandle->mId, layerInfo});
+            }
+        } else {
+            layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId);
+            if (layerInfoIterator != mActiveLayerInfos.end()) {
+                layerInfo = layerInfoIterator->second;
+            } else {
+                ALOGW("Inserting information about layer that is not registered: %" PRId64,
+                      layerHandle->mId);
+                return;
+            }
+        }
+    }
+    layerInfo->setVisibility(visible);
+}
+
+std::pair<float, bool> LayerHistory::getDesiredRefreshRateAndHDR() {
+    bool isHDR = false;
+    float newRefreshRate = 0.f;
+    std::lock_guard lock(mLock);
+
+    removeIrrelevantLayers();
+
+    // Iterate through all layers that have been recently updated, and find the max refresh rate.
+    for (const auto& [layerId, layerInfo] : mActiveLayerInfos) {
+        const float layerRefreshRate = layerInfo->getDesiredRefreshRate();
+        if (mTraceEnabled) {
+            // Store the refresh rate in traces for easy debugging.
+            std::string layerName = "LFPS " + layerInfo->getName();
+            ATRACE_INT(layerName.c_str(), std::round(layerRefreshRate));
+            ALOGD("%s: %f", layerName.c_str(), std::round(layerRefreshRate));
+        }
+        if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) {
+            newRefreshRate = layerRefreshRate;
+        }
+        isHDR |= layerInfo->getHDRContent();
+    }
+    if (mTraceEnabled) {
+        ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate);
+    }
+
+    return {newRefreshRate, isHDR};
+}
+
+void LayerHistory::removeIrrelevantLayers() {
+    const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
+    // Iterator pointing to first element in map
+    auto it = mActiveLayerInfos.begin();
+    while (it != mActiveLayerInfos.end()) {
+        // If last updated was before the obsolete time, remove it.
+        // Keep HDR layer around as long as they are visible.
+        if (!it->second->isVisible() ||
+            (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) {
+            // erase() function returns the iterator of the next
+            // to last deleted element.
+            if (mTraceEnabled) {
+                ALOGD("Layer %s obsolete", it->second->getName().c_str());
+                // Make sure to update systrace to indicate that the layer was erased.
+                std::string layerName = "LFPS " + it->second->getName();
+                ATRACE_INT(layerName.c_str(), 0);
+            }
+            auto id = it->first;
+            auto layerInfo = it->second;
+            layerInfo->clearHistory();
+            mInactiveLayerInfos.insert({id, layerInfo});
+            it = mActiveLayerInfos.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+void LayerHistory::clearHistory() {
+    std::lock_guard lock(mLock);
+
+    auto it = mActiveLayerInfos.begin();
+    while (it != mActiveLayerInfos.end()) {
+        auto id = it->first;
+        auto layerInfo = it->second;
+        layerInfo->clearHistory();
+        mInactiveLayerInfos.insert({id, layerInfo});
+        it = mActiveLayerInfos.erase(it);
+    }
+}
+
+} // namespace scheduler
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index c6fab07..5598cc1 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -25,40 +25,67 @@
 
 #include <utils/Timers.h>
 
+#include "LayerInfo.h"
 #include "SchedulerUtils.h"
 
 namespace android {
+namespace scheduler {
 
 /*
- * This class represents a circular buffer in which we keep layer history for
- * the past ARRAY_SIZE frames. Each time, a signal for new frame comes, the counter
- * gets incremented and includes all the layers that are requested to draw in that
- * frame.
- *
- * Once the buffer reaches the end of the array, it starts overriding the elements
- * at the beginning of the array.
+ * This class represents information about layers that are considered current. We keep an
+ * unordered map between layer name and LayerInfo.
  */
 class LayerHistory {
 public:
+    // Handle for each layer we keep track of.
+    class LayerHandle {
+    public:
+        LayerHandle(LayerHistory& lh, int64_t id) : mId(id), mLayerHistory(lh) {}
+        ~LayerHandle() { mLayerHistory.destroyLayer(mId); }
+
+        const int64_t mId;
+
+    private:
+        LayerHistory& mLayerHistory;
+    };
+
     LayerHistory();
     ~LayerHistory();
 
-    // Method for inserting layers and their requested present time into the ring buffer.
-    // The elements are going to be inserted into an unordered_map at the position 'now'.
-    void insert(const std::string layerName, nsecs_t presentTime);
-    // Method for incrementing the current slot in the ring buffer. It also clears the
-    // unordered_map, if it was created previously.
-    void incrementCounter();
-    // Returns unordered_map at the given at index. The index is decremented from 'now'. For
-    // example, 0 is now, 1 is previous frame.
-    const std::unordered_map<std::string, nsecs_t>& get(size_t index) const;
-    // Returns the total size of the ring buffer. The value is always the same regardless
-    // of how many slots we filled in.
-    static constexpr size_t getSize() { return scheduler::ARRAY_SIZE; }
+    // When the layer is first created, register it.
+    std::unique_ptr<LayerHandle> createLayer(const std::string name, float minRefreshRate,
+                                             float maxRefreshRate);
+
+    // Method for inserting layers and their requested present time into the unordered map.
+    void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr);
+    // Method for setting layer visibility
+    void setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible);
+
+    // Returns the desired refresh rate, which is a max refresh rate of all the current
+    // layers. See go/content-fps-detection-in-scheduler for more information.
+    std::pair<float, bool> getDesiredRefreshRateAndHDR();
+
+    // Clears all layer history.
+    void clearHistory();
+
+    // Removes the handle and the object from the map.
+    void destroyLayer(const int64_t id);
 
 private:
-    size_t mCounter = 0;
-    std::array<std::unordered_map<std::string, nsecs_t>, scheduler::ARRAY_SIZE> mElements;
+    // Removes the layers that have been idle for a given amount of time from mLayerInfos.
+    void removeIrrelevantLayers() REQUIRES(mLock);
+
+    // Information about currently active layers.
+    std::mutex mLock;
+    std::unordered_map<int64_t, std::shared_ptr<LayerInfo>> mActiveLayerInfos GUARDED_BY(mLock);
+    std::unordered_map<int64_t, std::shared_ptr<LayerInfo>> mInactiveLayerInfos GUARDED_BY(mLock);
+
+    // Each layer has it's own ID. This variable keeps track of the count.
+    static std::atomic<int64_t> sNextId;
+
+    // Flag whether to log layer FPS in systrace
+    bool mTraceEnabled = false;
 };
 
+} // namespace scheduler
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
new file mode 100644
index 0000000..e782dd5
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 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 "LayerInfo.h"
+
+#include <cinttypes>
+#include <cstdint>
+#include <numeric>
+#include <string>
+
+namespace android {
+namespace scheduler {
+
+LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate)
+      : mName(name),
+        mMinRefreshDuration(1e9f / maxRefreshRate),
+        mLowActivityRefreshDuration(1e9f / minRefreshRate),
+        mRefreshRateHistory(mMinRefreshDuration) {}
+
+LayerInfo::~LayerInfo() = default;
+
+void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) {
+    std::lock_guard lock(mLock);
+
+    // Buffers can come with a present time far in the future. That keeps them relevant.
+    mLastUpdatedTime = std::max(lastPresentTime, systemTime());
+    mPresentTimeHistory.insertPresentTime(mLastUpdatedTime);
+
+    if (mLastPresentTime == 0) {
+        // First frame
+        mLastPresentTime = lastPresentTime;
+        return;
+    }
+
+    const nsecs_t timeDiff = lastPresentTime - mLastPresentTime;
+    mLastPresentTime = lastPresentTime;
+    // Ignore time diff that are too high - those are stale values
+    if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return;
+    const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
+    const int fps = 1e9f / refreshDuration;
+    mRefreshRateHistory.insertRefreshRate(fps);
+}
+
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
new file mode 100644
index 0000000..a733781
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2019 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 <cinttypes>
+#include <cstdint>
+#include <deque>
+#include <mutex>
+#include <numeric>
+#include <string>
+
+#include <log/log.h>
+
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+#include "SchedulerUtils.h"
+
+namespace android {
+namespace scheduler {
+
+/*
+ * This class represents information about individial layers.
+ */
+class LayerInfo {
+    /**
+     * Struct that keeps the information about the refresh rate for last
+     * HISTORY_SIZE frames. This is used to better determine the refresh rate
+     * for individual layers.
+     */
+    class RefreshRateHistory {
+    public:
+        explicit RefreshRateHistory(nsecs_t minRefreshDuration)
+              : mMinRefreshDuration(minRefreshDuration) {}
+        void insertRefreshRate(int refreshRate) {
+            mElements.push_back(refreshRate);
+            if (mElements.size() > HISTORY_SIZE) {
+                mElements.pop_front();
+            }
+        }
+
+        float getRefreshRateAvg() const {
+            if (mElements.empty()) {
+                return 1e9f / mMinRefreshDuration;
+            }
+
+            return scheduler::calculate_mean(mElements);
+        }
+
+        void clearHistory() { mElements.clear(); }
+
+    private:
+        std::deque<nsecs_t> mElements;
+        static constexpr size_t HISTORY_SIZE = 30;
+        const nsecs_t mMinRefreshDuration;
+    };
+
+    /**
+     * Struct that keeps the information about the present time for last
+     * HISTORY_SIZE frames. This is used to better determine whether the given layer
+     * is still relevant and it's refresh rate should be considered.
+     */
+    class PresentTimeHistory {
+    public:
+        void insertPresentTime(nsecs_t presentTime) {
+            mElements.push_back(presentTime);
+            if (mElements.size() > HISTORY_SIZE) {
+                mElements.pop_front();
+            }
+        }
+
+        // Checks whether the present time that was inserted HISTORY_SIZE ago is within a
+        // certain threshold: TIME_EPSILON_NS.
+        bool isRelevant() const {
+            if (mElements.size() < 2) {
+                return false;
+            }
+
+            // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates
+            if (mElements.size() != HISTORY_SIZE &&
+                mElements.at(mElements.size() - 1) - mElements.at(0) < HISTORY_TIME.count()) {
+                return false;
+            }
+
+            // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds.
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
+            if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) {
+                return false;
+            }
+
+            return true;
+        }
+
+        bool isLowActivityLayer() const {
+            // We want to make sure that we received more than two frames from the layer
+            // in order to check low activity.
+            if (mElements.size() < 2) {
+                return false;
+            }
+
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count();
+            // Check the frame before last to determine whether there is low activity.
+            // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending
+            // infrequent updates.
+            if (mElements.at(mElements.size() - 2) < obsoleteEpsilon) {
+                return true;
+            }
+
+            return false;
+        }
+
+        void clearHistory() { mElements.clear(); }
+
+    private:
+        std::deque<nsecs_t> mElements;
+        static constexpr size_t HISTORY_SIZE = 90;
+        static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s;
+    };
+
+public:
+    LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate);
+    ~LayerInfo();
+
+    LayerInfo(const LayerInfo&) = delete;
+    LayerInfo& operator=(const LayerInfo&) = delete;
+
+    // Records the last requested oresent time. It also stores information about when
+    // the layer was last updated. If the present time is farther in the future than the
+    // updated time, the updated time is the present time.
+    void setLastPresentTime(nsecs_t lastPresentTime);
+
+    void setHDRContent(bool isHdr) {
+        std::lock_guard lock(mLock);
+        mIsHDR = isHdr;
+    }
+
+    void setVisibility(bool visible) {
+        std::lock_guard lock(mLock);
+        mIsVisible = visible;
+    }
+
+    // Checks the present time history to see whether the layer is relevant.
+    bool isRecentlyActive() const {
+        std::lock_guard lock(mLock);
+        return mPresentTimeHistory.isRelevant();
+    }
+
+    // Calculate the average refresh rate.
+    float getDesiredRefreshRate() const {
+        std::lock_guard lock(mLock);
+
+        if (mPresentTimeHistory.isLowActivityLayer()) {
+            return 1e9f / mLowActivityRefreshDuration;
+        }
+        return mRefreshRateHistory.getRefreshRateAvg();
+    }
+
+    bool getHDRContent() {
+        std::lock_guard lock(mLock);
+        return mIsHDR;
+    }
+
+    bool isVisible() {
+        std::lock_guard lock(mLock);
+        return mIsVisible;
+    }
+
+    // Return the last updated time. If the present time is farther in the future than the
+    // updated time, the updated time is the present time.
+    nsecs_t getLastUpdatedTime() {
+        std::lock_guard lock(mLock);
+        return mLastUpdatedTime;
+    }
+
+    std::string getName() const { return mName; }
+
+    void clearHistory() {
+        std::lock_guard lock(mLock);
+        mRefreshRateHistory.clearHistory();
+        mPresentTimeHistory.clearHistory();
+    }
+
+private:
+    const std::string mName;
+    const nsecs_t mMinRefreshDuration;
+    const nsecs_t mLowActivityRefreshDuration;
+    mutable std::mutex mLock;
+    nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0;
+    nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0;
+    RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock);
+    PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock);
+    bool mIsHDR GUARDED_BY(mLock) = false;
+    bool mIsVisible GUARDED_BY(mLock) = false;
+};
+
+} // namespace scheduler
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 1f18ead..fcb307f 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,8 +96,8 @@
     }
 
     mEventThread = eventThread;
-    mEvents =
-            eventThread->createEventConnection(std::move(resyncCallback), ResetIdleTimerCallback());
+    mEvents = eventThread->createEventConnection(std::move(resyncCallback),
+                                                 ISurfaceComposer::eConfigChangedSuppress);
     mEvents->stealReceiveChannel(&mEventTube);
     mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                    this);
@@ -150,10 +150,6 @@
     mEvents->requestNextVsync();
 }
 
-void MessageQueue::invalidateForHWC() {
-    mEvents->requestNextVsyncForHWC();
-}
-
 void MessageQueue::refresh() {
     mHandler->dispatchRefresh();
 }
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 245a8ac..0b2206d 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -91,7 +91,6 @@
     virtual void waitMessage() = 0;
     virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
     virtual void invalidate() = 0;
-    virtual void invalidateForHWC() = 0;
     virtual void refresh() = 0;
 };
 
@@ -136,8 +135,6 @@
     // sends INVALIDATE message at next VSYNC
     void invalidate() override;
 
-    // sends INVALIDATE message at next VSYNC, without resetting the idle timer in the Scheduler
-    void invalidateForHWC();
     // sends REFRESH message at next VSYNC
     void refresh() override;
 };
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
similarity index 79%
rename from services/surfaceflinger/Scheduler/IdleTimer.cpp
rename to services/surfaceflinger/Scheduler/OneShotTimer.cpp
index b28b1aa..4870a3b 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "IdleTimer.h"
+#include "OneShotTimer.h"
 
 #include <chrono>
 #include <thread>
@@ -22,23 +22,23 @@
 namespace android {
 namespace scheduler {
 
-IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-                     const TimeoutCallback& timeoutCallback)
+OneShotTimer::OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                           const TimeoutCallback& timeoutCallback)
       : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {}
 
-IdleTimer::~IdleTimer() {
+OneShotTimer::~OneShotTimer() {
     stop();
 }
 
-void IdleTimer::start() {
+void OneShotTimer::start() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
     }
-    mThread = std::thread(&IdleTimer::loop, this);
+    mThread = std::thread(&OneShotTimer::loop, this);
 }
 
-void IdleTimer::stop() {
+void OneShotTimer::stop() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::STOPPED;
@@ -49,7 +49,7 @@
     }
 }
 
-void IdleTimer::loop() {
+void OneShotTimer::loop() {
     while (true) {
         bool triggerReset = false;
         bool triggerTimeout = false;
@@ -84,8 +84,11 @@
                 constexpr auto zero = std::chrono::steady_clock::duration::zero();
                 auto waitTime = triggerTime - std::chrono::steady_clock::now();
                 if (waitTime > zero) mCondition.wait_for(mMutex, waitTime);
-                if (mState == TimerState::WAITING &&
-                    (triggerTime - std::chrono::steady_clock::now()) <= zero) {
+                if (mState == TimerState::RESET) {
+                    triggerTime = std::chrono::steady_clock::now() + mInterval;
+                    mState = TimerState::WAITING;
+                } else if (mState == TimerState::WAITING &&
+                           (triggerTime - std::chrono::steady_clock::now()) <= zero) {
                     triggerTimeout = true;
                     mState = TimerState::IDLE;
                 }
@@ -97,7 +100,7 @@
     }
 } // namespace scheduler
 
-void IdleTimer::reset() {
+void OneShotTimer::reset() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
similarity index 64%
rename from services/surfaceflinger/Scheduler/IdleTimer.h
rename to services/surfaceflinger/Scheduler/OneShotTimer.h
index 19f1267..fd1aa02 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -29,23 +29,41 @@
  * Class that sets off a timer for a given interval, and fires a callback when the
  * interval expires.
  */
-class IdleTimer {
+class OneShotTimer {
 public:
     using Interval = std::chrono::milliseconds;
     using ResetCallback = std::function<void()>;
     using TimeoutCallback = std::function<void()>;
 
-    IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-              const TimeoutCallback& timeoutCallback);
-    ~IdleTimer();
+    OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                 const TimeoutCallback& timeoutCallback);
+    ~OneShotTimer();
 
+    // Initializes and turns on the idle timer.
     void start();
+    // Stops the idle timer and any held resources.
     void stop();
+    // Resets the wakeup time and fires the reset callback.
     void reset();
 
 private:
     // Enum to track in what state is the timer.
-    enum class TimerState { STOPPED = 0, RESET = 1, WAITING = 2, IDLE = 3 };
+    enum class TimerState {
+        // The internal timer thread has been destroyed, and no state is
+        // tracked.
+        // Possible state transitions: RESET
+        STOPPED = 0,
+        // An external thread has just reset this timer.
+        // If there is a reset callback, then that callback is fired.
+        // Possible state transitions: STOPPED, WAITING
+        RESET = 1,
+        // This timer is waiting for the timeout interval to expire.
+        // Possible state transaitions: STOPPED, RESET, IDLE
+        WAITING = 2,
+        // The timeout interval has expired, so we are sleeping now.
+        // Possible state transaitions: STOPPED, RESET
+        IDLE = 3
+    };
 
     // Function that loops until the condition for stopping is met.
     void loop();
@@ -59,6 +77,7 @@
     // Lock used for synchronizing the waiting thread with the application thread.
     std::mutex mMutex;
 
+    // Current timer state
     TimerState mState GUARDED_BY(mMutex) = TimerState::RESET;
 
     // Interval after which timer expires.
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 7e2b03d..8a2604f 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -25,6 +25,7 @@
 
 namespace scheduler {
 
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
 PhaseOffsets::~PhaseOffsets() = default;
 
 namespace impl {
@@ -65,34 +66,48 @@
     property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
     const int highFpsLateSfOffsetNs = atoi(value);
 
-    mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
-                                                              : sfVsyncPhaseOffsetNs,
-                                        earlyAppOffsetNs != -1 ? earlyAppOffsetNs
-                                                               : vsyncPhaseOffsetNs};
-    mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs
-                                                                  : sfVsyncPhaseOffsetNs,
-                                          earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs
-                                                                   : vsyncPhaseOffsetNs};
-    mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
+    // Below defines the threshold when an offset is considered to be negative, i.e. targeting
+    // for the N+2 vsync instead of N+1. This means that:
+    // For offset < threshold, SF wake up (vsync_duration - offset) before HW vsync.
+    // For offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW vsync.
+    property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
+    const int phaseOffsetThresholdForNextVsyncNs = atoi(value);
 
-    mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
-                                                                  : highFpsLateSfOffsetNs,
-                                     highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
-                                                                   : highFpsLateAppOffsetNs};
-    mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
-                                                                      : highFpsLateSfOffsetNs,
-                                       highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
-                                                                       : highFpsLateAppOffsetNs};
-    mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
+    Offsets defaultOffsets;
+    Offsets highFpsOffsets;
+    defaultOffsets.early = {RefreshRateType::DEFAULT,
+                            earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+                            earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+    defaultOffsets.earlyGl = {RefreshRateType::DEFAULT,
+                              earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+                              earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+    defaultOffsets.late = {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
+
+    highFpsOffsets.early = {RefreshRateType::PERFORMANCE,
+                            highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
+                                                         : highFpsLateSfOffsetNs,
+                            highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+                                                          : highFpsLateAppOffsetNs};
+    highFpsOffsets.earlyGl = {RefreshRateType::PERFORMANCE,
+                              highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+                                                             : highFpsLateSfOffsetNs,
+                              highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+                                                              : highFpsLateAppOffsetNs};
+    highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
+                           highFpsLateAppOffsetNs};
+
+    mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
+    mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
+    mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
+
+    mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
+            ? phaseOffsetThresholdForNextVsyncNs
+            : std::numeric_limits<nsecs_t>::max();
 }
 
-PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
-    switch (mRefreshRateType) {
-        case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
-            return mHighRefreshRateOffsets;
-        default:
-            return mDefaultRefreshRateOffsets;
-    }
+PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
+        android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
+    return mOffsets.at(refreshRateType);
 }
 
 void PhaseOffsets::dump(std::string& result) const {
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index cbcaade..2b5c2f1 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <cinttypes>
+#include <unordered_map>
 
 #include "RefreshRateConfigs.h"
 #include "VSyncModulator.h"
@@ -42,8 +43,11 @@
 
     virtual nsecs_t getCurrentAppOffset() = 0;
     virtual nsecs_t getCurrentSfOffset() = 0;
+    virtual Offsets getOffsetsForRefreshRate(
+            RefreshRateConfigs::RefreshRateType refreshRateType) const = 0;
     virtual Offsets getCurrentOffsets() const = 0;
     virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
+    virtual nsecs_t getOffsetThresholdForNextVsync() const = 0;
     virtual void dump(std::string& result) const = 0;
 };
 
@@ -55,8 +59,14 @@
     nsecs_t getCurrentAppOffset() override;
     nsecs_t getCurrentSfOffset() override;
 
+    // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
+    Offsets getOffsetsForRefreshRate(
+            RefreshRateConfigs::RefreshRateType refreshRateType) const override;
+
     // Returns early, early GL, and late offsets for Apps and SF.
-    Offsets getCurrentOffsets() const override;
+    Offsets getCurrentOffsets() const override {
+        return getOffsetsForRefreshRate(mRefreshRateType);
+    }
 
     // This function should be called when the device is switching between different
     // refresh rates, to properly update the offsets.
@@ -64,18 +74,17 @@
         mRefreshRateType = refreshRateType;
     }
 
+    nsecs_t getOffsetThresholdForNextVsync() const override { return mOffsetThresholdForNextVsync; }
+
     // Returns current offsets in human friendly format.
     void dump(std::string& result) const override;
 
 private:
-    Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
-    Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
-
     std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
             RefreshRateConfigs::RefreshRateType::DEFAULT;
 
-    Offsets mDefaultRefreshRateOffsets;
-    Offsets mHighRefreshRateOffsets;
+    std::unordered_map<RefreshRateConfigs::RefreshRateType, Offsets> mOffsets;
+    nsecs_t mOffsetThresholdForNextVsync;
 };
 } // namespace impl
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 1aa6ade..d730058 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -47,20 +47,16 @@
         std::string name;
         // Refresh rate in frames per second, rounded to the nearest integer.
         uint32_t fps = 0;
+        // config Id (returned from HWC2::Display::Config::getId())
+        hwc2_config_t id;
     };
 
     // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
     // baking them in.
-    explicit RefreshRateConfigs(
-            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
-        init(configs);
-    }
-    ~RefreshRateConfigs() = default;
-
-    const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() {
+    const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() const {
         return mRefreshRates;
     }
-    std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) {
+    std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) const {
         const auto& refreshRate = mRefreshRates.find(type);
         if (refreshRate != mRefreshRates.end()) {
             return refreshRate->second;
@@ -68,12 +64,24 @@
         return nullptr;
     }
 
-private:
-    void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
+    RefreshRateType getRefreshRateType(hwc2_config_t id) const {
+        for (const auto& [type, refreshRate] : mRefreshRates) {
+            if (refreshRate->id == id) {
+                return type;
+            }
+        }
+
+        return RefreshRateType::DEFAULT;
+    }
+
+    void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
+        mRefreshRates.clear();
+
         // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
         mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
                               std::make_shared<RefreshRate>(
-                                      RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}));
+                                      RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0,
+                                                  HWC2_SCREEN_OFF_CONFIG_ID}));
 
         if (configs.size() < 1) {
             ALOGE("Device does not have valid configs. Config size is 0.");
@@ -96,11 +104,12 @@
         nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
         if (vsyncPeriod != 0) {
             const float fps = 1e9 / vsyncPeriod;
+            const int configId = configIdToVsyncPeriod[0].first;
             mRefreshRates.emplace(RefreshRateType::DEFAULT,
                                   std::make_shared<RefreshRate>(
-                                          RefreshRate{configIdToVsyncPeriod[0].first,
-                                                      base::StringPrintf("%2.ffps", fps),
-                                                      static_cast<uint32_t>(fps)}));
+                                          RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
+                                                      static_cast<uint32_t>(fps),
+                                                      configs.at(configId)->getId()}));
         }
 
         if (configs.size() < 2) {
@@ -112,14 +121,16 @@
         vsyncPeriod = configIdToVsyncPeriod[1].second;
         if (vsyncPeriod != 0) {
             const float fps = 1e9 / vsyncPeriod;
+            const int configId = configIdToVsyncPeriod[1].first;
             mRefreshRates.emplace(RefreshRateType::PERFORMANCE,
                                   std::make_shared<RefreshRate>(
-                                          RefreshRate{configIdToVsyncPeriod[1].first,
-                                                      base::StringPrintf("%2.ffps", fps),
-                                                      static_cast<uint32_t>(fps)}));
+                                          RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
+                                                      static_cast<uint32_t>(fps),
+                                                      configs.at(configId)->getId()}));
         }
     }
 
+private:
     std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
 };
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index ff63faf..7e7c630 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -41,12 +41,8 @@
     static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
 
 public:
-    explicit RefreshRateStats(const std::shared_ptr<RefreshRateConfigs>& refreshRateConfigs,
-                              const std::shared_ptr<TimeStats>& timeStats)
-          : mRefreshRateConfigs(refreshRateConfigs),
-            mTimeStats(timeStats),
-            mPreviousRecordedTime(systemTime()) {}
-    ~RefreshRateStats() = default;
+    RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats)
+          : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats) {}
 
     // Sets power mode. We only collect the information when the power mode is not
     // HWC_POWER_MODE_NORMAL. When power mode is HWC_POWER_MODE_NORMAL, we collect the stats based
@@ -83,7 +79,7 @@
         flushTime();
 
         std::unordered_map<std::string, int64_t> totalTime;
-        for (auto [type, config] : mRefreshRateConfigs->getRefreshRates()) {
+        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
             int64_t totalTimeForConfig = 0;
             if (!config) {
                 continue;
@@ -98,11 +94,11 @@
 
     // Traverses through the map of config modes and returns how long they've been running in easy
     // to read format.
-    std::string doDump() {
+    std::string doDump() const {
         std::ostringstream stream;
         stream << "+  Refresh rate: running time in seconds\n";
-        for (auto stats : getTotalTimes()) {
-            stream << stats.first.c_str() << ": " << getDateFormatFromMs(stats.second) << "\n";
+        for (const auto& [name, time] : const_cast<RefreshRateStats*>(this)->getTotalTimes()) {
+            stream << name << ": " << getDateFormatFromMs(time) << '\n';
         }
         return stream.str();
     }
@@ -126,12 +122,12 @@
         mPreviousRecordedTime = currentTime;
 
         mConfigModesTotalTime[mode] += timeElapsedMs;
-        for (const auto& [type, config] : mRefreshRateConfigs->getRefreshRates()) {
+        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
             if (!config) {
                 continue;
             }
             if (config->configId == mode) {
-                mTimeStats->recordRefreshRate(config->fps, timeElapsed);
+                mTimeStats.recordRefreshRate(config->fps, timeElapsed);
             }
         }
     }
@@ -148,17 +144,17 @@
     }
 
     // Keeps information about refresh rate configs that device has.
-    std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs;
+    const RefreshRateConfigs& mRefreshRateConfigs;
 
     // Aggregate refresh rate statistics for telemetry.
-    std::shared_ptr<TimeStats> mTimeStats;
+    TimeStats& mTimeStats;
 
     int64_t mCurrentConfigMode = SCREEN_OFF_CONFIG_ID;
     int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;
 
     std::unordered_map<int /* power mode */, int64_t /* duration in ms */> mConfigModesTotalTime;
 
-    nsecs_t mPreviousRecordedTime;
+    nsecs_t mPreviousRecordedTime = systemTime();
 };
 
 } // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 0063c8a..7acb470 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -28,6 +28,7 @@
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
+#include <input/InputWindow.h>
 #include <system/window.h>
 #include <ui/DisplayStatInfo.h>
 #include <utils/Timers.h>
@@ -37,8 +38,9 @@
 #include "DispSyncSource.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
+#include "LayerInfo.h"
+#include "OneShotTimer.h"
 #include "SchedulerUtils.h"
 #include "SurfaceFlingerProperties.h"
 
@@ -55,11 +57,13 @@
 
 std::atomic<int64_t> Scheduler::sNextId = 0;
 
-Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function)
+Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
+                     const scheduler::RefreshRateConfigs& refreshRateConfig)
       : mHasSyncFramework(running_without_sync_framework(true)),
         mDispSyncPresentTimeOffset(present_time_offset_from_vsync_ns(0)),
         mPrimaryHWVsyncEnabled(false),
-        mHWVsyncAvailable(false) {
+        mHWVsyncAvailable(false),
+        mRefreshRateConfigs(refreshRateConfig) {
     // Note: We create a local temporary with the real DispSync implementation
     // type temporarily so we can initialize it with the configured values,
     // before storing it for more generic use using the interface type.
@@ -69,6 +73,10 @@
     mEventControlThread = std::make_unique<impl::EventControlThread>(function);
 
     mSetIdleTimerMs = set_idle_timer_ms(0);
+    mSupportKernelTimer = support_kernel_idle_timer(false);
+
+    mSetTouchTimerMs = set_touch_timer_ms(0);
+    mSetDisplayPowerTimerMs = set_display_power_timer_ms(0);
 
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.set_idle_timer_ms", value, "0");
@@ -78,31 +86,57 @@
     }
 
     if (mSetIdleTimerMs > 0) {
-        mIdleTimer =
-                std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetIdleTimerMs),
-                                                       [this] { resetTimerCallback(); },
-                                                       [this] { expiredTimerCallback(); });
+        if (mSupportKernelTimer) {
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs),
+                    [this] { resetKernelTimerCallback(); },
+                    [this] { expiredKernelTimerCallback(); });
+        } else {
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); },
+                    [this] { expiredTimerCallback(); });
+        }
         mIdleTimer->start();
     }
+
+    if (mSetTouchTimerMs > 0) {
+        // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
+        mTouchTimer = std::make_unique<scheduler::OneShotTimer>(
+                std::chrono::milliseconds(mSetTouchTimerMs), [this] { resetTouchTimerCallback(); },
+                [this] { expiredTouchTimerCallback(); });
+        mTouchTimer->start();
+    }
+
+    if (mSetDisplayPowerTimerMs > 0) {
+        mDisplayPowerTimer = std::make_unique<scheduler::OneShotTimer>(
+                std::chrono::milliseconds(mSetDisplayPowerTimerMs),
+                [this] { resetDisplayPowerTimerCallback(); },
+                [this] { expiredDisplayPowerTimerCallback(); });
+        mDisplayPowerTimer->start();
+    }
 }
 
 Scheduler::~Scheduler() {
-    // Ensure the IdleTimer thread is joined before we start destroying state.
+    // Ensure the OneShotTimer threads are joined before we start destroying state.
+    mDisplayPowerTimer.reset();
+    mTouchTimer.reset();
     mIdleTimer.reset();
 }
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+        const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
+        ResyncCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
 
     std::unique_ptr<EventThread> eventThread =
             makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
-                            std::move(interceptCallback));
+                            offsetThresholdForNextVsync, std::move(interceptCallback));
 
     auto eventThreadConnection =
-            createConnectionInternal(eventThread.get(), std::move(resyncCallback));
+            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+                                     ISurfaceComposer::eConfigChangedSuppress);
     mConnections.emplace(id,
                          std::make_unique<Connection>(new ConnectionHandle(id),
                                                       eventThreadConnection,
@@ -111,25 +145,28 @@
 }
 
 std::unique_ptr<EventThread> Scheduler::makeEventThread(
-        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+        nsecs_t offsetThresholdForNextVsync,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     std::unique_ptr<VSyncSource> eventThreadSource =
-            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, offsetThresholdForNextVsync,
+                                             true, connectionName);
     return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
                                                std::move(interceptCallback), connectionName);
 }
 
-sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
-                                                              ResyncCallback&& resyncCallback) {
-    return eventThread->createEventConnection(std::move(resyncCallback),
-                                              [this] { resetIdleTimer(); });
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+        EventThread* eventThread, ResyncCallback&& resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
+    return eventThread->createEventConnection(std::move(resyncCallback), configChanged);
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
     RETURN_VALUE_IF_INVALID(nullptr);
     return createConnectionInternal(mConnections[handle->id]->thread.get(),
-                                    std::move(resyncCallback));
+                                    std::move(resyncCallback), configChanged);
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -174,12 +211,6 @@
     mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
 }
 
-void Scheduler::pauseVsyncCallback(const android::sp<android::Scheduler::ConnectionHandle>& handle,
-                                   bool pause) {
-    RETURN_IF_INVALID();
-    mConnections[handle->id]->thread->pauseVsyncCallback(pause);
-}
-
 void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
     stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
     stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
@@ -251,7 +282,6 @@
 
 void Scheduler::setVsyncPeriod(const nsecs_t period) {
     std::lock_guard<std::mutex> lock(mHWVsyncLock);
-    mPrimaryDispSync->reset();
     mPrimaryDispSync->setPeriod(period);
 
     if (!mPrimaryHWVsyncEnabled) {
@@ -261,12 +291,13 @@
     }
 }
 
-void Scheduler::addResyncSample(const nsecs_t timestamp) {
+void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodFlushed) {
     bool needsHwVsync = false;
+    *periodFlushed = false;
     { // Scope for the lock
         std::lock_guard<std::mutex> lock(mHWVsyncLock);
         if (mPrimaryHWVsyncEnabled) {
-            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodFlushed);
         }
     }
 
@@ -289,7 +320,7 @@
     mPrimaryDispSync->setIgnorePresentFences(ignore);
 }
 
-nsecs_t Scheduler::expectedPresentTime() {
+nsecs_t Scheduler::getDispSyncExpectedPresentTime() {
     return mPrimaryDispSync->expectedPresentTime();
 }
 
@@ -297,41 +328,79 @@
     mPrimaryDispSync->dump(result);
 }
 
-void Scheduler::addNativeWindowApi(int apiId) {
-    std::lock_guard<std::mutex> lock(mWindowApiHistoryLock);
-    mWindowApiHistory[mApiHistoryCounter] = apiId;
-    mApiHistoryCounter++;
-    mApiHistoryCounter = mApiHistoryCounter % scheduler::ARRAY_SIZE;
+std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer(
+        std::string const& name, int windowType) {
+    RefreshRateType refreshRateType = (windowType == InputWindowInfo::TYPE_WALLPAPER)
+            ? RefreshRateType::DEFAULT
+            : RefreshRateType::PERFORMANCE;
+
+    const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
+    const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
+
+    const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
+    const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
+    return mLayerHistory.createLayer(name, defaultFps, performanceFps);
+}
+
+void Scheduler::addLayerPresentTimeAndHDR(
+        const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle,
+        nsecs_t presentTime, bool isHDR) {
+    mLayerHistory.insert(layerHandle, presentTime, isHDR);
+}
+
+void Scheduler::setLayerVisibility(
+        const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, bool visible) {
+    mLayerHistory.setVisibility(layerHandle, visible);
 }
 
 void Scheduler::withPrimaryDispSync(std::function<void(DispSync&)> const& fn) {
     fn(*mPrimaryDispSync);
 }
 
-void Scheduler::updateFpsBasedOnNativeWindowApi() {
-    int mode;
+void Scheduler::updateFpsBasedOnContent() {
+    auto [refreshRate, isHDR] = mLayerHistory.getDesiredRefreshRateAndHDR();
+    const uint32_t refreshRateRound = std::round(refreshRate);
+    RefreshRateType newRefreshRateType;
     {
-        std::lock_guard<std::mutex> lock(mWindowApiHistoryLock);
-        mode = scheduler::calculate_mode(mWindowApiHistory);
-    }
-    ATRACE_INT("NativeWindowApiMode", mode);
+        std::lock_guard<std::mutex> lock(mFeatureStateLock);
+        if (mContentRefreshRate == refreshRateRound && mIsHDRContent == isHDR) {
+            return;
+        }
+        mContentRefreshRate = refreshRateRound;
+        ATRACE_INT("ContentFPS", mContentRefreshRate);
 
-    if (mode == NATIVE_WINDOW_API_MEDIA) {
-        // TODO(b/127365162): These callback names are not accurate anymore. Update.
-        mediaChangeRefreshRate(MediaFeatureState::MEDIA_PLAYING);
-        ATRACE_INT("DetectedVideo", 1);
-    } else {
-        mediaChangeRefreshRate(MediaFeatureState::MEDIA_OFF);
-        ATRACE_INT("DetectedVideo", 0);
+        mIsHDRContent = isHDR;
+        ATRACE_INT("ContentHDR", mIsHDRContent);
+
+        mCurrentContentFeatureState = refreshRateRound > 0
+                ? ContentFeatureState::CONTENT_DETECTION_ON
+                : ContentFeatureState::CONTENT_DETECTION_OFF;
+        newRefreshRateType = calculateRefreshRateType();
+        if (mRefreshRateType == newRefreshRateType) {
+            return;
+        }
+        mRefreshRateType = newRefreshRateType;
     }
+    changeRefreshRate(newRefreshRateType, ConfigEvent::Changed);
 }
 
 void Scheduler::setChangeRefreshRateCallback(
-        const ChangeRefreshRateCallback& changeRefreshRateCallback) {
+        const ChangeRefreshRateCallback&& changeRefreshRateCallback) {
     std::lock_guard<std::mutex> lock(mCallbackLock);
     mChangeRefreshRateCallback = changeRefreshRateCallback;
 }
 
+void Scheduler::setGetCurrentRefreshRateTypeCallback(
+        const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateTypeCallback) {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    mGetCurrentRefreshRateTypeCallback = getCurrentRefreshRateTypeCallback;
+}
+
+void Scheduler::setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod) {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    mGetVsyncPeriod = getVsyncPeriod;
+}
+
 void Scheduler::updateFrameSkipping(const int64_t skipCount) {
     ATRACE_INT("FrameSkipCount", skipCount);
     if (mSkipCount != skipCount) {
@@ -347,57 +416,176 @@
     }
 }
 
+void Scheduler::notifyTouchEvent() {
+    if (mTouchTimer) {
+        mTouchTimer->reset();
+    }
+
+    if (mSupportKernelTimer) {
+        resetIdleTimer();
+    }
+
+    // Touch event will boost the refresh rate to performance.
+    // Clear Layer History to get fresh FPS detection
+    mLayerHistory.clearHistory();
+}
+
+void Scheduler::setDisplayPowerState(bool normal) {
+    {
+        std::lock_guard<std::mutex> lock(mFeatureStateLock);
+        mIsDisplayPowerStateNormal = normal;
+    }
+
+    if (mDisplayPowerTimer) {
+        mDisplayPowerTimer->reset();
+    }
+
+    // Display Power event will boost the refresh rate to performance.
+    // Clear Layer History to get fresh FPS detection
+    mLayerHistory.clearHistory();
+}
+
 void Scheduler::resetTimerCallback() {
-    // We do not notify the applications about config changes when idle timer is reset.
-    timerChangeRefreshRate(IdleTimerState::RESET);
+    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false);
     ATRACE_INT("ExpiredIdleTimer", 0);
 }
 
+void Scheduler::resetKernelTimerCallback() {
+    ATRACE_INT("ExpiredKernelIdleTimer", 0);
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+        // If we're not in performance mode then the kernel timer shouldn't do
+        // anything, as the refresh rate during DPU power collapse will be the
+        // same.
+        if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
+            resyncToHardwareVsync(true, mGetVsyncPeriod());
+        }
+    }
+}
+
 void Scheduler::expiredTimerCallback() {
-    // We do not notify the applications about config changes when idle timer expires.
-    timerChangeRefreshRate(IdleTimerState::EXPIRED);
+    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false);
     ATRACE_INT("ExpiredIdleTimer", 1);
 }
 
+void Scheduler::resetTouchTimerCallback() {
+    handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true);
+    ATRACE_INT("TouchState", 1);
+}
+
+void Scheduler::expiredTouchTimerCallback() {
+    handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true);
+    ATRACE_INT("TouchState", 0);
+}
+
+void Scheduler::resetDisplayPowerTimerCallback() {
+    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true);
+    ATRACE_INT("ExpiredDisplayPowerTimer", 0);
+}
+
+void Scheduler::expiredDisplayPowerTimerCallback() {
+    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true);
+    ATRACE_INT("ExpiredDisplayPowerTimer", 1);
+}
+
+void Scheduler::expiredKernelTimerCallback() {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    ATRACE_INT("ExpiredKernelIdleTimer", 1);
+    if (mGetCurrentRefreshRateTypeCallback) {
+        if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
+            // Disable HW Vsync if the timer expired, as we don't need it
+            // enabled if we're not pushing frames, and if we're in PERFORMANCE
+            // mode then we'll need to re-update the DispSync model anyways.
+            disableHardwareVsync(false);
+        }
+    }
+}
+
 std::string Scheduler::doDump() {
     std::ostringstream stream;
     stream << "+  Idle timer interval: " << mSetIdleTimerMs << " ms" << std::endl;
+    stream << "+  Touch timer interval: " << mSetTouchTimerMs << " ms" << std::endl;
     return stream.str();
 }
 
-void Scheduler::mediaChangeRefreshRate(MediaFeatureState mediaFeatureState) {
-    // Default playback for media is DEFAULT when media is on.
-    RefreshRateType refreshRateType = RefreshRateType::DEFAULT;
-    ConfigEvent configEvent = ConfigEvent::None;
-
+template <class T>
+void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) {
+    ConfigEvent event = ConfigEvent::None;
+    RefreshRateType newRefreshRateType;
     {
         std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        mCurrentMediaFeatureState = mediaFeatureState;
-        // Only switch to PERFORMANCE if idle timer was reset, when turning
-        // media off. If the timer is IDLE, stay at DEFAULT.
-        if (mediaFeatureState == MediaFeatureState::MEDIA_OFF &&
-            mCurrentIdleTimerState == IdleTimerState::RESET) {
-            refreshRateType = RefreshRateType::PERFORMANCE;
+        if (*currentState == newState) {
+            return;
+        }
+        *currentState = newState;
+        newRefreshRateType = calculateRefreshRateType();
+        if (mRefreshRateType == newRefreshRateType) {
+            return;
+        }
+        mRefreshRateType = newRefreshRateType;
+        if (eventOnContentDetection &&
+            mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) {
+            event = ConfigEvent::Changed;
         }
     }
-    changeRefreshRate(refreshRateType, configEvent);
+    changeRefreshRate(newRefreshRateType, event);
 }
 
-void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) {
-    RefreshRateType refreshRateType = RefreshRateType::DEFAULT;
-    ConfigEvent configEvent = ConfigEvent::None;
+Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
+    // HDR content is not supported on PERFORMANCE mode
+    if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) {
+        return RefreshRateType::DEFAULT;
+    }
 
-    {
-        std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        mCurrentIdleTimerState = idleTimerState;
-        // Only switch to PERFOMANCE if the idle timer was reset, and media is
-        // not playing. Otherwise, stay at DEFAULT.
-        if (idleTimerState == IdleTimerState::RESET &&
-            mCurrentMediaFeatureState == MediaFeatureState::MEDIA_OFF) {
-            refreshRateType = RefreshRateType::PERFORMANCE;
+    // If Display Power is not in normal operation we want to be in performance mode.
+    // When coming back to normal mode, a grace period is given with DisplayPowerTimer
+    if (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == DisplayPowerTimerState::RESET) {
+        return RefreshRateType::PERFORMANCE;
+    }
+
+    // As long as touch is active we want to be in performance mode
+    if (mCurrentTouchState == TouchState::ACTIVE) {
+        return RefreshRateType::PERFORMANCE;
+    }
+
+    // If timer has expired as it means there is no new content on the screen
+    if (mCurrentIdleTimerState == IdleTimerState::EXPIRED) {
+        return RefreshRateType::DEFAULT;
+    }
+
+    // If content detection is off we choose performance as we don't know the content fps
+    if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_OFF) {
+        return RefreshRateType::PERFORMANCE;
+    }
+
+    // Content detection is on, find the appropriate refresh rate with minimal error
+    auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
+                            mRefreshRateConfigs.getRefreshRates().cend(),
+                            [rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
+                                return std::abs(l.second->fps - static_cast<float>(rate)) <
+                                        std::abs(r.second->fps - static_cast<float>(rate));
+                            });
+    RefreshRateType currRefreshRateType = iter->first;
+
+    // Some content aligns better on higher refresh rate. For example for 45fps we should choose
+    // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
+    // align well with both
+    constexpr float MARGIN = 0.05f;
+    float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
+            float(mContentRefreshRate);
+    if (std::abs(std::round(ratio) - ratio) > MARGIN) {
+        while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
+            ratio = iter->second->fps / float(mContentRefreshRate);
+
+            if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
+                currRefreshRateType = iter->first;
+                break;
+            }
+            ++iter;
         }
     }
-    changeRefreshRate(refreshRateType, configEvent);
+
+    return currRefreshRateType;
 }
 
 void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 73896d5..123036e 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -26,9 +26,9 @@
 #include "DispSync.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
 #include "LayerHistory.h"
+#include "OneShotTimer.h"
 #include "RefreshRateConfigs.h"
 #include "SchedulerUtils.h"
 
@@ -49,6 +49,7 @@
     }
 
     using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+    using GetCurrentRefreshRateTypeCallback = std::function<RefreshRateType()>;
     using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
     using GetVsyncPeriod = std::function<nsecs_t()>;
 
@@ -90,17 +91,19 @@
         std::atomic<nsecs_t> lastResyncTime = 0;
     };
 
-    explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function);
+    explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
+                       const scheduler::RefreshRateConfigs& refreshRateConfig);
 
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
-    sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
-                                          ResyncCallback,
+    sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
+                                          nsecs_t offsetThresholdForNextVsync, ResyncCallback,
                                           impl::EventThread::InterceptVSyncsCallback);
 
-    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
-                                                             ResyncCallback);
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            const sp<ConnectionHandle>& handle, ResyncCallback,
+            ISurfaceComposer::ConfigChanged configChanged);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -130,31 +133,56 @@
     // Offers ability to modify phase offset in the event thread.
     void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
 
-    // pause/resume vsync callback generation to avoid sending vsync callbacks during config switch
-    void pauseVsyncCallback(const sp<ConnectionHandle>& handle, bool pause);
-
     void getDisplayStatInfo(DisplayStatInfo* stats);
 
     void enableHardwareVsync();
     void disableHardwareVsync(bool makeUnavailable);
+    // Resyncs the scheduler to hardware vsync.
+    // If makeAvailable is true, then hardware vsync will be turned on.
+    // Otherwise, if hardware vsync is not already enabled then this method will
+    // no-op.
+    // The period is the vsync period from the current display configuration.
     void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
     // Creates a callback for resyncing.
     ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
     void setRefreshSkipCount(int count);
-    void addResyncSample(const nsecs_t timestamp);
+    // Passes a vsync sample to DispSync. periodFlushed will be true if
+    // DispSync detected that the vsync period changed, and false otherwise.
+    void addResyncSample(const nsecs_t timestamp, bool* periodFlushed);
     void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
     void setIgnorePresentFences(bool ignore);
-    nsecs_t expectedPresentTime();
-    // apiId indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer.
-    // TODO(b/123956502): Remove this call with V1 go/content-fps-detection-in-scheduler.
-    void addNativeWindowApi(int apiId);
-    // Updates FPS based on the most occured request for Native Window API.
-    void updateFpsBasedOnNativeWindowApi();
+    nsecs_t getDispSyncExpectedPresentTime();
+    // Registers the layer in the scheduler, and returns the handle for future references.
+    std::unique_ptr<scheduler::LayerHistory::LayerHandle> registerLayer(std::string const& name,
+                                                                        int windowType);
+
+    // Stores present time for a layer.
+    void addLayerPresentTimeAndHDR(
+            const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle,
+            nsecs_t presentTime, bool isHDR);
+    // Stores visibility for a layer.
+    void setLayerVisibility(
+            const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, bool visible);
+    // Updates FPS based on the most content presented.
+    void updateFpsBasedOnContent();
     // Callback that gets invoked when Scheduler wants to change the refresh rate.
-    void setChangeRefreshRateCallback(const ChangeRefreshRateCallback& changeRefreshRateCallback);
+    void setChangeRefreshRateCallback(const ChangeRefreshRateCallback&& changeRefreshRateCallback);
+    void setGetCurrentRefreshRateTypeCallback(
+            const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateType);
+    void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
 
     // Returns whether idle timer is enabled or not
     bool isIdleTimerEnabled() { return mSetIdleTimerMs > 0; }
+
+    // Function that resets the idle timer.
+    void resetIdleTimer();
+
+    // Function that resets the touch timer.
+    void notifyTouchEvent();
+
+    // Function that sets whether display power mode is normal or not.
+    void setDisplayPowerState(bool normal);
+
     // Returns relevant information about Scheduler for dumpsys purposes.
     std::string doDump();
 
@@ -163,7 +191,8 @@
 
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
-            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+            nsecs_t offsetThresholdForNextVsync,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
@@ -171,29 +200,51 @@
 
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
-    enum class MediaFeatureState { MEDIA_PLAYING, MEDIA_OFF };
+    enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF };
     enum class IdleTimerState { EXPIRED, RESET };
+    enum class TouchState { INACTIVE, ACTIVE };
+    enum class DisplayPowerTimerState { EXPIRED, RESET };
 
     // Creates a connection on the given EventThread and forwards the given callbacks.
-    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&);
+    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+                                                       ISurfaceComposer::ConfigChanged);
 
     nsecs_t calculateAverage() const;
     void updateFrameSkipping(const int64_t skipCount);
-    // Function that resets the idle timer.
-    void resetIdleTimer();
+
     // Function that is called when the timer resets.
     void resetTimerCallback();
     // Function that is called when the timer expires.
     void expiredTimerCallback();
+    // Function that is called when the timer resets when paired with a display
+    // driver timeout in the kernel. This enables hardware vsync when we move
+    // out from idle.
+    void resetKernelTimerCallback();
+    // Function that is called when the timer expires when paired with a display
+    // driver timeout in the kernel. This disables hardware vsync when we move
+    // into idle.
+    void expiredKernelTimerCallback();
+    // Function that is called when the touch timer resets.
+    void resetTouchTimerCallback();
+    // Function that is called when the touch timer expires.
+    void expiredTouchTimerCallback();
+    // Function that is called when the display power timer resets.
+    void resetDisplayPowerTimerCallback();
+    // Function that is called when the display power timer expires.
+    void expiredDisplayPowerTimerCallback();
     // Sets vsync period.
     void setVsyncPeriod(const nsecs_t period);
-    // Media feature's function to change the refresh rate.
-    void mediaChangeRefreshRate(MediaFeatureState mediaFeatureState);
-    // Idle timer feature's function to change the refresh rate.
-    void timerChangeRefreshRate(IdleTimerState idleTimerState);
+    // handles various timer features to change the refresh rate.
+    template <class T>
+    void handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection);
+    // Calculate the new refresh rate type
+    RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
     // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters.
     void changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent);
 
+    // Helper function to calculate error frames
+    float getErrorFrames(float contentFps, float configFps);
+
     // If fences from sync Framework are supported.
     const bool mHasSyncFramework;
 
@@ -226,28 +277,48 @@
     std::array<int64_t, scheduler::ARRAY_SIZE> mTimeDifferences{};
     size_t mCounter = 0;
 
-    // The following few fields follow native window api bits that come with buffers. If there are
-    // more buffers with NATIVE_WINDOW_API_MEDIA we render at 60Hz, otherwise we render at 90Hz.
-    // There is not dependency on timestamp for V0.
-    // TODO(b/123956502): Remove this when more robust logic for content fps detection is developed.
-    std::mutex mWindowApiHistoryLock;
-    std::array<int, scheduler::ARRAY_SIZE> mWindowApiHistory GUARDED_BY(mWindowApiHistoryLock);
-    int64_t mApiHistoryCounter = 0;
+    // Historical information about individual layers. Used for predicting the refresh rate.
+    scheduler::LayerHistory mLayerHistory;
 
     // Timer that records time between requests for next vsync. If the time is higher than a given
     // interval, a callback is fired. Set this variable to >0 to use this feature.
     int64_t mSetIdleTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mIdleTimer;
+    // Enables whether to use idle timer callbacks that support the kernel
+    // timer.
+    bool mSupportKernelTimer;
+
+    // Timer used to monitor touch events.
+    int64_t mSetTouchTimerMs = 0;
+    std::unique_ptr<scheduler::OneShotTimer> mTouchTimer;
+
+    // Timer used to monitor display power mode.
+    int64_t mSetDisplayPowerTimerMs = 0;
+    std::unique_ptr<scheduler::OneShotTimer> mDisplayPowerTimer;
 
     std::mutex mCallbackLock;
+    GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
     ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
+    GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
 
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
     std::mutex mFeatureStateLock;
-    MediaFeatureState mCurrentMediaFeatureState GUARDED_BY(mFeatureStateLock) =
-            MediaFeatureState::MEDIA_OFF;
+    ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) =
+            ContentFeatureState::CONTENT_DETECTION_OFF;
     IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
+    TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE;
+    DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) =
+            DisplayPowerTimerState::EXPIRED;
+    uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
+    RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
+    bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false;
+    bool mIsDisplayPowerStateNormal GUARDED_BY(mFeatureStateLock) = true;
+
+    const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
+
+    // Global config to force HDR content to work on DEFAULT refreshRate
+    static constexpr bool mForceHDRContentToDefaultRefreshRate = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index 9e6e8c7..ced1899 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <cinttypes>
 #include <numeric>
 #include <unordered_map>
@@ -23,6 +24,8 @@
 
 namespace android {
 namespace scheduler {
+using namespace std::chrono_literals;
+
 // This number is used to set the size of the arrays in scheduler that hold information
 // about layers.
 static constexpr size_t ARRAY_SIZE = 30;
@@ -31,13 +34,25 @@
 // the config is not visible to SF, and is completely maintained by HWC. However, we would
 // still like to keep track of time when the device is in this config.
 static constexpr int SCREEN_OFF_CONFIG_ID = -1;
+static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
+
+// This number is used when we try to determine how long do we keep layer information around
+// before we remove it. It is also used to determine how long the layer stays relevant.
+// This time period captures infrequent updates when playing YouTube video with static image,
+// or waiting idle in messaging app, when cursor is blinking.
+static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms;
+
+// Layer is considered low activity if the buffers come more than LOW_ACTIVITY_EPSILON_NS
+// apart. This is helping SF to vote for lower refresh rates when there is not activity
+// in screen.
+static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms;
 
 // Calculates the statistical mean (average) in the data structure (array, vector). The
 // function does not modify the contents of the array.
 template <typename T>
 auto calculate_mean(const T& v) {
     using V = typename T::value_type;
-    V sum = std::accumulate(v.begin(), v.end(), 0);
+    V sum = std::accumulate(v.begin(), v.end(), static_cast<V>(0));
     return sum / static_cast<V>(v.size());
 }
 
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
new file mode 100644
index 0000000..7a3bf8e
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2019 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 "VSyncModulator.h"
+
+#include <cutils/properties.h>
+#include <utils/Trace.h>
+
+#include <cinttypes>
+#include <mutex>
+
+namespace android {
+
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+VSyncModulator::VSyncModulator() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.vsync_trace_detailed_info", value, "0");
+    mTraceDetailedInfo = atoi(value);
+    // Populate the offset map with some default offsets.
+    const Offsets defaultOffsets = {RefreshRateType::DEFAULT, 0, 0};
+    setPhaseOffsets(defaultOffsets, defaultOffsets, defaultOffsets, 0);
+}
+
+void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+                                     nsecs_t thresholdForNextVsync) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mOffsetMap.insert_or_assign(OffsetType::Early, early);
+    mOffsetMap.insert_or_assign(OffsetType::EarlyGl, earlyGl);
+    mOffsetMap.insert_or_assign(OffsetType::Late, late);
+    mThresholdForNextVsync = thresholdForNextVsync;
+    updateOffsetsLocked();
+}
+
+void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
+    if (transactionStart == Scheduler::TransactionStart::EARLY) {
+        mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+    }
+
+    // An early transaction stays an early transaction.
+    if (transactionStart == mTransactionStart ||
+        mTransactionStart == Scheduler::TransactionStart::EARLY) {
+        return;
+    }
+    mTransactionStart = transactionStart;
+    updateOffsets();
+}
+
+void VSyncModulator::onTransactionHandled() {
+    if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
+    mTransactionStart = Scheduler::TransactionStart::NORMAL;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeInitiated() {
+    if (mRefreshRateChangePending) {
+        return;
+    }
+    mRefreshRateChangePending = true;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeCompleted() {
+    if (!mRefreshRateChangePending) {
+        return;
+    }
+    mRefreshRateChangePending = false;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshed(bool usedRenderEngine) {
+    bool updateOffsetsNeeded = false;
+    if (mRemainingEarlyFrameCount > 0) {
+        mRemainingEarlyFrameCount--;
+        updateOffsetsNeeded = true;
+    }
+    if (usedRenderEngine) {
+        mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
+        updateOffsetsNeeded = true;
+    } else if (mRemainingRenderEngineUsageCount > 0) {
+        mRemainingRenderEngineUsageCount--;
+        updateOffsetsNeeded = true;
+    }
+    if (updateOffsetsNeeded) {
+        updateOffsets();
+    }
+}
+
+VSyncModulator::Offsets VSyncModulator::getOffsets() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mOffsets;
+}
+
+VSyncModulator::Offsets VSyncModulator::getNextOffsets() {
+    return mOffsetMap.at(getNextOffsetType());
+}
+
+VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() {
+    // Early offsets are used if we're in the middle of a refresh rate
+    // change, or if we recently begin a transaction.
+    if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
+        mRefreshRateChangePending) {
+        return OffsetType::Early;
+    } else if (mRemainingRenderEngineUsageCount > 0) {
+        return OffsetType::EarlyGl;
+    } else {
+        return OffsetType::Late;
+    }
+}
+
+void VSyncModulator::updateOffsets() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    updateOffsetsLocked();
+}
+
+void VSyncModulator::updateOffsetsLocked() {
+    const Offsets desired = getNextOffsets();
+
+    if (mSfConnectionHandle != nullptr) {
+        mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
+    }
+
+    if (mAppConnectionHandle != nullptr) {
+        mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
+    }
+
+    flushOffsets();
+}
+
+void VSyncModulator::flushOffsets() {
+    OffsetType type = getNextOffsetType();
+    mOffsets = mOffsetMap.at(type);
+    if (!mTraceDetailedInfo) {
+        return;
+    }
+    ATRACE_INT("Vsync-EarlyOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early);
+    ATRACE_INT("Vsync-EarlyGLOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl);
+    ATRACE_INT("Vsync-LateOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late);
+    ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early);
+    ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl);
+    ATRACE_INT("Vsync-HighFpsLateOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dab2003..ddbd221 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,8 +16,6 @@
 
 #pragma once
 
-#include <utils/Errors.h>
-
 #include <cinttypes>
 #include <mutex>
 
@@ -30,16 +28,33 @@
  */
 class VSyncModulator {
 private:
-    // Number of frames we'll keep the early phase offsets once they are activated. This acts as a
-    // low-pass filter in case the client isn't quick enough in sending new transactions.
-    const int MIN_EARLY_FRAME_COUNT = 2;
+    // Number of frames we'll keep the early phase offsets once they are activated for a
+    // transaction. This acts as a low-pass filter in case the client isn't quick enough in
+    // sending new transactions.
+    const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
+
+    // Number of frames we'll keep the early gl phase offsets once they are activated.
+    // This acts as a low-pass filter to avoid scenarios where we rapidly
+    // switch in and out of gl composition.
+    const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
 
 public:
+    VSyncModulator();
+
+    // Wrapper for a collection of surfaceflinger/app offsets for a particular
+    // configuration .
     struct Offsets {
+        scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
         nsecs_t sf;
         nsecs_t app;
     };
 
+    enum class OffsetType {
+        Early,
+        EarlyGl,
+        Late,
+    };
+
     // Sets the phase offsets
     //
     // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
@@ -50,31 +65,10 @@
     // appEarly: Like sfEarly, but for the app-vsync
     // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
     // appLate: The regular app vsync phase offset.
-    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
-        mEarlyOffsets = early;
-        mEarlyGlOffsets = earlyGl;
-        mLateOffsets = late;
+    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+                         nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);
 
-        if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
-            mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
-        }
-
-        if (mAppConnectionHandle && late.app != mOffsets.load().app) {
-            mScheduler->setPhaseOffset(mAppConnectionHandle, late.app);
-        }
-
-        mOffsets = late;
-    }
-
-    Offsets getEarlyOffsets() const { return mEarlyOffsets; }
-
-    Offsets getEarlyGlOffsets() const { return mEarlyGlOffsets; }
-
-    void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
-        mSfEventThread = sfEventThread;
-        mAppEventThread = appEventThread;
-    }
-
+    // Sets the scheduler and vsync connection handlers.
     void setSchedulerAndHandles(Scheduler* scheduler,
                                 Scheduler::ConnectionHandle* appConnectionHandle,
                                 Scheduler::ConnectionHandle* sfConnectionHandle) {
@@ -83,97 +77,57 @@
         mSfConnectionHandle = sfConnectionHandle;
     }
 
-    void setTransactionStart(Scheduler::TransactionStart transactionStart) {
-        if (transactionStart == Scheduler::TransactionStart::EARLY) {
-            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
-        }
+    // Signals that a transaction has started, and changes offsets accordingly.
+    void setTransactionStart(Scheduler::TransactionStart transactionStart);
 
-        // An early transaction stays an early transaction.
-        if (transactionStart == mTransactionStart ||
-            mTransactionStart == Scheduler::TransactionStart::EARLY) {
-            return;
-        }
-        mTransactionStart = transactionStart;
-        updateOffsets();
-    }
+    // Signals that a transaction has been completed, so that we can finish
+    // special handling for a transaction.
+    void onTransactionHandled();
 
-    void onTransactionHandled() {
-        if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
-        mTransactionStart = Scheduler::TransactionStart::NORMAL;
-        updateOffsets();
-    }
+    // Called when we send a refresh rate change to hardware composer, so that
+    // we can move into early offsets.
+    void onRefreshRateChangeInitiated();
 
-    void onRefreshed(bool usedRenderEngine) {
-        bool updateOffsetsNeeded = false;
-        if (mRemainingEarlyFrameCount > 0) {
-            mRemainingEarlyFrameCount--;
-            updateOffsetsNeeded = true;
-        }
-        if (usedRenderEngine != mLastFrameUsedRenderEngine) {
-            mLastFrameUsedRenderEngine = usedRenderEngine;
-            updateOffsetsNeeded = true;
-        }
-        if (updateOffsetsNeeded) {
-            updateOffsets();
-        }
-    }
+    // Called when we detect from vsync signals that the refresh rate changed.
+    // This way we can move out of early offsets if no longer necessary.
+    void onRefreshRateChangeCompleted();
+
+    // Called when the display is presenting a new frame. usedRenderEngine
+    // should be set to true if RenderEngine was involved with composing the new
+    // frame.
+    void onRefreshed(bool usedRenderEngine);
+
+    // Returns the offsets that we are currently using
+    Offsets getOffsets() EXCLUDES(mMutex);
 
 private:
-    void updateOffsets() {
-        const Offsets desired = getOffsets();
-        const Offsets current = mOffsets;
+    // Returns the next offsets that we should be using
+    Offsets getNextOffsets() REQUIRES(mMutex);
+    // Returns the next offset type that we should use.
+    OffsetType getNextOffsetType();
+    // Updates offsets and persists them into the scheduler framework.
+    void updateOffsets() EXCLUDES(mMutex);
+    void updateOffsetsLocked() REQUIRES(mMutex);
+    // Updates the internal offsets and offset type.
+    void flushOffsets() REQUIRES(mMutex);
 
-        bool changed = false;
-        if (desired.sf != current.sf) {
-            if (mSfConnectionHandle != nullptr) {
-                mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
-            } else {
-                mSfEventThread->setPhaseOffset(desired.sf);
-            }
-            changed = true;
-        }
-        if (desired.app != current.app) {
-            if (mAppConnectionHandle != nullptr) {
-                mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
-            } else {
-                mAppEventThread->setPhaseOffset(desired.app);
-            }
-            changed = true;
-        }
-
-        if (changed) {
-            mOffsets = desired;
-        }
-    }
-
-    Offsets getOffsets() {
-        if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
-            mRemainingEarlyFrameCount > 0) {
-            return mEarlyOffsets;
-        } else if (mLastFrameUsedRenderEngine) {
-            return mEarlyGlOffsets;
-        } else {
-            return mLateOffsets;
-        }
-    }
-
-    Offsets mLateOffsets;
-    Offsets mEarlyOffsets;
-    Offsets mEarlyGlOffsets;
-
-    EventThread* mSfEventThread = nullptr;
-    EventThread* mAppEventThread = nullptr;
+    mutable std::mutex mMutex;
+    std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
+    nsecs_t mThresholdForNextVsync;
 
     Scheduler* mScheduler = nullptr;
     Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
     Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
 
-    std::atomic<Offsets> mOffsets;
+    Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};
 
     std::atomic<Scheduler::TransactionStart> mTransactionStart =
             Scheduler::TransactionStart::NORMAL;
-    std::atomic<bool> mLastFrameUsedRenderEngine = false;
+    std::atomic<bool> mRefreshRateChangePending = false;
     std::atomic<int> mRemainingEarlyFrameCount = 0;
+    std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+
+    bool mTraceDetailedInfo = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0345baf..99440a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -48,6 +48,8 @@
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <dvr/vr_flinger.h>
 #include <gui/BufferQueue.h>
+#include <gui/DebugEGLImageTracker.h>
+
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/IProducerListener.h>
@@ -95,12 +97,14 @@
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
 #include "Effects/Daltonizer.h"
+#include "RegionSamplingThread.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/DispSyncSource.h"
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/InjectVSyncSource.h"
 #include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
 #include "Scheduler/Scheduler.h"
 #include "TimeStats/TimeStats.h"
 
@@ -111,6 +115,7 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/types.h>
+#include <android/hardware/power/1.0/IPower.h>
 #include <configstore/Utils.h>
 
 #include <layerproto/LayerProtoParser.h>
@@ -122,6 +127,7 @@
 using namespace android::hardware::configstore::V1_0;
 using namespace android::sysprop;
 
+using android::hardware::power::V1_0::PowerHint;
 using base::StringAppendF;
 using ui::ColorMode;
 using ui::Dataspace;
@@ -266,49 +272,17 @@
     }
 }
 
-SurfaceFlingerBE::SurfaceFlingerBE()
-      : mHwcServiceName(getHwcServiceName()),
-        mFrameBuckets(),
-        mTotalTime(0),
-        mLastSwapTime(0),
-        mComposerSequenceId(0) {
-}
+SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
 
-SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory,
-                               SurfaceFlinger::SkipInitializationTag)
-      : BnSurfaceComposer(),
-        mFactory(factory),
-        mTransactionPending(false),
-        mAnimTransactionPending(false),
-        mTraversalNeededMainThread(false),
-        mLayersRemoved(false),
-        mLayersAdded(false),
-        mBootTime(systemTime()),
-        mPhaseOffsets{getFactory().createPhaseOffsets()},
-        mVisibleRegionsDirty(false),
-        mGeometryInvalid(false),
-        mAnimCompositionPending(false),
-        mBootStage(BootStage::BOOTLOADER),
-        mDebugRegion(0),
-        mDebugDisableHWC(0),
-        mDebugDisableTransformHint(0),
-        mDebugEnableProtectedContent(false),
-        mDebugInTransaction(0),
-        mLastTransactionTime(0),
-        mForceFullDamage(false),
-        mTracing(*this),
-        mTimeStats(factory.createTimeStats()),
-        mRefreshStartTime(0),
-        mHasPoweredOff(false),
-        mNumLayers(0),
-        mVrFlingerRequestsDisplay(false),
-        mMainThreadId(std::this_thread::get_id()),
-        mCompositionEngine{getFactory().createCompositionEngine()} {
-    mSetInputWindowsListener = new SetInputWindowsListener(this);
-}
+SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
+      : mFactory(factory),
+        mPhaseOffsets(mFactory.createPhaseOffsets()),
+        mInterceptor(mFactory.createSurfaceInterceptor(this)),
+        mTimeStats(mFactory.createTimeStats()),
+        mEventQueue(mFactory.createMessageQueue()),
+        mCompositionEngine(mFactory.createCompositionEngine()) {}
 
-SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
-      : SurfaceFlinger(factory, SkipInitialization) {
+SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
     ALOGI("SurfaceFlinger is starting");
 
     hasSyncFramework = running_without_sync_framework(true);
@@ -330,8 +304,8 @@
 
     mDefaultCompositionDataspace =
             static_cast<ui::Dataspace>(default_composition_dataspace(Dataspace::V0_SRGB));
-    mWideColorGamutCompositionDataspace =
-            static_cast<ui::Dataspace>(wcg_composition_dataspace(Dataspace::V0_SRGB));
+    mWideColorGamutCompositionDataspace = static_cast<ui::Dataspace>(wcg_composition_dataspace(
+            hasWideColorDisplay ? Dataspace::DISPLAY_P3 : Dataspace::V0_SRGB));
     defaultCompositionDataspace = mDefaultCompositionDataspace;
     wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace;
     defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
@@ -339,6 +313,9 @@
     wideColorGamutCompositionPixelFormat =
             static_cast<ui::PixelFormat>(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888));
 
+    mColorSpaceAgnosticDataspace =
+            static_cast<ui::Dataspace>(color_space_agnostic_dataspace(Dataspace::UNKNOWN));
+
     useContextPriority = use_context_priority(true);
 
     auto tmpPrimaryDisplayOrientation = primary_display_orientation(
@@ -381,6 +358,11 @@
     mPropagateBackpressure = !atoi(value);
     ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
 
+    property_get("debug.sf.enable_gl_backpressure", value, "0");
+    mPropagateBackpressureClientComposition = atoi(value);
+    ALOGI_IF(mPropagateBackpressureClientComposition,
+             "Enabling backpressure propagation for Client Composition");
+
     property_get("debug.sf.enable_hwc_vds", value, "0");
     mUseHwcVirtualDisplays = atoi(value);
     ALOGI_IF(mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
@@ -405,7 +387,8 @@
     mLumaSampling = atoi(value);
 
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
 
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
@@ -427,9 +410,7 @@
     mEventQueue->init(this);
 }
 
-SurfaceFlinger::~SurfaceFlinger()
-{
-}
+SurfaceFlinger::~SurfaceFlinger() = default;
 
 void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
 {
@@ -559,9 +540,9 @@
 
     // 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));
+    mWindowManager = defaultServiceManager()->getService(name);
+    if (mWindowManager != 0) {
+        mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
     }
     sp<IBinder> input(defaultServiceManager()->getService(
             String16("inputflinger")));
@@ -589,14 +570,10 @@
         mBootStage = BootStage::FINISHED;
 
         // set the refresh rate according to the policy
-        const auto displayId = getInternalDisplayIdLocked();
-        LOG_ALWAYS_FATAL_IF(!displayId);
-
         const auto& performanceRefreshRate =
-                mRefreshRateConfigs[*displayId]->getRefreshRate(RefreshRateType::PERFORMANCE);
+                mRefreshRateConfigs.getRefreshRate(RefreshRateType::PERFORMANCE);
 
-        if (performanceRefreshRate &&
-            isConfigAllowed(*displayId, performanceRefreshRate->configId)) {
+        if (performanceRefreshRate && isDisplayConfigAllowed(performanceRefreshRate->configId)) {
             setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
         } else {
             setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
@@ -626,7 +603,11 @@
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
-    postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
+    std::lock_guard lock(mTexturePoolMutex);
+    // We don't change the pool size, so the fix-up logic in postComposition will decide whether
+    // to actually delete this or not based on mTexturePoolSize
+    mTexturePool.push_back(texture);
+    ATRACE_INT("TexturePoolSize", mTexturePool.size());
 }
 
 // Do not call property_set on main thread which will be blocked by init
@@ -640,18 +621,22 @@
     Mutex::Autolock _l(mStateLock);
     // start the EventThread
     mScheduler =
-            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
+                                         mRefreshRateConfigs);
     auto resyncCallback =
             mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
 
     mAppConnectionHandle =
-            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
+            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                          resyncCallback,
                                          impl::EventThread::InterceptVSyncsCallback());
-    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
-                                                       resyncCallback, [this](nsecs_t timestamp) {
-                                                           mInterceptor->saveVSyncEvent(timestamp);
-                                                       });
+    mSfConnectionHandle =
+            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
+                                         resyncCallback, [this](nsecs_t timestamp) {
+                                             mInterceptor->saveVSyncEvent(timestamp);
+                                         });
 
     mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
     mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
@@ -667,6 +652,9 @@
                             renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
     renderEngineFeature |= (useContextPriority ?
                             renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
+    renderEngineFeature |=
+            (enable_protected_contents(false) ? renderengine::RenderEngine::ENABLE_PROTECTED_CONTEXT
+                                              : 0);
 
     // TODO(b/77156734): We need to stop casting and use HAL types when possible.
     // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
@@ -727,19 +715,36 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
-    if (mScheduler->isIdleTimerEnabled()) {
-        mScheduler->setChangeRefreshRateCallback(
-                [this](RefreshRateType type, Scheduler::ConfigEvent event) {
-                    Mutex::Autolock lock(mStateLock);
-                    setRefreshRateTo(type, event);
-                });
-    }
-    mRefreshRateConfigs[*display->getId()] = std::make_shared<scheduler::RefreshRateConfigs>(
-            getHwComposer().getConfigs(*display->getId()));
-    mRefreshRateStats =
-            std::make_unique<scheduler::RefreshRateStats>(mRefreshRateConfigs[*display->getId()],
-                                                          mTimeStats);
-    mRefreshRateStats->setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
+    mScheduler->setChangeRefreshRateCallback(
+            [this](RefreshRateType type, Scheduler::ConfigEvent event) {
+                Mutex::Autolock lock(mStateLock);
+                setRefreshRateTo(type, event);
+            });
+    mScheduler->setGetCurrentRefreshRateTypeCallback([this] {
+        Mutex::Autolock lock(mStateLock);
+        const auto display = getDefaultDisplayDeviceLocked();
+        if (!display) {
+            // If we don't have a default display the fallback to the default
+            // refresh rate type
+            return RefreshRateType::DEFAULT;
+        }
+
+        const int configId = display->getActiveConfig();
+        for (const auto& [type, refresh] : mRefreshRateConfigs.getRefreshRates()) {
+            if (refresh && refresh->configId == configId) {
+                return type;
+            }
+        }
+        // This should never happen, but just gracefully fallback to default.
+        return RefreshRateType::DEFAULT;
+    });
+    mScheduler->setGetVsyncPeriodCallback([this] {
+        Mutex::Autolock lock(mStateLock);
+        return getVsyncPeriod();
+    });
+
+    mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
+    mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
 
     ALOGV("Done initializing");
 }
@@ -814,12 +819,14 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getDisplayConfigsLocked(const sp<IBinder>& displayToken,
-                                                 Vector<DisplayInfo>* configs) {
+status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
+                                           Vector<DisplayInfo>* configs) {
     if (!displayToken || !configs) {
         return BAD_VALUE;
     }
 
+    Mutex::Autolock lock(mStateLock);
+
     const auto displayId = getPhysicalDisplayIdLocked(displayToken);
     if (!displayId) {
         return NAME_NOT_FOUND;
@@ -892,7 +899,9 @@
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = 1e9 / hwConfig->getVsyncPeriod();
-        info.appVsyncOffset = mPhaseOffsets->getCurrentAppOffset();
+        const auto refreshRateType = mRefreshRateConfigs.getRefreshRateType(hwConfig->getId());
+        const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType);
+        info.appVsyncOffset = offset.late.app;
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear
@@ -906,8 +915,7 @@
         //
         // We add an additional 1ms to allow for processing time and
         // differences between the ideal and actual refresh rate.
-        info.presentationDeadline =
-                hwConfig->getVsyncPeriod() - mPhaseOffsets->getCurrentSfOffset() + 1000000;
+        info.presentationDeadline = hwConfig->getVsyncPeriod() - offset.late.sf + 1000000;
 
         // All non-virtual displays are currently considered secure.
         info.secure = true;
@@ -945,18 +953,6 @@
 void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
     ATRACE_CALL();
 
-    // Lock is acquired by setRefreshRateTo.
-    const auto display = getDisplayDeviceLocked(info.displayToken);
-    if (!display) {
-        ALOGE("Attempt to set active config %d for invalid display token %p", info.configId,
-              info.displayToken.get());
-        return;
-    }
-    if (display->isVirtual()) {
-        ALOGW("Attempt to set active config %d for virtual display", info.configId);
-        return;
-    }
-
     // Don't check against the current mode yet. Worst case we set the desired
     // config twice. However event generation config might have changed so we need to update it
     // accordingly
@@ -966,11 +962,18 @@
     mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
 
     if (!mDesiredActiveConfigChanged) {
-        // This is the first time we set the desired
-        mScheduler->pauseVsyncCallback(mAppConnectionHandle, true);
-
         // This will trigger HWC refresh without resetting the idle timer.
         repaintEverythingForHWC();
+        // Start receiving vsync samples now, so that we can detect a period
+        // switch.
+        mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+        // As we called to set period, we will call to onRefreshRateChangeCompleted once
+        // DispSync model is locked.
+        mVsyncModulator.onRefreshRateChangeInitiated();
+        mPhaseOffsets->setRefreshRateType(info.type);
+        const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+        mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                        mPhaseOffsets->getOffsetThresholdForNextVsync());
     }
     mDesiredActiveConfigChanged = true;
     ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
@@ -992,29 +995,47 @@
 void SurfaceFlinger::setActiveConfigInternal() {
     ATRACE_CALL();
 
-    std::lock_guard<std::mutex> lock(mActiveConfigLock);
-    mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display) {
+        return;
+    }
 
-    const auto display = getDisplayDeviceLocked(mUpcomingActiveConfig.displayToken);
+    std::lock_guard<std::mutex> lock(mActiveConfigLock);
+    mRefreshRateStats.setConfigMode(mUpcomingActiveConfig.configId);
+
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
-    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+    mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
+
     if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
         mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
                                     mUpcomingActiveConfig.configId);
     }
 }
 
-bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::desiredActiveConfigChangeDone() {
+    std::lock_guard<std::mutex> lock(mActiveConfigLock);
+    mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
+    mDesiredActiveConfigChanged = false;
+    ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+
+    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+    mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
+    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
+}
+
+bool SurfaceFlinger::performSetActiveConfig() {
     ATRACE_CALL();
     if (mCheckPendingFence) {
-        if (mPreviousPresentFence != Fence::NO_FENCE &&
-            (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled)) {
+        if (previousFrameMissed()) {
             // fence has not signaled yet. wait for the next invalidate
-            repaintEverythingForHWC();
+            mEventQueue->invalidate();
             return true;
         }
 
@@ -1034,26 +1055,22 @@
         desiredActiveConfig = mDesiredActiveConfig;
     }
 
-    const auto display = getDisplayDevice(desiredActiveConfig.displayToken);
+    const auto display = getDefaultDisplayDeviceLocked();
     if (!display || display->getActiveConfig() == desiredActiveConfig.configId) {
         // display is not valid or we are already in the requested mode
         // on both cases there is nothing left to do
-        std::lock_guard<std::mutex> lock(mActiveConfigLock);
-        mScheduler->pauseVsyncCallback(mAppConnectionHandle, false);
-        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
-        mDesiredActiveConfigChanged = false;
-        ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+        desiredActiveConfigChangeDone();
         return false;
     }
 
     // Desired active config was set, it is different than the config currently in use, however
     // allowed configs might have change by the time we process the refresh.
     // Make sure the desired config is still allowed
-    if (!isConfigAllowed(*display->getId(), desiredActiveConfig.configId)) {
-        std::lock_guard<std::mutex> lock(mActiveConfigLock);
-        mDesiredActiveConfig.configId = display->getActiveConfig();
+    if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
+        desiredActiveConfigChangeDone();
         return false;
     }
+
     mUpcomingActiveConfig = desiredActiveConfig;
     const auto displayId = display->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
@@ -1063,7 +1080,7 @@
 
     // we need to submit an empty frame to HWC to start the process
     mCheckPendingFence = true;
-
+    mEventQueue->invalidate();
     return false;
 }
 
@@ -1074,6 +1091,7 @@
     }
 
     std::vector<ColorMode> modes;
+    bool isInternalDisplay = false;
     {
         ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
 
@@ -1083,9 +1101,20 @@
         }
 
         modes = getHwComposer().getColorModes(*displayId);
+        isInternalDisplay = displayId == getInternalDisplayIdLocked();
     }
     outColorModes->clear();
-    std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+
+    // If it's built-in display and the configuration claims it's not wide color capable,
+    // filter out all wide color modes. The typical reason why this happens is that the
+    // hardware is not good enough to support GPU composition of wide color, and thus the
+    // OEMs choose to disable this capability.
+    if (isInternalDisplay && !hasWideColorDisplay) {
+        std::remove_copy_if(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes),
+                            isWideColorMode);
+    } else {
+        std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+    }
 
     return NO_ERROR;
 }
@@ -1232,6 +1261,13 @@
     if (!display) {
         return BAD_VALUE;
     }
+
+    // Use hasWideColorDisplay to override built-in display.
+    const auto displayId = display->getId();
+    if (displayId && displayId == getInternalDisplayIdLocked()) {
+        *outIsWideColorDisplay = hasWideColorDisplay;
+        return NO_ERROR;
+    }
     *outIsWideColorDisplay = display->hasWideColorGamut();
     return NO_ERROR;
 }
@@ -1359,10 +1395,20 @@
     return getHwComposer().setDisplayBrightness(*displayId, brightness);
 }
 
+status_t SurfaceFlinger::notifyPowerHint(int32_t hintId) {
+    PowerHint powerHint = static_cast<PowerHint>(hintId);
+
+    if (powerHint == PowerHint::INTERACTION) {
+        mScheduler->notifyTouchEvent();
+    }
+
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
-        ISurfaceComposer::VsyncSource vsyncSource) {
+        ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
     auto resyncCallback = mScheduler->makeResyncCallback([this] {
         Mutex::Autolock lock(mStateLock);
         return getVsyncPeriod();
@@ -1371,7 +1417,8 @@
     const auto& handle =
             vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
 
-    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
+    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+                                                    configChanged);
 }
 
 // ----------------------------------------------------------------------------
@@ -1381,10 +1428,12 @@
 }
 
 void SurfaceFlinger::signalTransaction() {
+    mScheduler->resetIdleTimer();
     mEventQueue->invalidate();
 }
 
 void SurfaceFlinger::signalLayerUpdate() {
+    mScheduler->resetIdleTimer();
     mEventQueue->invalidate();
 }
 
@@ -1442,7 +1491,11 @@
         return;
     }
 
-    mScheduler->addResyncSample(timestamp);
+    bool periodFlushed = false;
+    mScheduler->addResyncSample(timestamp, &periodFlushed);
+    if (periodFlushed) {
+        mVsyncModulator.onRefreshRateChangeCompleted();
+    }
 }
 
 void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
@@ -1450,29 +1503,19 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
-bool SurfaceFlinger::isConfigAllowed(const DisplayId& displayId, int32_t config) {
-    std::lock_guard lock(mAllowedConfigsLock);
-
-    // if allowed configs are not set yet for this display, every config is considered allowed
-    if (mAllowedConfigs.find(displayId) == mAllowedConfigs.end()) {
-        return true;
-    }
-
-    return mAllowedConfigs[displayId]->isConfigAllowed(config);
+bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) const {
+    return mAllowedDisplayConfigs.empty() || mAllowedDisplayConfigs.count(configId);
 }
 
 void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::ConfigEvent event) {
-    if (mBootStage != BootStage::FINISHED) {
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display || mBootStage != BootStage::FINISHED) {
         return;
     }
     ATRACE_CALL();
 
     // Don't do any updating if the current fps is the same as the new one.
-    const auto displayId = getInternalDisplayIdLocked();
-    LOG_ALWAYS_FATAL_IF(!displayId);
-    const auto displayToken = getInternalDisplayTokenLocked();
-
-    const auto& refreshRateConfig = mRefreshRateConfigs[*displayId]->getRefreshRate(refreshRate);
+    const auto& refreshRateConfig = mRefreshRateConfigs.getRefreshRate(refreshRate);
     if (!refreshRateConfig) {
         ALOGV("Skipping refresh rate change request for unsupported rate.");
         return;
@@ -1480,18 +1523,12 @@
 
     const int desiredConfigId = refreshRateConfig->configId;
 
-    if (!isConfigAllowed(*displayId, desiredConfigId)) {
+    if (!isDisplayConfigAllowed(desiredConfigId)) {
         ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
         return;
     }
 
-    const auto display = getDisplayDeviceLocked(displayToken);
-    if (desiredConfigId == display->getActiveConfig()) {
-        return;
-    }
-
-    mPhaseOffsets->setRefreshRateType(refreshRate);
-    setDesiredActiveConfig({refreshRate, desiredConfigId, getInternalDisplayTokenLocked(), event});
+    setDesiredActiveConfig({refreshRate, desiredConfigId, event});
 }
 
 void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -1530,10 +1567,23 @@
 
 void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mStateLock);
+
+    // Enable / Disable HWVsync from the main thread to avoid race conditions with
+    // display power state.
+    postMessageAsync(new LambdaMessage(
+            [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+}
+
+void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
+    ATRACE_CALL();
+
+    mHWCVsyncPendingState = enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable;
+
     if (const auto displayId = getInternalDisplayIdLocked()) {
-        getHwComposer().setVsyncEnabled(*displayId,
-                                        enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
+        sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
+        if (display && display->isPoweredOn()) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
+        }
     }
 }
 
@@ -1631,12 +1681,39 @@
     setTransactionFlags(eDisplayTransactionNeeded);
 }
 
-void SurfaceFlinger::onMessageReceived(int32_t what) {
+bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS {
+    // We are storing the last 2 present fences. If sf's phase offset is to be
+    // woken up before the actual vsync but targeting the next vsync, we need to check
+    // fence N-2
+    const sp<Fence>& fence =
+            mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+            ? mPreviousPresentFences[0]
+            : mPreviousPresentFences[1];
+
+    return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
+}
+
+void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+    DisplayStatInfo stats;
+    mScheduler->getDisplayStatInfo(&stats);
+    const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
+    // Inflate the expected present time if we're targetting the next vsync.
+    mExpectedPresentTime =
+            mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+            ? presentTime
+            : presentTime + stats.vsyncPeriod;
+}
+
+void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
-            bool frameMissed = mPreviousPresentFence != Fence::NO_FENCE &&
-                    (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
+            // calculate the expected present time once and use the cached
+            // value throughout this frame to make sure all layers are
+            // seeing this same value.
+            populateExpectedPresentTime();
+
+            bool frameMissed = previousFrameMissed();
             bool hwcFrameMissed = mHadDeviceComposition && frameMissed;
             bool gpuFrameMissed = mHadClientComposition && frameMissed;
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
@@ -1658,16 +1735,16 @@
             if (mUseSmart90ForVideo) {
                 // This call is made each time SF wakes up and creates a new frame. It is part
                 // of video detection feature.
-                mScheduler->updateFpsBasedOnNativeWindowApi();
+                mScheduler->updateFpsBasedOnContent();
             }
 
             if (performSetActiveConfig()) {
                 break;
             }
 
-            // For now, only propagate backpressure when missing a hwc frame.
-            if (hwcFrameMissed) {
-                if (mPropagateBackpressure) {
+            if (frameMissed && mPropagateBackpressure) {
+                if ((hwcFrameMissed && !gpuFrameMissed) ||
+                    mPropagateBackpressureClientComposition) {
                     signalLayerUpdate();
                     break;
                 }
@@ -1704,22 +1781,22 @@
     ATRACE_CALL();
     uint32_t transactionFlags = peekTransactionFlags();
 
-    // Apply any ready transactions in the queues if there are still transactions that have not been
-    // applied, wake up during the next vsync period and check again
-    bool transactionNeeded = false;
-    if (!flushTransactionQueues()) {
-        transactionNeeded = true;
+    bool flushedATransaction = flushTransactionQueues();
+
+    bool runHandleTransaction = transactionFlags &&
+            ((transactionFlags != eTransactionFlushNeeded) || flushedATransaction);
+
+    if (runHandleTransaction) {
+        handleTransaction(eTransactionMask);
+    } else {
+        getTransactionFlags(eTransactionFlushNeeded);
     }
 
-    if (transactionFlags) {
-        handleTransaction(transactionFlags);
+    if (transactionFlushNeeded()) {
+        setTransactionFlags(eTransactionFlushNeeded);
     }
 
-    if (transactionNeeded) {
-        setTransactionFlags(eTransactionNeeded);
-    }
-
-    return transactionFlags;
+    return runHandleTransaction;
 }
 
 void SurfaceFlinger::handleMessageRefresh() {
@@ -1757,6 +1834,12 @@
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
+    if (mVisibleRegionsDirty) {
+        mVisibleRegionsDirty = false;
+        if (mTracingEnabled) {
+            mTracing.notify("visibleRegionsDirty");
+        }
+    }
 }
 
 
@@ -1766,9 +1849,6 @@
 
     if (mVisibleRegionsDirty) {
         computeLayerBounds();
-        if (mTracingEnabled) {
-            mTracing.notify("visibleRegionsDirty");
-        }
     }
 
     for (auto& layer : mLayersPendingRefresh) {
@@ -1835,7 +1915,14 @@
             RenderIntent renderIntent;
             pickColorMode(displayDevice, &colorMode, &targetDataspace, &renderIntent);
             display->setColorMode(colorMode, targetDataspace, renderIntent);
+
+            if (isHdrColorMode(colorMode)) {
+                targetDataspace = Dataspace::UNKNOWN;
+            } else if (mColorSpaceAgnosticDataspace != Dataspace::UNKNOWN) {
+                targetDataspace = mColorSpaceAgnosticDataspace;
+            }
         }
+
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             if (layer->isHdrY410()) {
                 layer->forceClientComposition(displayDevice);
@@ -1849,11 +1936,6 @@
                 layer->forceClientComposition(displayDevice);
             }
 
-            // TODO(b/111562338) remove when composer 2.3 is shipped.
-            if (layer->hasColorTransform()) {
-                layer->forceClientComposition(displayDevice);
-            }
-
             if (layer->getRoundedCornerState().radius > 0.0f) {
                 layer->forceClientComposition(displayDevice);
             }
@@ -1867,9 +1949,7 @@
 
             const auto& displayState = display->getState();
             layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport,
-                                   displayDevice->getSupportedPerFrameMetadata(),
-                                   isHdrColorMode(displayState.colorMode) ? Dataspace::UNKNOWN
-                                                                          : targetDataspace);
+                                   displayDevice->getSupportedPerFrameMetadata(), targetDataspace);
         }
     }
 
@@ -2031,9 +2111,11 @@
     }
 
     getBE().mDisplayTimeline.updateSignalTimes();
-    mPreviousPresentFence = displayDevice ? getHwComposer().getPresentFence(*displayDevice->getId())
-                                          : Fence::NO_FENCE;
-    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
+    mPreviousPresentFences[1] = mPreviousPresentFences[0];
+    mPreviousPresentFences[0] = displayDevice
+            ? getHwComposer().getPresentFence(*displayDevice->getId())
+            : Fence::NO_FENCE;
+    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
     DisplayStatInfo stats;
@@ -2115,21 +2197,33 @@
 
     {
         std::lock_guard lock(mTexturePoolMutex);
-        const size_t refillCount = mTexturePoolSize - mTexturePool.size();
-        if (refillCount > 0) {
+        if (mTexturePool.size() < mTexturePoolSize) {
+            const size_t refillCount = mTexturePoolSize - mTexturePool.size();
             const size_t offset = mTexturePool.size();
             mTexturePool.resize(mTexturePoolSize);
             getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
             ATRACE_INT("TexturePoolSize", mTexturePool.size());
+        } else if (mTexturePool.size() > mTexturePoolSize) {
+            const size_t deleteCount = mTexturePool.size() - mTexturePoolSize;
+            const size_t offset = mTexturePoolSize;
+            getRenderEngine().deleteTextures(deleteCount, mTexturePool.data() + offset);
+            mTexturePool.resize(mTexturePoolSize);
+            ATRACE_INT("TexturePoolSize", mTexturePool.size());
         }
     }
 
-    mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
+    mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
     mTransactionCompletedThread.sendCallbacks();
 
     if (mLumaSampling && mRegionSamplingThread) {
         mRegionSamplingThread->notifyNewContent();
     }
+
+    // Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the
+    // side-effect of getTotalSize(), so we check that again here
+    if (ATRACE_ENABLED()) {
+        ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize());
+    }
 }
 
 void SurfaceFlinger::computeLayerBounds() {
@@ -2154,7 +2248,6 @@
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
         ATRACE_NAME("rebuildLayerStacks VR Dirty");
-        mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
         for (const auto& pair : mDisplays) {
@@ -2242,8 +2335,9 @@
 //  - Dataspace::UNKNOWN
 //  - Dataspace::BT2020_HLG
 //  - Dataspace::BT2020_PQ
-Dataspace SurfaceFlinger::getBestDataspace(const sp<const DisplayDevice>& display,
-                                           Dataspace* outHdrDataSpace) const {
+Dataspace SurfaceFlinger::getBestDataspace(const sp<DisplayDevice>& display,
+                                           Dataspace* outHdrDataSpace,
+                                           bool* outIsHdrClientComposition) const {
     Dataspace bestDataSpace = Dataspace::V0_SRGB;
     *outHdrDataSpace = Dataspace::UNKNOWN;
 
@@ -2264,6 +2358,7 @@
             case Dataspace::BT2020_ITU_PQ:
                 bestDataSpace = Dataspace::DISPLAY_P3;
                 *outHdrDataSpace = Dataspace::BT2020_PQ;
+                *outIsHdrClientComposition = layer->getForceClientComposition(display);
                 break;
             case Dataspace::BT2020_HLG:
             case Dataspace::BT2020_ITU_HLG:
@@ -2293,7 +2388,8 @@
     }
 
     Dataspace hdrDataSpace;
-    Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace);
+    bool isHdrClientComposition = false;
+    Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace, &isHdrClientComposition);
 
     auto* profile = display->getCompositionDisplay()->getDisplayColorProfile();
 
@@ -2309,8 +2405,8 @@
     }
 
     // respect hdrDataSpace only when there is no legacy HDR support
-    const bool isHdr =
-            hdrDataSpace != Dataspace::UNKNOWN && !profile->hasLegacyHdrSupport(hdrDataSpace);
+    const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN &&
+            !profile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
     if (isHdr) {
         bestDataSpace = hdrDataSpace;
     }
@@ -2417,8 +2513,6 @@
     const auto& displayState = display->getState();
     const auto displayId = display->getId();
 
-    mPostFramebufferTime = systemTime();
-
     if (displayState.isEnabled) {
         if (displayId) {
             getHwComposer().presentAndGetReleaseFences(*displayId);
@@ -2481,8 +2575,7 @@
     State drawingState(mDrawingState);
 
     Mutex::Autolock _l(mStateLock);
-    const nsecs_t now = systemTime();
-    mDebugInTransaction = now;
+    mDebugInTransaction = systemTime();
 
     // Here we're guaranteed that some transaction flags are set
     // so we can call handleTransactionLocked() unconditionally.
@@ -2494,7 +2587,6 @@
     transactionFlags = getTransactionFlags(eTransactionMask);
     handleTransactionLocked(transactionFlags);
 
-    mLastTransactionTime = systemTime() - now;
     mDebugInTransaction = 0;
     invalidateHwcGeometry();
     // here the transaction has been committed
@@ -2519,9 +2611,6 @@
                 state.displayName = info->name;
                 mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state);
                 mInterceptor->saveDisplayCreation(state);
-                // TODO(b/123715322): Removes the per-display state that was added to the scheduler.
-                mRefreshRateConfigs[info->id] = std::make_shared<scheduler::RefreshRateConfigs>(
-                        getHwComposer().getConfigs(info->id));
             }
         } else {
             ALOGV("Removing display %s", to_string(info->id).c_str());
@@ -2533,7 +2622,6 @@
                 mCurrentState.displays.removeItemsAt(index);
             }
             mPhysicalDisplayTokens.erase(info->id);
-            mRefreshRateConfigs.erase(info->id);
         }
 
         processDisplayChangesLocked();
@@ -2936,7 +3024,7 @@
 }
 
 void SurfaceFlinger::commitInputWindowCommands() {
-    mInputWindowCommands.merge(mPendingInputWindowCommands);
+    mInputWindowCommands = mPendingInputWindowCommands;
     mPendingInputWindowCommands.clear();
 }
 
@@ -2986,6 +3074,13 @@
             if (l->isRemovedFromCurrentState()) {
                 latchAndReleaseBuffer(l);
             }
+
+            // If the layer has been removed and has no parent, then it will not be reachable
+            // when traversing layers on screen. Add the layer to the offscreenLayers set to
+            // ensure we can copy its current to drawing state.
+            if (!l->getParent()) {
+                mOffscreenLayers.emplace(l.get());
+            }
         }
         mLayersPendingRemoval.clear();
     }
@@ -2999,7 +3094,17 @@
         // clear the "changed" flags in current state
         mCurrentState.colorMatrixChanged = false;
 
-        mDrawingState.traverseInZOrder([](Layer* layer) { layer->commitChildList(); });
+        mDrawingState.traverseInZOrder([&](Layer* layer) {
+            layer->commitChildList();
+
+            // If the layer can be reached when traversing mDrawingState, then the layer is no
+            // longer offscreen. Remove the layer from the offscreenLayer set.
+            if (mOffscreenLayers.count(layer)) {
+                mOffscreenLayers.erase(layer);
+            }
+        });
+
+        commitOffscreenLayers();
     });
 
     mTransactionPending = false;
@@ -3027,6 +3132,18 @@
     }
 }
 
+void SurfaceFlinger::commitOffscreenLayers() {
+    for (Layer* offscreenLayer : mOffscreenLayers) {
+        offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [](Layer* layer) {
+            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+            if (!trFlags) return;
+
+            layer->doTransaction(0);
+            layer->commitChildList();
+        });
+    }
+}
+
 void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
                                            Region& outDirtyRegion, Region& outOpaqueRegion) {
     ATRACE_CALL();
@@ -3179,6 +3296,7 @@
 
 bool SurfaceFlinger::handlePageFlip()
 {
+    ATRACE_CALL();
     ALOGV("handlePageFlip");
 
     nsecs_t latchTime = systemTime();
@@ -3199,11 +3317,11 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (layer->hasReadyFrame()) {
             frameQueued = true;
-            nsecs_t expectedPresentTime;
-            expectedPresentTime = mScheduler->expectedPresentTime();
+            const nsecs_t expectedPresentTime = getExpectedPresentTime();
             if (layer->shouldPresentNow(expectedPresentTime)) {
                 mLayersWithQueuedFrames.push_back(layer);
             } else {
+                ATRACE_NAME("!layer->shouldPresentNow()");
                 layer->useEmptyDamage();
             }
         } else {
@@ -3280,15 +3398,13 @@
     const auto& displayState = display->getState();
     const auto displayId = display->getId();
     auto& renderEngine = getRenderEngine();
-    const bool supportProtectedContent =
-            mDebugEnableProtectedContent && renderEngine.supportsProtectedContent();
+    const bool supportProtectedContent = renderEngine.supportsProtectedContent();
 
     const Region bounds(displayState.bounds);
     const DisplayRenderArea renderArea(displayDevice);
     const bool hasClientComposition = getHwComposer().hasClientComposition(displayId);
     ATRACE_INT("hasClientComposition", hasClientComposition);
 
-    mat4 colorMatrix;
     bool applyColorMatrix = false;
 
     renderengine::DisplaySettings clientCompositionDisplay;
@@ -3308,8 +3424,11 @@
                     break;
                 }
             }
-            if (needsProtected != renderEngine.isProtected() &&
-                renderEngine.useProtectedContext(needsProtected)) {
+            if (needsProtected != renderEngine.isProtected()) {
+                renderEngine.useProtectedContext(needsProtected);
+            }
+            if (needsProtected != display->getRenderSurface()->isProtected() &&
+                needsProtected == renderEngine.isProtected()) {
                 display->getRenderSurface()->setProtected(needsProtected);
             }
         }
@@ -3327,6 +3446,7 @@
         clientCompositionDisplay.clip = displayState.scissor;
         const ui::Transform& displayTransform = displayState.transform;
         clientCompositionDisplay.globalTransform = displayTransform.asMatrix4();
+        clientCompositionDisplay.orientation = displayState.orientation;
 
         const auto* profile = display->getDisplayColorProfile();
         Dataspace outputDataspace = Dataspace::UNKNOWN;
@@ -3346,7 +3466,7 @@
         // Compute the global color transform matrix.
         applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
         if (applyColorMatrix) {
-            clientCompositionDisplay.colorTransform = colorMatrix;
+            clientCompositionDisplay.colorTransform = displayState.colorTransformMat;
         }
     }
 
@@ -3439,33 +3559,37 @@
         renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers,
                                 buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd),
                                 readyFence);
-        if (expensiveRenderingExpected && displayId) {
-            mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false);
-        }
+    } else if (displayId) {
+        mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false);
     }
     return true;
 }
 
-void SurfaceFlinger::drawWormhole(const Region& region) const {
-    auto& engine(getRenderEngine());
-    engine.fillRegionWithColor(region, 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,
-        bool addToCurrentState)
-{
+status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+                                        const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+                                        const sp<IBinder>& parentHandle,
+                                        const sp<Layer>& parentLayer, bool addToCurrentState) {
     // add this layer to the current state list
     {
         Mutex::Autolock _l(mStateLock);
+        sp<Layer> parent;
+        if (parentHandle != nullptr) {
+            parent = fromHandle(parentHandle);
+            if (parent == nullptr) {
+                return NAME_NOT_FOUND;
+            }
+        } else {
+            parent = parentLayer;
+        }
+
         if (mNumLayers >= MAX_LAYERS) {
             ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
                   MAX_LAYERS);
             return NO_MEMORY;
         }
+
+        mLayersByLocalBinderToken.emplace(handle->localBinder(), lbc);
+
         if (parent == nullptr && addToCurrentState) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else if (parent == nullptr) {
@@ -3517,27 +3641,48 @@
 }
 
 bool SurfaceFlinger::flushTransactionQueues() {
-    Mutex::Autolock _l(mStateLock);
-    auto it = mTransactionQueues.begin();
-    while (it != mTransactionQueues.end()) {
-        auto& [applyToken, transactionQueue] = *it;
+    // to prevent onHandleDestroyed from being called while the lock is held,
+    // we must keep a copy of the transactions (specifically the composer
+    // states) around outside the scope of the lock
+    std::vector<const TransactionState> transactions;
+    bool flushedATransaction = false;
+    {
+        Mutex::Autolock _l(mStateLock);
 
-        while (!transactionQueue.empty()) {
-            const auto&
-                    [states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks,
-                     postTime, privileged] = transactionQueue.front();
-            if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
-                break;
+        auto it = mTransactionQueues.begin();
+        while (it != mTransactionQueues.end()) {
+            auto& [applyToken, transactionQueue] = *it;
+
+            while (!transactionQueue.empty()) {
+                const auto& transaction = transactionQueue.front();
+                if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+                                                   transaction.states)) {
+                    setTransactionFlags(eTransactionFlushNeeded);
+                    break;
+                }
+                transactions.push_back(transaction);
+                applyTransactionState(transaction.states, transaction.displays, transaction.flags,
+                                      mPendingInputWindowCommands, transaction.desiredPresentTime,
+                                      transaction.buffer, transaction.callback,
+                                      transaction.postTime, transaction.privileged,
+                                      /*isMainThread*/ true);
+                transactionQueue.pop();
+                flushedATransaction = true;
             }
-            applyTransactionState(states, displays, flags, mPendingInputWindowCommands,
-                                  desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime,
-                                  privileged, /*isMainThread*/ true);
-            transactionQueue.pop();
-        }
 
-        it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+            if (transactionQueue.empty()) {
+                it = mTransactionQueues.erase(it);
+                mTransactionCV.broadcast();
+            } else {
+                it = std::next(it, 1);
+            }
+        }
     }
-    return mTransactionQueues.empty();
+    return flushedATransaction;
+}
+
+bool SurfaceFlinger::transactionFlushNeeded() {
+    return !mTransactionQueues.empty();
 }
 
 bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) {
@@ -3564,7 +3709,7 @@
 
 bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                                    const Vector<ComposerState>& states) {
-    nsecs_t expectedPresentTime = mScheduler->expectedPresentTime();
+    nsecs_t expectedPresentTime = getExpectedPresentTime();
     // Do not present if the desiredPresentTime has not passed unless it is more than one second
     // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
     if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
@@ -3589,7 +3734,7 @@
                                          const sp<IBinder>& applyToken,
                                          const InputWindowCommands& inputWindowCommands,
                                          int64_t desiredPresentTime,
-                                         const cached_buffer_t& uncacheBuffer,
+                                         const client_cache_t& uncacheBuffer,
                                          const std::vector<ListenerCallbacks>& listenerCallbacks) {
     ATRACE_CALL();
 
@@ -3604,12 +3749,27 @@
     }
 
     // If its TransactionQueue already has a pending TransactionState or if it is pending
-    if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+    auto itr = mTransactionQueues.find(applyToken);
+    // if this is an animation frame, wait until prior animation frame has
+    // been applied by SF
+    if (flags & eAnimation) {
+        while (itr != mTransactionQueues.end()) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                ALOGW_IF(err == TIMED_OUT,
+                         "setTransactionState timed out "
+                         "waiting for animation frame to apply");
+                break;
+            }
+            itr = mTransactionQueues.find(applyToken);
+        }
+    }
+    if (itr != mTransactionQueues.end() ||
         !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
         mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
                                                uncacheBuffer, listenerCallbacks, postTime,
                                                privileged);
-        setTransactionFlags(eTransactionNeeded);
+        setTransactionFlags(eTransactionFlushNeeded);
         return;
     }
 
@@ -3621,7 +3781,7 @@
                                            const Vector<DisplayState>& displays, uint32_t flags,
                                            const InputWindowCommands& inputWindowCommands,
                                            const int64_t desiredPresentTime,
-                                           const cached_buffer_t& uncacheBuffer,
+                                           const client_cache_t& uncacheBuffer,
                                            const std::vector<ListenerCallbacks>& listenerCallbacks,
                                            const int64_t postTime, bool privileged,
                                            bool isMainThread) {
@@ -3630,7 +3790,7 @@
     if (flags & eAnimation) {
         // For window updates that are part of an animation we must wait for
         // previous animation "frames" to be handled.
-        while (mAnimTransactionPending) {
+        while (!isMainThread && 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
@@ -3653,8 +3813,8 @@
     if (!listenerCallbacks.empty()) {
         mTransactionCompletedThread.run();
     }
-    for (const auto& [listener, callbackIds] : listenerCallbacks) {
-        mTransactionCompletedThread.addCallback(listener, callbackIds);
+    for (const auto& listenerCallback : listenerCallbacks) {
+        mTransactionCompletedThread.startRegistration(listenerCallback);
     }
 
     uint32_t clientStateFlags = 0;
@@ -3663,16 +3823,20 @@
                                                  postTime, privileged);
     }
 
+    for (const auto& listenerCallback : listenerCallbacks) {
+        mTransactionCompletedThread.endRegistration(listenerCallback);
+    }
+
     // If the state doesn't require a traversal and there are callbacks, send them now
-    if (!(clientStateFlags & eTraversalNeeded)) {
+    if (!(clientStateFlags & eTraversalNeeded) && !listenerCallbacks.empty()) {
         mTransactionCompletedThread.sendCallbacks();
     }
     transactionFlags |= clientStateFlags;
 
     transactionFlags |= addInputWindowCommands(inputWindowCommands);
 
-    if (uncacheBuffer.token) {
-        BufferStateLayerCache::getInstance().erase(uncacheBuffer.token, uncacheBuffer.cacheId);
+    if (uncacheBuffer.isValid()) {
+        ClientCache::getInstance().erase(uncacheBuffer);
     }
 
     // If a synchronous transaction is explicitly requested without any changes, force a transaction
@@ -3709,8 +3873,9 @@
         if (flags & eAnimation) {
             mAnimTransactionPending = true;
         }
-
-        mPendingSyncInputWindows = mPendingInputWindowCommands.syncInputWindows;
+        if (mPendingInputWindowCommands.syncInputWindows) {
+            mPendingSyncInputWindows = true;
+        }
 
         // applyTransactionState can be called by either the main SF thread or by
         // another process through setTransactionState.  While a given process may wish
@@ -3798,6 +3963,11 @@
 
     sp<Layer> layer(client->getLayerUser(s.surface));
     if (layer == nullptr) {
+        for (auto& listenerCallback : listenerCallbacks) {
+            mTransactionCompletedThread.registerUnpresentedCallbackHandle(
+                    new CallbackHandle(listenerCallback.transactionCompletedListener,
+                                       listenerCallback.callbackIds, s.surface));
+        }
         return 0;
     }
 
@@ -4027,20 +4197,19 @@
     bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
     sp<GraphicBuffer> buffer;
     if (bufferChanged && cacheIdChanged) {
-        BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.cacheId,
-                                                 s.buffer);
+        ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
+        ClientCache::getInstance().registerErasedRecipient(s.cachedBuffer,
+                                                           wp<ClientCache::ErasedRecipient>(layer));
+        getRenderEngine().cacheExternalTextureBuffer(s.buffer);
         buffer = s.buffer;
     } else if (cacheIdChanged) {
-        buffer = BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
-                                                          s.cachedBuffer.cacheId);
+        buffer = ClientCache::getInstance().get(s.cachedBuffer);
     } else if (bufferChanged) {
         buffer = s.buffer;
     }
     if (buffer) {
-        if (layer->setBuffer(buffer)) {
+        if (layer->setBuffer(buffer, postTime, desiredPresentTime, s.cachedBuffer)) {
             flags |= eTraversalNeeded;
-            layer->setPostTime(postTime);
-            layer->setDesiredPresentTime(desiredPresentTime);
         }
     }
     if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded;
@@ -4066,13 +4235,19 @@
 status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
                                      uint32_t h, PixelFormat format, uint32_t flags,
                                      LayerMetadata metadata, sp<IBinder>* handle,
-                                     sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
+                                     sp<IGraphicBufferProducer>* gbp,
+                                     const sp<IBinder>& parentHandle,
+                                     const sp<Layer>& parentLayer) {
     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;
     }
 
+    ALOG_ASSERT(parentLayer == nullptr || parentHandle == nullptr,
+            "Expected only one of parentLayer or parentHandle to be non-null. "
+            "Programmer error?");
+
     status_t result = NO_ERROR;
 
     sp<Layer> layer;
@@ -4086,7 +4261,7 @@
     if (metadata.has(METADATA_WINDOW_TYPE)) {
         int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
         if (windowType == 441731) {
-            metadata.setInt32(METADATA_WINDOW_TYPE, 2024); // TYPE_NAVIGATION_BAR_PANEL
+            metadata.setInt32(METADATA_WINDOW_TYPE, InputWindowInfo::TYPE_NAVIGATION_BAR_PANEL);
             primaryDisplayOnly = true;
         }
     }
@@ -4136,8 +4311,8 @@
     }
 
     bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
-    result = addClientLayer(client, *handle, *gbp, layer, *parent,
-            addToCurrentState);
+    result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
+                            addToCurrentState);
     if (result != NO_ERROR) {
         return result;
     }
@@ -4254,6 +4429,16 @@
         mCurrentState.layersSortedByZ.remove(layer);
     }
     markLayerPendingRemovalLocked(layer);
+
+    auto it = mLayersByLocalBinderToken.begin();
+    while (it != mLayersByLocalBinderToken.end()) {
+        if (it->second == layer) {
+            it = mLayersByLocalBinderToken.erase(it);
+        } else {
+            it++;
+        }
+    }
+
     layer.clear();
 }
 
@@ -4299,6 +4484,13 @@
             new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
 }
 
+void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled) {
+    if (mHWCVsyncState != enabled) {
+        getHwComposer().setVsyncEnabled(displayId, enabled);
+        mHWCVsyncState = enabled;
+    }
+}
+
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
     if (display->isVirtual()) {
         ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
@@ -4325,6 +4517,7 @@
         // Turn on the display
         getHwComposer().setPowerMode(*displayId, mode);
         if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
             mScheduler->onScreenAcquired(mAppConnectionHandle);
             mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
         }
@@ -4350,6 +4543,9 @@
             mScheduler->onScreenReleased(mAppConnectionHandle);
         }
 
+        // Make sure HWVsync is disabled before turning off the display
+        setVsyncEnabledInHWC(*displayId, HWC2::Vsync::Disable);
+
         getHwComposer().setPowerMode(*displayId, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
@@ -4375,10 +4571,8 @@
 
     if (display->isPrimary()) {
         mTimeStats->setPowerMode(mode);
-        if (mRefreshRateStats) {
-            // Update refresh rate stats.
-            mRefreshRateStats->setPowerMode(mode);
-        }
+        mRefreshRateStats.setPowerMode(mode);
+        mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL);
     }
 
     ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
@@ -4543,6 +4737,14 @@
     StringAppendF(&result, "Scheduler enabled.");
     StringAppendF(&result, "+  Smart 90 for video detection: %s\n\n",
                   mUseSmart90ForVideo ? "on" : "off");
+    StringAppendF(&result, "Allowed Display Configs: ");
+    for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
+        if (refresh.second && isDisplayConfigAllowed(refresh.second->configId)) {
+            StringAppendF(&result, "%dHz, ", refresh.second->fps);
+        }
+    }
+    StringAppendF(&result, "(config override by backdoor: %s)\n\n",
+                  mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
     mScheduler->dump(mAppConnectionHandle, result);
 }
 
@@ -4668,7 +4870,7 @@
 }
 
 void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
-    StringAppendF(&result, "Device has wide color display: %d\n", hasWideColorDisplay);
+    StringAppendF(&result, "Device has wide color built-in display: %d\n", hasWideColorDisplay);
     StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
     StringAppendF(&result, "DisplayColorSetting: %s\n",
                   decodeDisplayColorSetting(mDisplayColorSetting).c_str());
@@ -4828,6 +5030,8 @@
 
     getRenderEngine().dump(result);
 
+    DebugEGLImageTracker::getInstance()->dump(result);
+
     if (const auto display = getDefaultDisplayDeviceLocked()) {
         display->getCompositionDisplay()->getState().undefinedRegion.dump(result,
                                                                           "undefinedRegion");
@@ -4906,7 +5110,10 @@
     result.append("\nScheduler state:\n");
     result.append(mScheduler->doDump() + "\n");
     StringAppendF(&result, "+  Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
-    result.append(mRefreshRateStats->doDump() + "\n");
+    result.append(mRefreshRateStats.doDump() + "\n");
+
+    result.append(mTimeStats->miniDump());
+    result.append("\n");
 }
 
 const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
@@ -4967,7 +5174,8 @@
         case SET_POWER_MODE:
         case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
         case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
-        case GET_DISPLAYED_CONTENT_SAMPLE: {
+        case GET_DISPLAYED_CONTENT_SAMPLE:
+        case NOTIFY_POWER_HINT: {
             if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
                 IPCThreadState* ipc = IPCThreadState::self();
                 ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
@@ -5013,7 +5221,18 @@
         case SET_DISPLAY_BRIGHTNESS: {
             return OK;
         }
-        case CAPTURE_LAYERS:
+        case CAPTURE_LAYERS: {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            // allow media to capture layer for video thumbnails
+            if ((uid != AID_GRAPHICS && uid != AID_MEDIA) &&
+                !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+                ALOGE("Permission Denial: can't capture layer pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+            return OK;
+        }
         case CAPTURE_SCREEN:
         case ADD_REGION_SAMPLING_LISTENER:
         case REMOVE_REGION_SAMPLING_LISTENER: {
@@ -5034,6 +5253,14 @@
             ALOGE("Attempting to access SurfaceFlinger with unused code: %u", code);
             return PERMISSION_DENIED;
         }
+        case CAPTURE_SCREEN_BY_ID: {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int uid = ipc->getCallingUid();
+            if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
+                return OK;
+            }
+            return PERMISSION_DENIED;
+        }
     }
 
     // These codes are used for the IBinder protocol to either interrogate the recipient
@@ -5046,7 +5273,7 @@
     }
     // Numbers from 1000 to 1034 are currently used for backdoors. The code
     // in onTransact verifies that the user is root, and has access to use SF.
-    if (code >= 1000 && code <= 1034) {
+    if (code >= 1000 && code <= 1035) {
         ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
         return OK;
     }
@@ -5103,13 +5330,13 @@
             }
             case 1008:  // toggle use of hw composer
                 n = data.readInt32();
-                mDebugDisableHWC = n ? 1 : 0;
+                mDebugDisableHWC = n != 0;
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
             case 1009:  // toggle use of transform hint
                 n = data.readInt32();
-                mDebugDisableTransformHint = n ? 1 : 0;
+                mDebugDisableTransformHint = n != 0;
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -5191,7 +5418,7 @@
             }
             case 1017: {
                 n = data.readInt32();
-                mForceFullDamage = static_cast<bool>(n);
+                mForceFullDamage = n != 0;
                 return NO_ERROR;
             }
             case 1018: { // Modify Choreographer's phase offset
@@ -5229,7 +5456,12 @@
                 return NO_ERROR;
             }
             case 1023: { // Set native mode
+                int32_t colorMode;
+
                 mDisplayColorSetting = static_cast<DisplayColorSetting>(data.readInt32());
+                if (data.readInt32(&colorMode) == NO_ERROR) {
+                    mForceColorMode = static_cast<ColorMode>(colorMode);
+                }
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -5349,11 +5581,6 @@
                 }
                 return NO_ERROR;
             }
-            case 1032: {
-                n = data.readInt32();
-                mDebugEnableProtectedContent = n;
-                return NO_ERROR;
-            }
             // Set trace flags
             case 1033: {
                 n = data.readUint32();
@@ -5366,14 +5593,31 @@
                 // TODO(b/129297325): expose this via developer menu option
                 n = data.readInt32();
                 if (n && !mRefreshRateOverlay) {
-                    std::lock_guard<std::mutex> lock(mActiveConfigLock);
+                    RefreshRateType type;
+                    {
+                        std::lock_guard<std::mutex> lock(mActiveConfigLock);
+                        type = mDesiredActiveConfig.type;
+                    }
                     mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
-                    mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type);
+                    mRefreshRateOverlay->changeRefreshRate(type);
                 } else if (!n) {
                     mRefreshRateOverlay.reset();
                 }
                 return NO_ERROR;
             }
+            case 1035: {
+                n = data.readInt32();
+                mDebugDisplayConfigSetByBackdoor = false;
+                if (n >= 0) {
+                    const auto displayToken = getInternalDisplayToken();
+                    status_t result = setAllowedDisplayConfigs(displayToken, {n});
+                    if (result != NO_ERROR) {
+                        return result;
+                    }
+                    mDebugDisplayConfigSetByBackdoor = true;
+                }
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -5386,7 +5630,7 @@
 
 void SurfaceFlinger::repaintEverythingForHWC() {
     mRepaintEverything = true;
-    mEventQueue->invalidateForHWC();
+    mEventQueue->invalidate();
 }
 
 // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
@@ -5403,7 +5647,8 @@
 };
 
 status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken,
-                                       sp<GraphicBuffer>* outBuffer, const Dataspace reqDataspace,
+                                       sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers,
+                                       const Dataspace reqDataspace,
                                        const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
                                        uint32_t reqWidth, uint32_t reqHeight,
                                        bool useIdentityTransform,
@@ -5436,13 +5681,79 @@
     auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
                                     std::placeholders::_1);
     return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
-                               useIdentityTransform);
+                               useIdentityTransform, outCapturedSecureLayers);
 }
 
-status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
-                                       sp<GraphicBuffer>* outBuffer, const Dataspace reqDataspace,
-                                       const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
-                                       float frameScale, bool childrenOnly) {
+static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) {
+    switch (colorMode) {
+        case ColorMode::DISPLAY_P3:
+        case ColorMode::BT2100_PQ:
+        case ColorMode::BT2100_HLG:
+        case ColorMode::DISPLAY_BT2020:
+            return Dataspace::DISPLAY_P3;
+        default:
+            return Dataspace::V0_SRGB;
+    }
+}
+
+const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
+    const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
+    if (displayToken) {
+        return getDisplayDeviceLocked(displayToken);
+    }
+    // Couldn't find display by displayId. Try to get display by layerStack since virtual displays
+    // may not have a displayId.
+    for (const auto& [token, display] : mDisplays) {
+        if (display->getLayerStack() == displayOrLayerStack) {
+            return display;
+        }
+    }
+    return nullptr;
+}
+
+status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace,
+                                       sp<GraphicBuffer>* outBuffer) {
+    sp<DisplayDevice> display;
+    uint32_t width;
+    uint32_t height;
+    ui::Transform::orientation_flags captureOrientation;
+    {
+        Mutex::Autolock _l(mStateLock);
+        display = getDisplayByIdOrLayerStack(displayOrLayerStack);
+        if (!display) {
+            return BAD_VALUE;
+        }
+
+        width = uint32_t(display->getViewport().width());
+        height = uint32_t(display->getViewport().height());
+
+        captureOrientation = fromSurfaceComposerRotation(
+                static_cast<ISurfaceComposer::Rotation>(display->getOrientation()));
+        if (captureOrientation == ui::Transform::orientation_flags::ROT_90) {
+            captureOrientation = ui::Transform::orientation_flags::ROT_270;
+        } else if (captureOrientation == ui::Transform::orientation_flags::ROT_270) {
+            captureOrientation = ui::Transform::orientation_flags::ROT_90;
+        }
+        *outDataspace =
+                pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode);
+    }
+
+    DisplayRenderArea renderArea(display, Rect(), width, height, *outDataspace, captureOrientation,
+                                 false /* captureSecureLayers */);
+
+    auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
+                                    std::placeholders::_1);
+    bool ignored = false;
+    return captureScreenCommon(renderArea, traverseLayers, outBuffer, ui::PixelFormat::RGBA_8888,
+                               false /* useIdentityTransform */,
+                               ignored /* outCapturedSecureLayers */);
+}
+
+status_t SurfaceFlinger::captureLayers(
+        const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
+        const Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
+        const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& excludeHandles,
+        float frameScale, bool childrenOnly) {
     ATRACE_CALL();
 
     class LayerRenderArea : public RenderArea {
@@ -5527,34 +5838,50 @@
         const bool mChildrenOnly;
     };
 
-    auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
-    auto parent = layerHandle->owner.promote();
-
-    if (parent == nullptr || parent->isRemovedFromCurrentState()) {
-        ALOGE("captureLayers called with a removed parent");
-        return NAME_NOT_FOUND;
-    }
-
-    const int uid = IPCThreadState::self()->getCallingUid();
-    const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
-    if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
-        ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
-        return PERMISSION_DENIED;
-    }
-
+    int reqWidth = 0;
+    int reqHeight = 0;
+    sp<Layer> parent;
     Rect crop(sourceCrop);
-    if (sourceCrop.width() <= 0) {
-        crop.left = 0;
-        crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
-    }
+    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
 
-    if (sourceCrop.height() <= 0) {
-        crop.top = 0;
-        crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
-    }
+    {
+        Mutex::Autolock _l(mStateLock);
 
-    int32_t reqWidth = crop.width() * frameScale;
-    int32_t reqHeight = crop.height() * frameScale;
+        parent = fromHandle(layerHandleBinder);
+        if (parent == nullptr || parent->isRemovedFromCurrentState()) {
+            ALOGE("captureLayers called with an invalid or removed parent");
+            return NAME_NOT_FOUND;
+        }
+
+        const int uid = IPCThreadState::self()->getCallingUid();
+        const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+        if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
+            return PERMISSION_DENIED;
+        }
+
+        if (sourceCrop.width() <= 0) {
+            crop.left = 0;
+            crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
+        }
+
+        if (sourceCrop.height() <= 0) {
+            crop.top = 0;
+            crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
+        }
+        reqWidth = crop.width() * frameScale;
+        reqHeight = crop.height() * frameScale;
+
+        for (const auto& handle : excludeHandles) {
+            sp<Layer> excludeLayer = fromHandle(handle);
+            if (excludeLayer != nullptr) {
+                excludeLayers.emplace(excludeLayer);
+            } else {
+                ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
+                return NAME_NOT_FOUND;
+            }
+        }
+    } // mStateLock
 
     // really small crop or frameScale
     if (reqWidth <= 0) {
@@ -5565,25 +5892,38 @@
     }
 
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
-
-    auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
+    auto traverseLayers = [parent, childrenOnly,
+                           &excludeLayers](const LayerVector::Visitor& visitor) {
         parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
             if (!layer->isVisible()) {
                 return;
             } else if (childrenOnly && layer == parent.get()) {
                 return;
             }
+
+            sp<Layer> p = layer;
+            while (p != nullptr) {
+                if (excludeLayers.count(p) != 0) {
+                    return;
+                }
+                p = p->getParent();
+            }
+
             visitor(layer);
         });
     };
-    return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, false);
+
+    bool outCapturedSecureLayers = false;
+    return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, false,
+                               outCapturedSecureLayers);
 }
 
 status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
                                              TraverseLayersFunction traverseLayers,
                                              sp<GraphicBuffer>* outBuffer,
                                              const ui::PixelFormat reqPixelFormat,
-                                             bool useIdentityTransform) {
+                                             bool useIdentityTransform,
+                                             bool& outCapturedSecureLayers) {
     ATRACE_CALL();
 
     // TODO(b/116112787) Make buffer usage a parameter.
@@ -5594,13 +5934,15 @@
                                              static_cast<android_pixel_format>(reqPixelFormat), 1,
                                              usage, "screenshot");
 
-    return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform);
+    return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform,
+                               outCapturedSecureLayers);
 }
 
 status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
                                              TraverseLayersFunction traverseLayers,
                                              const sp<GraphicBuffer>& buffer,
-                                             bool useIdentityTransform) {
+                                             bool useIdentityTransform,
+                                             bool& outCapturedSecureLayers) {
     // This mutex protects syncFd and captureResult for communication of the return values from the
     // main thread back to this Binder thread
     std::mutex captureMutex;
@@ -5629,7 +5971,8 @@
             Mutex::Autolock _l(mStateLock);
             renderArea.render([&] {
                 result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(),
-                                                 useIdentityTransform, forSystem, &fd);
+                                                 useIdentityTransform, forSystem, &fd,
+                                                 outCapturedSecureLayers);
             });
         }
 
@@ -5671,8 +6014,9 @@
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    const auto sourceCrop = renderArea.getSourceCrop();
     const auto rotation = renderArea.getRotationFlags();
+    const auto transform = renderArea.getTransform();
+    const auto sourceCrop = renderArea.getSourceCrop();
 
     renderengine::DisplaySettings clientCompositionDisplay;
     std::vector<renderengine::LayerSettings> clientCompositionLayers;
@@ -5680,31 +6024,34 @@
     // assume that bounds are never offset, and that they are the same as the
     // buffer bounds.
     clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
-    ui::Transform transform = renderArea.getTransform();
+    clientCompositionDisplay.clip = sourceCrop;
     clientCompositionDisplay.globalTransform = transform.asMatrix4();
+
+    // Now take into account the rotation flag. We append a transform that
+    // rotates the layer stack about the origin, then translate by buffer
+    // boundaries to be in the right quadrant.
     mat4 rotMatrix;
-    // Displacement for repositioning the clipping rectangle after rotating it
-    // with the rotation hint.
     int displacementX = 0;
     int displacementY = 0;
     float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
     switch (rotation) {
         case ui::Transform::ROT_90:
             rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
-            displacementX = reqWidth;
+            displacementX = renderArea.getBounds().getHeight();
             break;
         case ui::Transform::ROT_180:
             rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
-            displacementX = reqWidth;
-            displacementY = reqHeight;
+            displacementY = renderArea.getBounds().getWidth();
+            displacementX = renderArea.getBounds().getHeight();
             break;
         case ui::Transform::ROT_270:
             rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
-            displacementY = reqHeight;
+            displacementY = renderArea.getBounds().getWidth();
             break;
         default:
             break;
     }
+
     // We need to transform the clipping window into the right spot.
     // First, rotate the clipping rectangle by the rotation hint to get the
     // right orientation
@@ -5720,15 +6067,14 @@
     // Now reposition the clipping rectangle with the displacement vector
     // computed above.
     const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-
     clientCompositionDisplay.clip =
             Rect(newClipLeft + displacementX, newClipTop + displacementY,
                  newClipRight + displacementX, newClipBottom + displacementY);
 
-    // We need to perform the same transformation in layer space, so propagate
-    // it to the global transform.
     mat4 clipTransform = displacementMat * rotMatrix;
-    clientCompositionDisplay.globalTransform *= clipTransform;
+    clientCompositionDisplay.globalTransform =
+            clipTransform * clientCompositionDisplay.globalTransform;
+
     clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
     clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
 
@@ -5766,21 +6112,19 @@
 status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
                                                  TraverseLayersFunction traverseLayers,
                                                  ANativeWindowBuffer* buffer,
-                                                 bool useIdentityTransform,
-                                                 bool forSystem,
-                                                 int* outSyncFd) {
+                                                 bool useIdentityTransform, bool forSystem,
+                                                 int* outSyncFd, bool& outCapturedSecureLayers) {
     ATRACE_CALL();
 
-    bool secureLayerIsVisible = false;
-
     traverseLayers([&](Layer* layer) {
-        secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
+        outCapturedSecureLayers =
+                outCapturedSecureLayers || (layer->isVisible() && layer->isSecure());
     });
 
     // We allow the system server to take screenshots of secure layers for
     // use in situations like the Screen-rotation animation and place
     // the impetus on WindowManager to not persist them.
-    if (secureLayerIsVisible && !forSystem) {
+    if (outCapturedSecureLayers && !forSystem) {
         ALOGW("FB is protected: PERMISSION_DENIED");
         return PERMISSION_DENIED;
     }
@@ -5826,106 +6170,94 @@
     }
 }
 
-void SurfaceFlinger::setAllowedDisplayConfigsInternal(
-        const android::sp<android::IBinder>& displayToken,
-        std::unique_ptr<const AllowedDisplayConfigs>&& allowedConfigs) {
-    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
-    if (!displayId) {
-        ALOGE("setAllowedDisplayConfigsInternal: getPhysicalDisplayId failed");
+void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
+                                                      const std::vector<int32_t>& allowedConfigs) {
+    if (!display->isPrimary()) {
         return;
     }
 
     ALOGV("Updating allowed configs");
-    {
-        std::lock_guard lock(mAllowedConfigsLock);
-        mAllowedConfigs[*displayId] = std::move(allowedConfigs);
-    }
+    mAllowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(), allowedConfigs.end());
 
     // Set the highest allowed config by iterating backwards on available refresh rates
-    const auto& refreshRates = mRefreshRateConfigs[*displayId]->getRefreshRates();
+    const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
     for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
-        if (iter->second && isConfigAllowed(*displayId, iter->second->configId)) {
+        if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
             ALOGV("switching to config %d", iter->second->configId);
-            setDesiredActiveConfig({iter->first, iter->second->configId, displayToken,
-                                    Scheduler::ConfigEvent::Changed});
+            setDesiredActiveConfig(
+                    {iter->first, iter->second->configId, Scheduler::ConfigEvent::Changed});
             break;
         }
     }
 }
 
-status_t SurfaceFlinger::setAllowedDisplayConfigs(const android::sp<android::IBinder>& displayToken,
+status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                                   const std::vector<int32_t>& allowedConfigs) {
     ATRACE_CALL();
 
-    if (!displayToken) {
-        ALOGE("setAllowedDisplayConfigs: displayToken is null");
+    if (!displayToken || allowedConfigs.empty()) {
         return BAD_VALUE;
     }
 
-    if (!allowedConfigs.size()) {
-        ALOGE("setAllowedDisplayConfigs: empty config set provided");
-        return BAD_VALUE;
+    if (mDebugDisplayConfigSetByBackdoor) {
+        // ignore this request as config is overridden by backdoor
+        return NO_ERROR;
     }
 
-    {
-        ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
-        const auto displayId = getPhysicalDisplayIdLocked(displayToken);
-        if (!displayId) {
-            ALOGE("setAllowedDisplayConfigs: display not found");
-            return NAME_NOT_FOUND;
-        }
-    }
-
-    auto allowedDisplayConfigsBuilder = AllowedDisplayConfigs::Builder();
-    for (int config : allowedConfigs) {
-        ALOGV("setAllowedDisplayConfigs: Adding config to the allowed configs = %d", config);
-        allowedDisplayConfigsBuilder.addConfig(config);
-    }
-    auto allowedDisplayConfigs = allowedDisplayConfigsBuilder.build();
     postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
-        setAllowedDisplayConfigsInternal(displayToken, std::move(allowedDisplayConfigs));
+        const auto display = getDisplayDeviceLocked(displayToken);
+        if (!display) {
+            ALOGE("Attempt to set allowed display configs for invalid display token %p",
+                  displayToken.get());
+        } else if (display->isVirtual()) {
+            ALOGW("Attempt to set allowed display configs for virtual display");
+        } else {
+            setAllowedDisplayConfigsInternal(display, allowedConfigs);
+        }
     }));
+
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getAllowedDisplayConfigs(const android::sp<android::IBinder>& displayToken,
+status_t SurfaceFlinger::getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                                   std::vector<int32_t>* outAllowedConfigs) {
     ATRACE_CALL();
 
-    if (!displayToken) {
-        ALOGE("getAllowedDisplayConfigs: displayToken is null");
+    if (!displayToken || !outAllowedConfigs) {
         return BAD_VALUE;
     }
 
-    if (!outAllowedConfigs) {
-        ALOGE("getAllowedDisplayConfigs: outAllowedConfigs is null");
-        return BAD_VALUE;
-    }
+    Mutex::Autolock lock(mStateLock);
 
-    ConditionalLock stateLock(mStateLock, std::this_thread::get_id() != mMainThreadId);
-    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
-    if (!displayId) {
-        ALOGE("getAllowedDisplayConfigs: display not found");
+    const auto display = getDisplayDeviceLocked(displayToken);
+    if (!display) {
         return NAME_NOT_FOUND;
     }
 
-    std::lock_guard allowedConfigLock(mAllowedConfigsLock);
-    auto allowedConfigIterator = mAllowedConfigs.find(displayId.value());
-    if (allowedConfigIterator != mAllowedConfigs.end()) {
-        allowedConfigIterator->second->getAllowedConfigs(outAllowedConfigs);
+    if (display->isPrimary()) {
+        outAllowedConfigs->assign(mAllowedDisplayConfigs.begin(), mAllowedDisplayConfigs.end());
     }
 
     return NO_ERROR;
 }
 
-// ----------------------------------------------------------------------------
-
-void SetInputWindowsListener::onSetInputWindowsFinished() {
+void SurfaceFlinger::SetInputWindowsListener::onSetInputWindowsFinished() {
     mFlinger->setInputWindowsFinished();
 }
 
-}; // namespace android
+sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+    BBinder *b = handle->localBinder();
+    if (b == nullptr) {
+        return nullptr;
+    }
+    auto it = mLayersByLocalBinderToken.find(b);
+    if (it != mLayersByLocalBinderToken.end()) {
+        return it->second.promote();
+    }
+    return nullptr;
+}
 
+} // namespace android
 
 #if defined(__gl_h_)
 #error "don't include gl/gl.h in this file"
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3d8b6b7..0e6eacf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SURFACE_FLINGER_H
-#define ANDROID_SURFACE_FLINGER_H
+#pragma once
 
 #include <sys/types.h>
 
@@ -47,28 +46,19 @@
 #include <utils/Trace.h>
 #include <utils/threads.h>
 
-#include "AllowedDisplayConfigs.h"
-#include "Barrier.h"
-#include "BufferStateLayerCache.h"
+#include "ClientCache.h"
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/PowerAdvisor.h"
 #include "Effects/Daltonizer.h"
 #include "FrameTracker.h"
 #include "LayerStats.h"
 #include "LayerVector.h"
-#include "RegionSamplingThread.h"
-#include "Scheduler/DispSync.h"
-#include "Scheduler/EventThread.h"
-#include "Scheduler/MessageQueue.h"
-#include "Scheduler/PhaseOffsets.h"
 #include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/RefreshRateStats.h"
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
 #include "SurfaceFlingerFactory.h"
-#include "SurfaceInterceptor.h"
 #include "SurfaceTracing.h"
 #include "TransactionCompletedThread.h"
 
@@ -84,62 +74,44 @@
 #include <thread>
 #include <type_traits>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 
 using namespace android::surfaceflinger;
 
 namespace android {
 
-using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
-
-// ---------------------------------------------------------------------------
-
 class Client;
-class ColorLayer;
-class DisplayEventConnection;
-class EventControlThread;
 class EventThread;
-class IGraphicBufferConsumer;
+class HWComposer;
 class IGraphicBufferProducer;
 class IInputFlinger;
 class InjectVSyncSource;
 class Layer;
+class MessageBase;
 class RefreshRateOverlay;
-class Surface;
-class SurfaceFlingerBE;
+class RegionSamplingThread;
 class TimeStats;
-class VSyncSource;
 
 namespace compositionengine {
 class DisplaySurface;
 } // namespace compositionengine
 
-namespace impl {
-class EventThread;
-} // namespace impl
-
 namespace renderengine {
 class RenderEngine;
-}
-
-typedef std::function<void(const LayerVector::Visitor&)> TraverseLayersFunction;
+} // namespace renderengine
 
 namespace dvr {
 class VrFlinger;
 } // namespace dvr
 
-namespace surfaceflinger {
-class NativeWindowSurface;
-} // namespace surfaceflinger
-
-// ---------------------------------------------------------------------------
-
 enum {
-    eTransactionNeeded        = 0x01,
-    eTraversalNeeded          = 0x02,
+    eTransactionNeeded = 0x01,
+    eTraversalNeeded = 0x02,
     eDisplayTransactionNeeded = 0x04,
     eDisplayLayerStackChanged = 0x08,
-    eTransactionMask          = 0x0f,
+    eTransactionFlushNeeded = 0x10,
+    eTransactionMask = 0x1f,
 };
 
 enum class DisplayColorSetting : int32_t {
@@ -164,35 +136,28 @@
 
     // Only accessed from the main thread.
     struct CompositePresentTime {
-        nsecs_t composite { -1 };
-        std::shared_ptr<FenceTime> display { FenceTime::NO_FENCE };
+        nsecs_t composite = -1;
+        std::shared_ptr<FenceTime> display = FenceTime::NO_FENCE;
     };
     std::queue<CompositePresentTime> mCompositePresentTimes;
 
     static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
-    nsecs_t mFrameBuckets[NUM_BUCKETS];
-    nsecs_t mTotalTime;
-    std::atomic<nsecs_t> mLastSwapTime;
+    nsecs_t mFrameBuckets[NUM_BUCKETS] = {};
+    nsecs_t mTotalTime = 0;
+    std::atomic<nsecs_t> mLastSwapTime = 0;
 
     // Double- vs. triple-buffering stats
     struct BufferingStats {
-        BufferingStats()
-          : numSegments(0),
-            totalTime(0),
-            twoBufferTime(0),
-            doubleBufferedTime(0),
-            tripleBufferedTime(0) {}
-
-        size_t numSegments;
-        nsecs_t totalTime;
+        size_t numSegments = 0;
+        nsecs_t totalTime = 0;
 
         // "Two buffer" means that a third buffer was never used, whereas
         // "double-buffered" means that on average the segment only used two
         // buffers (though it may have used a third for some part of the
         // segment)
-        nsecs_t twoBufferTime;
-        nsecs_t doubleBufferedTime;
-        nsecs_t tripleBufferedTime;
+        nsecs_t twoBufferTime = 0;
+        nsecs_t doubleBufferedTime = 0;
+        nsecs_t tripleBufferedTime = 0;
     };
     mutable Mutex mBufferingStatsMutex;
     std::unordered_map<std::string, BufferingStats> mBufferingStats;
@@ -200,16 +165,7 @@
     // The composer sequence id is a monotonically increasing integer that we
     // use to differentiate callbacks from different hardware composer
     // instances. Each hardware composer instance gets a different sequence id.
-    int32_t mComposerSequenceId;
-};
-
-class SetInputWindowsListener : public BnSetInputWindowsListener {
-public:
-    SetInputWindowsListener(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger) {}
-    void onSetInputWindowsFinished() override;
-
-private:
-    const sp<SurfaceFlinger> mFlinger;
+    int32_t mComposerSequenceId = 0;
 };
 
 class SurfaceFlinger : public BnSurfaceComposer,
@@ -337,11 +293,20 @@
     // TODO: this should be made accessible only to EventThread
     void setPrimaryVsyncEnabled(bool enabled);
 
+    // main thread function to enable/disable h/w composer event
+    void setPrimaryVsyncEnabledInternal(bool enabled);
+
     // called on the main thread by MessageQueue when an internal message
     // is received
     // TODO: this should be made accessible only to MessageQueue
     void onMessageReceived(int32_t what);
 
+    // populates the expected present time for this frame.
+    // When we are in negative offsets, we perform a correction so that the
+    // predicted vsync for the *next* frame is used instead.
+    void populateExpectedPresentTime();
+    nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; }
+
     // for debugging only
     // TODO: this should be made accessible only to HWComposer
     const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
@@ -352,22 +317,23 @@
         const sp<IGraphicBufferProducer>& bufferProducer) const;
 
     inline void onLayerCreated() { mNumLayers++; }
-    inline void onLayerDestroyed() { mNumLayers--; }
+    inline void onLayerDestroyed(Layer* layer) {
+        mNumLayers--;
+        mOffscreenLayers.erase(layer);
+    }
 
     TransactionCompletedThread& getTransactionCompletedThread() {
         return mTransactionCompletedThread;
     }
 
-    void setInputWindowsFinished();
+    sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
 
 private:
-    friend class Client;
-    friend class DisplayEventConnection;
-    friend class impl::EventThread;
-    friend class Layer;
     friend class BufferLayer;
     friend class BufferQueueLayer;
     friend class BufferStateLayer;
+    friend class Client;
+    friend class Layer;
     friend class MonitoredProducer;
     friend class RefreshRateOverlay;
     friend class RegionSamplingThread;
@@ -435,30 +401,33 @@
                              const Vector<DisplayState>& displays, uint32_t flags,
                              const sp<IBinder>& applyToken,
                              const InputWindowCommands& inputWindowCommands,
-                             int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
+                             int64_t desiredPresentTime, const client_cache_t& uncacheBuffer,
                              const std::vector<ListenerCallbacks>& listenerCallbacks) override;
     void bootFinished() override;
     bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& bufferProducer) const override;
     status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
     sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress) override;
     status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
-                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
-                           Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-                           bool useIdentityTransform, ISurfaceComposer::Rotation rotation,
-                           bool captureSecureLayers) override;
-    status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
-                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
-                           const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
+            bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace,
+            const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
+            uint32_t reqWidth, uint32_t reqHeight,
+            bool useIdentityTransform, ISurfaceComposer::Rotation rotation, bool captureSecureLayers) override;
+    status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
+                           sp<GraphicBuffer>* outBuffer) override;
+    status_t captureLayers(
+            const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+            const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+            const Rect& sourceCrop,
+            const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& exclude,
+            float frameScale, bool childrenOnly) override;
+
     status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
     status_t getDisplayConfigs(const sp<IBinder>& displayToken,
-                               Vector<DisplayInfo>* configs) override {
-        Mutex::Autolock _l(mStateLock);
-        return getDisplayConfigsLocked(displayToken, configs);
-    }
-    status_t getDisplayConfigsLocked(const sp<IBinder>& displayToken, Vector<DisplayInfo>* configs)
-            REQUIRES(mStateLock);
+                               Vector<DisplayInfo>* configs) override;
     int getActiveConfig(const sp<IBinder>& displayToken) override;
     status_t getDisplayColorModes(const sp<IBinder>& displayToken,
                                   Vector<ui::ColorMode>* configs) override;
@@ -502,6 +471,7 @@
     status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
                                          bool* outSupport) const override;
     status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const override;
+    status_t notifyPowerHint(int32_t hintId) override;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
@@ -532,23 +502,15 @@
     void signalLayerUpdate();
     void signalRefresh();
 
+    using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
     struct ActiveConfigInfo {
         RefreshRateType type;
         int configId;
-        sp<IBinder> displayToken;
         Scheduler::ConfigEvent event;
 
         bool operator!=(const ActiveConfigInfo& other) const {
-            if (type != other.type) {
-                return true;
-            }
-            if (configId != other.configId) {
-                return true;
-            }
-            if (displayToken != other.displayToken) {
-                return true;
-            }
-            return (event != other.event);
+            return type != other.type || configId != other.configId || event != other.event;
         }
     };
 
@@ -557,20 +519,22 @@
     // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
     void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock);
     // Once HWC has returned the present fence, this sets the active config and a new refresh
-    // rate in SF. It also triggers HWC vsync.
+    // rate in SF.
     void setActiveConfigInternal() REQUIRES(mStateLock);
     // Active config is updated on INVALIDATE call in a state machine-like manner. When the
     // desired config was set, HWC needs to update the panel on the next refresh, and when
     // we receive the fence back, we know that the process was complete. It returns whether
     // we need to wait for the next invalidate
-    bool performSetActiveConfig();
+    bool performSetActiveConfig() REQUIRES(mStateLock);
+    // Called when active config is no longer is progress
+    void desiredActiveConfigChangeDone() REQUIRES(mStateLock);
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
 
     // called on the main thread in response to setAllowedDisplayConfigs()
-    void setAllowedDisplayConfigsInternal(
-            const sp<IBinder>& displayToken,
-            std::unique_ptr<const AllowedDisplayConfigs>&& allowedConfigs) REQUIRES(mStateLock);
+    void setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
+                                          const std::vector<int32_t>& allowedConfigs)
+            REQUIRES(mStateLock);
 
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
@@ -587,6 +551,7 @@
     void updateInputWindowInfo();
     void commitInputWindowCommands() REQUIRES(mStateLock);
     void executeInputWindowCommands();
+    void setInputWindowsFinished();
     void updateCursorAsync();
 
     /* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -602,11 +567,14 @@
                                const Vector<DisplayState>& displays, uint32_t flags,
                                const InputWindowCommands& inputWindowCommands,
                                const int64_t desiredPresentTime,
-                               const cached_buffer_t& uncacheBuffer,
+                               const client_cache_t& uncacheBuffer,
                                const std::vector<ListenerCallbacks>& listenerCallbacks,
                                const int64_t postTime, bool privileged, bool isMainThread = false)
             REQUIRES(mStateLock);
+    // Returns true if at least one transaction was flushed
     bool flushTransactionQueues();
+    // Returns true if there is at least one transaction that needs to be flushed
+    bool transactionFlushNeeded();
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t peekTransactionFlags();
     // Can only be called from the main thread or with mStateLock held
@@ -614,6 +582,7 @@
     uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart);
     void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction() REQUIRES(mStateLock);
+    void commitOffscreenLayers();
     bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
     bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                        const Vector<ComposerState>& states);
@@ -629,7 +598,8 @@
      */
     status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
                          PixelFormat format, uint32_t flags, LayerMetadata metadata,
-                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
+                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
+                         const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer = nullptr);
 
     status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
                                     uint32_t h, uint32_t flags, LayerMetadata metadata,
@@ -657,12 +627,10 @@
     void markLayerPendingRemovalLocked(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
-    status_t addClientLayer(const sp<Client>& client,
-            const sp<IBinder>& handle,
-            const sp<IGraphicBufferProducer>& gbc,
-            const sp<Layer>& lbc,
-            const sp<Layer>& parent,
-            bool addToCurrentState);
+    status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
+                            const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
+                            const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer,
+                            bool addToCurrentState);
 
     // Traverse through all the layers and compute and cache its bounds.
     void computeLayerBounds();
@@ -673,18 +641,22 @@
 
     void startBootAnim();
 
+    using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>;
+
     void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
                                 ANativeWindowBuffer* buffer, bool useIdentityTransform,
                                 int* outSyncFd);
     status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
                                  sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat,
-                                 bool useIdentityTransform);
+                                 bool useIdentityTransform, bool& outCapturedSecureLayers);
     status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
-                                 const sp<GraphicBuffer>& buffer, bool useIdentityTransform);
+                                 const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
+                                 bool& outCapturedSecureLayers);
+    const sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack);
     status_t captureScreenImplLocked(const RenderArea& renderArea,
                                      TraverseLayersFunction traverseLayers,
                                      ANativeWindowBuffer* buffer, bool useIdentityTransform,
-                                     bool forSystem, int* outSyncFd);
+                                     bool forSystem, int* outSyncFd, bool& outCapturedSecureLayers);
     void traverseLayersInDisplay(const sp<const DisplayDevice>& display,
                                  const LayerVector::Visitor& visitor);
 
@@ -785,8 +757,8 @@
                                     nsecs_t compositeToPresentLatency);
     void rebuildLayerStacks();
 
-    ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& display,
-                                   ui::Dataspace* outHdrDataSpace) const;
+    ui::Dataspace getBestDataspace(const sp<DisplayDevice>& display, ui::Dataspace* outHdrDataSpace,
+                                   bool* outIsHdrClientComposition) const;
 
     // Returns the appropriate ColorMode, Dataspace and RenderIntent for the
     // DisplayDevice. The function only returns the supported ColorMode,
@@ -819,7 +791,6 @@
 
     void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
-    void drawWormhole(const Region& region) const;
 
     /* ------------------------------------------------------------------------
      * Display management
@@ -843,7 +814,7 @@
     // the desired refresh rate.
     void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock);
 
-    bool isConfigAllowed(const DisplayId& displayId, int32_t config);
+    bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock);
 
     /*
      * Display identification
@@ -873,6 +844,9 @@
         return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
     }
 
+    bool previousFrameMissed();
+    void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
+
     /*
      * Debugging & dumpsys
      */
@@ -958,12 +932,12 @@
     // access must be protected by mStateLock
     mutable Mutex mStateLock;
     State mCurrentState{LayerVector::StateSet::Current};
-    std::atomic<int32_t> mTransactionFlags{0};
+    std::atomic<int32_t> mTransactionFlags = 0;
     Condition mTransactionCV;
-    bool mTransactionPending;
-    bool mAnimTransactionPending;
-    SortedVector< sp<Layer> > mLayersPendingRemoval;
-    bool mTraversalNeededMainThread;
+    bool mTransactionPending = false;
+    bool mAnimTransactionPending = false;
+    SortedVector<sp<Layer>> mLayersPendingRemoval;
+    bool mTraversalNeededMainThread = false;
 
     // guards access to the mDrawing state if tracing is enabled.
     mutable std::mutex mDrawingStateLock;
@@ -978,35 +952,34 @@
     size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
 
     // protected by mStateLock (but we could use another lock)
-    bool mLayersRemoved;
-    bool mLayersAdded;
+    bool mLayersRemoved = false;
+    bool mLayersAdded = false;
 
-    std::atomic<bool> mRepaintEverything{false};
+    std::atomic<bool> mRepaintEverything = false;
 
     // constant members (no synchronization needed for access)
-    nsecs_t mBootTime;
-    bool mGpuToCpuSupported;
+    const nsecs_t mBootTime = systemTime();
+    bool mGpuToCpuSupported = false;
     std::unique_ptr<EventThread> mInjectorEventThread;
     std::unique_ptr<InjectVSyncSource> mVSyncInjector;
-    std::unique_ptr<EventControlThread> mEventControlThread;
 
     // Calculates correct offsets.
     VSyncModulator mVsyncModulator;
     // Keeps track of all available phase offsets for different refresh types.
-    std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
+    const std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
-    bool mVisibleRegionsDirty;
+    bool mVisibleRegionsDirty = false;
     // Set during transaction commit stage to track if the input info for a layer has changed.
-    bool mInputInfoChanged{false};
-    bool mGeometryInvalid;
-    bool mAnimCompositionPending;
+    bool mInputInfoChanged = false;
+    bool mGeometryInvalid = false;
+    bool mAnimCompositionPending = false;
     std::vector<sp<Layer>> mLayersWithQueuedFrames;
     // Tracks layers that need to update a display's dirty region.
     std::vector<sp<Layer>> mLayersPendingRefresh;
-    sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
+    std::array<sp<Fence>, 2> mPreviousPresentFences = {Fence::NO_FENCE, Fence::NO_FENCE};
     // True if in the previous frame at least one layer was composed via the GPU.
     bool mHadClientComposition = false;
     // True if in the previous frame at least one layer was composed via HW Composer.
@@ -1019,7 +992,7 @@
         BOOTANIMATION,
         FINISHED,
     };
-    BootStage mBootStage;
+    BootStage mBootStage = BootStage::BOOTLOADER;
 
     struct HotplugEvent {
         hwc2_display_t hwcDisplayId;
@@ -1033,27 +1006,27 @@
     std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
     std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
+    // protected by mStateLock
+    std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
+
     // don't use a lock for these, we don't care
-    int mDebugRegion;
-    int mDebugDisableHWC;
-    int mDebugDisableTransformHint;
-    bool mDebugEnableProtectedContent;
-    volatile nsecs_t mDebugInSwapBuffers;
-    volatile nsecs_t mDebugInTransaction;
-    nsecs_t mLastTransactionTime;
-    nsecs_t mPostFramebufferTime;
-    bool mForceFullDamage;
+    int mDebugRegion = 0;
+    bool mDebugDisableHWC = false;
+    bool mDebugDisableTransformHint = false;
+    volatile nsecs_t mDebugInTransaction = 0;
+    bool mForceFullDamage = false;
     bool mPropagateBackpressure = true;
-    std::unique_ptr<SurfaceInterceptor> mInterceptor{mFactory.createSurfaceInterceptor(this)};
-    SurfaceTracing mTracing;
+    bool mPropagateBackpressureClientComposition = false;
+    std::unique_ptr<SurfaceInterceptor> mInterceptor;
+    SurfaceTracing mTracing{*this};
     bool mTracingEnabled = false;
     bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
     LayerStats mLayerStats;
-    std::shared_ptr<TimeStats> mTimeStats;
+    const std::shared_ptr<TimeStats> mTimeStats;
     bool mUseHwcVirtualDisplays = false;
-    std::atomic<uint32_t> mFrameMissedCount{0};
-    std::atomic<uint32_t> mHwcFrameMissedCount{0};
-    std::atomic<uint32_t> mGpuFrameMissedCount{0};
+    std::atomic<uint32_t> mFrameMissedCount = 0;
+    std::atomic<uint32_t> mHwcFrameMissedCount = 0;
+    std::atomic<uint32_t> mGpuFrameMissedCount = 0;
 
     TransactionCompletedThread mTransactionCompletedThread;
 
@@ -1061,16 +1034,16 @@
     bool mLayerTripleBufferingDisabled = false;
 
     // these are thread safe
-    mutable std::unique_ptr<MessageQueue> mEventQueue{mFactory.createMessageQueue()};
+    std::unique_ptr<MessageQueue> mEventQueue;
     FrameTracker mAnimFrameTracker;
 
     // protected by mDestroyedLayerLock;
     mutable Mutex mDestroyedLayerLock;
     Vector<Layer const *> mDestroyedLayers;
 
-    nsecs_t mRefreshStartTime;
+    nsecs_t mRefreshStartTime = 0;
 
-    std::atomic<bool> mRefreshPending{false};
+    std::atomic<bool> mRefreshPending = false;
 
     // We maintain a pool of pre-generated texture names to hand out to avoid
     // layer creation needing to run on the main thread (which it would
@@ -1087,7 +1060,7 @@
     struct TransactionState {
         TransactionState(const Vector<ComposerState>& composerStates,
                          const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
-                         int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
+                         int64_t desiredPresentTime, const client_cache_t& uncacheBuffer,
                          const std::vector<ListenerCallbacks>& listenerCallbacks, int64_t postTime,
                          bool privileged)
               : states(composerStates),
@@ -1103,7 +1076,7 @@
         Vector<DisplayState> displays;
         uint32_t flags;
         const int64_t desiredPresentTime;
-        cached_buffer_t buffer;
+        client_cache_t buffer;
         std::vector<ListenerCallbacks> callback;
         const int64_t postTime;
         bool privileged;
@@ -1114,21 +1087,24 @@
      * Feature prototyping
      */
 
-    bool mInjectVSyncs;
+    bool mInjectVSyncs = false;
 
     // Static screen stats
-    bool mHasPoweredOff;
+    bool mHasPoweredOff = false;
 
-    size_t mNumLayers;
+    size_t mNumLayers = 0;
 
     // Verify that transaction is being called by an approved process:
     // either AID_GRAPHICS or AID_SYSTEM.
     status_t CheckTransactCodeCredentials(uint32_t code);
 
+    // to linkToDeath
+    sp<IBinder> mWindowManager;
+
     std::unique_ptr<dvr::VrFlinger> mVrFlinger;
-    std::atomic<bool> mVrFlingerRequestsDisplay;
+    std::atomic<bool> mVrFlingerRequestsDisplay = false;
     static bool useVrFlinger;
-    std::thread::id mMainThreadId;
+    std::thread::id mMainThreadId = std::this_thread::get_id();
 
     DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED;
 
@@ -1143,6 +1119,7 @@
 
     ui::Dataspace mDefaultCompositionDataspace;
     ui::Dataspace mWideColorGamutCompositionDataspace;
+    ui::Dataspace mColorSpaceAgnosticDataspace;
 
     SurfaceFlingerBE mBE;
     std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
@@ -1154,14 +1131,13 @@
     std::unique_ptr<Scheduler> mScheduler;
     sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
-    std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
 
-    std::unordered_map<DisplayId, std::shared_ptr<scheduler::RefreshRateConfigs>>
-            mRefreshRateConfigs;
+    scheduler::RefreshRateConfigs mRefreshRateConfigs;
+    scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};
 
-    std::mutex mAllowedConfigsLock;
-    std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs
-            GUARDED_BY(mAllowedConfigsLock);
+    // All configs are allowed if the set is empty.
+    using DisplayConfigs = std::set<int32_t>;
+    DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock);
 
     std::mutex mActiveConfigLock;
     // This bit is set once we start setting the config. We read from this bit during the
@@ -1175,23 +1151,45 @@
     bool mDesiredActiveConfigChanged GUARDED_BY(mActiveConfigLock) = false;
     bool mCheckPendingFence = false;
 
-    /* ------------------------------------------------------------------------ */
     bool mLumaSampling = true;
     sp<RegionSamplingThread> mRegionSamplingThread;
+    ui::DisplayPrimaries mInternalDisplayPrimaries;
 
     sp<IInputFlinger> mInputFlinger;
-
     InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
     // Should only be accessed by the main thread.
     InputWindowCommands mInputWindowCommands;
-    ui::DisplayPrimaries mInternalDisplayPrimaries;
 
-    sp<SetInputWindowsListener> mSetInputWindowsListener;
+    struct SetInputWindowsListener : BnSetInputWindowsListener {
+        explicit SetInputWindowsListener(sp<SurfaceFlinger> flinger)
+              : mFlinger(std::move(flinger)) {}
+
+        void onSetInputWindowsFinished() override;
+
+        const sp<SurfaceFlinger> mFlinger;
+    };
+
+    const sp<SetInputWindowsListener> mSetInputWindowsListener = new SetInputWindowsListener(this);
+
     bool mPendingSyncInputWindows GUARDED_BY(mStateLock);
     Hwc2::impl::PowerAdvisor mPowerAdvisor;
 
     std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay;
-};
-}; // namespace android
 
-#endif // ANDROID_SURFACE_FLINGER_H
+    // Flag used to set override allowed display configs from backdoor
+    bool mDebugDisplayConfigSetByBackdoor = false;
+
+    // A set of layers that have no parent so they are not drawn on screen.
+    // Should only be accessed by the main thread.
+    // The Layer pointer is removed from the set when the destructor is called so there shouldn't
+    // be any issues with a raw pointer referencing an invalid object.
+    std::unordered_set<Layer*> mOffscreenLayers;
+
+    // Flags to capture the state of Vsync in HWC
+    HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
+    HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
+
+    nsecs_t mExpectedPresentTime;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 26d2c21..e425b2a 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -73,8 +73,10 @@
             return std::make_unique<scheduler::impl::PhaseOffsets>();
         }
 
-        std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) override {
-            return std::make_unique<Scheduler>(callback);
+        std::unique_ptr<Scheduler> createScheduler(
+                std::function<void(bool)> callback,
+                const scheduler::RefreshRateConfigs& refreshRateConfig) override {
+            return std::make_unique<Scheduler>(callback, refreshRateConfig);
         }
 
         std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index fc1d0f8..c2bc808 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -71,7 +71,9 @@
     virtual std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) = 0;
     virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
     virtual std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() = 0;
-    virtual std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) = 0;
+    virtual std::unique_ptr<Scheduler> createScheduler(
+            std::function<void(bool)> callback,
+            const scheduler::RefreshRateConfigs& refreshRateConfig) = 0;
     virtual std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) = 0;
 
     virtual sp<StartPropertySetThread> createStartPropertySetThread(
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 09b793a..768074a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2019 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/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
@@ -162,15 +177,11 @@
 
 bool use_color_management(bool defaultValue) {
     auto tmpuseColorManagement = SurfaceFlingerProperties::use_color_management();
-    auto tmpHasHDRDisplay = SurfaceFlingerProperties::has_HDR_display();
-    auto tmpHasWideColorDisplay = SurfaceFlingerProperties::has_wide_color_display();
+    auto tmpHasHDRDisplayVal = has_HDR_display(defaultValue);
+    auto tmpHasWideColorDisplayVal = has_wide_color_display(defaultValue);
 
     auto tmpuseColorManagementVal = tmpuseColorManagement.has_value() ? *tmpuseColorManagement :
         defaultValue;
-    auto tmpHasHDRDisplayVal = tmpHasHDRDisplay.has_value() ? *tmpHasHDRDisplay :
-        defaultValue;
-    auto tmpHasWideColorDisplayVal = tmpHasWideColorDisplay.has_value() ? *tmpHasWideColorDisplay :
-        defaultValue;
 
     return tmpuseColorManagementVal || tmpHasHDRDisplayVal || tmpHasWideColorDisplayVal;
 }
@@ -207,6 +218,14 @@
     return static_cast<int32_t>(defaultValue);
 }
 
+int64_t color_space_agnostic_dataspace(Dataspace defaultValue) {
+    auto temp = SurfaceFlingerProperties::color_space_agnostic_dataspace();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return static_cast<int64_t>(defaultValue);
+}
+
 int32_t set_idle_timer_ms(int32_t defaultValue) {
     auto temp = SurfaceFlingerProperties::set_idle_timer_ms();
     if (temp.has_value()) {
@@ -215,6 +234,22 @@
     return defaultValue;
 }
 
+int32_t set_touch_timer_ms(int32_t defaultValue) {
+    auto temp = SurfaceFlingerProperties::set_touch_timer_ms();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
+int32_t set_display_power_timer_ms(int32_t defaultValue) {
+    auto temp = SurfaceFlingerProperties::set_display_power_timer_ms();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
 bool use_smart_90_for_video(bool defaultValue) {
     auto temp = SurfaceFlingerProperties::use_smart_90_for_video();
     if (temp.has_value()) {
@@ -223,6 +258,22 @@
     return defaultValue;
 }
 
+bool enable_protected_contents(bool defaultValue) {
+    auto temp = SurfaceFlingerProperties::enable_protected_contents();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
+bool support_kernel_idle_timer(bool defaultValue) {
+    auto temp = SurfaceFlingerProperties::support_kernel_idle_timer();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
 #define DISPLAY_PRIMARY_SIZE 3
 
 constexpr float kSrgbRedX = 0.4123f;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index b2fafdd..5f88322 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2019 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 SURFACEFLINGERPROPERTIES_H_
 #define SURFACEFLINGERPROPERTIES_H_
@@ -55,10 +70,21 @@
 int32_t wcg_composition_pixel_format(
         android::hardware::graphics::common::V1_2::PixelFormat defaultValue);
 
+int64_t color_space_agnostic_dataspace(
+        android::hardware::graphics::common::V1_2::Dataspace defaultValue);
+
 int32_t set_idle_timer_ms(int32_t defaultValue);
 
+int32_t set_touch_timer_ms(int32_t defaultValue);
+
+int32_t set_display_power_timer_ms(int32_t defaultValue);
+
 bool use_smart_90_for_video(bool defaultValue);
 
+bool enable_protected_contents(bool defaultValue);
+
+bool support_kernel_idle_timer(bool defaultValue);
+
 android::ui::DisplayPrimaries getDisplayNativePrimaries();
 } // namespace sysprop
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 7bfe033..a02d14c 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -116,7 +116,14 @@
                                   layer->mCurrentState.frameNumber_legacy);
     }
     addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode());
-    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
+    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags,
+                   layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
+                           layer_state_t::eLayerSecure);
+    addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
+    addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
+    addRelativeParentLocked(transaction, layerId,
+                            getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
+                            layer->mCurrentState.z);
 }
 
 void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
@@ -150,7 +157,7 @@
     return NO_ERROR;
 }
 
-const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) {
+const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) const {
     const sp<const IBinder>& handle(weakHandle.promote());
     const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
     const sp<const Layer> layer(layerHandle->owner.promote());
@@ -158,14 +165,31 @@
     return layer;
 }
 
-const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) {
+const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) const {
     return layer->getName().string();
 }
 
-int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) {
+int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) const {
     return layer->sequence;
 }
 
+int32_t SurfaceInterceptor::getLayerIdFromWeakRef(const wp<const Layer>& layer) const {
+    if (layer == nullptr) {
+        return -1;
+    }
+    auto strongLayer = layer.promote();
+    return strongLayer == nullptr ? -1 : getLayerId(strongLayer);
+}
+
+int32_t SurfaceInterceptor::getLayerIdFromHandle(const sp<const IBinder>& handle) const {
+    if (handle == nullptr) {
+        return -1;
+    }
+    const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
+    const sp<const Layer> layer(layerHandle->owner.promote());
+    return layer == nullptr ? -1 : getLayerId(layer);
+}
+
 Increment* SurfaceInterceptor::createTraceIncrementLocked() {
     Increment* increment(mTrace.add_increment());
     increment->set_time_stamp(systemTime());
@@ -252,24 +276,23 @@
     }
 }
 
-void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId,
-        uint8_t flags)
-{
+void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags,
+                                        uint8_t mask) {
     // There can be multiple flags changed
-    if (flags & layer_state_t::eLayerHidden) {
+    if (mask & layer_state_t::eLayerHidden) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         HiddenFlagChange* flagChange(change->mutable_hidden_flag());
-        flagChange->set_hidden_flag(true);
+        flagChange->set_hidden_flag(flags & layer_state_t::eLayerHidden);
     }
-    if (flags & layer_state_t::eLayerOpaque) {
+    if (mask & layer_state_t::eLayerOpaque) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         OpaqueFlagChange* flagChange(change->mutable_opaque_flag());
-        flagChange->set_opaque_flag(true);
+        flagChange->set_opaque_flag(flags & layer_state_t::eLayerOpaque);
     }
-    if (flags & layer_state_t::eLayerSecure) {
+    if (mask & layer_state_t::eLayerSecure) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         SecureFlagChange* flagChange(change->mutable_secure_flag());
-        flagChange->set_secure_flag(true);
+        flagChange->set_secure_flag(flags & layer_state_t::eLayerSecure);
     }
 }
 
@@ -320,6 +343,35 @@
     overrideChange->set_override_scaling_mode(overrideScalingMode);
 }
 
+void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId,
+                                           int32_t parentId) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    ReparentChange* overrideChange(change->mutable_reparent());
+    overrideChange->set_parent_id(parentId);
+}
+
+void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int32_t layerId,
+                                                   int32_t parentId) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    ReparentChildrenChange* overrideChange(change->mutable_reparent_children());
+    overrideChange->set_parent_id(parentId);
+}
+
+void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
+                                                 bool detached) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    DetachChildrenChange* overrideChange(change->mutable_detach_children());
+    overrideChange->set_detach_children(detached);
+}
+
+void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
+                                                 int32_t parentId, int z) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    RelativeParentChange* overrideChange(change->mutable_relative_parent());
+    overrideChange->set_relative_parent_id(parentId);
+    overrideChange->set_z(z);
+}
+
 void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction,
         const layer_state_t& state)
 {
@@ -351,7 +403,7 @@
         addTransparentRegionLocked(transaction, layerId, state.transparentRegion);
     }
     if (state.what & layer_state_t::eFlagsChanged) {
-        addFlagsLocked(transaction, layerId, state.flags);
+        addFlagsLocked(transaction, layerId, state.flags, state.mask);
     }
     if (state.what & layer_state_t::eLayerStackChanged) {
         addLayerStackLocked(transaction, layerId, state.layerStack);
@@ -380,6 +432,19 @@
     if (state.what & layer_state_t::eOverrideScalingModeChanged) {
         addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode);
     }
+    if (state.what & layer_state_t::eReparent) {
+        addReparentLocked(transaction, layerId, getLayerIdFromHandle(state.parentHandleForChild));
+    }
+    if (state.what & layer_state_t::eReparentChildren) {
+        addReparentChildrenLocked(transaction, layerId, getLayerIdFromHandle(state.reparentHandle));
+    }
+    if (state.what & layer_state_t::eDetachChildren) {
+        addDetachChildrenLocked(transaction, layerId, true);
+    }
+    if (state.what & layer_state_t::eRelativeLayerChanged) {
+        addRelativeParentLocked(transaction, layerId,
+                                getLayerIdFromHandle(state.relativeLayerHandle), state.z);
+    }
 }
 
 void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 563a44c..7f86c14 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -116,9 +116,11 @@
     void addInitialDisplayStateLocked(Increment* increment, const DisplayDeviceState& display);
 
     status_t writeProtoFileLocked();
-    const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle);
-    const std::string getLayerName(const sp<const Layer>& layer);
-    int32_t getLayerId(const sp<const Layer>& layer);
+    const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle) const;
+    const std::string getLayerName(const sp<const Layer>& layer) const;
+    int32_t getLayerId(const sp<const Layer>& layer) const;
+    int32_t getLayerIdFromWeakRef(const wp<const Layer>& layer) const;
+    int32_t getLayerIdFromHandle(const sp<const IBinder>& weakHandle) const;
 
     Increment* createTraceIncrementLocked();
     void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
@@ -141,7 +143,7 @@
             const layer_state_t::matrix22_t& matrix);
     void addTransparentRegionLocked(Transaction* transaction, int32_t layerId,
             const Region& transRegion);
-    void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags);
+    void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags, uint8_t mask);
     void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
     void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius);
@@ -153,6 +155,11 @@
     void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates,
             const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
             const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags);
+    void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
+    void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
+    void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
+    void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
+                                 int z);
 
     // Add display transactions to the trace
     DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId);
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 4be2ee9..18524f0 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -41,7 +41,7 @@
  */
 class SurfaceTracing {
 public:
-    SurfaceTracing(SurfaceFlinger& flinger);
+    explicit SurfaceTracing(SurfaceFlinger& flinger);
     void enable();
     bool disable();
     status_t writeToFile();
@@ -61,7 +61,7 @@
     void setTraceFlags(uint32_t flags);
 
 private:
-    static constexpr auto kDefaultBufferCapInByte = 100_MB;
+    static constexpr auto kDefaultBufferCapInByte = 5_MB;
     static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
 
     class LayersTraceBuffer { // ring buffer
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 78c6e74..c97a19b 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -67,6 +67,16 @@
     }
 }
 
+std::string TimeStats::miniDump() {
+    ATRACE_CALL();
+
+    std::string result = "TimeStats miniDump:\n";
+    std::lock_guard<std::mutex> lock(mMutex);
+    android::base::StringAppendF(&result, "Number of tracked layers is %zu\n",
+                                 mTimeStatsTracker.size());
+    return result;
+}
+
 void TimeStats::incrementTotalFrames() {
     if (!mEnabled.load()) return;
 
@@ -252,7 +262,8 @@
           postTime);
 
     std::lock_guard<std::mutex> lock(mMutex);
-    if (!mTimeStatsTracker.count(layerID) && layerNameIsValid(layerName)) {
+    if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS &&
+        layerNameIsValid(layerName)) {
         mTimeStatsTracker[layerID].layerName = layerName;
     }
     if (!mTimeStatsTracker.count(layerID)) return;
@@ -291,6 +302,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.frameTime.latchTime = latchTime;
@@ -306,6 +320,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.frameTime.desiredTime = desiredTime;
@@ -321,6 +338,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.frameTime.acquireTime = acquireTime;
@@ -338,6 +358,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.acquireFence = acquireFence;
@@ -353,6 +376,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.frameTime.presentTime = presentTime;
@@ -374,6 +400,9 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mTimeStatsTracker.count(layerID)) return;
     LayerRecord& layerRecord = mTimeStatsTracker[layerID];
+    if (layerRecord.waitData < 0 ||
+        layerRecord.waitData >= static_cast<int32_t>(layerRecord.timeRecords.size()))
+        return;
     TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
     if (timeRecord.frameTime.frameNumber == frameNumber) {
         timeRecord.presentFence = presentFence;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index d8c0786..2bcb568 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -41,6 +41,7 @@
 
     virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
     virtual bool isEnabled() = 0;
+    virtual std::string miniDump() = 0;
 
     virtual void incrementTotalFrames() = 0;
     virtual void incrementMissedFrames() = 0;
@@ -112,6 +113,7 @@
 
     void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
     bool isEnabled() override;
+    std::string miniDump() override;
 
     void incrementTotalFrames() override;
     void incrementMissedFrames() override;
@@ -137,8 +139,6 @@
     void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
     void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;
 
-    // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU
-    // static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_TIME_RECORDS = 64;
 
 private:
@@ -159,6 +159,8 @@
     std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker;
     PowerTime mPowerTime;
     GlobalRecord mGlobalRecord;
+
+    static const size_t MAX_NUM_LAYER_RECORDS = 200;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index 1d2217d..c519f8d 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -34,7 +34,8 @@
 //         >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
 //
 // See CallbackIdsHash for a explaniation of why this works
-static int compareCallbackIds(const std::vector<CallbackId>& c1, const std::vector<CallbackId> c2) {
+static int compareCallbackIds(const std::vector<CallbackId>& c1,
+                              const std::vector<CallbackId>& c2) {
     if (c1.empty()) {
         return !c2.empty();
     }
@@ -74,14 +75,15 @@
     mThread = std::thread(&TransactionCompletedThread::threadMain, this);
 }
 
-status_t TransactionCompletedThread::addCallback(const sp<ITransactionCompletedListener>& listener,
-                                                 const std::vector<CallbackId>& callbackIds) {
+status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
         ALOGE("cannot add callback because the callback thread isn't running");
         return BAD_VALUE;
     }
 
+    auto& [listener, callbackIds] = listenerCallbacks;
+
     if (mCompletedTransactions.count(listener) == 0) {
         status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
         if (err != NO_ERROR) {
@@ -90,11 +92,41 @@
         }
     }
 
+    mRegisteringTransactions.insert(listenerCallbacks);
+
     auto& transactionStatsDeque = mCompletedTransactions[listener];
     transactionStatsDeque.emplace_back(callbackIds);
+
     return NO_ERROR;
 }
 
+status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
+    std::lock_guard lock(mMutex);
+    if (!mRunning) {
+        ALOGE("cannot add callback because the callback thread isn't running");
+        return BAD_VALUE;
+    }
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    if (itr == mRegisteringTransactions.end()) {
+        ALOGE("cannot end a registration that does not exist");
+        return BAD_VALUE;
+    }
+
+    mRegisteringTransactions.erase(itr);
+
+    return NO_ERROR;
+}
+
+bool TransactionCompletedThread::isRegisteringTransaction(
+        const sp<ITransactionCompletedListener>& transactionListener,
+        const std::vector<CallbackId>& callbackIds) {
+    ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    return itr != mRegisteringTransactions.end();
+}
+
 status_t TransactionCompletedThread::registerPendingCallbackHandle(
         const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
@@ -104,7 +136,7 @@
     }
 
     // If we can't find the transaction stats something has gone wrong. The client should call
-    // addCallback before trying to register a pending callback handle.
+    // startRegistration before trying to register a pending callback handle.
     TransactionStats* transactionStats;
     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
     if (err != NO_ERROR) {
@@ -116,7 +148,7 @@
     return NO_ERROR;
 }
 
-status_t TransactionCompletedThread::addPresentedCallbackHandles(
+status_t TransactionCompletedThread::finalizePendingCallbackHandles(
         const std::deque<sp<CallbackHandle>>& handles) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
@@ -140,6 +172,9 @@
             } else {
                 ALOGW("there are more latched callbacks than there were registered callbacks");
             }
+            if (listener->second.size() == 0) {
+                mPendingTransactions.erase(listener);
+            }
         } else {
             ALOGW("cannot find listener in mPendingTransactions");
         }
@@ -154,7 +189,7 @@
     return NO_ERROR;
 }
 
-status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
+status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
         const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
@@ -185,7 +220,7 @@
 
 status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
     // If we can't find the transaction stats something has gone wrong. The client should call
-    // addCallback before trying to add a presnted callback handle.
+    // startRegistration before trying to add a callback handle.
     TransactionStats* transactionStats;
     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
     if (err != NO_ERROR) {
@@ -193,8 +228,14 @@
     }
 
     transactionStats->latchTime = handle->latchTime;
-    transactionStats->surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
-                                                handle->previousReleaseFence);
+    // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
+    // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
+    // destroyed the client side is dead and there won't be anyone to send the callback to.
+    sp<IBinder> surfaceControl = handle->surfaceControl.promote();
+    if (surfaceControl) {
+        transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
+                                                    handle->previousReleaseFence);
+    }
     return NO_ERROR;
 }
 
@@ -215,6 +256,7 @@
 
     while (mKeepRunning) {
         mConditionVariable.wait(mMutex);
+        std::vector<ListenerStats> completedListenerStats;
 
         // For each listener
         auto completedTransactionsItr = mCompletedTransactions.begin();
@@ -228,9 +270,18 @@
             while (transactionStatsItr != transactionStatsDeque.end()) {
                 auto& transactionStats = *transactionStatsItr;
 
+                // If this transaction is still registering, it is not safe to send a callback
+                // because there could be surface controls that haven't been added to
+                // transaction stats or mPendingTransactions.
+                if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
+                    break;
+                }
+
                 // If we are still waiting on the callback handles for this transaction, stop
                 // here because all transaction callbacks for the same listener must come in order
-                if (mPendingTransactions[listener].count(transactionStats.callbackIds) != 0) {
+                auto pendingTransactions = mPendingTransactions.find(listener);
+                if (pendingTransactions != mPendingTransactions.end() &&
+                    pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
                     break;
                 }
 
@@ -258,11 +309,27 @@
             } else {
                 completedTransactionsItr++;
             }
+
+            completedListenerStats.push_back(std::move(listenerStats));
         }
 
         if (mPresentFence) {
             mPresentFence.clear();
         }
+
+        // If everyone else has dropped their reference to a layer and its listener is dead,
+        // we are about to cause the layer to be deleted. If this happens at the wrong time and
+        // we are holding mMutex, we will cause a deadlock.
+        //
+        // The deadlock happens because this thread is holding on to mMutex and when we delete
+        // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
+        // then call's TransactionCompletedThread::run() which tries to grab mMutex.
+        //
+        // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
+        // to the layer.
+        mMutex.unlock();
+        completedListenerStats.clear();
+        mMutex.lock();
     }
 }
 
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index 09feb75..e255e50 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -21,6 +21,7 @@
 #include <mutex>
 #include <thread>
 #include <unordered_map>
+#include <unordered_set>
 
 #include <android-base/thread_annotations.h>
 
@@ -30,6 +31,12 @@
 
 namespace android {
 
+struct ITransactionCompletedListenerHash {
+    std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
+        return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get() : nullptr);
+    }
+};
+
 struct CallbackIdsHash {
     // CallbackId vectors have several properties that let us get away with this simple hash.
     // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
@@ -37,11 +44,27 @@
     // 2) CallbackId vectors for the same listener either are identical or contain none of the
     // same members. It is sufficient to just check the first CallbackId in the vectors. If
     // they match, they are the same. If they do not match, they are not the same.
-    std::size_t operator()(const std::vector<CallbackId> callbackIds) const {
+    std::size_t operator()(const std::vector<CallbackId>& callbackIds) const {
         return std::hash<CallbackId>{}((callbackIds.empty()) ? 0 : callbackIds.front());
     }
 };
 
+struct ListenerCallbacksHash {
+    std::size_t HashCombine(size_t value1, size_t value2) const {
+        return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2));
+    }
+
+    std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const {
+        struct ITransactionCompletedListenerHash listenerHasher;
+        struct CallbackIdsHash callbackIdsHasher;
+
+        std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener);
+        std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds);
+
+        return HashCombine(listenerHash, callbackIdsHash);
+    }
+};
+
 class CallbackHandle : public RefBase {
 public:
     CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
@@ -49,7 +72,7 @@
 
     sp<ITransactionCompletedListener> listener;
     std::vector<CallbackId> callbackIds;
-    sp<IBinder> surfaceControl;
+    wp<IBinder> surfaceControl;
 
     bool releasePreviousBuffer = false;
     sp<Fence> previousReleaseFence;
@@ -64,10 +87,12 @@
     void run();
 
     // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
-    // to be included in the callback. This functions should be call before attempting to add any
-    // callback handles.
-    status_t addCallback(const sp<ITransactionCompletedListener>& transactionListener,
-                         const std::vector<CallbackId>& callbackIds);
+    // to be included in the callback. This functions should be call before attempting to register
+    // any callback handles.
+    status_t startRegistration(const ListenerCallbacks& listenerCallbacks);
+    // Ends the registration. After this is called, no more CallbackHandles will be registered.
+    // It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
+    status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
 
     // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle
     // that needs to be latched and presented this frame. This function should be called once the
@@ -76,11 +101,11 @@
     // presented.
     status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
     // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
-    status_t addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
+    status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
 
     // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
     // presented this frame.
-    status_t addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
+    status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
 
     void addPresentFence(const sp<Fence>& presentFence);
 
@@ -89,6 +114,9 @@
 private:
     void threadMain();
 
+    bool isRegisteringTransaction(const sp<ITransactionCompletedListener>& transactionListener,
+                                  const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
+
     status_t findTransactionStats(const sp<ITransactionCompletedListener>& listener,
                                   const std::vector<CallbackId>& callbackIds,
                                   TransactionStats** outTransactionStats) REQUIRES(mMutex);
@@ -106,13 +134,6 @@
     };
     sp<ThreadDeathRecipient> mDeathRecipient;
 
-    struct ITransactionCompletedListenerHash {
-        std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
-            return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get()
-                                                    : nullptr);
-        }
-    };
-
     // Protects the creation and destruction of mThread
     std::mutex mThreadMutex;
 
@@ -121,11 +142,15 @@
     std::mutex mMutex;
     std::condition_variable_any mConditionVariable;
 
+    std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> mRegisteringTransactions
+            GUARDED_BY(mMutex);
+
     std::unordered_map<
             sp<ITransactionCompletedListener>,
             std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
             ITransactionCompletedListenerHash>
             mPendingTransactions GUARDED_BY(mMutex);
+
     std::unordered_map<sp<ITransactionCompletedListener>, std::deque<TransactionStats>,
                        ITransactionCompletedListenerHash>
             mCompletedTransactions GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index cb368b0..d03cb7b 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -43,7 +43,7 @@
         type: "nano",
     },
     srcs: ["*.proto"],
-    no_framework_libs: true,
+    sdk_version: "core_platform",
     target: {
         android: {
             jarjar_rules: "jarjar-rules.txt",
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 7288232..d3381e5 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -299,6 +299,7 @@
 
     StringAppendF(&result, "crop=%s, ", crop.to_string().c_str());
     StringAppendF(&result, "cornerRadius=%f, ", cornerRadius);
+    StringAppendF(&result, "isProtected=%1d, ", isProtected);
     StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
     StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
     StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str());
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index fe6dc93..56ab4e3 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -36,7 +36,7 @@
 prop {
     api_name: "vsync_event_phase_offset_ns"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
 }
@@ -44,7 +44,7 @@
 prop {
     api_name: "vsync_sf_event_phase_offset_ns"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
 }
@@ -53,7 +53,7 @@
 prop {
     api_name: "use_context_priority"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_context_priority"
 }
@@ -62,7 +62,7 @@
 prop {
     api_name: "max_frame_buffer_acquired_buffers"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
 }
@@ -80,7 +80,7 @@
 prop {
     api_name: "has_wide_color_display"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_wide_color_display"
 }
@@ -90,7 +90,7 @@
 prop {
     api_name: "running_without_sync_framework"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.running_without_sync_framework"
 }
@@ -108,7 +108,7 @@
 prop {
     api_name: "has_HDR_display"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_HDR_display"
 }
@@ -117,7 +117,7 @@
 prop {
     api_name: "present_time_offset_from_vsync_ns"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
 }
@@ -129,7 +129,7 @@
 prop {
     api_name: "force_hwc_copy_for_virtual_displays"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
 }
@@ -139,7 +139,7 @@
 prop {
     api_name: "max_virtual_display_dimension"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_virtual_display_dimension"
 }
@@ -151,7 +151,7 @@
 prop {
     api_name: "use_vr_flinger"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_vr_flinger"
 }
@@ -161,7 +161,7 @@
 prop {
     api_name: "start_graphics_allocator_service"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.start_graphics_allocator_service"
 }
@@ -171,7 +171,7 @@
     api_name: "primary_display_orientation"
     type: Enum
     enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.primary_display_orientation"
 }
@@ -182,7 +182,7 @@
 prop {
     api_name: "use_color_management"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_color_management"
 }
@@ -209,7 +209,7 @@
 prop {
     api_name: "default_composition_dataspace"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_dataspace"
 }
@@ -220,7 +220,7 @@
 prop {
     api_name: "default_composition_pixel_format"
     type: Integer
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_pixel_format"
 }
@@ -235,7 +235,7 @@
 prop {
     api_name: "wcg_composition_dataspace"
     type: Long
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_dataspace"
 }
@@ -246,11 +246,25 @@
 prop {
     api_name: "wcg_composition_pixel_format"
     type: Integer
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
 }
 
+# colorSpaceAgnosticDataspace specifies the data space that
+# SurfaceFlinger expects for surfaces which are color space agnostic.
+# The variable works only when useColorManagement is specified. If
+# unspecified, the data space follows what SurfaceFlinger expects for
+# surfaces when useColorManagement is specified.
+
+prop {
+    api_name: "color_space_agnostic_dataspace"
+    type: Long
+    scope: System
+    access: Readonly
+    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+}
+
 # Return the native panel primary data. The data includes red, green,
 # blue and white. The primary format is CIE 1931 XYZ color space.
 # If unspecified, the primaries is sRGB gamut by default.
@@ -258,7 +272,7 @@
 prop {
     api_name: "display_primary_red"
     type: DoubleList
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_red"
 }
@@ -266,7 +280,7 @@
 prop {
     api_name: "display_primary_green"
     type: DoubleList
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_green"
 }
@@ -274,7 +288,7 @@
 prop {
     api_name: "display_primary_blue"
     type: DoubleList
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_blue"
 }
@@ -282,7 +296,7 @@
 prop {
     api_name: "display_primary_white"
     type: DoubleList
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_white"
 }
@@ -293,17 +307,58 @@
 prop {
     api_name: "set_idle_timer_ms"
     type: Integer
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
 }
 
+# setTouchTimerMs indicates what is considered a timeout in milliseconds for Scheduler.
+# This value is used by the Scheduler to trigger touch inactivity callbacks that will switch the
+# display to a lower refresh rate. Setting this property to 0 means there is no timer.
+prop {
+    api_name: "set_touch_timer_ms"
+    type: Integer
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.set_touch_timer_ms"
+}
+
+# setDisplayPowerTimerMs indicates what is considered a timeout in milliseconds for Scheduler.
+# This value is used by the Scheduler to trigger display power inactivity callbacks that will
+# keep the display in peak refresh rate as long as display power is not in normal mode.
+# Setting this property to 0 means there is no timer.
+prop {
+    api_name: "set_display_power_timer_ms"
+    type: Integer
+    scope: System
+    access: Readonly
+    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+}
+
 # useSmart90ForVideo indicates whether Scheduler should detect content FPS, and try to adjust the
 # screen refresh rate based on that.
 prop {
     api_name: "use_smart_90_for_video"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
 }
+
+prop {
+    api_name: "enable_protected_contents"
+    type: Boolean
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.protected_contents"
+}
+
+# Indicates whether Scheduler's idle timer should support a display driver timeout in the kernel.
+# The value of set_idle_timer_ms should be shorter in time than the timeout duration in the kernel.
+prop {
+    api_name: "support_kernel_idle_timer"
+    type: Boolean
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.support_kernel_idle_timer"
+}
diff --git a/services/surfaceflinger/sysprop/api/system-current.txt b/services/surfaceflinger/sysprop/api/system-current.txt
index d802177..79854b3 100644
--- a/services/surfaceflinger/sysprop/api/system-current.txt
+++ b/services/surfaceflinger/sysprop/api/system-current.txt
@@ -1 +1,45 @@
 // Signature format: 2.0
+package android.sysprop {
+
+  public final class SurfaceFlingerProperties {
+    method public static java.util.Optional<java.lang.Long> color_space_agnostic_dataspace();
+    method public static java.util.Optional<java.lang.Long> default_composition_dataspace();
+    method public static java.util.Optional<java.lang.Integer> default_composition_pixel_format();
+    method public static java.util.List<java.lang.Double> display_primary_blue();
+    method public static java.util.List<java.lang.Double> display_primary_green();
+    method public static java.util.List<java.lang.Double> display_primary_red();
+    method public static java.util.List<java.lang.Double> display_primary_white();
+    method public static java.util.Optional<java.lang.Boolean> enable_protected_contents();
+    method public static java.util.Optional<java.lang.Boolean> force_hwc_copy_for_virtual_displays();
+    method public static java.util.Optional<java.lang.Boolean> has_HDR_display();
+    method public static java.util.Optional<java.lang.Boolean> has_wide_color_display();
+    method public static java.util.Optional<java.lang.Long> max_frame_buffer_acquired_buffers();
+    method public static java.util.Optional<java.lang.Long> max_virtual_display_dimension();
+    method public static java.util.Optional<java.lang.Long> present_time_offset_from_vsync_ns();
+    method public static java.util.Optional<android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values> primary_display_orientation();
+    method public static java.util.Optional<java.lang.Boolean> running_without_sync_framework();
+    method public static java.util.Optional<java.lang.Integer> set_display_power_timer_ms();
+    method public static java.util.Optional<java.lang.Integer> set_idle_timer_ms();
+    method public static java.util.Optional<java.lang.Integer> set_touch_timer_ms();
+    method public static java.util.Optional<java.lang.Boolean> start_graphics_allocator_service();
+    method public static java.util.Optional<java.lang.Boolean> support_kernel_idle_timer();
+    method public static java.util.Optional<java.lang.Boolean> use_color_management();
+    method public static java.util.Optional<java.lang.Boolean> use_context_priority();
+    method public static java.util.Optional<java.lang.Boolean> use_smart_90_for_video();
+    method public static java.util.Optional<java.lang.Boolean> use_vr_flinger();
+    method public static java.util.Optional<java.lang.Long> vsync_event_phase_offset_ns();
+    method public static java.util.Optional<java.lang.Long> vsync_sf_event_phase_offset_ns();
+    method public static java.util.Optional<java.lang.Long> wcg_composition_dataspace();
+    method public static java.util.Optional<java.lang.Integer> wcg_composition_pixel_format();
+  }
+
+  public enum SurfaceFlingerProperties.primary_display_orientation_values {
+    method public String getPropValue();
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_0;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_180;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_270;
+    enum_constant public static final android.sysprop.SurfaceFlingerProperties.primary_display_orientation_values ORIENTATION_90;
+  }
+
+}
+
diff --git a/services/surfaceflinger/test.png b/services/surfaceflinger/test.png
new file mode 100644
index 0000000..773dcc3
--- /dev/null
+++ b/services/surfaceflinger/test.png
Binary files differ
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index f121a95..53a3611 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -19,9 +19,11 @@
     srcs: [
         "BufferGenerator.cpp",
         "Credentials_test.cpp",
+        "InvalidHandles_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
         "Transaction_test.cpp",
+        "VirtualDisplay_test.cpp",
     ],
     data: ["SurfaceFlinger_test.filter"],
     static_libs: [
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
new file mode 100644
index 0000000..42d1f5a
--- /dev/null
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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 <binder/Binder.h>
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/Rect.h>
+
+namespace android {
+namespace {
+
+class NotALayer : public BBinder {};
+
+/**
+ * For all of these tests we make a SurfaceControl with an invalid layer handle
+ * and verify we aren't able to trick SurfaceFlinger.
+ */
+class InvalidHandleTest : public ::testing::Test {
+protected:
+    sp<SurfaceComposerClient> mScc;
+    sp<SurfaceControl> mNotSc;
+    void SetUp() override {
+        mScc = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mScc->initCheck());
+        mNotSc = makeNotSurfaceControl();
+    }
+
+    sp<SurfaceControl> makeNotSurfaceControl() {
+        return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
+    }
+};
+
+TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) {
+    auto notSc = makeNotSurfaceControl();
+    ASSERT_EQ(nullptr,
+              mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
+                                  notSc.get())
+                      .get());
+}
+
+TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    sp<GraphicBuffer> outBuffer;
+
+    ASSERT_EQ(NAME_NOT_FOUND,
+              sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index be862c9..6b4634a 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*"
+            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*"
         }
 }
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 5cc946a..26c6da9 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -43,14 +43,17 @@
 constexpr uint32_t SIZE_UPDATE = 134;
 constexpr uint32_t STACK_UPDATE = 1;
 constexpr uint64_t DEFERRED_UPDATE = 0;
+constexpr int32_t RELATIVE_Z = 42;
 constexpr float ALPHA_UPDATE = 0.29f;
 constexpr float CORNER_RADIUS_UPDATE = 0.2f;
 constexpr float POSITION_UPDATE = 121;
 const Rect CROP_UPDATE(16, 16, 32, 32);
 
 const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
-constexpr auto TEST_SURFACE_NAME = "BG Interceptor Test Surface";
-constexpr auto UNIQUE_TEST_SURFACE_NAME = "BG Interceptor Test Surface#0";
+constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface";
+constexpr auto TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface";
+constexpr auto UNIQUE_TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface#0";
+constexpr auto UNIQUE_TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface#0";
 constexpr auto LAYER_NAME = "Layer Create and Delete Test";
 constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0";
 
@@ -136,12 +139,15 @@
     void TearDown() override {
         mComposerClient->dispose();
         mBGSurfaceControl.clear();
+        mFGSurfaceControl.clear();
         mComposerClient.clear();
     }
 
     sp<SurfaceComposerClient> mComposerClient;
     sp<SurfaceControl> mBGSurfaceControl;
+    sp<SurfaceControl> mFGSurfaceControl;
     int32_t mBGLayerId;
+    int32_t mFGLayerId;
 
 public:
     using TestTransactionAction = void (SurfaceInterceptorTest::*)(Transaction&);
@@ -177,6 +183,10 @@
     bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
     bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
     bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
+    bool reparentUpdateFound(const SurfaceChange& change, bool found);
+    bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
+    bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
+    bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
     bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
 
     // Find all of the updates in the single trace
@@ -209,6 +219,10 @@
     void opaqueFlagUpdate(Transaction&);
     void secureFlagUpdate(Transaction&);
     void deferredTransactionUpdate(Transaction&);
+    void reparentUpdate(Transaction&);
+    void relativeParentUpdate(Transaction&);
+    void detachChildrenUpdate(Transaction&);
+    void reparentChildrenUpdate(Transaction&);
     void surfaceCreation(Transaction&);
     void displayCreation(Transaction&);
     void displayDeletion(Transaction&);
@@ -250,21 +264,30 @@
     ssize_t displayHeight = info.h;
 
     // Background surface
-    mBGSurfaceControl = mComposerClient->createSurface(
-            String8(TEST_SURFACE_NAME), displayWidth, displayHeight,
-            PIXEL_FORMAT_RGBA_8888, 0);
+    mBGSurfaceControl = mComposerClient->createSurface(String8(TEST_BG_SURFACE_NAME), displayWidth,
+                                                       displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
     ASSERT_TRUE(mBGSurfaceControl != nullptr);
     ASSERT_TRUE(mBGSurfaceControl->isValid());
 
+    // Foreground surface
+    mFGSurfaceControl = mComposerClient->createSurface(String8(TEST_FG_SURFACE_NAME), displayWidth,
+                                                       displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
+    ASSERT_TRUE(mFGSurfaceControl != nullptr);
+    ASSERT_TRUE(mFGSurfaceControl->isValid());
+
     Transaction t;
     t.setDisplayLayerStack(display, 0);
-    ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
-            .show(mBGSurfaceControl)
-            .apply());
+    ASSERT_EQ(NO_ERROR,
+              t.setLayer(mBGSurfaceControl, INT_MAX - 3)
+                      .show(mBGSurfaceControl)
+                      .setLayer(mFGSurfaceControl, INT_MAX - 3)
+                      .show(mFGSurfaceControl)
+                      .apply());
 }
 
 void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) {
-    mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_SURFACE_NAME);
+    mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_BG_SURFACE_NAME);
+    mFGLayerId = getSurfaceId(trace, UNIQUE_TEST_FG_SURFACE_NAME);
 }
 
 void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
@@ -364,6 +387,22 @@
                                    DEFERRED_UPDATE);
 }
 
+void SurfaceInterceptorTest::reparentUpdate(Transaction& t) {
+    t.reparent(mBGSurfaceControl, mFGSurfaceControl->getHandle());
+}
+
+void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) {
+    t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl->getHandle(), RELATIVE_Z);
+}
+
+void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
+    t.detachChildren(mBGSurfaceControl);
+}
+
+void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
+    t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl->getHandle());
+}
+
 void SurfaceInterceptorTest::displayCreation(Transaction&) {
     sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
     SurfaceComposerClient::destroyDisplay(testDisplay);
@@ -389,6 +428,10 @@
     runInTransaction(&SurfaceInterceptorTest::opaqueFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::secureFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
+    runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
+    runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
+    runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
+    runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
 }
 
 void SurfaceInterceptorTest::surfaceCreation(Transaction&) {
@@ -569,6 +612,46 @@
     return foundDeferred;
 }
 
+bool SurfaceInterceptorTest::reparentUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.reparent().parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::relativeParentUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.relative_parent().relative_parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
+    bool detachChildren(change.detach_children().detach_children());
+    if (detachChildren && !found) {
+        found = true;
+    } else if (detachChildren && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.reparent_children().parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
 bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace,
         SurfaceChange::SurfaceChangeCase changeCase) {
     bool foundUpdate = false;
@@ -620,6 +703,18 @@
                         case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
                             foundUpdate = deferredTransactionUpdateFound(change, foundUpdate);
                             break;
+                        case SurfaceChange::SurfaceChangeCase::kReparent:
+                            foundUpdate = reparentUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kReparentChildren:
+                            foundUpdate = reparentChildrenUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kRelativeParent:
+                            foundUpdate = relativeParentUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kDetachChildren:
+                            foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
+                            break;
                         case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET:
                             break;
                     }
@@ -644,6 +739,10 @@
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
 }
 
 bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -798,6 +897,26 @@
             SurfaceChange::SurfaceChangeCase::kDeferredTransaction);
 }
 
+TEST_F(SurfaceInterceptorTest, InterceptReparentUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::reparentUpdate,
+                SurfaceChange::SurfaceChangeCase::kReparent);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptReparentChildrenUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::reparentChildrenUpdate,
+                SurfaceChange::SurfaceChangeCase::kReparentChildren);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::relativeParentUpdate,
+                SurfaceChange::SurfaceChangeCase::kRelativeParent);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
+                SurfaceChange::SurfaceChangeCase::kDetachChildren);
+}
+
 TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) {
     captureTest(&SurfaceInterceptorTest::runAllUpdates,
                 &SurfaceInterceptorTest::assertAllUpdatesFound);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index d62afa5..aed7b40 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -231,6 +231,20 @@
         *sc = std::make_unique<ScreenCapture>(outBuffer);
     }
 
+    static void captureChildLayersExcluding(
+            std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
+            std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeLayers) {
+        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+        SurfaceComposerClient::Transaction().apply(true);
+
+        sp<GraphicBuffer> outBuffer;
+        ASSERT_EQ(NO_ERROR,
+                  sf->captureLayers(parentHandle, &outBuffer, ui::Dataspace::V0_SRGB,
+                                    ui::PixelFormat::RGBA_8888, Rect::EMPTY_RECT, excludeLayers,
+                                    1.0f, true));
+        *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);
@@ -371,6 +385,18 @@
         return createLayer(mClient, name, width, height, flags, parent);
     }
 
+    sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
+                                        SurfaceControl* parent = nullptr) {
+        auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
+                                        PIXEL_FORMAT_RGBA_8888,
+                                        ISurfaceComposerClient::eFXSurfaceColor, parent);
+        asTransaction([&](Transaction& t) {
+            t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
+            t.setAlpha(colorLayer, color.a / 255.0f);
+        });
+        return colorLayer;
+    }
+
     ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
         // wait for previous transactions (such as setSize) to complete
         Transaction().apply(true);
@@ -1042,6 +1068,103 @@
     screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
 }
 
+TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) {
+    sp<SurfaceControl> parent =
+            LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+                                              ISurfaceComposerClient::eFXSurfaceColor);
+
+    sp<SurfaceControl> childLayer;
+    ASSERT_NO_FATAL_FAILURE(
+            childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
+                                                           0 /* buffer height */,
+                                                           ISurfaceComposerClient::eFXSurfaceColor,
+                                                           parent.get()));
+    Transaction()
+            .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
+            .setColor(parent, half3{0.0f, 0.0f, 0.0f})
+            .show(childLayer)
+            .show(parent)
+            .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight))
+            .setCrop_legacy(childLayer, Rect(0, 0, 20, 30))
+            .apply();
+
+    Transaction()
+            .setRelativeLayer(childLayer, parent->getHandle(), -1)
+            .setLayer(childLayer, 1)
+            .apply();
+
+    {
+        SCOPED_TRACE("setLayer above");
+        // Set layer should get applied and place the child above.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
+    }
+
+    Transaction()
+            .setLayer(childLayer, 1)
+            .setRelativeLayer(childLayer, parent->getHandle(), -1)
+            .apply();
+
+    {
+        SCOPED_TRACE("setRelative below");
+        // Set relative layer should get applied and place the child below.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
+    }
+}
+
+TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) {
+    sp<SurfaceControl> parent =
+            LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+                                              ISurfaceComposerClient::eFXSurfaceColor);
+    sp<SurfaceControl> relativeParent =
+            LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */,
+                    0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceColor);
+
+    sp<SurfaceControl> childLayer;
+    ASSERT_NO_FATAL_FAILURE(
+            childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
+                                                           0 /* buffer height */,
+                                                           ISurfaceComposerClient::eFXSurfaceColor,
+                                                           parent.get()));
+    Transaction()
+            .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
+            .setColor(parent, half3{0.0f, 0.0f, 0.0f})
+            .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f})
+            .show(childLayer)
+            .show(parent)
+            .show(relativeParent)
+            .setLayer(parent, mLayerZBase - 1)
+            .setLayer(relativeParent, mLayerZBase)
+            .apply();
+
+    Transaction()
+            .setRelativeLayer(childLayer, relativeParent->getHandle(), 1)
+            .apply();
+
+    {
+        SCOPED_TRACE("setLayer above");
+        // Set layer should get applied and place the child above.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
+    }
+
+    Transaction()
+        .hide(relativeParent)
+        .apply();
+
+    {
+        SCOPED_TRACE("hide relative parent");
+        // The relative should no longer be visible.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
+    }
+}
+
 void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) {
     sp<SurfaceControl> layerR;
     sp<SurfaceControl> layerG;
@@ -1255,11 +1378,12 @@
 
     // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
     // to receive them...we are expected to take care with the results.
+    bool outCapturedSecureLayers;
     ASSERT_EQ(NO_ERROR,
-              composer->captureScreen(mDisplay, &outBuffer,
-                      ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
-                      Rect(), 0, 0, false,
-                      ISurfaceComposer::eRotateNone, true));
+              composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers,
+                                      ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0,
+                                      0, false, ISurfaceComposer::eRotateNone, true));
+    ASSERT_EQ(true, outCapturedSecureLayers);
     ScreenCapture sc(outBuffer);
     sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
 }
@@ -4303,6 +4427,30 @@
     }
 }
 
+TEST_F(LayerUpdateTest, MergingTransactionFlags) {
+    Transaction().hide(mFGSurfaceControl).apply();
+    std::unique_ptr<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before merge");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectBGColor(0, 12);
+        sc->expectBGColor(75, 75);
+        sc->expectBGColor(145, 145);
+    }
+
+    Transaction t1, t2;
+    t1.show(mFGSurfaceControl);
+    t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */);
+    t1.merge(std::move(t2));
+    t1.apply();
+
+    {
+        SCOPED_TRACE("after merge");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectFGColor(75, 75);
+    }
+}
+
 class ChildLayerTest : public LayerUpdateTest {
 protected:
     void SetUp() override {
@@ -4663,6 +4811,48 @@
         mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
     }
 }
+TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
+    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+    sp<SurfaceControl> childNewClient =
+            newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+    ASSERT_TRUE(childNewClient != nullptr);
+    ASSERT_TRUE(childNewClient->isValid());
+
+    fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+    Transaction()
+            .hide(mChild)
+            .show(childNewClient)
+            .setPosition(childNewClient, 10, 10)
+            .setPosition(mFGSurfaceControl, 64, 64)
+            .apply();
+
+    {
+        mCapture = screenshot();
+        Rect rect = Rect(74, 74, 84, 84);
+        mCapture->expectBorder(rect, Color{195, 63, 63, 255});
+        mCapture->expectColor(rect, Color{200, 200, 200, 255});
+    }
+
+    Transaction()
+            .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
+                                          mFGSurfaceControl->getSurface()->getNextFrameNumber())
+            .apply();
+    Transaction().detachChildren(mFGSurfaceControl).apply();
+    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
+
+    // BufferLayer can still dequeue buffers even though there's a detached layer with a
+    // deferred transaction.
+    {
+        SCOPED_TRACE("new buffer");
+        mCapture = screenshot();
+        Rect rect = Rect(74, 74, 84, 84);
+        mCapture->expectBorder(rect, Color::RED);
+        mCapture->expectColor(rect, Color{200, 200, 200, 255});
+    }
+}
 
 TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
     asTransaction([&](Transaction& t) {
@@ -5238,6 +5428,57 @@
     mCapture->expectChildColor(0, 0);
 }
 
+TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child2, 200, 0, 200);
+
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            .show(child2)
+            .setLayer(child, 1)
+            .setLayer(child2, 2)
+            .apply(true);
+
+    // Child2 would be visible but its excluded, so we should see child1 color instead.
+    ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+    mCapture->checkPixel(10, 10, 0, 0, 0);
+    mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
+// Like the last test but verifies that children are also exclude.
+TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
+    auto fgHandle = mFGSurfaceControl->getHandle();
+
+    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child, 200, 200, 200);
+    sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+    fillSurfaceRGBA8(child2, 200, 0, 200);
+    sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
+                                              PIXEL_FORMAT_RGBA_8888, 0, child2.get());
+    fillSurfaceRGBA8(child2, 200, 0, 200);
+
+    SurfaceComposerClient::Transaction()
+            .show(child)
+            .show(child2)
+            .show(child3)
+            .setLayer(child, 1)
+            .setLayer(child2, 2)
+            .apply(true);
+
+    // Child2 would be visible but its excluded, so we should see child1 color instead.
+    ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+    mCapture->checkPixel(10, 10, 0, 0, 0);
+    mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
 TEST_F(ScreenCaptureTest, CaptureTransparent) {
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
@@ -5720,4 +5961,126 @@
                 allowedConfigs.end());
 }
 
+class RelativeZTest : public LayerTransactionTest {
+protected:
+    virtual void SetUp() {
+        LayerTransactionTest::SetUp();
+        ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+        const auto display = SurfaceComposerClient::getInternalDisplayToken();
+        ASSERT_FALSE(display == nullptr);
+
+        // Back layer
+        mBackgroundLayer = createColorLayer("Background layer", Color::RED);
+
+        // Front layer
+        mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
+
+        asTransaction([&](Transaction& t) {
+            t.setDisplayLayerStack(display, 0);
+            t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
+            t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
+        });
+    }
+
+    virtual void TearDown() {
+        LayerTransactionTest::TearDown();
+        mBackgroundLayer = 0;
+        mForegroundLayer = 0;
+    }
+
+    sp<SurfaceControl> mBackgroundLayer;
+    sp<SurfaceControl> mForegroundLayer;
+};
+
+// When a layer is reparented offscreen, remove relative z order if the relative parent
+// is still onscreen so that the layer is not drawn.
+TEST_F(RelativeZTest, LayerRemoved) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    // Background layer (RED)
+    //   Child layer (WHITE) (relative to foregroud layer)
+    // Foregroud layer (GREEN)
+    sp<SurfaceControl> childLayer =
+            createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
+
+    Transaction{}
+            .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
+            .show(childLayer)
+            .apply();
+
+    {
+        // The childLayer should be in front of the FG control.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLayer, nullptr).apply();
+
+    // Background layer (RED)
+    //   Child layer (WHITE)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
+
+    {
+        // The relative z info for child layer should be reset, leaving FG control on top.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+}
+
+// When a layer is reparented offscreen, preseve relative z order if the relative parent
+// is also offscreen. Regression test b/132613412
+TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1 (WHITE)
+    //     child level 2a (BLUE)
+    //       child level 3 (GREEN) (relative to child level 2b)
+    //     child level 2b (BLACK)
+    sp<SurfaceControl> childLevel1 =
+            createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
+    sp<SurfaceControl> childLevel2a =
+            createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
+    sp<SurfaceControl> childLevel2b =
+            createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
+    sp<SurfaceControl> childLevel3 =
+            createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
+
+    Transaction{}
+            .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
+            .show(childLevel2a)
+            .show(childLevel2b)
+            .show(childLevel3)
+            .apply();
+
+    {
+        // The childLevel3 should be in front of childLevel2b.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLevel1, nullptr).apply();
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1 (WHITE)
+    //     child level 2 back (BLUE)
+    //       child level 3 (GREEN) (relative to child level 2b)
+    //     child level 2 front (BLACK)
+    Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
+
+    {
+        // Nothing should change at this point since relative z info was preserved.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/VirtualDisplay_test.cpp b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
new file mode 100644
index 0000000..9fd2227
--- /dev/null
+++ b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 <binder/Binder.h>
+
+#include <gtest/gtest.h>
+#include <gui/GLConsumer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+namespace android {
+namespace {
+
+class VirtualDisplayTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        sp<IGraphicBufferConsumer> consumer;
+
+        BufferQueue::createBufferQueue(&mProducer, &consumer);
+        consumer->setConsumerName(String8("Virtual disp consumer"));
+        consumer->setDefaultBufferSize(100, 100);
+
+        mGLConsumer = new GLConsumer(consumer, GLConsumer::TEXTURE_EXTERNAL, true, false);
+    }
+
+    sp<IGraphicBufferProducer> mProducer;
+    sp<GLConsumer> mGLConsumer;
+};
+
+TEST_F(VirtualDisplayTest, VirtualDisplayDestroyedSurfaceReuse) {
+    sp<IBinder> virtualDisplay =
+            SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
+
+    SurfaceComposerClient::Transaction t;
+    t.setDisplaySurface(virtualDisplay, mProducer);
+    t.apply(true);
+
+    SurfaceComposerClient::destroyDisplay(virtualDisplay);
+    virtualDisplay.clear();
+    // Sync here to ensure the display was completely destroyed in SF
+    t.apply(true);
+
+    sp<Surface> surface = new Surface(mProducer);
+    sp<ANativeWindow> window(surface);
+
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(), NATIVE_WINDOW_API_EGL));
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index f9e0b64..a892a2a 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -54,10 +54,11 @@
 namespace {
 
 // Mock test helpers
+using ::testing::_;
+using ::testing::DoAll;
 using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::SetArgPointee;
-using ::testing::_;
 
 using Transaction = SurfaceComposerClient::Transaction;
 
diff --git a/services/surfaceflinger/tests/unittests/AllowedDisplayConfigsTest.cpp b/services/surfaceflinger/tests/unittests/AllowedDisplayConfigsTest.cpp
deleted file mode 100644
index 4274254..0000000
--- a/services/surfaceflinger/tests/unittests/AllowedDisplayConfigsTest.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2019 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 "LibSurfaceFlingerUnittests"
-#define LOG_NDEBUG 0
-
-#include <memory>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include <log/log.h>
-
-#include "AllowedDisplayConfigs.h"
-
-namespace android {
-namespace {
-
-class AllowedDisplayConfigsTest : public testing::Test {
-protected:
-    AllowedDisplayConfigsTest();
-    ~AllowedDisplayConfigsTest() override;
-
-    void buildAllowedConfigs();
-
-    const std::vector<int32_t> expectedConfigs = {0, 2, 7, 129};
-    constexpr static int32_t notAllowedConfig = 5;
-    std::unique_ptr<const AllowedDisplayConfigs> mAllowedConfigs;
-};
-
-AllowedDisplayConfigsTest::AllowedDisplayConfigsTest() {
-    const ::testing::TestInfo* const test_info =
-            ::testing::UnitTest::GetInstance()->current_test_info();
-    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-}
-
-AllowedDisplayConfigsTest::~AllowedDisplayConfigsTest() {
-    const ::testing::TestInfo* const test_info =
-            ::testing::UnitTest::GetInstance()->current_test_info();
-    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
-}
-
-void AllowedDisplayConfigsTest::buildAllowedConfigs() {
-    AllowedDisplayConfigs::Builder builder;
-    for (int config : expectedConfigs) {
-        builder.addConfig(config);
-    }
-    mAllowedConfigs = builder.build();
-}
-
-/* ------------------------------------------------------------------------
- * Test cases
- */
-
-TEST_F(AllowedDisplayConfigsTest, checkConfigs) {
-    buildAllowedConfigs();
-
-    // Check that all expected configs are allowed
-    for (int config : expectedConfigs) {
-        EXPECT_TRUE(mAllowedConfigs->isConfigAllowed(config));
-    }
-
-    // Check that all the allowed configs are expected
-    std::vector<int32_t> allowedConfigVector;
-    mAllowedConfigs->getAllowedConfigs(&allowedConfigVector);
-    EXPECT_EQ(allowedConfigVector, expectedConfigs);
-
-    // Check that notAllowedConfig is indeed not allowed
-    EXPECT_TRUE(std::find(expectedConfigs.begin(), expectedConfigs.end(), notAllowedConfig) ==
-                expectedConfigs.end());
-    EXPECT_FALSE(mAllowedConfigs->isConfigAllowed(notAllowedConfig));
-}
-
-TEST_F(AllowedDisplayConfigsTest, getAllowedConfigsNullptr) {
-    buildAllowedConfigs();
-
-    // No other expectations rather than no crash
-    mAllowedConfigs->getAllowedConfigs(nullptr);
-}
-
-} // namespace
-} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 12b41fd..4917bc2 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -35,20 +35,21 @@
     srcs: [
         ":libsurfaceflinger_sources",
         "libsurfaceflinger_unittest_main.cpp",
-        "AllowedDisplayConfigsTest.cpp",
-        "CompositionTest.cpp",
+        "CachingTest.cpp",
+	"CompositionTest.cpp",
         "DispSyncSourceTest.cpp",
         "DisplayIdentificationTest.cpp",
         "DisplayTransactionTest.cpp",
         "EventControlThreadTest.cpp",
         "EventThreadTest.cpp",
-        "IdleTimerTest.cpp",
+        "OneShotTimerTest.cpp",
         "LayerHistoryTest.cpp",
         "LayerMetadataTest.cpp",
         "SchedulerTest.cpp",
         "SchedulerUtilsTest.cpp",
         "RefreshRateConfigsTest.cpp",
         "RefreshRateStatsTest.cpp",
+        "RegionSamplingTest.cpp",
         "TimeStatsTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplay.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp
new file mode 100644
index 0000000..74ce540
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019 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 "CachingTest"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include "BufferStateLayer.h"
+
+namespace android {
+
+class SlotGenerationTest : public testing::Test {
+protected:
+    BufferStateLayer::HwcSlotGenerator mHwcSlotGenerator;
+    sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+    sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+    sp<GraphicBuffer> mBuffer3{new GraphicBuffer(10, 10, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+};
+
+TEST_F(SlotGenerationTest, getHwcCacheSlot_Invalid) {
+    sp<IBinder> binder = new BBinder();
+    // test getting invalid client_cache_id
+    client_cache_t id;
+    uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
+    EXPECT_EQ(BufferQueue::INVALID_BUFFER_SLOT, slot);
+}
+
+TEST_F(SlotGenerationTest, getHwcCacheSlot_Basic) {
+    sp<IBinder> binder = new BBinder();
+    client_cache_t id;
+    id.token = binder;
+    id.id = 0;
+    uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
+    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);
+
+    client_cache_t idB;
+    idB.token = binder;
+    idB.id = 1;
+    slot = mHwcSlotGenerator.getHwcCacheSlot(idB);
+    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 2, slot);
+
+    slot = mHwcSlotGenerator.getHwcCacheSlot(idB);
+    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 2, slot);
+
+    slot = mHwcSlotGenerator.getHwcCacheSlot(id);
+    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);
+}
+
+TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) {
+    sp<IBinder> binder = new BBinder();
+    std::vector<client_cache_t> ids;
+    uint32_t cacheId = 0;
+    // fill up cache
+    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        client_cache_t id;
+        id.token = binder;
+        id.id = cacheId;
+        ids.push_back(id);
+
+        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
+        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
+        cacheId++;
+    }
+    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(ids[i]);
+        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
+    }
+
+    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        client_cache_t id;
+        id.token = binder;
+        id.id = cacheId;
+        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
+        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
+        cacheId++;
+    }
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ef3dfef..e6211c4 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -125,7 +125,7 @@
     }
 
     void setupScheduler() {
-        mScheduler = new TestableScheduler();
+        mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
         mScheduler->mutableEventControlThread().reset(mEventControlThread);
         mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
         EXPECT_CALL(*mEventThread.get(), registerDisplayEventConnection(_));
@@ -253,13 +253,16 @@
     static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
 
     static void setupPreconditions(CompositionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    setPowerMode(HWC_DISPLAY,
+                                 static_cast<Hwc2::IComposerClient::PowerMode>(
+                                         Derived::INIT_POWER_MODE)))
+                .WillOnce(Return(Error::NONE));
 
         FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical,
                                true /* isPrimary */)
                 .setCapabilities(&test->mDefaultCapabilities)
+                .setPowerMode(Derived::INIT_POWER_MODE)
                 .inject(&test->mFlinger, test->mComposer);
         Mock::VerifyAndClear(test->mComposer);
 
@@ -282,6 +285,13 @@
     }
 
     template <typename Case>
+    static void setupPreconditionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                                Return(Error::NONE)));
+    }
+
+    template <typename Case>
     static void setupCommonCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mComposer,
                     setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
@@ -293,11 +303,6 @@
         EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1);
 
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
-        // TODO: remove once we verify that we can just grab the fence from the
-        // FramebufferSurface.
-        EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
-            return base::unique_fd();
-        }));
 
         EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
         EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -393,6 +398,9 @@
     static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_OFF;
 
     template <typename Case>
+    static void setupPreconditionCallExpectations(CompositionTest*) {}
+
+    template <typename Case>
     static void setupCommonCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
 
@@ -856,7 +864,7 @@
     }
 
     static void cleanupInjectedLayers(CompositionTest* test) {
-        EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(2);
+        EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(1);
         Base::cleanupInjectedLayers(test);
     }
 
@@ -1022,6 +1030,7 @@
     using CompositionResult = CompositionResultCase;
 
     static void setupCommon(CompositionTest* test) {
+        Display::template setupPreconditionCallExpectations<ThisCase>(test);
         Display::setupPreconditions(test);
 
         auto layer = Layer::createLayer(test);
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 92bdebd..0aa8cf5 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -51,6 +51,7 @@
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder;
 
     static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms;
+    static constexpr std::chrono::nanoseconds mOffsetThresholdForNextVsync = 16ms;
     static constexpr int mIterations = 100;
 };
 
@@ -78,7 +79,8 @@
 
 void DispSyncSourceTest::createDispSyncSource() {
     createDispSync();
-    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true,
+    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(),
+                                                       mOffsetThresholdForNextVsync.count(), true,
                                                        "DispSyncSourceTest");
     mDispSyncSource->setCallback(this);
 }
@@ -142,23 +144,5 @@
     }
 }
 
-TEST_F(DispSyncSourceTest, pauseCallbacks) {
-    createDispSyncSource();
-    EXPECT_TRUE(mDispSyncSource);
-
-    mDispSyncSource->setVSyncEnabled(true);
-    EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());
-    mDispSync->triggerCallback();
-    EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
-
-    mDispSyncSource->pauseVsyncCallback(true);
-    mDispSync->triggerCallback();
-    EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-
-    mDispSyncSource->pauseVsyncCallback(false);
-    mDispSync->triggerCallback();
-    EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-}
-
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 9bf29a2..5f58e7d 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -179,7 +179,7 @@
 }
 
 void DisplayTransactionTest::setupScheduler() {
-    mScheduler = new TestableScheduler();
+    mScheduler = new TestableScheduler(mFlinger.mutableRefreshRateConfigs());
     mScheduler->mutableEventControlThread().reset(mEventControlThread);
     mScheduler->mutablePrimaryDispSync().reset(mPrimaryDispSync);
     EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
@@ -358,6 +358,9 @@
                 .WillRepeatedly(Return(0));
         EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
                 .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
+                .WillRepeatedly(Return(0));
+
         return injector;
     }
 
@@ -376,6 +379,8 @@
                 .WillRepeatedly(Return(0));
         EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
                 .WillRepeatedly(Return(0));
+        EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
+                .WillRepeatedly(Return(0));
     }
 
     static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
@@ -405,6 +410,7 @@
 
     // The HWC active configuration id
     static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
+    static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
 
     static void injectPendingHotplugEvent(DisplayTransactionTest* test,
                                           HWC2::Connection connection) {
@@ -422,6 +428,7 @@
                 .setWidth(DisplayVariant::WIDTH)
                 .setHeight(DisplayVariant::HEIGHT)
                 .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
+                .setPowerMode(INIT_POWER_MODE)
                 .inject(&test->mFlinger, test->mComposer);
     }
 
@@ -430,6 +437,10 @@
         EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
                                 Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    setPowerMode(HWC_DISPLAY_ID,
+                                 static_cast<Hwc2::IComposerClient::PowerMode>(INIT_POWER_MODE)))
+                .WillOnce(Return(Error::NONE));
         injectHwcDisplayWithNoDefaultCapabilities(test);
     }
 
@@ -462,9 +473,6 @@
                     getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
                                         IComposerClient::Attribute::DPI_Y, _))
                 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                                Return(Error::NONE)));
 
         if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
             EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
@@ -1198,6 +1206,7 @@
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
+        EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
         auto displayDevice = mInjector.inject();
 
         displayDevice->getCompositionDisplay()
@@ -1885,10 +1894,6 @@
     Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
     Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
 
-    EXPECT_CALL(*mComposer, getDisplayCapabilities(Case::Display::HWC_DISPLAY_ID, _))
-            .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                            Return(Error::NONE)));
-
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
             .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
@@ -2141,6 +2146,7 @@
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -2185,6 +2191,7 @@
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
     EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
+    EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
     display.inject();
 
     // There is a change to the viewport state
@@ -2830,7 +2837,6 @@
 
 struct DispSyncIsSupportedVariant {
     static void setupBeginResyncCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mPrimaryDispSync, reset()).Times(1);
         EXPECT_CALL(*test->mPrimaryDispSync, setPeriod(DEFAULT_REFRESH_RATE)).Times(1);
         EXPECT_CALL(*test->mPrimaryDispSync, beginResync()).Times(1);
     }
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 249c78f..dbd9b84 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -56,9 +56,8 @@
     public:
         MockEventThreadConnection(android::impl::EventThread* eventThread,
                                   ResyncCallback&& resyncCallback,
-                                  ResetIdleTimerCallback&& resetIdleTimerCallback)
-              : EventThreadConnection(eventThread, std::move(resyncCallback),
-                                      std::move(resetIdleTimerCallback)) {}
+                                  ISurfaceComposer::ConfigChanged configChanged)
+              : EventThreadConnection(eventThread, std::move(resyncCallback), configChanged) {}
         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
     };
 
@@ -69,11 +68,11 @@
     ~EventThreadTest() override;
 
     void createThread();
-    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder);
+    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
+                                                   ISurfaceComposer::ConfigChanged configChanged);
 
     void expectVSyncSetEnabledCallReceived(bool expectedState);
     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
-    void expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause);
     VSyncSource::Callback* expectVSyncSetCallbackCallReceived();
     void expectInterceptCallReceived(nsecs_t expectedTimestamp);
     void expectVsyncEventReceivedByConnection(const char* name,
@@ -88,9 +87,7 @@
     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
-    AsyncCallRecorder<void (*)(bool)> mVSyncPauseVsyncCallbackCallRecorder;
     AsyncCallRecorder<void (*)()> mResyncCallRecorder;
-    AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
     ConnectionEventRecorder mConnectionEventCallRecorder{0};
 
@@ -114,11 +111,9 @@
     EXPECT_CALL(mVSyncSource, setPhaseOffset(_))
             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
 
-    EXPECT_CALL(mVSyncSource, pauseVsyncCallback(_))
-            .WillRepeatedly(Invoke(mVSyncPauseVsyncCallbackCallRecorder.getInvocable()));
-
     createThread();
-    mConnection = createConnection(mConnectionEventCallRecorder);
+    mConnection = createConnection(mConnectionEventCallRecorder,
+                                   ISurfaceComposer::eConfigChangedDispatch);
 
     // A display must be connected for VSYNC events to be delivered.
     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
@@ -146,10 +141,10 @@
 }
 
 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
-        ConnectionEventRecorder& recorder) {
+        ConnectionEventRecorder& recorder, ISurfaceComposer::ConfigChanged configChanged) {
     sp<MockEventThreadConnection> connection =
             new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
-                                          mResetIdleTimerCallRecorder.getInvocable());
+                                          configChanged);
     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
     return connection;
 }
@@ -166,12 +161,6 @@
     EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value()));
 }
 
-void EventThreadTest::expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause) {
-    auto args = mVSyncPauseVsyncCallbackCallRecorder.waitForCall();
-    ASSERT_TRUE(args.has_value());
-    EXPECT_EQ(expectedPause, std::get<0>(args.value()));
-}
-
 VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() {
     auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall();
     return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr;
@@ -236,7 +225,6 @@
     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
-    EXPECT_FALSE(mResetIdleTimerCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
 }
@@ -246,7 +234,7 @@
     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
 
     // Signal that we want the next vsync event to be posted to the connection.
-    mThread->requestNextVsync(mConnection, false);
+    mThread->requestNextVsync(mConnection);
 
     // EventThread should not enable vsync callbacks.
     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
@@ -254,10 +242,9 @@
 
 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
     // Signal that we want the next vsync event to be posted to the connection
-    mThread->requestNextVsync(mConnection, true);
+    mThread->requestNextVsync(mConnection);
 
-    // EventThread should immediately reset the idle timer and request a resync.
-    EXPECT_TRUE(mResetIdleTimerCallRecorder.waitForCall().has_value());
+    // EventThread should immediately request a resync.
     EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
 
     // EventThread should enable vsync callbacks.
@@ -284,7 +271,9 @@
 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
     // Create a first connection, register it, and request a vsync rate of zero.
     ConnectionEventRecorder firstConnectionEventRecorder{0};
-    sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
+    sp<MockEventThreadConnection> firstConnection =
+            createConnection(firstConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(0, firstConnection);
 
     // By itself, this should not enable vsync events
@@ -294,7 +283,8 @@
     // However if there is another connection which wants events at a nonzero rate.....
     ConnectionEventRecorder secondConnectionEventRecorder{0};
     sp<MockEventThreadConnection> secondConnection =
-            createConnection(secondConnectionEventRecorder);
+            createConnection(secondConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, secondConnection);
 
     // EventThread should enable vsync callbacks.
@@ -380,7 +370,9 @@
 
 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -404,7 +396,9 @@
 
 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -431,16 +425,6 @@
     expectVSyncSetPhaseOffsetCallReceived(321);
 }
 
-TEST_F(EventThreadTest, pauseVsyncCallbackForwardsToVSyncSource) {
-    mThread->pauseVsyncCallback(true);
-    expectVSyncPauseVsyncCallbackCallReceived(true);
-}
-
-TEST_F(EventThreadTest, resumeVsyncCallbackForwardsToVSyncSource) {
-    mThread->pauseVsyncCallback(false);
-    expectVSyncPauseVsyncCallbackCallReceived(false);
-}
-
 TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
@@ -476,5 +460,18 @@
     expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7);
 }
 
+TEST_F(EventThreadTest, suppressConfigChanged) {
+    ConnectionEventRecorder suppressConnectionEventRecorder{0};
+    sp<MockEventThreadConnection> suppressConnection =
+            createConnection(suppressConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
+
+    mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 9);
+    expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9);
+
+    auto args = suppressConnectionEventRecorder.waitForCall();
+    ASSERT_FALSE(args.has_value());
+}
+
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index 0739f15..1d75011 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -23,6 +23,8 @@
 namespace android {
 namespace scheduler {
 
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
+
 class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
     nsecs_t FAKE_PHASE_OFFSET_NS = 0;
 
@@ -33,20 +35,27 @@
     nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
     nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
 
+    PhaseOffsets::Offsets getOffsetsForRefreshRate(
+            RefreshRateType /*refreshRateType*/) const override {
+        return getCurrentOffsets();
+    }
+
     // Returns early, early GL, and late offsets for Apps and SF.
     PhaseOffsets::Offsets getCurrentOffsets() const override {
-        return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
+        return Offsets{{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
     }
 
     // This function should be called when the device is switching between different
     // refresh rates, to properly update the offsets.
-    void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+    void setRefreshRateType(RefreshRateType /*refreshRateType*/) override {}
+
+    nsecs_t getOffsetThresholdForNextVsync() const override { return FAKE_PHASE_OFFSET_NS; }
 
     // Returns current offsets in human friendly format.
     void dump(std::string& /*result*/) const override {}
 };
 
 } // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 3fb1a6e..8e7440c 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -7,6 +7,7 @@
 #include <log/log.h>
 
 #include <mutex>
+#include <thread>
 
 #include "Scheduler/LayerHistory.h"
 
@@ -14,6 +15,7 @@
 using testing::Return;
 
 namespace android {
+namespace scheduler {
 
 class LayerHistoryTest : public testing::Test {
 public:
@@ -22,6 +24,18 @@
 
 protected:
     std::unique_ptr<LayerHistory> mLayerHistory;
+
+    static constexpr float MIN_REFRESH_RATE = 30.f;
+    static constexpr float MAX_REFRESH_RATE = 90.f;
+    static constexpr auto RELEVANT_FRAME_THRESHOLD = 90u;
+    static constexpr uint64_t THIRTY_FPS_INTERVAL = 33'333'333;
+
+    void forceRelevancy(const std::unique_ptr<LayerHistory::LayerHandle>& testLayer) {
+        mLayerHistory->setVisibility(testLayer, true);
+        for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) {
+            mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+        }
+    };
 };
 
 LayerHistoryTest::LayerHistoryTest() {
@@ -30,145 +44,97 @@
 LayerHistoryTest::~LayerHistoryTest() {}
 
 namespace {
-TEST_F(LayerHistoryTest, simpleInsertAndGet) {
-    mLayerHistory->insert("TestLayer", 0);
-
-    const std::unordered_map<std::string, nsecs_t>& testMap = mLayerHistory->get(0);
-    EXPECT_EQ(1, testMap.size());
-    auto element = testMap.find("TestLayer");
-    EXPECT_EQ("TestLayer", element->first);
-    EXPECT_EQ(0, element->second);
-
-    // Testing accessing object at an empty container will return an empty map.
-    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(1);
-    EXPECT_EQ(0, emptyMap.size());
-}
-
-TEST_F(LayerHistoryTest, multipleInserts) {
-    mLayerHistory->insert("TestLayer0", 0);
-    mLayerHistory->insert("TestLayer1", 1);
-    mLayerHistory->insert("TestLayer2", 2);
-    mLayerHistory->insert("TestLayer3", 3);
-
-    const std::unordered_map<std::string, nsecs_t>& testMap = mLayerHistory->get(0);
-    // Because the counter was not incremented, all elements were inserted into the first
-    // container.
-    EXPECT_EQ(4, testMap.size());
-    auto element = testMap.find("TestLayer0");
-    EXPECT_EQ("TestLayer0", element->first);
-    EXPECT_EQ(0, element->second);
-
-    element = testMap.find("TestLayer1");
-    EXPECT_EQ("TestLayer1", element->first);
-    EXPECT_EQ(1, element->second);
-
-    element = testMap.find("TestLayer2");
-    EXPECT_EQ("TestLayer2", element->first);
-    EXPECT_EQ(2, element->second);
-
-    element = testMap.find("TestLayer3");
-    EXPECT_EQ("TestLayer3", element->first);
-    EXPECT_EQ(3, element->second);
-
-    // Testing accessing object at an empty container will return an empty map.
-    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(1);
-    EXPECT_EQ(0, emptyMap.size());
-}
-
-TEST_F(LayerHistoryTest, incrementingCounter) {
-    mLayerHistory->insert("TestLayer0", 0);
-    mLayerHistory->incrementCounter();
-    mLayerHistory->insert("TestLayer1", 1);
-    mLayerHistory->insert("TestLayer2", 2);
-    mLayerHistory->incrementCounter();
-    mLayerHistory->insert("TestLayer3", 3);
-
-    // Because the counter was incremented, the elements were inserted into different
-    // containers.
-    // We expect the get method to access the slot at the current counter of the index
-    // is 0.
-    const std::unordered_map<std::string, nsecs_t>& testMap1 = mLayerHistory->get(0);
-    EXPECT_EQ(1, testMap1.size());
-    auto element = testMap1.find("TestLayer3");
-    EXPECT_EQ("TestLayer3", element->first);
-    EXPECT_EQ(3, element->second);
-
-    const std::unordered_map<std::string, nsecs_t>& testMap2 = mLayerHistory->get(1);
-    EXPECT_EQ(2, testMap2.size());
-    element = testMap2.find("TestLayer1");
-    EXPECT_EQ("TestLayer1", element->first);
-    EXPECT_EQ(1, element->second);
-    element = testMap2.find("TestLayer2");
-    EXPECT_EQ("TestLayer2", element->first);
-    EXPECT_EQ(2, element->second);
-
-    const std::unordered_map<std::string, nsecs_t>& testMap3 = mLayerHistory->get(2);
-    EXPECT_EQ(1, testMap3.size());
-    element = testMap3.find("TestLayer0");
-    EXPECT_EQ("TestLayer0", element->first);
-    EXPECT_EQ(0, element->second);
-
-    // Testing accessing object at an empty container will return an empty map.
-    const std::unordered_map<std::string, nsecs_t>& emptyMap = mLayerHistory->get(3);
-    EXPECT_EQ(0, emptyMap.size());
-}
-
-TEST_F(LayerHistoryTest, clearTheMap) {
-    mLayerHistory->insert("TestLayer0", 0);
-
-    const std::unordered_map<std::string, nsecs_t>& testMap1 = mLayerHistory->get(0);
-    EXPECT_EQ(1, testMap1.size());
-    auto element = testMap1.find("TestLayer0");
-    EXPECT_EQ("TestLayer0", element->first);
-    EXPECT_EQ(0, element->second);
-
-    mLayerHistory->incrementCounter();
-    // The array currently contains 30 elements.
-    for (int i = 1; i < 30; ++i) {
-        mLayerHistory->insert("TestLayer0", i);
-        mLayerHistory->incrementCounter();
-    }
-    // Expect the map to be cleared.
-    const std::unordered_map<std::string, nsecs_t>& testMap2 = mLayerHistory->get(0);
-    EXPECT_EQ(0, testMap2.size());
-
-    mLayerHistory->insert("TestLayer30", 30);
-    const std::unordered_map<std::string, nsecs_t>& testMap3 = mLayerHistory->get(0);
-    element = testMap3.find("TestLayer30");
-    EXPECT_EQ("TestLayer30", element->first);
-    EXPECT_EQ(30, element->second);
-    // The original element in this location does not exist anymore.
-    element = testMap3.find("TestLayer0");
-    EXPECT_EQ(testMap3.end(), element);
-}
-
-TEST_F(LayerHistoryTest, testingGet) {
-    // The array currently contains 30 elements.
-    for (int i = 0; i < 30; ++i) {
-        const auto name = "TestLayer" + std::to_string(i);
-        mLayerHistory->insert(name, i);
-        mLayerHistory->incrementCounter();
+TEST_F(LayerHistoryTest, oneLayer) {
+    std::unique_ptr<LayerHistory::LayerHandle> testLayer =
+            mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(testLayer, true);
+    for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+        mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
     }
 
-    // The counter should be set to 0, and the map at 0 should be cleared.
-    const std::unordered_map<std::string, nsecs_t>& testMap1 = mLayerHistory->get(0);
-    EXPECT_EQ(0, testMap1.size());
+    // Add a few more. This time we should get MAX refresh rate as the layer
+    // becomes relevant
+    static constexpr auto A_FEW = 10;
+    for (auto i = 0u; i < A_FEW; i++) {
+        EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+        mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+    }
+}
 
-    // This should return (ARRAY_SIZE + (counter - 3)) % ARRAY_SIZE
-    const std::unordered_map<std::string, nsecs_t>& testMap2 = mLayerHistory->get(3);
-    EXPECT_EQ(1, testMap2.size());
-    auto element = testMap2.find("TestLayer27");
-    EXPECT_EQ("TestLayer27", element->first);
-    EXPECT_EQ(27, element->second);
+TEST_F(LayerHistoryTest, oneHDRLayer) {
+    std::unique_ptr<LayerHistory::LayerHandle> testLayer =
+            mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(testLayer, true);
 
-    // If the user gives an out of bound index, we should mod it with ARRAY_SIZE first,
-    // so requesting element 40 would be the same as requesting element 10.
-    const std::unordered_map<std::string, nsecs_t>& testMap3 = mLayerHistory->get(40);
-    EXPECT_EQ(1, testMap3.size());
-    element = testMap3.find("TestLayer20");
-    EXPECT_EQ("TestLayer20", element->first);
-    EXPECT_EQ(20, element->second);
+    mLayerHistory->insert(testLayer, 0, true /*isHDR*/);
+    EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+    EXPECT_EQ(true, mLayerHistory->getDesiredRefreshRateAndHDR().second);
+
+    mLayerHistory->setVisibility(testLayer, false);
+    EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+    EXPECT_EQ(false, mLayerHistory->getDesiredRefreshRateAndHDR().second);
+}
+
+TEST_F(LayerHistoryTest, explicitTimestamp) {
+    std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer =
+            mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(test30FpsLayer, true);
+
+    nsecs_t startTime = systemTime();
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
+    }
+
+    EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+}
+
+TEST_F(LayerHistoryTest, multipleLayers) {
+    std::unique_ptr<LayerHistory::LayerHandle> testLayer =
+            mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(testLayer, true);
+    std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer =
+            mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(test30FpsLayer, true);
+    std::unique_ptr<LayerHistory::LayerHandle> testLayer2 =
+            mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
+    mLayerHistory->setVisibility(testLayer2, true);
+
+    nsecs_t startTime = systemTime();
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+    }
+    EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+
+    startTime = systemTime();
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
+    }
+    EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+
+    for (int i = 10; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
+    }
+    EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+
+    // This frame is only around for 9 occurrences, so it doesn't throw
+    // anything off.
+    for (int i = 0; i < 9; i++) {
+        mLayerHistory->insert(testLayer2, 0, false /*isHDR*/);
+    }
+    EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+    // After 1200 ms frames become obsolete.
+    std::this_thread::sleep_for(std::chrono::milliseconds(1500));
+
+    mLayerHistory->insert(test30FpsLayer,
+                          startTime + (RELEVANT_FRAME_THRESHOLD * THIRTY_FPS_INTERVAL),
+                          false /*isHDR*/);
+    EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
 }
 
 } // namespace
+} // namespace scheduler
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
similarity index 72%
rename from services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
rename to services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index ea39bf5..0208728 100644
--- a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -21,17 +21,17 @@
 #include <utils/Log.h>
 
 #include "AsyncCallRecorder.h"
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 using namespace std::chrono_literals;
 
 namespace android {
 namespace scheduler {
 
-class IdleTimerTest : public testing::Test {
+class OneShotTimerTest : public testing::Test {
 protected:
-    IdleTimerTest() = default;
-    ~IdleTimerTest() override = default;
+    OneShotTimerTest() = default;
+    ~OneShotTimerTest() override = default;
 
     // This timeout should be used when a 3ms callback is expected.
     // While the tests typically request a callback after 3ms, the scheduler
@@ -46,7 +46,7 @@
     AsyncCallRecorder<void (*)()> mResetTimerCallback;
     AsyncCallRecorder<void (*)()> mExpiredTimerCallback;
 
-    std::unique_ptr<IdleTimer> mIdleTimer;
+    std::unique_ptr<OneShotTimer> mIdleTimer;
 
     void clearPendingCallbacks() {
         while (mExpiredTimerCallback.waitForCall(0us).has_value()) {
@@ -55,13 +55,14 @@
 };
 
 namespace {
-TEST_F(IdleTimerTest, createAndDestroyTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, [] {}, [] {});
+TEST_F(OneShotTimerTest, createAndDestroyTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+            3ms, [] {}, [] {});
 }
 
-TEST_F(IdleTimerTest, startStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(30ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(30ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     auto startTime = std::chrono::steady_clock::now();
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -70,7 +71,7 @@
     bool callbackCalled = mExpiredTimerCallback.waitForCall(25ms).has_value();
     // Under ideal conditions there should be no event. But occasionally
     // it is possible that the wait just prior takes more than 30ms, and
-    // a callback is observed. We check the elapsed time since before the IdleTimer
+    // a callback is observed. We check the elapsed time since before the OneShotTimer
     // thread was started as a sanity check to not have a flakey test.
     EXPECT_FALSE(callbackCalled && std::chrono::steady_clock::now() - startTime < 30ms);
 
@@ -79,9 +80,9 @@
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, resetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     // Observe any event that happens in about 25ms. We don't care if one was
@@ -104,26 +105,26 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, resetBackToBackTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetBackToBackTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
     mIdleTimer->reset();
-    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
+    EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
 
     mIdleTimer->reset();
-    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
+    EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
 
     mIdleTimer->reset();
-    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
+    EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
 
     mIdleTimer->reset();
-    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
+    EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
 
     // A single callback should be generated after 30ms
@@ -135,9 +136,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, startNotCalledTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startNotCalledTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     // The start hasn't happened, so the callback does not happen.
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
@@ -147,9 +148,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, idleTimerIdlesTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
@@ -167,18 +168,18 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, timeoutCallbackExecutionTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
@@ -190,9 +191,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index b218ad6..5067fe8 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -37,7 +37,9 @@
 class RefreshRateConfigsTest : public testing::Test {
 protected:
     static constexpr int CONFIG_ID_60 = 0;
+    static constexpr hwc2_config_t HWC2_CONFIG_ID_60 = 0;
     static constexpr int CONFIG_ID_90 = 1;
+    static constexpr hwc2_config_t HWC2_CONFIG_ID_90 = 1;
     static constexpr int64_t VSYNC_60 = 16666667;
     static constexpr int64_t VSYNC_90 = 11111111;
 
@@ -49,6 +51,8 @@
         ASSERT_EQ(left.name, right.name);
         ASSERT_EQ(left.fps, right.fps);
     }
+
+    RefreshRateConfigs mConfigs;
 };
 
 RefreshRateConfigsTest::RefreshRateConfigsTest() {
@@ -69,26 +73,27 @@
  */
 TEST_F(RefreshRateConfigsTest, zeroDeviceConfigs_storesPowerSavingConfig) {
     std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs;
-    RefreshRateConfigs configs(displayConfigs);
+    mConfigs.populate(displayConfigs);
 
     // We always store a configuration for screen off.
-    const auto& rates = configs.getRefreshRates();
+    const auto& rates = mConfigs.getRefreshRates();
     ASSERT_EQ(1, rates.size());
     const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
     ASSERT_NE(rates.end(), powerSavingRate);
     ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
     ASSERT_EQ(rates.end(), rates.find(RefreshRateType::DEFAULT));
 
-    RefreshRate expectedConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+    RefreshRate expectedConfig =
+            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
     assertRatesEqual(expectedConfig, *powerSavingRate->second);
 
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    assertRatesEqual(expectedConfig, *configs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::PERFORMANCE));
-    ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::DEFAULT));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    assertRatesEqual(expectedConfig, *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
+    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
 
     // Sanity check that getRefreshRate() does not modify the underlying configs.
-    ASSERT_EQ(1, configs.getRefreshRates().size());
+    ASSERT_EQ(1, mConfigs.getRefreshRates().size());
 }
 
 TEST_F(RefreshRateConfigsTest, oneDeviceConfig_storesDefaultConfig) {
@@ -97,9 +102,9 @@
     auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
     config60.setVsyncPeriod(VSYNC_60);
     displayConfigs.push_back(config60.build());
-    RefreshRateConfigs configs(displayConfigs);
+    mConfigs.populate(displayConfigs);
 
-    const auto& rates = configs.getRefreshRates();
+    const auto& rates = mConfigs.getRefreshRates();
     ASSERT_EQ(2, rates.size());
     const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
     const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
@@ -107,20 +112,21 @@
     ASSERT_NE(rates.end(), defaultRate);
     ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
 
-    RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+    RefreshRate expectedPowerSavingConfig =
+            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
     assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
-    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60};
+    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
     assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
 
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
     assertRatesEqual(expectedPowerSavingConfig,
-                     *configs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::DEFAULT));
-    assertRatesEqual(expectedDefaultConfig, *configs.getRefreshRate(RefreshRateType::DEFAULT));
-    ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::PERFORMANCE));
+                     *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
+    assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
+    ASSERT_FALSE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
 
     // Sanity check that getRefreshRate() does not modify the underlying configs.
-    ASSERT_EQ(2, configs.getRefreshRates().size());
+    ASSERT_EQ(2, mConfigs.getRefreshRates().size());
 }
 
 TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesPerformanceConfig) {
@@ -132,9 +138,9 @@
     auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
     config90.setVsyncPeriod(VSYNC_90);
     displayConfigs.push_back(config90.build());
-    RefreshRateConfigs configs(displayConfigs);
+    mConfigs.populate(displayConfigs);
 
-    const auto& rates = configs.getRefreshRates();
+    const auto& rates = mConfigs.getRefreshRates();
     ASSERT_EQ(3, rates.size());
     const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING);
     const auto& defaultRate = rates.find(RefreshRateType::DEFAULT);
@@ -143,21 +149,23 @@
     ASSERT_NE(rates.end(), defaultRate);
     ASSERT_NE(rates.end(), performanceRate);
 
-    RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+    RefreshRate expectedPowerSavingConfig =
+            RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
     assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
-    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60};
+    RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
     assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
-    RefreshRate expectedPerformanceConfig = RefreshRate{CONFIG_ID_90, "90fps", 90};
+    RefreshRate expectedPerformanceConfig =
+            RefreshRate{CONFIG_ID_90, "90fps", 90, HWC2_CONFIG_ID_90};
     assertRatesEqual(expectedPerformanceConfig, *performanceRate->second);
 
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
     assertRatesEqual(expectedPowerSavingConfig,
-                     *configs.getRefreshRate(RefreshRateType::POWER_SAVING));
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::DEFAULT));
-    assertRatesEqual(expectedDefaultConfig, *configs.getRefreshRate(RefreshRateType::DEFAULT));
-    ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::PERFORMANCE));
+                     *mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
+    assertRatesEqual(expectedDefaultConfig, *mConfigs.getRefreshRate(RefreshRateType::DEFAULT));
+    ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
     assertRatesEqual(expectedPerformanceConfig,
-                     *configs.getRefreshRate(RefreshRateType::PERFORMANCE));
+                     *mConfigs.getRefreshRate(RefreshRateType::PERFORMANCE));
 }
 } // namespace
 } // namespace scheduler
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 10f5af8..411ec61 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -42,11 +42,9 @@
     RefreshRateStatsTest();
     ~RefreshRateStatsTest();
 
-    void init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs);
-
-    std::unique_ptr<RefreshRateStats> mRefreshRateStats;
-    std::shared_ptr<android::mock::TimeStats> mTimeStats;
-    std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs;
+    mock::TimeStats mTimeStats;
+    RefreshRateConfigs mRefreshRateConfigs;
+    RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, mTimeStats};
 };
 
 RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -61,22 +59,16 @@
     ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
 }
 
-void RefreshRateStatsTest::init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs) {
-    mTimeStats = std::make_shared<android::mock::TimeStats>();
-    mRefreshRateConfigs = std::make_shared<RefreshRateConfigs>(configs);
-    mRefreshRateStats = std::make_unique<RefreshRateStats>(mRefreshRateConfigs, mTimeStats);
-}
-
 namespace {
 /* ------------------------------------------------------------------------
  * Test cases
  */
 TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
     std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
-    init(configs);
+    mRefreshRateConfigs.populate(configs);
 
     // There is one default config, so the refresh rates should have one item.
-    EXPECT_EQ(1, mRefreshRateStats->getTotalTimes().size());
+    EXPECT_EQ(1, mRefreshRateStats.getTotalTimes().size());
 }
 
 TEST_F(RefreshRateStatsTest, oneConfigTest) {
@@ -87,12 +79,12 @@
     std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
     configs.push_back(config.build());
 
-    init(configs);
+    mRefreshRateConfigs.populate(configs);
 
-    EXPECT_CALL(*mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
-    EXPECT_CALL(*mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
+    EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
+    EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
 
-    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(2, times.size());
     EXPECT_NE(0u, times.count("ScreenOff"));
     EXPECT_EQ(1u, times.count("90fps"));
@@ -105,29 +97,29 @@
 
     // Screen is off by default.
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(0, times["90fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
-    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
-    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
+    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
+    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_LT(ninety, times["90fps"]);
 
-    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
-    ninety = mRefreshRateStats->getTotalTimes()["90fps"];
+    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
+    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
-    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
+    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
     // does not update refresh rates that come from the config.
     EXPECT_LT(screenOff, times["ScreenOff"]);
@@ -146,13 +138,13 @@
     config60.setVsyncPeriod(VSYNC_60);
     configs.push_back(config60.build());
 
-    init(configs);
+    mRefreshRateConfigs.populate(configs);
 
-    EXPECT_CALL(*mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
-    EXPECT_CALL(*mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
-    EXPECT_CALL(*mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
+    EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
+    EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
+    EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
 
-    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(3, times.size());
     EXPECT_NE(0u, times.count("ScreenOff"));
     EXPECT_EQ(1u, times.count("60fps"));
@@ -168,60 +160,60 @@
 
     // Screen is off by default.
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(sixty, times["60fps"]);
     EXPECT_EQ(ninety, times["90fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
-    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
-    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
+    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
+    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_EQ(sixty, times["60fps"]);
     EXPECT_LT(ninety, times["90fps"]);
 
     // When power mode is normal, time for configs updates.
-    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
-    ninety = mRefreshRateStats->getTotalTimes()["90fps"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
+    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_LT(sixty, times["60fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
-    sixty = mRefreshRateStats->getTotalTimes()["60fps"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
+    sixty = mRefreshRateStats.getTotalTimes()["60fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_LT(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
-    ninety = mRefreshRateStats->getTotalTimes()["90fps"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
+    ninety = mRefreshRateStats.getTotalTimes()["90fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_EQ(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_LT(sixty, times["60fps"]);
 
     // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
     // does not update refresh rates that come from the config.
-    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
-    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
-    sixty = mRefreshRateStats->getTotalTimes()["60fps"];
+    mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
+    mRefreshRateStats.setConfigMode(CONFIG_ID_90);
+    sixty = mRefreshRateStats.getTotalTimes()["60fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
-    screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
+    mRefreshRateStats.setConfigMode(CONFIG_ID_60);
+    screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
-    times = mRefreshRateStats->getTotalTimes();
+    times = mRefreshRateStats.getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90fps"]);
     EXPECT_EQ(sixty, times["60fps"]);
diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
new file mode 100644
index 0000000..160f041
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2019 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 "RegionSamplingTest"
+
+#include <ui/Transform.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <array>
+#include <limits>
+
+#include "RegionSamplingThread.h"
+
+namespace android {
+
+struct RegionSamplingTest : testing::Test {
+public:
+    static uint32_t constexpr kBlack = 0;
+    static uint32_t constexpr kWhite = std::numeric_limits<uint32_t>::max();
+    static int constexpr kWidth = 98;
+    static int constexpr kStride = 100;
+    static int constexpr kHeight = 29;
+    static int constexpr kOrientation = ui::Transform::ROT_0;
+    std::array<uint32_t, kHeight * kStride> buffer;
+    Rect const whole_area{0, 0, kWidth, kHeight};
+};
+
+TEST_F(RegionSamplingTest, calculate_mean_white) {
+    std::fill(buffer.begin(), buffer.end(), kWhite);
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(1.0f));
+}
+
+TEST_F(RegionSamplingTest, calculate_mean_black) {
+    std::fill(buffer.begin(), buffer.end(), kBlack);
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(0.0f));
+}
+
+TEST_F(RegionSamplingTest, calculate_mean_partial_region) {
+    auto const halfway_down = kHeight >> 1;
+    auto const half = halfway_down * kStride;
+    Rect const partial_region = {whole_area.left, whole_area.top, whole_area.right,
+                                 whole_area.top + halfway_down};
+    std::fill(buffer.begin(), buffer.begin() + half, 0);
+    std::fill(buffer.begin() + half, buffer.end(), kWhite);
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, partial_region),
+                testing::FloatEq(0.0f));
+}
+
+TEST_F(RegionSamplingTest, calculate_mean_mixed_values) {
+    std::generate(buffer.begin(), buffer.end(), [n = 0]() mutable {
+        uint32_t const pixel = (n % std::numeric_limits<uint8_t>::max()) << ((n % 3) * CHAR_BIT);
+        n++;
+        return pixel;
+    });
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatNear(0.083f, 0.01f));
+}
+
+TEST_F(RegionSamplingTest, bimodal_tiebreaker) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ % 2) ? kBlack : kWhite; });
+    // presently there's no tiebreaking strategy in place, accept either of the means
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::AnyOf(testing::FloatEq(1.0), testing::FloatEq(0.0f)));
+}
+
+TEST_F(RegionSamplingTest, bounds_checking) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect invalid_region{0, 0, 4, kHeight + 1};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 0, -4, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{3, 0, 2, 0};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 3, 0, 2};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+}
+
+// workaround for b/133849373
+TEST_F(RegionSamplingTest, orientation_90) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect tl_region{0, 0, 4, 4};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           tl_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           tl_region),
+                testing::Eq(0.0));
+
+    Rect br_region{kWidth - 4, kHeight - 4, kWidth, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           br_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           br_region),
+                testing::Eq(1.0));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index ec76538..740115e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,8 @@
     class MockEventThreadConnection : public android::EventThreadConnection {
     public:
         explicit MockEventThreadConnection(EventThread* eventThread)
-              : EventThreadConnection(eventThread, ResyncCallback(), ResetIdleTimerCallback()) {}
+              : EventThreadConnection(eventThread, ResyncCallback(),
+                                      ISurfaceComposer::eConfigChangedSuppress) {}
         ~MockEventThreadConnection() = default;
 
         MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -33,18 +34,21 @@
         MOCK_METHOD0(requestNextVsync, void());
     };
 
+    scheduler::RefreshRateConfigs mRefreshRateConfigs;
+
     /**
      * This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
      * the same.
      */
     class MockScheduler : public android::Scheduler {
     public:
-        MockScheduler(std::unique_ptr<EventThread> eventThread)
-              : Scheduler([](bool) {}), mEventThread(std::move(eventThread)) {}
+        MockScheduler(const scheduler::RefreshRateConfigs& refreshRateConfigs,
+                      std::unique_ptr<EventThread> eventThread)
+              : Scheduler([](bool) {}, refreshRateConfigs), mEventThread(std::move(eventThread)) {}
 
         std::unique_ptr<EventThread> makeEventThread(
                 const char* /* connectionName */, DispSync* /* dispSync */,
-                nsecs_t /* phaseOffsetNs */,
+                nsecs_t /* phaseOffsetNs */, nsecs_t /* offsetThresholdForNextVsync */,
                 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
             return std::move(mEventThread);
         }
@@ -71,7 +75,7 @@
 
     std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
     mEventThread = eventThread.get();
-    mScheduler = std::make_unique<MockScheduler>(std::move(eventThread));
+    mScheduler = std::make_unique<MockScheduler>(mRefreshRateConfigs, std::move(eventThread));
     EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
 
     mEventThreadConnection = new MockEventThreadConnection(mEventThread);
@@ -81,7 +85,7 @@
     EXPECT_CALL(*mEventThread, createEventConnection(_, _))
             .WillRepeatedly(Return(mEventThreadConnection));
 
-    mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+    mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16, ResyncCallback(),
                                                      impl::EventThread::InterceptVSyncsCallback());
     EXPECT_TRUE(mConnectionHandle != nullptr);
 }
@@ -102,7 +106,10 @@
     // exceptions, just gracefully continues.
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
-            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+            returnedValue =
+                    mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -123,7 +130,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -152,7 +161,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue != nullptr);
     ASSERT_EQ(returnedValue, mEventThreadConnection);
 
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index dcbf973..cb6980e 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -17,15 +17,18 @@
 #pragma once
 
 #include <gmock/gmock.h>
+#include <gui/ISurfaceComposer.h>
 
 #include "Scheduler/EventThread.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/Scheduler.h"
 
 namespace android {
 
 class TestableScheduler : public Scheduler {
 public:
-    TestableScheduler() : Scheduler([](bool) {}) {}
+    TestableScheduler(const scheduler::RefreshRateConfigs& refreshRateConfig)
+          : Scheduler([](bool) {}, refreshRateConfig) {}
 
     // Creates EventThreadConnection with the given eventThread. Creates Scheduler::Connection
     // and adds it to the list of connectins. Returns the ConnectionHandle for the
@@ -33,7 +36,7 @@
     sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) {
         sp<EventThreadConnection> eventThreadConnection =
                 new EventThreadConnection(eventThread.get(), ResyncCallback(),
-                                          ResetIdleTimerCallback());
+                                          ISurfaceComposer::eConfigChangedSuppress);
         const int64_t id = sNextId++;
         mConnections.emplace(id,
                              std::make_unique<Scheduler::Connection>(new ConnectionHandle(id),
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 46fd964..64d34ee 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -31,6 +31,7 @@
 #include "FakePhaseOffsets.h"
 #include "Layer.h"
 #include "NativeWindowSurface.h"
+#include "Scheduler/MessageQueue.h"
 #include "StartPropertySetThread.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceFlingerFactory.h"
@@ -85,7 +86,8 @@
         return std::make_unique<scheduler::FakePhaseOffsets>();
     }
 
-    std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>) override {
+    std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>,
+                                               const scheduler::RefreshRateConfigs&) override {
         // TODO: Use test-fixture controlled factory
         return nullptr;
     }
@@ -275,11 +277,13 @@
 
     auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what); }
 
-    auto captureScreenImplLocked(const RenderArea& renderArea,
-                                 TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer,
-                                 bool useIdentityTransform, bool forSystem, int* outSyncFd) {
+    auto captureScreenImplLocked(
+            const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers,
+            ANativeWindowBuffer* buffer, bool useIdentityTransform, bool forSystem, int* outSyncFd) {
+        bool ignored;
         return mFlinger->captureScreenImplLocked(renderArea, traverseLayers, buffer,
-                                                 useIdentityTransform, forSystem, outSyncFd);
+                                                 useIdentityTransform, forSystem, outSyncFd,
+                                                 ignored);
     }
 
     auto traverseLayersInDisplay(const sp<const DisplayDevice>& display,
@@ -337,6 +341,7 @@
     auto& mutableScheduler() { return mFlinger->mScheduler; }
     auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; }
     auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; }
+    auto& mutableRefreshRateConfigs() { return mFlinger->mRefreshRateConfigs; }
 
     ~TestableSurfaceFlinger() {
         // All these pointer and container clears help ensure that GMock does
@@ -381,6 +386,7 @@
         static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
         static constexpr int32_t DEFAULT_DPI = 320;
         static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0;
+        static constexpr int32_t DEFAULT_POWER_MODE = 2;
 
         FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType,
                                bool isPrimary)
@@ -426,6 +432,11 @@
             return *this;
         }
 
+        auto& setPowerMode(int mode) {
+            mPowerMode = mode;
+            return *this;
+        }
+
         void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
             static const std::unordered_set<HWC2::Capability> defaultCapabilities;
             if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
@@ -445,6 +456,7 @@
             config.setDpiY(mDpiY);
             display->mutableConfigs().emplace(mActiveConfig, config.build());
             display->mutableIsConnected() = true;
+            display->setPowerMode(static_cast<HWC2::PowerMode>(mPowerMode));
 
             flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = display.get();
 
@@ -469,6 +481,7 @@
         int32_t mDpiX = DEFAULT_DPI;
         int32_t mDpiY = DEFAULT_DPI;
         int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
+        int32_t mPowerMode = DEFAULT_POWER_MODE;
         const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr;
     };
 
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index bb92020..3c7e1da 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -122,7 +122,6 @@
     MOCK_METHOD3(setLayerPerFrameMetadataBlobs,
                  Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadataBlob>&));
     MOCK_METHOD2(setDisplayBrightness, Error(Display, float));
-    MOCK_METHOD2(getDisplayBrightnessSupport, Error(Display, bool*));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index afcda5b..9ca116d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -31,10 +31,11 @@
     MOCK_METHOD0(reset, void());
     MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&));
     MOCK_METHOD0(beginResync, void());
-    MOCK_METHOD1(addResyncSample, bool(nsecs_t));
+    MOCK_METHOD2(addResyncSample, bool(nsecs_t, bool*));
     MOCK_METHOD0(endResync, void());
     MOCK_METHOD1(setPeriod, void(nsecs_t));
     MOCK_METHOD0(getPeriod, nsecs_t());
+    MOCK_METHOD0(getIntendedPeriod, nsecs_t());
     MOCK_METHOD1(setRefreshSkipCount, void(int));
     MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int));
     MOCK_METHOD1(setIgnorePresentFences, void(bool));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index cb4a300..ed35ebf 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -29,7 +29,7 @@
     ~EventThread() override;
 
     MOCK_CONST_METHOD2(createEventConnection,
-                       sp<EventThreadConnection>(ResyncCallback, ResetIdleTimerCallback));
+                       sp<EventThreadConnection>(ResyncCallback, ISurfaceComposer::ConfigChanged));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
@@ -39,7 +39,7 @@
     MOCK_METHOD1(registerDisplayEventConnection,
                  status_t(const sp<android::EventThreadConnection> &));
     MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &));
-    MOCK_METHOD2(requestNextVsync, void(const sp<android::EventThreadConnection> &, bool));
+    MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &));
     MOCK_METHOD1(pauseVsyncCallback, void(bool));
 };
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index e22d3e8..1b1c1a7 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -35,7 +35,6 @@
     MOCK_METHOD0(waitMessage, void());
     MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
     MOCK_METHOD0(invalidate, void());
-    MOCK_METHOD0(invalidateForHWC, void());
     MOCK_METHOD0(refresh, void());
 };
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 08fdb9d..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -30,6 +30,7 @@
 
     MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
     MOCK_METHOD0(isEnabled, bool());
+    MOCK_METHOD0(miniDump, std::string());
     MOCK_METHOD0(incrementTotalFrames, void());
     MOCK_METHOD0(incrementMissedFrames, void());
     MOCK_METHOD0(incrementClientCompositionFrames, void());
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index a7fd912..b71964b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -350,7 +350,7 @@
     while (!buffer_state_->compare_exchange_weak(
         current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
         std::memory_order_acquire)) {
-      ALOGI(
+      ALOGV(
           "%s: Failed to post to the new consumer. "
           "Current buffer state was changed to %" PRIx32
           " when trying to acquire the buffer and modify the buffer state to "
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index d9df204..1604775 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,180 +1,153 @@
 cc_library_shared {
-  name: "libvr_hwc-hal",
+    name: "libvr_hwc-hal",
 
-  srcs: [
-    "impl/vr_hwc.cpp",
-    "impl/vr_composer_client.cpp",
-  ],
+    srcs: [
+        "impl/vr_hwc.cpp",
+        "impl/vr_composer_client.cpp",
+    ],
 
-  static_libs: [
-    "libbroadcastring",
-    "libdisplay",
-  ],
+    static_libs: [
+        "libbroadcastring",
+        "libdisplay",
+    ],
 
-  shared_libs: [
-    "android.frameworks.vr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-    "android.hardware.graphics.mapper@2.0",
-    "android.hardware.graphics.mapper@3.0",
-    "libbase",
-    "libbufferhubqueue",
-    "libbinder",
-    "libcutils",
-    "libfmq",
-    "libhardware",
-    "libhidlbase",
-    "libhidltransport",
-    "liblog",
-    "libsync",
-    "libui",
-    "libutils",
-    "libpdx_default_transport",
-  ],
+    shared_libs: [
+        "android.frameworks.vr.composer@1.0",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "libbase",
+        "libbufferhubqueue",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libsync",
+        "libui",
+        "libutils",
+        "libpdx_default_transport",
+    ],
 
-  header_libs: [
-    "android.hardware.graphics.composer@2.1-command-buffer",
-    "android.hardware.graphics.composer@2.1-hal",
-  ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
 
-  export_header_lib_headers: [
-    "android.hardware.graphics.composer@2.1-hal",
-  ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
 
-  export_static_lib_headers: [
-    "libdisplay",
-  ],
+    export_static_lib_headers: [
+        "libdisplay",
+    ],
 
-  export_shared_lib_headers: [
-    "android.frameworks.vr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-  ],
+    export_shared_lib_headers: [
+        "android.frameworks.vr.composer@1.0",
+        "android.hardware.graphics.composer@2.1",
+    ],
 
-  export_include_dirs: ["."],
+    export_include_dirs: ["."],
 
-  cflags: [
-    "-DLOG_TAG=\"vr_hwc\"",
-    "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
-    "-Wall",
-    "-Werror",
-    "-Wno-error=unused-private-field",
-    // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
-    "-Wno-sign-compare",
-    "-Wno-unused-parameter",
-  ],
+    cflags: [
+        "-DLOG_TAG=\"vr_hwc\"",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-Wall",
+        "-Werror",
+        "-Wno-error=unused-private-field",
+        // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
+        "-Wno-sign-compare",
+        "-Wno-unused-parameter",
+    ],
 
 }
 
 cc_library_static {
-  name: "libvr_hwc-binder",
-  srcs: [
-    "aidl/android/dvr/IVrComposer.aidl",
-    "aidl/android/dvr/IVrComposerCallback.aidl",
-    "aidl/android/dvr/parcelable_composer_frame.cpp",
-    "aidl/android/dvr/parcelable_composer_layer.cpp",
-    "aidl/android/dvr/parcelable_unique_fd.cpp",
-  ],
-  aidl: {
-    include_dirs: ["frameworks/native/services/vr/hardware_composer/aidl"],
-    export_aidl_headers: true,
-  },
-  export_include_dirs: ["aidl"],
-
-  cflags: [
-    "-Wall",
-    "-Werror",
-  ],
-
-  shared_libs: [
-    "libbinder",
-    "libui",
-    "libutils",
-    "libvr_hwc-hal",
-  ],
-}
-
-cc_library_static {
-  name: "libvr_hwc-impl",
-  srcs: [
-    "vr_composer.cpp",
-  ],
-  static_libs: [
-    "libvr_hwc-binder",
-  ],
-  shared_libs: [
-    "libbase",
-    "libbinder",
-    "liblog",
-    "libui",
-    "libutils",
-    "libvr_hwc-hal",
-  ],
-  export_shared_lib_headers: [
-    "libvr_hwc-hal",
-  ],
-  cflags: [
-    "-DLOG_TAG=\"vr_hwc\"",
-    "-Wall",
-    "-Werror",
-  ],
+    name: "libvr_hwc-impl",
+    srcs: [
+        "vr_composer.cpp",
+    ],
+    static_libs: [
+        "libvr_hwc-binder",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libui",
+        "libutils",
+        "libvr_hwc-hal",
+    ],
+    export_shared_lib_headers: [
+        "libvr_hwc-hal",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"vr_hwc\"",
+        "-Wall",
+        "-Werror",
+    ],
 }
 
 cc_binary {
-  name: "vr_hwc",
-  vintf_fragments: ["manifest_vr_hwc.xml"],
-  srcs: [
-    "vr_hardware_composer_service.cpp"
-  ],
-  static_libs: [
-    "libvr_hwc-impl",
-    // NOTE: This needs to be included after the *-impl lib otherwise the
-    // symbols in the *-binder library get optimized out.
-    "libvr_hwc-binder",
-  ],
-  shared_libs: [
-    "android.frameworks.vr.composer@1.0",
-    "android.hardware.graphics.composer@2.1",
-    "libbase",
-    "libbinder",
-    "liblog",
-    "libhardware",
-    "libhwbinder",
-    "libui",
-    "libutils",
-    "libvr_hwc-hal",
-  ],
-  cflags: [
-    "-DLOG_TAG=\"vr_hwc\"",
-    "-Wall",
-    "-Werror",
-  ],
-  init_rc: [
-    "vr_hwc.rc",
-  ],
+    name: "vr_hwc",
+    vintf_fragments: ["manifest_vr_hwc.xml"],
+    srcs: [
+        "vr_hardware_composer_service.cpp",
+    ],
+    static_libs: [
+        "libvr_hwc-impl",
+        // NOTE: This needs to be included after the *-impl lib otherwise the
+        // symbols in the *-binder library get optimized out.
+        "libvr_hwc-binder",
+    ],
+    shared_libs: [
+        "android.frameworks.vr.composer@1.0",
+        "android.hardware.graphics.composer@2.1",
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libhardware",
+        "libhwbinder",
+        "libhidlbase",
+        "libui",
+        "libutils",
+        "libvr_hwc-hal",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"vr_hwc\"",
+        "-Wall",
+        "-Werror",
+    ],
+    init_rc: [
+        "vr_hwc.rc",
+    ],
 }
 
 cc_test {
-  name: "vr_hwc_test",
-  gtest: true,
-  srcs: ["tests/vr_composer_test.cpp"],
-  static_libs: [
-    "libgtest",
-    "libvr_hwc-impl",
-    // NOTE: This needs to be included after the *-impl lib otherwise the
-    // symbols in the *-binder library get optimized out.
-    "libvr_hwc-binder",
-  ],
-  cflags: [
-    "-Wall",
-    "-Werror",
-    // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
-    "-Wno-sign-compare",
-    "-Wno-unused-parameter",
-  ],
-  shared_libs: [
-    "libbase",
-    "libbinder",
-    "liblog",
-    "libui",
-    "libutils",
-  ],
+    name: "vr_hwc_test",
+    gtest: true,
+    srcs: ["tests/vr_composer_test.cpp"],
+    static_libs: [
+        "libgtest",
+        "libvr_hwc-impl",
+        // NOTE: This needs to be included after the *-impl lib otherwise the
+        // symbols in the *-binder library get optimized out.
+        "libvr_hwc-binder",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
+        "-Wno-sign-compare",
+        "-Wno-unused-parameter",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libui",
+        "libutils",
+    ],
 }
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
new file mode 100644
index 0000000..a1d5392
--- /dev/null
+++ b/services/vr/hardware_composer/aidl/Android.bp
@@ -0,0 +1,27 @@
+cc_library_static {
+    name: "libvr_hwc-binder",
+    srcs: [
+        "android/dvr/IVrComposer.aidl",
+        "android/dvr/IVrComposerCallback.aidl",
+        "android/dvr/parcelable_composer_frame.cpp",
+        "android/dvr/parcelable_composer_layer.cpp",
+        "android/dvr/parcelable_unique_fd.cpp",
+    ],
+    aidl: {
+        local_include_dirs: ["."],
+        export_aidl_headers: true,
+    },
+    export_include_dirs: ["."],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libui",
+        "libutils",
+        "libvr_hwc-hal",
+    ],
+}
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index fb7932d..7323277 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -994,6 +994,26 @@
   vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr);
 }
 
+Return<void> VrHwc::debug(const hidl_handle& fd,
+                          const hidl_vec<hidl_string>& args) {
+  std::string result;
+
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
+    for (const auto& pair : displays_) {
+      result += StringPrintf("Display id: %d\n", static_cast<int>(pair.first));
+      pair.second->dumpDebugInfo(&result);
+    }
+    result += "\n";
+  }
+
+  FILE* out = fdopen(dup(fd->data[0]), "w");
+  fprintf(out, "%s", result.c_str());
+  fclose(out);
+
+  return Void();
+}
+
 void HwcLayer::dumpDebugInfo(std::string* result) const {
   if (!result) {
     return;
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index e8c0212..15358c5 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -295,6 +295,9 @@
   void RegisterObserver(Observer* observer) override;
   void UnregisterObserver(Observer* observer) override;
 
+  Return<void> debug(const hidl_handle& fd,
+                     const hidl_vec<hidl_string>& args) override;
+
  private:
   class VsyncCallback : public BnVsyncCallback {
    public:
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 0263481..dcaa663 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -62,7 +62,7 @@
 service_src = [
     "main.cpp",
     "VirtualTouchpadService.cpp",
-    "aidl/android/dvr/VirtualTouchpadService.aidl",
+    ":virtualtouchpad_aidl",
 ]
 
 service_static_libs = [
@@ -99,7 +99,7 @@
 client_src = [
     "VirtualTouchpadClient.cpp",
     "DvrVirtualTouchpadClient.cpp",
-    "aidl/android/dvr/VirtualTouchpadService.aidl",
+    ":virtualtouchpad_aidl",
 ]
 
 client_shared_libs = [
@@ -122,3 +122,9 @@
     name: "libvirtualtouchpadclient",
     export_include_dirs: ["include"],
 }
+
+filegroup {
+    name: "virtualtouchpad_aidl",
+    srcs: ["aidl/android/dvr/IVirtualTouchpadService.aidl"],
+    path: "aidl",
+}
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl
similarity index 97%
rename from services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
rename to services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl
index 256203c..89aa44a 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl
@@ -1,7 +1,7 @@
 package android.dvr;
 
 /** @hide */
-interface VirtualTouchpadService
+interface IVirtualTouchpadService
 {
   const String SERVICE_NAME = "virtual_touchpad";
 
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 7d73f06..268e4bd 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -13,12 +13,6 @@
  public:
   // VirtualTouchpad implementation:
   static std::unique_ptr<VirtualTouchpad> Create();
-  status_t Attach() override;
-  status_t Detach() override;
-  status_t Touch(int touchpad, float x, float y, float pressure) override;
-  status_t ButtonState(int touchpad, int buttons) override;
-  status_t Scroll(int touchpad, float x, float y) override;
-  void dumpInternal(String8& result) override;
 
  protected:
   VirtualTouchpadClient() {}
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index 99315ef..0de0f9e 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -1,5 +1,5 @@
 service virtual_touchpad /system/bin/virtual_touchpad
   class core
   user system
-  group system input
+  group system input uhid
   writepid /dev/cpuset/system/tasks
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index b15bed9..7747734 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -12,21 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-ndk_headers {
-    name: "libvulkan_headers",
-    from: "include",
-    to: "",
-    srcs: [
-        "include/vulkan/vk_platform.h",
-        "include/vulkan/vulkan.h",
-        "include/vulkan/vulkan_core.h",
-        "include/vulkan/vulkan_android.h",
-    ],
-    license: "include/vulkan/NOTICE",
-}
-
+// This module makes the Vulkan libhardware HAL headers available, for
+// the loader and for HAL/driver implementations.
 cc_library_headers {
-    name: "vulkan_headers",
+    name: "hwvulkan_headers",
     vendor_available: true,
     header_libs: [
         "libcutils_headers",
@@ -39,18 +28,6 @@
     export_include_dirs: ["include"],
 }
 
-cc_library_headers {
-    name: "vulkan_headers_ndk",
-    export_include_dirs: ["include"],
-    sdk_version: "24",
-}
-
-llndk_library {
-    name: "libvulkan",
-    symbol_file: "libvulkan/libvulkan.map.txt",
-    export_include_dirs: ["include"],
-}
-
 subdirs = [
     "nulldrv",
     "libvulkan",
diff --git a/vulkan/README.md b/vulkan/README.md
index 9fba728..0f66097 100644
--- a/vulkan/README.md
+++ b/vulkan/README.md
@@ -10,19 +10,8 @@
 
 ## Code Generation
 
-We generate several parts of the loader and tools from a Vulkan API description file, stored in `api/vulkan.api`. Code generation must be done manually because the generator tools aren't part of the platform toolchain (yet?). Files named `foo_gen.*` are generated from the API file and a template file named `foo.tmpl`.
+We generate several parts of the loader and tools driectly from the Vulkan Registry (external/vulkan-headers/registry/vk.xml). Code generation must be done manually because the generator is not part of the platform toolchain (yet?). Files named `foo_gen.*` are generated by the code generator.
 
  To run the generator:
-
-### One-time setup
-- Install [golang](https://golang.org/), if you don't have it already.
-- Create a directory (e.g. `$HOME/lib/go`) for local go sources and binaries and add it to `$GOPATH`.
-- `$ git clone https://android.googlesource.com/platform/tools/gpu $GOPATH/src/android.googlesource.com/platform/tools/gpu`
-- `$ go get android.googlesource.com/platform/tools/gpu/api/...`
-- You should now have `$GOPATH/bin/apic`. You might want to add `$GOPATH/bin` to your `$PATH`.
-
-### Generating code
-To generate `libvulkan/*_gen.*`,
-- `$ cd libvulkan`
-- `$ apic template ../api/vulkan.api code-generator.tmpl`
-Similar for `nulldrv/null_driver_gen.*`.
+- Install Python3 (if not already installed)
+- `$ ./<path to>/frameworks/native/vulkan/scripts/code_generator.py`
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
deleted file mode 100644
index a7c4c30..0000000
--- a/vulkan/api/platform.api
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2015 The Khronos Group Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and/or associated documentation files (the
-// "Materials"), to deal in the Materials without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Materials, and to
-// permit persons to whom the Materials are furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Materials.
-//
-// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-
-// Platform types, as defined or included in vk_platform.h
-
-type u64 size_t
-
-// VK_USE_PLATFORM_XLIB_KHR
-@internal class Display {}
-@internal class Window {}
-@internal type u64 VisualID
-
-// VK_USE_PLATFORM_XCB_KHR
-@internal class xcb_connection_t {}
-@internal type u32 xcb_window_t
-@internal type u32 xcb_visualid_t
-
-// VK_USE_PLATFORM_WAYLAND_KHR
-@internal class wl_display {}
-@internal class wl_surface {}
-
-// VK_USE_PLATFORM_MIR_KHR
-@internal class MirConnection {}
-@internal class MirSurface {}
-
-// VK_USE_PLATFORM_ANDROID_KHR
-@internal class ANativeWindow {}
-@internal class AHardwareBuffer {}
-@internal type void* buffer_handle_t
-
-// VK_USE_PLATFORM_WIN32_KHR
-@internal type void* HINSTANCE
-@internal type void* HWND
-@internal type void* HANDLE
-@internal type u32   DWORD
-@internal type u16*  LPCWSTR
-@internal class SECURITY_ATTRIBUTES {}
-
-// VK_USE_PLATFORM_XLIB_XRANDR_EXT
-@internal type u64 RROutput
-
-// VK_USE_PLATFORM_FUCHSIA
-@internal type u32 zx_handle_t
\ No newline at end of file
diff --git a/vulkan/api/templates/asciidoc.tmpl b/vulkan/api/templates/asciidoc.tmpl
deleted file mode 100644
index 3009e19..0000000
--- a/vulkan/api/templates/asciidoc.tmpl
+++ /dev/null
@@ -1,151 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{if not (Global "AsciiDocPath")}}{{Global "AsciiDocPath" "../../doc/specs/vulkan/"}}{{end}}
-{{$ | Macro "AsciiDoc.Main"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  AsciiDoc generation main entry point.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Main"}}
-  {{$docPath := Global "AsciiDocPath"}}
-
-  {{/* Generate AsciiDoc files for API enums and bitfields (flags). */}}
-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{$filename := print $docPath "enums/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Enum" $e) "File" $filename}}
-    {{else}}
-      {{$filename := print $docPath "flags/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Flag" $e) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API commands (protos). */}}
-  {{range $f := (AllCommands $)}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{$filename := print $docPath "protos/" $f.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Proto" $f) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API structs. */}}
-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{$filename := print $docPath "structs/" $c.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Struct" $c) "File" $filename}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{AsSigned $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{$first := Macro "EnumFirstEntry" $}}
-    {{$last  := Macro "EnumLastEntry" $}}
-    {{$name}}_BEGIN_RANGE = {{$first}},
-    {{$name}}_END_RANGE = {{$last}},
-    {{$name}}_NUM = ({{$last}} - {{$first}} + 1),
-    {{$name}}_MAX_ENUM = 0x7FFFFFFF
-  } {{Macro "EnumName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Flag"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $e := $.Entries}}
-    {{Macro "BitfieldEntryName" $e}} = {{printf "%#.8x" $e.Value}}, {{Macro "Docs" $e.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-{{end}}
-
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API class.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} {
-    {{range $f := $.Fields}}
-      {{Node "Type" $f}} {{$f.Name}}{{Macro "ArrayPostfix" (TypeOf $f)}}; {{Macro "Docs" $f.Docs}}
-    {{end}}
-  } {{Macro "StructName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API function.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Proto"}}
-  {{AssertType $ "Function"}}
-
-  {{Macro "Docs" $.Docs}}
-  {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Wraps the specified Code in AsciiDoc source tags then writes to the specified File.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Write"}}
-  {{AssertType $.Code "string"}}
-  {{AssertType $.File "string"}}
-
-  {{$code := $.Code | Format (Global "clang-format")}}
-  {{JoinWith "\n" (Macro "AsciiDoc.Header") $code (Macro "AsciiDoc.Footer") ""| Write $.File}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source header.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Header"}}
-[source,{basebackend@docbook:c++:cpp}]
-------------------------------------------------------------------------------
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source footer.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Footer"}}
-------------------------------------------------------------------------------
-{{end}}
diff --git a/vulkan/api/templates/vk_xml.tmpl b/vulkan/api/templates/vk_xml.tmpl
deleted file mode 100644
index 893bde7..0000000
--- a/vulkan/api/templates/vk_xml.tmpl
+++ /dev/null
@@ -1,435 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vk.xml" | Reflow 4 | Write "vk.xml"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vk.xml"}}
-<?xml version="1.0" encoding="UTF-8"?>
-<registry>
-    »<comment>«
-Copyright (c) 2015 The Khronos Group Inc.

-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and/or associated documentation files (the
-"Materials"), to deal in the Materials without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Materials, and to
-permit persons to whom the Materials are furnished to do so, subject to
-the following conditions:

-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Materials.

-THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

-------------------------------------------------------------------------

-This file, vk.xml, is the Vulkan API Registry.»
-    </comment>

-    <!-- SECTION: Vulkan type definitions -->
-    <types>»
-        <type name="vk_platform" category="include">#include "vk_platform.h"</type>

-        <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
-    «((major &lt;&lt; 22) | (minor &lt;&lt; 12) | patch)</type>»

-        <type category="define">// Vulkan API version supported by this file««
-#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})</type>

-        »»<type category="define">««
-#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-#define <name>VK_NONDISP_HANDLE_OPERATOR_BOOL</name>() explicit operator bool() const { return handle != 0; }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-«#endif
-      »»»</type>

-      <type category="define">«««
-#define <name>VK_DEFINE_HANDLE</name>(obj) typedef struct obj##_T* obj;</type>
-      »»»<type category="define">«««
-#if defined(__cplusplus)
-    »»#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-        »// The bool operator only works if there are no implicit conversions from an obj to
-        // a bool-compatible type, which can then be used to unintentionally violate type safety.
-        // C++11 and above supports the "explicit" keyword on conversion operators to stop this
-        // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-        // the object handle as a bool in expressions like:
-        //     if (obj) vkDestroy(obj);
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; }
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            explicit obj(uint64_t x) : handle(x) { } \
-            obj(decltype(nullptr)) : handle(0) { }
-    «#else»
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj(uint64_t x) : handle(x) { }
-    «#endif
-    #define <name>VK_DEFINE_NONDISP_HANDLE</name>(obj) \»
-        struct obj { \
-            obj() { } \
-            VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj&amp; operator =(uint64_t x) { handle = x; return *this; } \
-            bool operator==(const obj&amp; other) const { return handle == other.handle; } \
-            bool operator!=(const obj&amp; other) const { return handle != other.handle; } \
-            bool operator!() const { return !handle; } \
-            VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-            uint64_t handle; \
-        };
-««#else
-    »#define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;«
-#endif
-        »»</type>

-        <type category="define">
-#if defined(__cplusplus) &amp;&amp; ((defined(_MSC_VER) &amp;&amp; _MSC_VER &gt;= 1800) || __cplusplus &gt;= 201103L)
-    »#define <name>VK_NULL_HANDLE</name> nullptr
-«#else
-    »#define VK_NULL_HANDLE 0
-«#endif
-        »»</type>

-        <type requires="vk_platform" name="VkDeviceSize"/>
-        <type requires="vk_platform" name="VkSampleMask"/>
-        <type requires="vk_platform" name="VkFlags"/>
-        <!-- Basic C types, pulled in via vk_platform.h -->
-        <type requires="vk_platform" name="char"/>
-        <type requires="vk_platform" name="float"/>
-        <type requires="vk_platform" name="VkBool32"/>
-        <type requires="vk_platform" name="uint8_t"/>
-        <type requires="vk_platform" name="uint32_t"/>
-        <type requires="vk_platform" name="uint64_t"/>
-        <type requires="vk_platform" name="int32_t"/>
-        <type requires="vk_platform" name="size_t"/>
-        <!-- Bitfield types -->
-        {{range $e := $.Enums}}
-          {{if $e.IsBitfield}}
-            {{$bits := print (Macro "EnumName" $e | TrimRight "s") "Bits"}}
-            <type{{if $e.Entries}} requires="{{$bits}}"{{end}} category="bitmask">typedef <type>VkFlags</type> <name>{{$e.Name}}</name>;</type>§
-            {{if $e.Entries}}{{Macro "XML.Docs" $e.Docs}}
-            {{else}}{{Macro "XML.Docs" (Strings $e.Docs "(no bits yet)")}}
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types which can be void pointers or class pointers, selected at compile time -->
-        {{range $i, $p := $.Pseudonyms}}
-          {{     if (GetAnnotation $p "dispatchHandle")}}
-            {{if Global "VK_DEFINE_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{else if (GetAnnotation $p "nonDispatchHandle")}}
-            {{if Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_NONDISP_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_NONDISP_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types generated from corresponding <enums> tags below -->
-        {{range $e := SortBy $.Enums "EnumName"}}
-          {{if and $e.Entries (not (GetAnnotation $e "internal"))}}
-            {{if $e.IsBitfield}}
-              <type name="{{Macro "EnumName" $e | TrimRight "s"}}Bits" category="enum"/>
-            {{else}}
-              <type name="{{$e.Name}}" category="enum"/>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- The PFN_vk*Function types are used by VkAllocCallbacks below -->
-        <type>typedef void* (VKAPI *<name>PFN_vkAllocFunction</name>)(«
-          void*                           pUserData,
-          size_t                          size,
-          size_t                          alignment,
-          <type>VkSystemAllocType</type>               allocType);</type>»
-        <type>typedef void (VKAPI *<name>PFN_vkFreeFunction</name>)(«
-          void*                           pUserData,
-          void*                           pMem);</type>»

-        <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below -->
-        <type>typedef void (VKAPI *<name>PFN_vkVoidFunction</name>)(void);</type>

-        <!-- Struct types -->
-        {{range $c := $.Classes}}
-          {{if not (GetAnnotation $c "internal")}}
-            {{Macro "Struct" $c}}
-          {{end}}
-        {{end}}
-    «</types>

-    <!-- SECTION: Vulkan enumerant (token) definitions. -->

-    <enums namespace="VK" comment="Misc. hardcoded constants - not an enumerated type">»
-            <!-- This is part of the header boilerplate -->
-      {{range $d := $.Definitions}}
-        {{if HasPrefix $d.Name "VK_"}}
-        <enum value="{{$d.Expression}}"        name="{{$d.Name}}"/>{{Macro "XML.Docs" $d.Docs}}
-        {{end}}
-      {{end}}
-        <enum value="1000.0f"  name="VK_LOD_CLAMP_NONE"/>
-        <enum value="(-0U)" name="VK_REMAINING_MIP_LEVELS"/>
-        <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
-        <enum value="(_0ULL)" name="VK_WHOLE_SIZE"/>
-        <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
-        <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
-        <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
-    «</enums>

-    <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in»
-         their own numeric namespaces. The "name" attribute is the C enum
-         type name, and is pulled in from a <type> definition above
-         (slightly clunky, but retains the type / enum distinction). "type"
-         attributes of "enum" or "bitmask" indicate that these values should
-         be generated inside an appropriate definition. -->«

-    {{range $e := $.Enums}}
-      {{if not (or $e.IsBitfield (GetAnnotation $e "internal"))}}
-        {{Macro "XML.Enum" $e}}
-      {{end}}
-    {{end}}

-    <!-- Flags -->
-    {{range $e := $.Enums}}
-      {{if $e.IsBitfield}}
-        {{Macro "XML.Bitfield" $e}}
-      {{end}}
-    {{end}}

-    <!-- SECTION: Vulkan command definitions -->
-    <commands namespace="vk">»
-    {{range $f := AllCommands $}}
-      {{if not (GetAnnotation $f "pfn")}}
-        {{Macro "XML.Function" $f}}
-      {{end}}
-    {{end}}
-    «</commands>

-    <!-- SECTION: Vulkan API interface definitions -->
-    <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">»
-        <require comment="Header boilerplate">»
-            <type name="vk_platform"/>
-        «</require>
-        <require comment="API version">»
-            <type name="VK_API_VERSION"/>
-        «</require>
-        <require comment="API constants">»
-            <enum name="VK_LOD_CLAMP_NONE"/>
-            <enum name="VK_REMAINING_MIP_LEVELS"/>
-            <enum name="VK_REMAINING_ARRAY_LAYERS"/>
-            <enum name="VK_WHOLE_SIZE"/>
-            <enum name="VK_ATTACHMENT_UNUSED"/>
-            <enum name="VK_TRUE"/>
-            <enum name="VK_FALSE"/>
-        «</require>
-        <require comment="All functions (TODO: split by type)">»
-        {{range $f := AllCommands $}}
-          {{if not (GetAnnotation $f "pfn")}}
-          <command name="{{$f.Name}}"/>
-          {{end}}
-        {{end}}
-        </require>
-        «<require comment="Types not directly used by the API">»
-            <!-- Include <type name="typename"/> here for e.g. structs that»
-                 are not parameter types of commands, but still need to be
-                 defined in the API.
-             «-->
-            <type name="VkBufferMemoryBarrier"/>
-            <type name="VkDispatchIndirectCmd"/>
-            <type name="VkDrawIndexedIndirectCmd"/>
-            <type name="VkDrawIndirectCmd"/>
-            <type name="VkImageMemoryBarrier"/>
-            <type name="VkMemoryBarrier"/>
-        «</require>
-    «</feature>

-    <!-- SECTION: Vulkan extension interface definitions (none yet) -->
-«</registry>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{if $.Entries}}
-  <enums namespace="VK" name="{{Macro "EnumName" $ | TrimRight "s"}}Bits" type="bitmask">»
-  {{range $e := $.Entries}}
-    {{$pos := Bitpos $e.Value}}
-    <enum §
-      {{if gt $pos -1}} bitpos="{{$pos}}"    §
-      {{else}}value="{{if $e.Value}}{{printf "0x%.8X" $e.Value}}{{else}}0{{end}}"    §
-      {{end}}name="{{Macro "BitfieldEntryName" $e}}" §
-      {{if $d := $e.Docs}} comment="{{$d | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  «</enums>
-  {{end}}
-
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  <enums namespace="VK" name="{{Macro "EnumName" $}}" type="enum" §
-         expand="{{Macro "EnumName" $ | SplitPascalCase | Upper | JoinWith "_"}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-  {{range $i, $e := $.Entries}}
-    <enum value="{{AsSigned $e.Value}}"     name="{{Macro "BitfieldEntryName" $e}}"{{if $e.Docs}} comment="{{$e.Docs | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  {{if $lu := GetAnnotation $ "lastUnused"}}
-    <unused start="{{index $lu.Arguments 0}}"/>
-  {{end}}
-  «</enums>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  <type category="{{Macro "StructType" $}}" name="{{Macro "StructName" $}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-    {{range $f := $.Fields}}
-    <member>{{Node "XML.Type" $f}}        <name>{{$f.Name}}</name>{{Macro "XML.ArrayPostfix" $f}}</member>{{Macro "XML.Docs" $f.Docs}}
-    {{end}}
-  «</type>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Function"}}
-  {{AssertType $ "Function"}}
-
-    {{$ts := GetAnnotation $ "threadSafety"}}
-    <command{{if $ts}} threadsafe="{{index $ts.Arguments 0}}"{{end}}>»
-        <proto>{{Node "XML.Type" $.Return}} <name>{{$.Name}}</name></proto>
-        {{range $p := $.CallParameters}}
-          <param>{{Node "XML.Type" $p}} <name>{{$p.Name}}{{Macro "ArrayPostfix" $p}}</name></param>
-        {{end}}
-    «</command>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the XML translation for the specified documentation block (string array).
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Docs"}}
-  {{if $}} <!-- {{JoinWith "  " $ | Replace "<" "" | Replace ">" ""}} -->{{end}}
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified type.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Type.Class"      }}<type>{{Macro "StructName" $.Type}}</type>{{end}}
-{{define "XML.Type.Pseudonym"  }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.Enum"       }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.StaticArray"}}{{Node "XML.Type" $.Type.ValueType}}{{end}}
-{{define "XML.Type.Pointer"    }}{{if $.Type.Const}}{{Node "XML.ConstType" $.Type.To}}{{else}}{{Node "XML.Type" $.Type.To}}{{end}}*{{end}}
-{{define "XML.Type.Slice"      }}<type>{{Node "XML.Type" $.Type.To}}</type>*{{end}}
-{{define "XML.Type#s8"         }}<type>int8_t</type>{{end}}
-{{define "XML.Type#u8"         }}<type>uint8_t</type>{{end}}
-{{define "XML.Type#s16"        }}<type>int16_t</type>{{end}}
-{{define "XML.Type#u16"        }}<type>uint16_t</type>{{end}}
-{{define "XML.Type#s32"        }}<type>int32_t</type>{{end}}
-{{define "XML.Type#u32"        }}<type>uint32_t</type>{{end}}
-{{define "XML.Type#f32"        }}<type>float</type>{{end}}
-{{define "XML.Type#s64"        }}<type>int64_t</type>{{end}}
-{{define "XML.Type#u64"        }}<type>uint64_t</type>{{end}}
-{{define "XML.Type#f64"        }}<type>double</type>{{end}}
-{{define "XML.Type#char"       }}<type>char</type>{{end}}
-{{define "XML.Type#void"       }}void{{end}}
-
-{{define "XML.ConstType_Default"}}const {{Node "XML.Type" $.Type}}{{end}}
-{{define "XML.ConstType.Pointer"}}{{Node "XML.Type" $.Type}} const{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type and name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameter"}}
-  {{AssertType $ "Parameter"}}
-
-  <type>{{Macro "ParameterType" $}}</type> <name>{{$.Name}}{{Macro "ArrayPostfix" $}}</name>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C type-name paired parameters for the given
-  command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameters"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "XML.Parameter" | JoinWith ", "}}
-  {{if not $.CallParameters}}<type>void</type>{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the fixed-size-array postfix for pseudonym types annotated with @array
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.ArrayPostfix"}}{{Node "XML.ArrayPostfix" $}}{{end}}
-{{define "XML.ArrayPostfix.StaticArray"}}[{{Node "XML.NamedValue" $.Type.SizeExpr}}]{{end}}
-{{define "XML.ArrayPostfix_Default"}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the value of the given constant, or the <enum> tagged name if existant.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.NamedValue.Definition"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue.EnumEntry"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue_Default"}}{{$.Node}}{{end}}
diff --git a/vulkan/api/templates/vulkan_common.tmpl b/vulkan/api/templates/vulkan_common.tmpl
deleted file mode 100644
index f694c56..0000000
--- a/vulkan/api/templates/vulkan_common.tmpl
+++ /dev/null
@@ -1,223 +0,0 @@
-{{$clang_style := "{BasedOnStyle: Google, AccessModifierOffset: -4, ColumnLimit: 200, ContinuationIndentWidth: 8, IndentWidth: 4, AlignOperands: true, CommentPragmas: '.*'}"}}
-{{Global "clang-format" (Strings "clang-format" "-style" $clang_style)}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified type.
--------------------------------------------------------------------------------
-*/}}
-{{define "Type.Class"      }}{{if GetAnnotation $.Type "internal"}}struct {{end}}{{Macro "StructName" $.Type}}{{end}}
-{{define "Type.Pseudonym"  }}{{$.Type.Name}}{{end}}
-{{define "Type.Enum"       }}{{$.Type.Name}}{{end}}
-{{define "Type.StaticArray"}}{{Node "Type" $.Type.ValueType}}{{end}}
-{{define "Type.Pointer"    }}{{if $.Type.Const}}{{Node "ConstType" $.Type.To}}{{else}}{{Node "Type" $.Type.To}}{{end}}*{{end}}
-{{define "Type.Slice"      }}{{Log "%T %+v" $.Node $.Node}}{{Node "Type" $.Type.To}}*{{end}}
-{{define "Type#bool"       }}bool{{end}}
-{{define "Type#int"        }}int{{end}}
-{{define "Type#uint"       }}unsigned int{{end}}
-{{define "Type#s8"         }}int8_t{{end}}
-{{define "Type#u8"         }}uint8_t{{end}}
-{{define "Type#s16"        }}int16_t{{end}}
-{{define "Type#u16"        }}uint16_t{{end}}
-{{define "Type#s32"        }}int32_t{{end}}
-{{define "Type#u32"        }}uint32_t{{end}}
-{{define "Type#f32"        }}float{{end}}
-{{define "Type#s64"        }}int64_t{{end}}
-{{define "Type#u64"        }}uint64_t{{end}}
-{{define "Type#f64"        }}double{{end}}
-{{define "Type#void"       }}void{{end}}
-{{define "Type#char"       }}char{{end}}
-
-{{define "ConstType_Default"}}const {{Node "Type" $.Type}}{{end}}
-{{define "ConstType.Pointer"}}{{Node "Type" $.Type}} const{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified documentation block (string array).
--------------------------------------------------------------------------------
-*/}}
-{{define "Docs"}}
-  {{if $}}// {{$ | JoinWith "\n// "}}{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a bitfield entry.
--------------------------------------------------------------------------------
-*/}}
-{{define "BitfieldEntryName"}}
-  {{AssertType $ "EnumEntry"}}
-
-  {{Macro "EnumEntry" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of an enum type.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumName"}}{{AssertType $ "Enum"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of an enum entry.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumEntry"}}
-  {{AssertType $.Owner "Enum"}}
-  {{AssertType $.Name "string"}}
-
-  {{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of the first entry of an enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumFirstEntry"}}
-  {{AssertType $ "Enum"}}
-
-  {{range $i, $e := $.Entries}}
-    {{if not $i}}{{$e.Name}}{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of the last entry of an enum.
--------------------------------------------------------------------------------
-*/}}{{define "EnumLastEntry"}}
-  {{AssertType $ "Enum"}}
-
-  {{range $i, $e := $.Entries}}
-    {{if not (HasMore $i $.Entries)}}{{$e.Name}}{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a struct (class) type.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructName"}}{{AssertType $ "Class"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a function.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionName"}}{{AssertType $ "Function"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the fixed-size-array postfix for pseudonym types annotated with @array
--------------------------------------------------------------------------------
-*/}}
-{{define "ArrayPostfix"}}{{Node "ArrayPostfix" $}}{{end}}
-{{define "ArrayPostfix.StaticArray"}}[{{$.Type.Size}}]{{end}}
-{{define "ArrayPostfix_Default"}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type and name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "Parameter"}}
-  {{AssertType $ "Parameter"}}
-
-  {{if GetAnnotation $ "readonly"}}const {{end}}{{Macro "ParameterType" $}} {{$.Name}}{{Macro "ArrayPostfix" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "ParameterName"}}
-  {{AssertType $ "Parameter"}}
-
-  {{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "ParameterType"}}{{AssertType $ "Parameter"}}{{Node "Type" $}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C type-name paired parameters for the given
-  command.
--------------------------------------------------------------------------------
-*/}}
-{{define "Parameters"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "Parameter" | JoinWith ", "}}
-  {{if not $.CallParameters}}void{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer name for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionPtrName"}}
-  {{AssertType $ "Function"}}
-
-  PFN_{{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Parses const variables as text Globals.
--------------------------------------------------------------------------------
-*/}}
-{{define "DefineGlobals"}}
-  {{AssertType $ "API"}}
-
-  {{range $d := $.Definitions}}
-    {{Global $d.Name $d.Expression}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Given a function, return "Global", "Instance", or "Device" depending on which
-  dispatch table the function belongs to.
--------------------------------------------------------------------------------
-*/}}
-{{define "Vtbl#VkInstance"      }}Instance{{end}}
-{{define "Vtbl#VkPhysicalDevice"}}Instance{{end}}
-{{define "Vtbl#VkDevice"        }}Device{{end}}
-{{define "Vtbl#VkQueue"         }}Device{{end}}
-{{define "Vtbl#VkCommandBuffer" }}Device{{end}}
-{{define "Vtbl_Default"         }}Global{{end}}
-{{define "Vtbl"}}
-  {{AssertType $ "Function"}}
-
-  {{if gt (len $.CallParameters) 0}}
-    {{Node "Vtbl" (index $.CallParameters 0)}}
-  {{else}}Global
-  {{end}}
-{{end}}
diff --git a/vulkan/api/templates/vulkan_h.tmpl b/vulkan/api/templates/vulkan_h.tmpl
deleted file mode 100644
index 83a5e40..0000000
--- a/vulkan/api/templates/vulkan_h.tmpl
+++ /dev/null
@@ -1,295 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vulkan.h" | Format (Global "clang-format") | Write "../include/vulkan.h"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vulkan.h"}}
-#ifndef __vulkan_h_
-#define __vulkan_h_ 1

-#ifdef __cplusplus
-extern "C" {
-#endif

-/*
-** Copyright (c) 2015-2016 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/

-/*
-** This header is generated from the Khronos Vulkan API Registry.
-**
-*/

-#define VK_VERSION_1_0 1
-#include "vk_platform.h"

-#define VK_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch))

-// Vulkan API version supported by this file
-#define VK_API_VERSION \
-    VK_MAKE_VERSION({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})

-#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
-#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
-#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)

-#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-    #define VK_NULL_HANDLE nullptr
-#else
-    #define VK_NULL_HANDLE 0
-#endif

-#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj;

-#if defined(__cplusplus)
-#if ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-// The bool operator only works if there are no implicit conversions from an obj to
-// a bool-compatible type, which can then be used to unintentionally violate type safety.
-// C++11 and above supports the "explicit" keyword on conversion operators to stop this
-// from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-// the object handle as a bool in expressions like:
-//     if (obj) vkDestroy(obj);
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-    explicit operator bool() const { return handle != 0; }
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    explicit obj(uint64_t x) : handle(x) { } \
-    obj(decltype(nullptr)) : handle(0) { }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    obj(uint64_t x) : handle(x) { }
-#endif
-#define VK_DEFINE_NONDISP_HANDLE(obj)                                              \
-    struct obj {                                                                   \
-        obj() : handle(0) { }                                                      \
-        VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj)                             \
-        obj& operator=(uint64_t x) {                                               \
-            handle = x;                                                            \
-            return *this;                                                          \
-        }                                                                          \
-        bool operator==(const obj& other) const { return handle == other.handle; } \
-        bool operator!=(const obj& other) const { return handle != other.handle; } \
-        bool operator!() const { return !handle; }                                 \
-        VK_NONDISP_HANDLE_OPERATOR_BOOL()                                          \
-        uint64_t handle;                                                           \
-    };
-#else
-#define VK_DEFINE_NONDISP_HANDLE(obj) \
-    typedef struct obj##_T { uint64_t handle; } obj;
-#endif

-#define VK_LOD_CLAMP_NONE         1000.0f
-#define VK_REMAINING_MIP_LEVELS   (~0U)
-#define VK_REMAINING_ARRAY_LAYERS (~0U)
-#define VK_WHOLE_SIZE             (~0ULL)
-#define VK_ATTACHMENT_UNUSED      (~0U)
-define VK_QUEUE_FAMILY_IGNORED    (~0U)
-define VK_SUBPASS_EXTERNAL        (~0U)
-{{range $d := $.Definitions}}
-  {{if HasPrefix $d.Name "VK_"}}#define {{$d.Name}}  {{$d.Expression}}{{end}}
-{{end}}

-{{range $i, $p := $.Pseudonyms}}
-  {{if GetAnnotation $p "dispatchHandle"}}VK_DEFINE_HANDLE({{$p.Name}})
-  {{else if GetAnnotation $p "nonDispatchHandle"}}VK_DEFINE_NONDISP_HANDLE({{$p.Name}})
-  {{end}}
-{{end}}

-// ------------------------------------------------------------------------------------------------
-// Enumerations

-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{Macro "Enum" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Flags

-  {{range $e := $.Enums}}
-    {{if $e.IsBitfield}}
-      {{Macro "Bitfield" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Vulkan structures

-  {{/* Function pointers */}}
-  {{range $f := AllCommands $}}
-    {{if GetAnnotation $f "pfn"}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{Macro "Struct" $c}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// API functions

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-#ifdef VK_NO_PROTOTYPES

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionDecl" $f}}
-    {{end}}
-  {{end}}

-#endif

-#ifdef __cplusplus
-}
-#endif

-#endif
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $b := $.Entries}}
-    {{Macro "BitfieldEntryName" $b}} = {{printf "0x%.8X" $b.Value}}, {{Macro "Docs" $b.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{printf "0x%.8X" $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name  := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{if GetAnnotation $ "enumMaxOnly"}}
-      VK_MAX_ENUM({{$name | SplitOn "VK_"}})
-    {{else}}
-      {{$first := Macro "EnumFirstEntry" $ | SplitOn $name | TrimLeft "_"}}
-      {{$last  := Macro "EnumLastEntry" $  | SplitOn $name | TrimLeft "_"}}
-      VK_ENUM_RANGE({{$name | SplitOn "VK_"}}, {{$first}}, {{$last}})
-    {{end}}
-  } {{Macro "EnumName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{Macro "StructType" $}} {
-    {{ForEach $.Fields "Field" | JoinWith "\n"}}
-  } {{Macro "StructName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class field.
--------------------------------------------------------------------------------
-*/}}
-{{define "Field"}}
-  {{AssertType $ "Field"}}
-
-  {{Node "Type" $}} {{$.Name}}§
-  {{Macro "ArrayPostfix" (TypeOf $)}}; {{Macro "Docs" $.Docs}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionTypedef"}}
-  {{AssertType $ "Function"}}
-
-  typedef {{Node "Type" $.Return}} (VKAPI* {{Macro "FunctionPtrName" $}})({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionDecl"}}
-  {{AssertType $ "Function"}}
-
-  {{if not (GetAnnotation $ "fptr")}}
-    {{Macro "Docs" $.Docs}}
-    {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-  {{end}}
-{{end}}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
deleted file mode 100644
index 7604c95..0000000
--- a/vulkan/api/vulkan.api
+++ /dev/null
@@ -1,12163 +0,0 @@
-// Copyright (c) 2015 The Khronos Group Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and/or associated documentation files (the
-// "Materials"), to deal in the Materials without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Materials, and to
-// permit persons to whom the Materials are furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Materials.
-//
-// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-
-import platform "platform.api"
-
-///////////////
-// Constants //
-///////////////
-
-// API version (major.minor.patch)
-define VERSION_MAJOR 1
-define VERSION_MINOR 1
-define VERSION_PATCH 96
-
-// API limits
-define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
-define VK_UUID_SIZE                     16
-define VK_MAX_EXTENSION_NAME_SIZE       256
-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.
-@vulkan1_1
-define VK_MAX_DEVICE_GROUP_SIZE         32
-@vulkan1_1
-define VK_LUID_SIZE                     8
-@vulkan1_1
-define VK_QUEUE_FAMILY_EXTERNAL         -2
-@extension("VK_EXT_queue_family_foreign")
-define VK_QUEUE_FAMILY_FOREIGN_EXT      -3
-@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
-define VK_MAX_DRIVER_NAME_SIZE_KHR      256
-@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
-define VK_MAX_DRIVER_INFO_SIZE_KHR      256
-
-// API keywords
-define VK_TRUE        1
-define VK_FALSE       0
-
-// API keyword, but needs special handling by some templates
-define NULL_HANDLE 0
-
-// 1
-@extension("VK_KHR_surface") define VK_KHR_SURFACE_SPEC_VERSION                 25
-@extension("VK_KHR_surface") define VK_KHR_SURFACE_EXTENSION_NAME               "VK_KHR_surface"
-
-// 2
-@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
-@extension("VK_KHR_display") define VK_KHR_DISPLAY_SPEC_VERSION                 21
-@extension("VK_KHR_display") define VK_KHR_DISPLAY_EXTENSION_NAME               "VK_KHR_display"
-
-// 4
-@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION     9
-@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_display_swapchain"
-
-// 5
-@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_SPEC_VERSION       6
-@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_NAME               "VK_KHR_xlib_surface"
-
-// 6
-@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_SPEC_VERSION         6
-@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_NAME                 "VK_KHR_xcb_surface"
-
-// 7
-@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
-@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_NAME         "VK_KHR_wayland_surface"
-
-// 8 - VK_KHR_mir_surface removed
-
-// 9
-@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
-@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_NAME         "VK_KHR_android_surface"
-
-// 10
-@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION     6
-@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME             "VK_KHR_win32_surface"
-
-// 11
-@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     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       9
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
-
-// 13
-@extension("VK_NV_glsl_shader") define VK_NV_GLSL_SHADER_SPEC_VERSION           1
-@extension("VK_NV_glsl_shader") define VK_NV_GLSL_SHADER_NAME                   "VK_NV_glsl_shader"
-
-// 14
-@extension("VK_EXT_depth_range_unrestricted") define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION   1
-@extension("VK_EXT_depth_range_unrestricted") define VK_EXT_DEPTH_RANGE_UNRESTRICTED_NAME           "VK_EXT_depth_range_unrestricted"
-
-// 15
-@extension("VK_KHR_sampler_mirror_clamp_to_edge") define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION   1
-@extension("VK_KHR_sampler_mirror_clamp_to_edge") define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_NAME           "VK_KHR_sampler_mirror_clamp_to_edge"
-
-// 16
-@extension("VK_IMG_filter_cubic") define VK_IMG_FILTER_CUBIC_SPEC_VERSION       1
-@extension("VK_IMG_filter_cubic") define VK_IMG_FILTER_CUBIC_NAME               "VK_IMG_filter_cubic"
-
-// 19
-@extension("VK_AMD_rasterization_order") define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION   1
-@extension("VK_AMD_rasterization_order") define VK_AMD_RASTERIZATION_ORDER_NAME           "VK_AMD_rasterization_order"
-
-// 21
-@extension("VK_AMD_shader_trinary_minmax") define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1
-@extension("VK_AMD_shader_trinary_minmax") define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax"
-
-// 22
-@extension("VK_AMD_shader_explicit_vertex_parameter") define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1
-@extension("VK_AMD_shader_explicit_vertex_parameter") define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
-
-// 23
-@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_SPEC_VERSION       4
-@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_NAME               "VK_EXT_debug_marker"
-
-// 26
-@extension("VK_AMD_gcn_shader") define VK_AMD_GCN_SHADER_SPEC_VERSION 1
-@extension("VK_AMD_gcn_shader") define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader"
-
-// 27
-@extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1
-@extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation"
-
-// 28
-@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
-@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
-
-// 29
-@extension("VK_EXT_transform_feedback") define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1
-@extension("VK_EXT_transform_feedback") define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback"
-
-// 34
-@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
-
-// 36
-@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
-@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
-
-// 37
-@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
-@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
-
-// 38
-@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
-@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
-
-// 42
-@extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1
-@extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
-
-// 43
-@extension("VK_AMD_shader_info") define VK_AMD_SHADER_INFO_SPEC_VERSION 1
-@extension("VK_AMD_shader_info") define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info"
-
-// 47
-@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
-@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
-
-// 51
-@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
-@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
-
-// 54
-@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
-@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
-
-// 57
-@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
-@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
-
-// 58
-@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
-
-// 59
-@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
-
-// 60
-@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
-@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_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
-@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
-
-// 63
-@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_SPEC_VERSION 1
-@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
-
-// 64
-@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
-@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
-
-// 65
-@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
-@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
-
-// 66
-@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
-@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
-
-// 68
-@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
-@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
-
-// 70
-@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
-@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
-
-// 71
-@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
-@extension("VK_KHR_external_memory_capabilities") define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
-
-// 73
-@extension("VK_KHR_external_memory") define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1
-@extension("VK_KHR_external_memory") define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory"
-
-// 74
-@extension("VK_KHR_external_memory_win32") define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_memory_win32") define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
-
-// 75
-@extension("VK_KHR_external_memory_fd") define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
-@extension("VK_KHR_external_memory_fd") define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
-
-// 76
-@extension("VK_KHR_win32_keyed_mutex") define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-@extension("VK_KHR_win32_keyed_mutex") define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
-
-// 77
-@extension("VK_KHR_external_semaphore_capabilities") define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore_capabilities") define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
-
-// 78
-@extension("VK_KHR_external_semaphore") define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore") define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
-
-// 79
-@extension("VK_KHR_external_semaphore_win32") define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore_win32") define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
-
-// 80
-@extension("VK_KHR_external_semaphore_fd") define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
-@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 2
-@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
-
-// 82
-@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
-@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
-
-// 83
-@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
-@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
-
-// 84
-@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
-@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
-
-// 85
-@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
-
-// 86
-@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
-@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
-
-// 87
-@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
-@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
-
-// 88
-@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
-@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
-
-// 89
-@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
-@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
-
-// 90
-@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
-@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
-
-// 91
-@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
-@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-
-// 92
-@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
-@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_COUNTER_EXTENSION_NAME "VK_EXT_display_control"
-
-// 93
-@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
-@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
-
-// 95
-@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
-@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
-
-// 96
-@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
-@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
-
-// 97
-@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
-@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
-
-// 98
-@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
-@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
-
-// 99
-@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
-@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
-
-// 100
-@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
-@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
-
-// 102
-@extension("VK_EXT_conservative_rasterization") define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1
-@extension("VK_EXT_conservative_rasterization") define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization"
-
-// 105
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 3
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
-
-// 106
-@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
-@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
-
-// 110
-@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_SPEC_VERSION 1
-@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_EXTENSION_NAME "VK_KHR_create_renderpass2"
-
-// 112
-@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-// 113
-@extension("VK_KHR_external_fence_capabilities") define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_capabilities") define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
-
-// 114
-@extension("VK_KHR_external_fence") define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
-@extension("VK_KHR_external_fence") define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
-
-// 115
-@extension("VK_KHR_external_fence_win32") define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_win32") define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
-
-// 116
-@extension("VK_KHR_external_fence_fd") define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_fd") define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
-
-// 118
-@extension("VK_KHR_maintenance2") define VK_KHR_MAINTENANCE2_SPEC_VERSION 1
-@extension("VK_KHR_maintenance2") define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
-
-// 120
-@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
-@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
-
-// 121
-@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
-@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
-
-// 122
-@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
-@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
-
-// 123
-@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_SPEC_VERSION 1
-@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
-
-// 124
-@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_SPEC_VERSION 1
-@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
-
-// 126
-@extension("VK_EXT_external_memory_dma_buf") define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1
-@extension("VK_EXT_external_memory_dma_buf") define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf"
-
-// 127
-@extension("VK_EXT_queue_family_foreign") define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1
-@extension("VK_EXT_queue_family_foreign") define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign"
-
-// 128
-@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
-@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
-
-// 128
-@extension("VK_EXT_debug_utils") define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1
-@extension("VK_EXT_debug_utils") define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
-
-// 130
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
-
-// 131
-@extension("VK_EXT_sampler_filter_minmax") define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1
-@extension("VK_EXT_sampler_filter_minmax") define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax"
-
-// 132
-@extension("VK_KHR_storage_buffer_storage_class") define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1
-@extension("VK_KHR_storage_buffer_storage_class") define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class"
-
-// 133
-@extension("VK_AMD_gpu_shader_int16") define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1
-@extension("VK_AMD_gpu_shader_int16") define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16"
-
-// 137
-@extension("VK_AMD_mixed_attachment_samples") define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1
-@extension("VK_AMD_mixed_attachment_samples") define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples"
-
-// 138
-@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
-@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
-
-// 139
-@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
-@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
-
-// 141
-@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
-@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
-
-// 144
-@extension("VK_EXT_sample_locations") define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1
-@extension("VK_EXT_sample_locations") define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations"
-
-// 145
-@extension("VK_KHR_relaxed_block_layout") define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1
-@extension("VK_KHR_relaxed_block_layout") define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout"
-
-// 147
-@extension("VK_KHR_get_memory_requirements2") define VK_KHR_GET_MEMORY_REQUIREMENTS2_SPEC_VERSION 1
-@extension("VK_KHR_get_memory_requirements2") define VK_KHR_GET_MEMORY_REQUIREMENTS2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
-
-// 148
-@extension("VK_KHR_image_format_list") define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1
-@extension("VK_KHR_image_format_list") define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list"
-
-// 149
-@extension("VK_EXT_blend_operation_advanced") define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2
-@extension("VK_EXT_blend_operation_advanced") define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced"
-
-// 150
-@extension("VK_NV_fragment_coverage_to_color") define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1
-@extension("VK_NV_fragment_coverage_to_color") define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color"
-
-// 153
-@extension("VK_NV_framebuffer_mixed_samples") define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1
-@extension("VK_NV_framebuffer_mixed_samples") define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples"
-
-// 154
-@extension("VK_NV_fill_rectangle") define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1
-@extension("VK_NV_fill_rectangle") define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle"
-
-// 156
-@extension("VK_EXT_post_depth_coverage") define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1
-@extension("VK_EXT_post_depth_coverage") define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage"
-
-// 157
-@extension("VK_KHR_sampler_ycbcr_conversion") define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1
-@extension("VK_KHR_sampler_ycbcr_conversion") define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
-
-// 158
-@extension("VK_KHR_bind_memory2") define VK_KHR_BIND_MEMORY2_SPEC_VERSION 1
-@extension("VK_KHR_bind_memory2") define VK_KHR_BIND_MEMORY2_EXTENSION_NAME "VK_KHR_bind_memory2"
-
-// 159
-@extension("VK_EXT_image_drm_format_modifier") define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
-@extension("VK_EXT_image_drm_format_modifier") define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
-
-// 161
-@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
-@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-
-// 162
-@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
-@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
-
-// 163
-@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"
-
-// 165
-@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
-@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
-
-// 166
-@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_SPEC_VERSION 3
-@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
-
-// 167
-@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
-@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
-
-// 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"
-
-// 170
-@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
-
-// 175
-@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 1
-@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
-
-// 178
-@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1
-@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
-
-// 179
-@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1
-@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host"
-
-// 180
-@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
-@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
-
-// 181
-@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
-@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
-
-// 186
-@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
-@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
-
-// 190
-@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
-@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
-
-// 191
-@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
-@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
-
-// 197
-@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
-@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
-
-// 198
-@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
-@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
-
-// 199
-@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
-@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
-
-// 201
-@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
-@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
-
-// 202
-@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
-@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
-
-// 203
-@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_SPEC_VERSION 1
-@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
-
-// 204
-@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
-@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
-
-// 205
-@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
-@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
-
-// 206
-@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
-@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
-
-// 207
-@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
-@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
-
-// 212
-@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
-@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
-
-// 213
-@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2
-@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_EXENSION_NAME "VK_EXT_pci_bus_info"
-
-// 215
-@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
-@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
-
-// 219
-@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
-@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
-
-// 222
-@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
-@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
-
-// 224
-@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
-@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
-
-// 225
-@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
-@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
-
-// 247
-@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
-@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
-
-/////////////
-//  Types  //
-/////////////
-
-type u32 VkBool32
-type u32 VkFlags
-type u64 VkDeviceSize
-type u32 VkSampleMask
-
-/// Dispatchable handle types.
-@dispatchHandle type u64 VkInstance
-@dispatchHandle type u64 VkPhysicalDevice
-@dispatchHandle type u64 VkDevice
-@dispatchHandle type u64 VkQueue
-@dispatchHandle type u64 VkCommandBuffer
-
-/// Non dispatchable handle types.
-@nonDispatchHandle type u64 VkDeviceMemory
-@nonDispatchHandle type u64 VkCommandPool
-@nonDispatchHandle type u64 VkBuffer
-@nonDispatchHandle type u64 VkBufferView
-@nonDispatchHandle type u64 VkImage
-@nonDispatchHandle type u64 VkImageView
-@nonDispatchHandle type u64 VkShaderModule
-@nonDispatchHandle type u64 VkPipeline
-@nonDispatchHandle type u64 VkPipelineLayout
-@nonDispatchHandle type u64 VkSampler
-@nonDispatchHandle type u64 VkDescriptorSet
-@nonDispatchHandle type u64 VkDescriptorSetLayout
-@nonDispatchHandle type u64 VkDescriptorPool
-@nonDispatchHandle type u64 VkFence
-@nonDispatchHandle type u64 VkSemaphore
-@nonDispatchHandle type u64 VkEvent
-@nonDispatchHandle type u64 VkQueryPool
-@nonDispatchHandle type u64 VkFramebuffer
-@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
-
-// 2
-@extension("VK_KHR_swapchain")  @nonDispatchHandle type u64 VkSwapchainKHR
-
-// 3
-@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayKHR
-@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayModeKHR
-
-// 12
-@extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
-
-// 86
-@extension("VK_KHR_descriptor_update_template") @nonDispatchHandle type u64 VkDescriptorUpdateTemplateKHR
-
-// 87
-@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkObjectTableNVX
-@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkIndirectCommandsLayoutNVX
-
-// 129
-@extension("VK_EXT_debug_utils") @nonDispatchHandle type u64 VkDebugUtilsMessengerEXT
-
-// 157
-@extension("VK_KHR_sampler_ycbcr_conversion") @nonDispatchHandle type u64 VkSamplerYcbcrConversionKHR
-
-// 161
-@extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
-
-// 166
-@extension("VK_NV_ray_tracing") @nonDispatchHandle type u64 VkAccelerationStructureNV
-
-/////////////
-//  Enums  //
-/////////////
-
-enum VkImageLayout {
-    VK_IMAGE_LAYOUT_UNDEFINED                               = 0x00000000,   /// Implicit layout an image is when its contents are undefined due to various reasons (e.g. right after creation)
-    VK_IMAGE_LAYOUT_GENERAL                                 = 0x00000001,   /// General layout when image can be used for any kind of access
-    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                = 0x00000002,   /// Optimal layout when image is only used for color attachment read/write
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        = 0x00000003,   /// Optimal layout when image is only used for depth/stencil attachment read/write
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL         = 0x00000004,   /// Optimal layout when image is used for read only depth/stencil attachment and shader access
-    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                = 0x00000005,   /// Optimal layout when image is used for read only shader access
-    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL                    = 0x00000006,   /// Optimal layout when image is used only as source of transfer operations
-    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,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR                      = 1000111000,
-
-    //@extension("VK_KHR_maintenance2") // 118
-    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR  = 1000117000,
-    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR  = 1000117001,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV                 = 1000164003,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT        = 1000218000,
-}
-
-enum VkAttachmentLoadOp {
-    VK_ATTACHMENT_LOAD_OP_LOAD                              = 0x00000000,
-    VK_ATTACHMENT_LOAD_OP_CLEAR                             = 0x00000001,
-    VK_ATTACHMENT_LOAD_OP_DONT_CARE                         = 0x00000002,
-}
-
-enum VkAttachmentStoreOp {
-    VK_ATTACHMENT_STORE_OP_STORE                            = 0x00000000,
-    VK_ATTACHMENT_STORE_OP_DONT_CARE                        = 0x00000001,
-}
-
-enum VkImageType {
-    VK_IMAGE_TYPE_1D                                        = 0x00000000,
-    VK_IMAGE_TYPE_2D                                        = 0x00000001,
-    VK_IMAGE_TYPE_3D                                        = 0x00000002,
-}
-
-enum VkImageTiling {
-    VK_IMAGE_TILING_OPTIMAL                                 = 0x00000000,
-    VK_IMAGE_TILING_LINEAR                                  = 0x00000001,
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT                 = 1000158000,
-}
-
-enum VkImageViewType {
-    VK_IMAGE_VIEW_TYPE_1D                                   = 0x00000000,
-    VK_IMAGE_VIEW_TYPE_2D                                   = 0x00000001,
-    VK_IMAGE_VIEW_TYPE_3D                                   = 0x00000002,
-    VK_IMAGE_VIEW_TYPE_CUBE                                 = 0x00000003,
-    VK_IMAGE_VIEW_TYPE_1D_ARRAY                             = 0x00000004,
-    VK_IMAGE_VIEW_TYPE_2D_ARRAY                             = 0x00000005,
-    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY                           = 0x00000006,
-}
-
-enum VkCommandBufferLevel {
-    VK_COMMAND_BUFFER_LEVEL_PRIMARY                         = 0x00000000,
-    VK_COMMAND_BUFFER_LEVEL_SECONDARY                       = 0x00000001,
-}
-
-enum VkComponentSwizzle {
-    VK_COMPONENT_SWIZZLE_IDENTITY                           = 0x00000000,
-    VK_COMPONENT_SWIZZLE_ZERO                               = 0x00000001,
-    VK_COMPONENT_SWIZZLE_ONE                                = 0x00000002,
-    VK_COMPONENT_SWIZZLE_R                                  = 0x00000003,
-    VK_COMPONENT_SWIZZLE_G                                  = 0x00000004,
-    VK_COMPONENT_SWIZZLE_B                                  = 0x00000005,
-    VK_COMPONENT_SWIZZLE_A                                  = 0x00000006,
-}
-
-enum VkDescriptorType {
-    VK_DESCRIPTOR_TYPE_SAMPLER                              = 0x00000000,
-    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER               = 0x00000001,
-    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE                        = 0x00000002,
-    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE                        = 0x00000003,
-    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER                 = 0x00000004,
-    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER                 = 0x00000005,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER                       = 0x00000006,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER                       = 0x00000007,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC               = 0x00000008,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC               = 0x00000009,
-    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT                     = 0x0000000a,
-
-    //@extension("VK_EXT_inline_uniform_block") // 139
-    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT             = 1000138000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV            = 1000165000,
-}
-
-enum VkQueryType {
-    VK_QUERY_TYPE_OCCLUSION                                 = 0x00000000,
-    VK_QUERY_TYPE_PIPELINE_STATISTICS                       = 0x00000001, /// Optional
-    VK_QUERY_TYPE_TIMESTAMP                                 = 0x00000002,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT             = 1000028004,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV  = 1000165000,
-}
-
-enum VkBorderColor {
-    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK                 = 0x00000000,
-    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK                   = 0x00000001,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK                      = 0x00000002,
-    VK_BORDER_COLOR_INT_OPAQUE_BLACK                        = 0x00000003,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE                      = 0x00000004,
-    VK_BORDER_COLOR_INT_OPAQUE_WHITE                        = 0x00000005,
-}
-
-enum VkPipelineBindPoint {
-    VK_PIPELINE_BIND_POINT_GRAPHICS                         = 0x00000000,
-    VK_PIPELINE_BIND_POINT_COMPUTE                          = 0x00000001,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_BIND_POINT_RAY_TRACING_NV                   = 1000165000,
-}
-
-enum VkPrimitiveTopology {
-    VK_PRIMITIVE_TOPOLOGY_POINT_LIST                        = 0x00000000,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST                         = 0x00000001,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                        = 0x00000002,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST                     = 0x00000003,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP                    = 0x00000004,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                      = 0x00000005,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY          = 0x00000006,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY         = 0x00000007,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY      = 0x00000008,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY     = 0x00000009,
-    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST                        = 0x0000000a,
-}
-
-enum VkSharingMode {
-    VK_SHARING_MODE_EXCLUSIVE                               = 0x00000000,
-    VK_SHARING_MODE_CONCURRENT                              = 0x00000001,
-}
-
-enum VkIndexType {
-    VK_INDEX_TYPE_UINT16                                    = 0x00000000,
-    VK_INDEX_TYPE_UINT32                                    = 0x00000001,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_INDEX_TYPE_NONE_NV                                   = 1000165000,
-}
-
-enum VkFilter {
-    VK_FILTER_NEAREST                                       = 0x00000000,
-    VK_FILTER_LINEAR                                        = 0x00000001,
-
-    //@extension("VK_IMG_filter_cubic") // 16
-    VK_FILTER_CUBIC_IMG                                     = 1000015000,
-}
-
-enum VkSamplerMipmapMode {
-    VK_SAMPLER_MIPMAP_MODE_NEAREST                          = 0x00000001,   /// Choose nearest mip level
-    VK_SAMPLER_MIPMAP_MODE_LINEAR                           = 0x00000002,   /// Linear filter between mip levels
-}
-
-enum VkSamplerAddressMode {
-    VK_SAMPLER_ADDRESS_MODE_REPEAT                          = 0x00000000,
-    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT                 = 0x00000001,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE                   = 0x00000002,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER                 = 0x00000003,
-    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE            = 0x00000004,
-}
-
-enum VkCompareOp {
-    VK_COMPARE_OP_NEVER                                     = 0x00000000,
-    VK_COMPARE_OP_LESS                                      = 0x00000001,
-    VK_COMPARE_OP_EQUAL                                     = 0x00000002,
-    VK_COMPARE_OP_LESS_OR_EQUAL                             = 0x00000003,
-    VK_COMPARE_OP_GREATER                                   = 0x00000004,
-    VK_COMPARE_OP_NOT_EQUAL                                 = 0x00000005,
-    VK_COMPARE_OP_GREATER_OR_EQUAL                          = 0x00000006,
-    VK_COMPARE_OP_ALWAYS                                    = 0x00000007,
-}
-
-enum VkPolygonMode {
-    VK_POLYGON_MODE_FILL                                    = 0x00000000,
-    VK_POLYGON_MODE_LINE                                    = 0x00000001,
-    VK_POLYGON_MODE_POINT                                   = 0x00000002,
-
-    //@extension("VK_NV_fill_rectangle") // 154
-    VK_POLYGON_MODE_FILL_RECTANGLE_NV                       = 1000153000,
-}
-
-enum VkFrontFace {
-    VK_FRONT_FACE_COUNTER_CLOCKWISE                         = 0x00000000,
-    VK_FRONT_FACE_CLOCKWISE                                 = 0x00000001,
-}
-
-enum VkBlendFactor {
-    VK_BLEND_FACTOR_ZERO                                    = 0x00000000,
-    VK_BLEND_FACTOR_ONE                                     = 0x00000001,
-    VK_BLEND_FACTOR_SRC_COLOR                               = 0x00000002,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR                     = 0x00000003,
-    VK_BLEND_FACTOR_DST_COLOR                               = 0x00000004,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR                     = 0x00000005,
-    VK_BLEND_FACTOR_SRC_ALPHA                               = 0x00000006,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA                     = 0x00000007,
-    VK_BLEND_FACTOR_DST_ALPHA                               = 0x00000008,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA                     = 0x00000009,
-    VK_BLEND_FACTOR_CONSTANT_COLOR                          = 0x0000000a,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR                = 0x0000000b,
-    VK_BLEND_FACTOR_CONSTANT_ALPHA                          = 0x0000000c,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA                = 0x0000000d,
-    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE                      = 0x0000000e,
-    VK_BLEND_FACTOR_SRC1_COLOR                              = 0x0000000f,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR                    = 0x00000010,
-    VK_BLEND_FACTOR_SRC1_ALPHA                              = 0x00000011,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA                    = 0x00000012,
-}
-
-enum VkBlendOp {
-    VK_BLEND_OP_ADD                                         = 0x00000000,
-    VK_BLEND_OP_SUBTRACT                                    = 0x00000001,
-    VK_BLEND_OP_REVERSE_SUBTRACT                            = 0x00000002,
-    VK_BLEND_OP_MIN                                         = 0x00000003,
-    VK_BLEND_OP_MAX                                         = 0x00000004,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    VK_BLEND_OP_ZERO_EXT                                    = 1000148000,
-    VK_BLEND_OP_SRC_EXT                                     = 1000148001,
-    VK_BLEND_OP_DST_EXT                                     = 1000148002,
-    VK_BLEND_OP_SRC_OVER_EXT                                = 1000148003,
-    VK_BLEND_OP_DST_OVER_EXT                                = 1000148004,
-    VK_BLEND_OP_SRC_IN_EXT                                  = 1000148005,
-    VK_BLEND_OP_DST_IN_EXT                                  = 1000148006,
-    VK_BLEND_OP_SRC_OUT_EXT                                 = 1000148007,
-    VK_BLEND_OP_DST_OUT_EXT                                 = 1000148008,
-    VK_BLEND_OP_SRC_ATOP_EXT                                = 1000148009,
-    VK_BLEND_OP_DST_ATOP_EXT                                = 1000148010,
-    VK_BLEND_OP_XOR_EXT                                     = 1000148011,
-    VK_BLEND_OP_MULTIPLY_EXT                                = 1000148012,
-    VK_BLEND_OP_SCREEN_EXT                                  = 1000148013,
-    VK_BLEND_OP_OVERLAY_EXT                                 = 1000148014,
-    VK_BLEND_OP_DARKEN_EXT                                  = 1000148015,
-    VK_BLEND_OP_LIGHTEN_EXT                                 = 1000148016,
-    VK_BLEND_OP_COLORDODGE_EXT                              = 1000148017,
-    VK_BLEND_OP_COLORBURN_EXT                               = 1000148018,
-    VK_BLEND_OP_HARDLIGHT_EXT                               = 1000148019,
-    VK_BLEND_OP_SOFTLIGHT_EXT                               = 1000148020,
-    VK_BLEND_OP_DIFFERENCE_EXT                              = 1000148021,
-    VK_BLEND_OP_EXCLUSION_EXT                               = 1000148022,
-    VK_BLEND_OP_INVERT_EXT                                  = 1000148023,
-    VK_BLEND_OP_INVERT_RGB_EXT                              = 1000148024,
-    VK_BLEND_OP_LINEARDODGE_EXT                             = 1000148025,
-    VK_BLEND_OP_LINEARBURN_EXT                              = 1000148026,
-    VK_BLEND_OP_VIVIDLIGHT_EXT                              = 1000148027,
-    VK_BLEND_OP_LINEARLIGHT_EXT                             = 1000148028,
-    VK_BLEND_OP_PINLIGHT_EXT                                = 1000148029,
-    VK_BLEND_OP_HARDMIX_EXT                                 = 1000148030,
-    VK_BLEND_OP_HSL_HUE_EXT                                 = 1000148031,
-    VK_BLEND_OP_HSL_SATURATION_EXT                          = 1000148032,
-    VK_BLEND_OP_HSL_COLOR_EXT                               = 1000148033,
-    VK_BLEND_OP_HSL_LUMINOSITY_EXT                          = 1000148034,
-    VK_BLEND_OP_PLUS_EXT                                    = 1000148035,
-    VK_BLEND_OP_PLUS_CLAMPED_EXT                            = 1000148036,
-    VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT                      = 1000148037,
-    VK_BLEND_OP_PLUS_DARKER_EXT                             = 1000148038,
-    VK_BLEND_OP_MINUS_EXT                                   = 1000148039,
-    VK_BLEND_OP_MINUS_CLAMPED_EXT                           = 1000148040,
-    VK_BLEND_OP_CONTRAST_EXT                                = 1000148041,
-    VK_BLEND_OP_INVERT_OVG_EXT                              = 1000148042,
-    VK_BLEND_OP_RED_EXT                                     = 1000148043,
-    VK_BLEND_OP_GREEN_EXT                                   = 1000148044,
-    VK_BLEND_OP_BLUE_EXT                                    = 1000148045,
-}
-
-enum VkStencilOp {
-    VK_STENCIL_OP_KEEP                                      = 0x00000000,
-    VK_STENCIL_OP_ZERO                                      = 0x00000001,
-    VK_STENCIL_OP_REPLACE                                   = 0x00000002,
-    VK_STENCIL_OP_INCREMENT_AND_CLAMP                       = 0x00000003,
-    VK_STENCIL_OP_DECREMENT_AND_CLAMP                       = 0x00000004,
-    VK_STENCIL_OP_INVERT                                    = 0x00000005,
-    VK_STENCIL_OP_INCREMENT_AND_WRAP                        = 0x00000006,
-    VK_STENCIL_OP_DECREMENT_AND_WRAP                        = 0x00000007,
-}
-
-enum VkLogicOp {
-    VK_LOGIC_OP_CLEAR                                       = 0x00000000,
-    VK_LOGIC_OP_AND                                         = 0x00000001,
-    VK_LOGIC_OP_AND_REVERSE                                 = 0x00000002,
-    VK_LOGIC_OP_COPY                                        = 0x00000003,
-    VK_LOGIC_OP_AND_INVERTED                                = 0x00000004,
-    VK_LOGIC_OP_NO_OP                                       = 0x00000005,
-    VK_LOGIC_OP_XOR                                         = 0x00000006,
-    VK_LOGIC_OP_OR                                          = 0x00000007,
-    VK_LOGIC_OP_NOR                                         = 0x00000008,
-    VK_LOGIC_OP_EQUIVALENT                                  = 0x00000009,
-    VK_LOGIC_OP_INVERT                                      = 0x0000000a,
-    VK_LOGIC_OP_OR_REVERSE                                  = 0x0000000b,
-    VK_LOGIC_OP_COPY_INVERTED                               = 0x0000000c,
-    VK_LOGIC_OP_OR_INVERTED                                 = 0x0000000d,
-    VK_LOGIC_OP_NAND                                        = 0x0000000e,
-    VK_LOGIC_OP_SET                                         = 0x0000000f,
-}
-
-enum VkSystemAllocationScope {
-    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND                      = 0x00000000,
-    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT                       = 0x00000001,
-    VK_SYSTEM_ALLOCATION_SCOPE_CACHE                        = 0x00000002,
-    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE                       = 0x00000003,
-    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE                     = 0x00000004,
-}
-
-enum VkInternalAllocationType {
-    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE                  = 0x00000000,
-}
-
-enum VkPhysicalDeviceType {
-    VK_PHYSICAL_DEVICE_TYPE_OTHER                           = 0x00000000,
-    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU                  = 0x00000001,
-    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU                    = 0x00000002,
-    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU                     = 0x00000003,
-    VK_PHYSICAL_DEVICE_TYPE_CPU                             = 0x00000004,
-}
-
-enum VkVertexInputRate {
-    VK_VERTEX_INPUT_RATE_VERTEX                             = 0x00000000,
-    VK_VERTEX_INPUT_RATE_INSTANCE                           = 0x00000001,
-}
-
-/// Vulkan format definitions
-enum VkFormat {
-    VK_FORMAT_UNDEFINED                                     = 0,
-    VK_FORMAT_R4G4_UNORM_PACK8                              = 1,
-    VK_FORMAT_R4G4B4A4_UNORM_PACK16                         = 2,
-    VK_FORMAT_B4G4R4A4_UNORM_PACK16                         = 3,
-    VK_FORMAT_R5G6B5_UNORM_PACK16                           = 4,
-    VK_FORMAT_B5G6R5_UNORM_PACK16                           = 5,
-    VK_FORMAT_R5G5B5A1_UNORM_PACK16                         = 6,
-    VK_FORMAT_B5G5R5A1_UNORM_PACK16                         = 7,
-    VK_FORMAT_A1R5G5B5_UNORM_PACK16                         = 8,
-    VK_FORMAT_R8_UNORM                                      = 9,
-    VK_FORMAT_R8_SNORM                                      = 10,
-    VK_FORMAT_R8_USCALED                                    = 11,
-    VK_FORMAT_R8_SSCALED                                    = 12,
-    VK_FORMAT_R8_UINT                                       = 13,
-    VK_FORMAT_R8_SINT                                       = 14,
-    VK_FORMAT_R8_SRGB                                       = 15,
-    VK_FORMAT_R8G8_UNORM                                    = 16,
-    VK_FORMAT_R8G8_SNORM                                    = 17,
-    VK_FORMAT_R8G8_USCALED                                  = 18,
-    VK_FORMAT_R8G8_SSCALED                                  = 19,
-    VK_FORMAT_R8G8_UINT                                     = 20,
-    VK_FORMAT_R8G8_SINT                                     = 21,
-    VK_FORMAT_R8G8_SRGB                                     = 22,
-    VK_FORMAT_R8G8B8_UNORM                                  = 23,
-    VK_FORMAT_R8G8B8_SNORM                                  = 24,
-    VK_FORMAT_R8G8B8_USCALED                                = 25,
-    VK_FORMAT_R8G8B8_SSCALED                                = 26,
-    VK_FORMAT_R8G8B8_UINT                                   = 27,
-    VK_FORMAT_R8G8B8_SINT                                   = 28,
-    VK_FORMAT_R8G8B8_SRGB                                   = 29,
-    VK_FORMAT_B8G8R8_UNORM                                  = 30,
-    VK_FORMAT_B8G8R8_SNORM                                  = 31,
-    VK_FORMAT_B8G8R8_USCALED                                = 32,
-    VK_FORMAT_B8G8R8_SSCALED                                = 33,
-    VK_FORMAT_B8G8R8_UINT                                   = 34,
-    VK_FORMAT_B8G8R8_SINT                                   = 35,
-    VK_FORMAT_B8G8R8_SRGB                                   = 36,
-    VK_FORMAT_R8G8B8A8_UNORM                                = 37,
-    VK_FORMAT_R8G8B8A8_SNORM                                = 38,
-    VK_FORMAT_R8G8B8A8_USCALED                              = 39,
-    VK_FORMAT_R8G8B8A8_SSCALED                              = 40,
-    VK_FORMAT_R8G8B8A8_UINT                                 = 41,
-    VK_FORMAT_R8G8B8A8_SINT                                 = 42,
-    VK_FORMAT_R8G8B8A8_SRGB                                 = 43,
-    VK_FORMAT_B8G8R8A8_UNORM                                = 44,
-    VK_FORMAT_B8G8R8A8_SNORM                                = 45,
-    VK_FORMAT_B8G8R8A8_USCALED                              = 46,
-    VK_FORMAT_B8G8R8A8_SSCALED                              = 47,
-    VK_FORMAT_B8G8R8A8_UINT                                 = 48,
-    VK_FORMAT_B8G8R8A8_SINT                                 = 49,
-    VK_FORMAT_B8G8R8A8_SRGB                                 = 50,
-    VK_FORMAT_A8B8G8R8_UNORM_PACK32                         = 51,
-    VK_FORMAT_A8B8G8R8_SNORM_PACK32                         = 52,
-    VK_FORMAT_A8B8G8R8_USCALED_PACK32                       = 53,
-    VK_FORMAT_A8B8G8R8_SSCALED_PACK32                       = 54,
-    VK_FORMAT_A8B8G8R8_UINT_PACK32                          = 55,
-    VK_FORMAT_A8B8G8R8_SINT_PACK32                          = 56,
-    VK_FORMAT_A8B8G8R8_SRGB_PACK32                          = 57,
-    VK_FORMAT_A2R10G10B10_UNORM_PACK32                      = 58,
-    VK_FORMAT_A2R10G10B10_SNORM_PACK32                      = 59,
-    VK_FORMAT_A2R10G10B10_USCALED_PACK32                    = 60,
-    VK_FORMAT_A2R10G10B10_SSCALED_PACK32                    = 61,
-    VK_FORMAT_A2R10G10B10_UINT_PACK32                       = 62,
-    VK_FORMAT_A2R10G10B10_SINT_PACK32                       = 63,
-    VK_FORMAT_A2B10G10R10_UNORM_PACK32                      = 64,
-    VK_FORMAT_A2B10G10R10_SNORM_PACK32                      = 65,
-    VK_FORMAT_A2B10G10R10_USCALED_PACK32                    = 66,
-    VK_FORMAT_A2B10G10R10_SSCALED_PACK32                    = 67,
-    VK_FORMAT_A2B10G10R10_UINT_PACK32                       = 68,
-    VK_FORMAT_A2B10G10R10_SINT_PACK32                       = 69,
-    VK_FORMAT_R16_UNORM                                     = 70,
-    VK_FORMAT_R16_SNORM                                     = 71,
-    VK_FORMAT_R16_USCALED                                   = 72,
-    VK_FORMAT_R16_SSCALED                                   = 73,
-    VK_FORMAT_R16_UINT                                      = 74,
-    VK_FORMAT_R16_SINT                                      = 75,
-    VK_FORMAT_R16_SFLOAT                                    = 76,
-    VK_FORMAT_R16G16_UNORM                                  = 77,
-    VK_FORMAT_R16G16_SNORM                                  = 78,
-    VK_FORMAT_R16G16_USCALED                                = 79,
-    VK_FORMAT_R16G16_SSCALED                                = 80,
-    VK_FORMAT_R16G16_UINT                                   = 81,
-    VK_FORMAT_R16G16_SINT                                   = 82,
-    VK_FORMAT_R16G16_SFLOAT                                 = 83,
-    VK_FORMAT_R16G16B16_UNORM                               = 84,
-    VK_FORMAT_R16G16B16_SNORM                               = 85,
-    VK_FORMAT_R16G16B16_USCALED                             = 86,
-    VK_FORMAT_R16G16B16_SSCALED                             = 87,
-    VK_FORMAT_R16G16B16_UINT                                = 88,
-    VK_FORMAT_R16G16B16_SINT                                = 89,
-    VK_FORMAT_R16G16B16_SFLOAT                              = 90,
-    VK_FORMAT_R16G16B16A16_UNORM                            = 91,
-    VK_FORMAT_R16G16B16A16_SNORM                            = 92,
-    VK_FORMAT_R16G16B16A16_USCALED                          = 93,
-    VK_FORMAT_R16G16B16A16_SSCALED                          = 94,
-    VK_FORMAT_R16G16B16A16_UINT                             = 95,
-    VK_FORMAT_R16G16B16A16_SINT                             = 96,
-    VK_FORMAT_R16G16B16A16_SFLOAT                           = 97,
-    VK_FORMAT_R32_UINT                                      = 98,
-    VK_FORMAT_R32_SINT                                      = 99,
-    VK_FORMAT_R32_SFLOAT                                    = 100,
-    VK_FORMAT_R32G32_UINT                                   = 101,
-    VK_FORMAT_R32G32_SINT                                   = 102,
-    VK_FORMAT_R32G32_SFLOAT                                 = 103,
-    VK_FORMAT_R32G32B32_UINT                                = 104,
-    VK_FORMAT_R32G32B32_SINT                                = 105,
-    VK_FORMAT_R32G32B32_SFLOAT                              = 106,
-    VK_FORMAT_R32G32B32A32_UINT                             = 107,
-    VK_FORMAT_R32G32B32A32_SINT                             = 108,
-    VK_FORMAT_R32G32B32A32_SFLOAT                           = 109,
-    VK_FORMAT_R64_UINT                                      = 110,
-    VK_FORMAT_R64_SINT                                      = 111,
-    VK_FORMAT_R64_SFLOAT                                    = 112,
-    VK_FORMAT_R64G64_UINT                                   = 113,
-    VK_FORMAT_R64G64_SINT                                   = 114,
-    VK_FORMAT_R64G64_SFLOAT                                 = 115,
-    VK_FORMAT_R64G64B64_UINT                                = 116,
-    VK_FORMAT_R64G64B64_SINT                                = 117,
-    VK_FORMAT_R64G64B64_SFLOAT                              = 118,
-    VK_FORMAT_R64G64B64A64_UINT                             = 119,
-    VK_FORMAT_R64G64B64A64_SINT                             = 120,
-    VK_FORMAT_R64G64B64A64_SFLOAT                           = 121,
-    VK_FORMAT_B10G11R11_UFLOAT_PACK32                       = 122,
-    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32                        = 123,
-    VK_FORMAT_D16_UNORM                                     = 124,
-    VK_FORMAT_X8_D24_UNORM_PACK32                           = 125,
-    VK_FORMAT_D32_SFLOAT                                    = 126,
-    VK_FORMAT_S8_UINT                                       = 127,
-    VK_FORMAT_D16_UNORM_S8_UINT                             = 128,
-    VK_FORMAT_D24_UNORM_S8_UINT                             = 129,
-    VK_FORMAT_D32_SFLOAT_S8_UINT                            = 130,
-    VK_FORMAT_BC1_RGB_UNORM_BLOCK                           = 131,
-    VK_FORMAT_BC1_RGB_SRGB_BLOCK                            = 132,
-    VK_FORMAT_BC1_RGBA_UNORM_BLOCK                          = 133,
-    VK_FORMAT_BC1_RGBA_SRGB_BLOCK                           = 134,
-    VK_FORMAT_BC2_UNORM_BLOCK                               = 135,
-    VK_FORMAT_BC2_SRGB_BLOCK                                = 136,
-    VK_FORMAT_BC3_UNORM_BLOCK                               = 137,
-    VK_FORMAT_BC3_SRGB_BLOCK                                = 138,
-    VK_FORMAT_BC4_UNORM_BLOCK                               = 139,
-    VK_FORMAT_BC4_SNORM_BLOCK                               = 140,
-    VK_FORMAT_BC5_UNORM_BLOCK                               = 141,
-    VK_FORMAT_BC5_SNORM_BLOCK                               = 142,
-    VK_FORMAT_BC6H_UFLOAT_BLOCK                             = 143,
-    VK_FORMAT_BC6H_SFLOAT_BLOCK                             = 144,
-    VK_FORMAT_BC7_UNORM_BLOCK                               = 145,
-    VK_FORMAT_BC7_SRGB_BLOCK                                = 146,
-    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK                       = 147,
-    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK                        = 148,
-    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK                     = 149,
-    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK                      = 150,
-    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK                     = 151,
-    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK                      = 152,
-    VK_FORMAT_EAC_R11_UNORM_BLOCK                           = 153,
-    VK_FORMAT_EAC_R11_SNORM_BLOCK                           = 154,
-    VK_FORMAT_EAC_R11G11_UNORM_BLOCK                        = 155,
-    VK_FORMAT_EAC_R11G11_SNORM_BLOCK                        = 156,
-    VK_FORMAT_ASTC_4x4_UNORM_BLOCK                          = 157,
-    VK_FORMAT_ASTC_4x4_SRGB_BLOCK                           = 158,
-    VK_FORMAT_ASTC_5x4_UNORM_BLOCK                          = 159,
-    VK_FORMAT_ASTC_5x4_SRGB_BLOCK                           = 160,
-    VK_FORMAT_ASTC_5x5_UNORM_BLOCK                          = 161,
-    VK_FORMAT_ASTC_5x5_SRGB_BLOCK                           = 162,
-    VK_FORMAT_ASTC_6x5_UNORM_BLOCK                          = 163,
-    VK_FORMAT_ASTC_6x5_SRGB_BLOCK                           = 164,
-    VK_FORMAT_ASTC_6x6_UNORM_BLOCK                          = 165,
-    VK_FORMAT_ASTC_6x6_SRGB_BLOCK                           = 166,
-    VK_FORMAT_ASTC_8x5_UNORM_BLOCK                          = 167,
-    VK_FORMAT_ASTC_8x5_SRGB_BLOCK                           = 168,
-    VK_FORMAT_ASTC_8x6_UNORM_BLOCK                          = 169,
-    VK_FORMAT_ASTC_8x6_SRGB_BLOCK                           = 170,
-    VK_FORMAT_ASTC_8x8_UNORM_BLOCK                          = 171,
-    VK_FORMAT_ASTC_8x8_SRGB_BLOCK                           = 172,
-    VK_FORMAT_ASTC_10x5_UNORM_BLOCK                         = 173,
-    VK_FORMAT_ASTC_10x5_SRGB_BLOCK                          = 174,
-    VK_FORMAT_ASTC_10x6_UNORM_BLOCK                         = 175,
-    VK_FORMAT_ASTC_10x6_SRGB_BLOCK                          = 176,
-    VK_FORMAT_ASTC_10x8_UNORM_BLOCK                         = 177,
-    VK_FORMAT_ASTC_10x8_SRGB_BLOCK                          = 178,
-    VK_FORMAT_ASTC_10x10_UNORM_BLOCK                        = 179,
-    VK_FORMAT_ASTC_10x10_SRGB_BLOCK                         = 180,
-    VK_FORMAT_ASTC_12x10_UNORM_BLOCK                        = 181,
-    VK_FORMAT_ASTC_12x10_SRGB_BLOCK                         = 182,
-    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,
-    VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG                   = 1000054002,
-    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG                   = 1000054003,
-    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG                    = 1000054004,
-    VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG                    = 1000054005,
-    VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG                    = 1000054006,
-    VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG                    = 1000054007,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    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,
-}
-
-/// Structure type enumerant
-enum VkStructureType {
-    VK_STRUCTURE_TYPE_APPLICATION_INFO                          = 0,
-    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO                      = 1,
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO                  = 2,
-    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO                        = 3,
-    VK_STRUCTURE_TYPE_SUBMIT_INFO                               = 4,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO                      = 5,
-    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE                       = 6,
-    VK_STRUCTURE_TYPE_BIND_SPARSE_INFO                          = 7,
-    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO                         = 8,
-    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO                     = 9,
-    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO                         = 10,
-    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO                    = 11,
-    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO                        = 12,
-    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO                   = 13,
-    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO                         = 14,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO                    = 15,
-    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO                 = 16,
-    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO                = 17,
-    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO         = 18,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO   = 19,
-    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO   = 21,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO       = 22,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO  = 23,
-    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO    = 24,
-    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO  = 25,
-    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO    = 26,
-    VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO        = 27,
-    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO             = 28,
-    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO              = 29,
-    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO               = 30,
-    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO                       = 31,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO         = 32,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO               = 33,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO              = 34,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET                      = 35,
-    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET                       = 36,
-    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO                   = 37,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO                   = 38,
-    VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO                  = 39,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO              = 40,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO           = 41,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO                 = 42,
-    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO                    = 43,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER                     = 44,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER                      = 45,
-    VK_STRUCTURE_TYPE_MEMORY_BARRIER                            = 46,
-    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,
-    VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR           = 1000002001,
-
-    //@extension("VK_KHR_display_swapchain") // 4
-    VK_STRUCTURE_TYPE_DISPLAY_DISPLAY_PRESENT_INFO_KHR          = 1000003000,
-
-    //@extension("VK_KHR_xlib_surface") // 5
-    VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR              = 1000004000,
-
-    //@extension("VK_KHR_xcb_surface") // 6
-    VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR               = 1000005000,
-
-    //@extension("VK_KHR_wayland_surface") // 7
-    VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR           = 1000006000,
-
-    //@extension("VK_KHR_android_surface") // 9
-    VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR           = 1000008000,
-
-    //@extension("VK_KHR_win32_surface") // 10
-    VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR             = 1000009000,
-
-    //@extension("VK_ANDROID_native_buffer") // 11
-    VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID                     = 1000010000,
-    VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID       = 1000010001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID = 1000010002,
-
-    //@extension("VK_EXT_debug_report") // 12
-    VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT     = 1000011000,
-
-    //@extension("VK_AMD_rasterization_order") // 19
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000,
-
-    //@extension("VK_EXT_debug_marker") // 23
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT         = 1000022000,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT          = 1000022001,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT              = 1000022002,
-
-    //@extension("VK_NV_dedicated_allocation") // 27
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT       = 1000028000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT     = 1000028001,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT   = 1000028002,
-
-    //@extension("VK_AMD_texture_gather_bias_lod") // 42
-    VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD  = 1000041000,
-
-    //@extension("VK_NV_corner_sampled_image") // 51
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV  = 1000050000,
-
-    //@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,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV            = 1000056001,
-
-    //@extension("VK_NV_external_memory_win32") // 58
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV        = 1000057000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV        = 1000057001,
-
-    //@extension("VK_NV_win32_keyed_mutex") // 59
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
-
-    //@extension("VK_KHR_get_physical_device_properties2") // 60
-    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,
-
-    //@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,
-
-    //@extension("VK_NN_vi_surface") // 63
-    VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN                 = 1000062000,
-
-    //@extension("VK_EXT_astc_decode_mode") // 68
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT           = 1000067000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT  = 1000067001,
-
-    //@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,
-    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,
-
-    //@extension("VK_KHR_external_memory") // 73
-    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,
-
-    //@extension("VK_KHR_external_memory_win32") // 74
-    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,
-
-    //@extension("VK_KHR_external_memory_fd") // 75
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR                 = 1000074000,
-    VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR                  = 1000074001,
-
-    //@extension("VK_KHR_win32_keyed_mutex") // 76
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR    = 1000075000,
-
-    //@extension("VK_KHR_external_semaphore_capabilities") // 77
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR   = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR         = 1000076001,
-
-    //@extension("VK_KHR_external_semaphore") // 78
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR          = 1000077000,
-
-    //@extension("VK_KHR_external_semaphore_win32") // 79
-    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,
-
-    //@extension("VK_KHR_external_semaphore_fd") // 80
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR              = 1000079000,
-    VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR                 = 1000079001,
-
-    //@extension("VK_KHR_push_descriptor") // 81
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR    = 1000080000,
-
-    //@extension("VK_KHR_16bit_storage") // 84
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR    = 1000083000,
-
-    //@extension("VK_KHR_incremental_present") // 85
-    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR                       = 1000084000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT        = 1000081001,
-    VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT                      = 1000081002,
-
-    //@extension("VK_KHR_shader_float16_int8") // 83
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR     = 1000082000,
-
-    //@extension("VK_KHR_descriptor_update_template") // 86
-    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR    = 1000085000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    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,
-    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX   = 1000086003,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX      = 1000086004,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX    = 1000086005,
-
-    //@extension("VK_NV_clip_space_w_scaling") // 88
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV  = 1000087000,
-
-    //@extension("VK_EXT_display_surface_counter") // 91
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT                = 1000090000,
-
-    //@extension("VK_EXT_display_control") // 92
-    VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT                    = 1000091000,
-    VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT                     = 1000091001,
-    VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT                    = 1000091002,
-    VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT         = 1000091003,
-
-    //@extension("VK_GOOGLE_display_timing") // 93
-    VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE                 = 1000092000,
-
-    //@extension("VK_NVX_multiview_per_view_attributes") // 98
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX  = 1000097000,
-
-    //@extension("VK_NV_viewport_swizzle") // 99
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV    = 1000098000,
-
-    //@extension("VK_EXT_discard_rectangles") // 100
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT  = 1000099000,
-    VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT  = 1000099001,
-
-    //@extension("VK_EXT_conservative_rasterization") // 102
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
-
-    //@extension("VK_KHR_create_renderpass2") // 110
-    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR              = 1000109000,
-    VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR                = 1000109001,
-    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR                 = 1000109002,
-    VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR                  = 1000109003,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR             = 1000109004,
-    VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR                    = 1000109005,
-    VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR                      = 1000109006,
-
-    //@extension("VK_EXT_hdr_metadata") // 106
-    VK_STRUCTURE_TYPE_HDR_METADATA_EXT                          = 1000105000,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR   = 1000111000,
-
-    //@extension("VK_KHR_external_fence_capabilities") // 113
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR   = 1000112000,
-    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR             = 1000112001,
-
-    //@extension("VK_KHR_external_fence") // 114
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR              = 1000113000,
-
-    //@extension("VK_KHR_external_fence_win32") // 115
-    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,
-
-    //@extension("VK_KHR_external_fence_fd") // 117
-    VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR                  = 1000115000,
-    VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR                     = 1000115001,
-
-    //@extension("VK_KHR_maintenance2") // 118
-    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,
-
-    //@extension("VK_KHR_get_surface_capabilities2") // 120
-    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,
-
-    //@extension("VK_KHR_variable_pointers") // 121
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
-
-    //@extension("VK_KHR_display_properties2") // 122
-    VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR                  = 1000121000,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR            = 1000121001,
-    VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR             = 1000121002,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR                  = 1000121003,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR          = 1000121004,
-
-    //@extension("VK_MVK_ios_surface") // 123
-    VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK               = 1000122000,
-
-    //@extension("VK_MVK_macos_surface") // 124
-    VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK             = 1000123000,
-
-    //@extension("VK_KHR_dedicated_allocation") // 128
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR         = 1000127000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR        = 1000127001,
-
-    //@extension("VK_EXT_debug_utils") // 129
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT          = 1000128000,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT           = 1000128001,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT                     = 1000128002,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT   = 1000128003,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT     = 1000128004,
-
-    //@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID             = 1000129000,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID        = 1000129001,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002,
-    VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID       = 1000129003,
-    VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID   = 1000129004,
-    VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID                           = 1000129005,
-
-    //@extension("VK_EXT_sampler_filter_minmax") // 131
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
-    VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
-
-    //@extension("VK_EXT_inline_uniform_block") // 139
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT     = 1000138000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT   = 1000138001,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT         = 1000138002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT  = 1000138003,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT                         = 1000143000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT       = 1000143001,
-    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,
-
-    //@extension("VK_KHR_get_memory_requirements2") // 147
-    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,
-
-    //@extension("VK_KHR_image_format_list") // 148
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR             = 1000147000,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    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,
-
-    //@extension("VK_NV_fragment_coverage_to_color") // 150
-    VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
-
-    //@extension("VK_NV_framebuffer_mixed_samples") // 153
-    VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    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,
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT               = 1000158000,
-    VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT                    = 1000158001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT    = 1000158002,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT        = 1000158003,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT    = 1000158004,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT              = 1000158005,
-
-    //@extension("VK_KHR_bind_memory2") // 158
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR                       = 1000157000,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR                        = 1000157001,
-
-    //@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_EXT_descriptor_indexing") // 162
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT           = 1000161000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT              = 1000161001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT            = 1000161002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT    = 1000161003,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT   = 1000161004,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV                   = 1000165000,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV                 = 1000165001,
-    VK_STRUCTURE_TYPE_GEOMETRY_NV                                           = 1000165003,
-    VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV                                 = 1000165004,
-    VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV                                      = 1000165005,
-    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV            = 1000165006,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV        = 1000165007,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV    = 1000165008,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV             = 1000165009,
-    VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV               = 1000165011,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV                        = 1000165012,
-
-    //@extension("VK_NV_representative_fragment_test") // 167
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
-    VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
-
-    //@extension("VK_KHR_maintenance3") // 169
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR      = 1000168000,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR                 = 1000168001,
-
-    //@extension("VK_EXT_global_priority") // 175
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT      = 1000174000,
-
-    //@extension("VK_KHR_8bit_storage") // 178
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR         = 1000177000,
-
-    //@extension("VK_EXT_external_memory_host") // 179
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT                   = 1000178000,
-    VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT                    = 1000178001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT   = 1000178002,
-
-    //@extension("VK_KHR_shader_atomic_int64") // 181
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR  = 1000180000,
-
-    //@extension("VK_EXT_calibrated_timestamps") // 185
-    VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT                     = 1000184000,
-
-    //@extension("VK_KHR_driver_properties") // 197
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR             = 1000196000,
-
-    //@extension("VK_KHR_shader_float_controls") // 198
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR     = 1000197000,
-
-    //@extension("VK_AMD_shader_core_properties") // 186
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD        = 1000185000,
-
-    //@extension("VK_AMD_memory_overallocation_behavior") // 190
-    VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD      = 1000189000,
-
-    //@extension("VK_EXT_vertex_attribute_divisor") // 191
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT   = 1000190000,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT       = 1000190001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT     = 1000190002,
-
-    //@extension("VK_NV_device_diagnostic_checkpoints") // 207
-    VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV                        = 1000206000,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV     = 1000206001,
-
-    //@extension("VK_KHR_vulkan_memory_model") // 212
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
-
-    //@extension("VK_EXT_pci_bus_info") // 213
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT   = 1000212000,
-
-    //@extension("VK_FUCHSIA_imagepipe_surface") // 215
-    VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA     = 1000214000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT     = 1000218000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT   = 1000218001,
-    VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT      = 1000218002,
-
-    //@extension("VK_EXT_scalar_block_layout")
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT  = 1000221000,
-
-    //@extension("VK_EXT_separate_stencil_usage") // 247
-    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT       = 1000246000,
-}
-
-enum VkSubpassContents {
-    VK_SUBPASS_CONTENTS_INLINE                              = 0x00000000,
-    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS           = 0x00000001,
-}
-
-enum VkPipelineCacheHeaderVersion {
-    VK_PIPELINE_CACHE_HEADER_VERSION_ONE                    = 1,
-}
-
-@lastUnused(-11)
-/// Error and return codes
-enum VkResult {
-    // Return codes for successful operation execution (positive values)
-    VK_SUCCESS                                              = 0,
-    VK_NOT_READY                                            = 1,
-    VK_TIMEOUT                                              = 2,
-    VK_EVENT_SET                                            = 3,
-    VK_EVENT_RESET                                          = 4,
-    VK_INCOMPLETE                                           = 5,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_SUBOPTIMAL_KHR                                       = 1000001003,
-
-    // Error codes (negative values)
-    VK_ERROR_OUT_OF_HOST_MEMORY                             = 0xFFFFFFFF, // -1
-    VK_ERROR_OUT_OF_DEVICE_MEMORY                           = 0xFFFFFFFE, // -2
-    VK_ERROR_INITIALIZATION_FAILED                          = 0xFFFFFFFD, // -3
-    VK_ERROR_DEVICE_LOST                                    = 0xFFFFFFFC, // -4
-    VK_ERROR_MEMORY_MAP_FAILED                              = 0xFFFFFFFB, // -5
-    VK_ERROR_LAYER_NOT_PRESENT                              = 0xFFFFFFFA, // -6
-    VK_ERROR_EXTENSION_NOT_PRESENT                          = 0xFFFFFFF9, // -7
-    VK_ERROR_FEATURE_NOT_PRESENT                            = 0xFFFFFFF8, // -8
-    VK_ERROR_INCOMPATIBLE_DRIVER                            = 0xFFFFFFF7, // -9
-    VK_ERROR_TOO_MANY_OBJECTS                               = 0xFFFFFFF6, // -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
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_ERROR_OUT_OF_DATE_KHR                                = 0xC4653214, // -1000001004
-
-    //@extension("VK_KHR_display_swapchain") // 4
-    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR                       = 0xC4652A47, // -1000003001
-
-    //@extension("VK_EXT_debug_report") // 12
-    VK_ERROR_VALIDATION_FAILED_EXT                          = 0xC4650B07, // -1000011001
-
-    //@extension("VK_NV_glsl_shader") // 13
-    VK_ERROR_INVALID_SHADER_NV                              = 0xC4650720, // -1000012000
-
-    //@extension("VK_KHR_maintenance1") // 70
-    VK_ERROR_OUT_OF_POOL_MEMORY_KHR                         = 0xC4642878, // -1000069000
-
-    //@extension("VK_KHR_external_memory") // 73
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR                    = 0xC4641CBD, // -1000072003
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT   = 0xC462CCD0, // -1000158000
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_ERROR_FRAGMENTATION_EXT                              = 0xc462c118, // -1000161000
-
-    //@extension("VK_EXT_global_priority") // 175
-    VK_ERROR_NOT_PERMITTED_EXT                              = 0xC4628E4F, // -1000174001
-}
-
-enum VkDynamicState {
-    VK_DYNAMIC_STATE_VIEWPORT                               = 0x00000000,
-    VK_DYNAMIC_STATE_SCISSOR                                = 0x00000001,
-    VK_DYNAMIC_STATE_LINE_WIDTH                             = 0x00000002,
-    VK_DYNAMIC_STATE_DEPTH_BIAS                             = 0x00000003,
-    VK_DYNAMIC_STATE_BLEND_CONSTANTS                        = 0x00000004,
-    VK_DYNAMIC_STATE_DEPTH_BOUNDS                           = 0x00000005,
-    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK                   = 0x00000006,
-    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK                     = 0x00000007,
-    VK_DYNAMIC_STATE_STENCIL_REFERENCE                      = 0x00000008,
-
-    //@extension("VK_NV_clip_space_w_scaling") // 88
-    VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV                  = 1000087000,
-
-    //@extension("VK_EXT_discard_rectangles") // 100
-    VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT                  = 1000099000,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT                   = 1000143000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV       = 1000164004,
-    VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV        = 1000164006,
-
-    //@extension("VK_NV_scissor_exclusive") // 206
-    VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV                   = 1000205001,
-}
-
-enum VkObjectType {
-    VK_OBJECT_TYPE_UNKNOWN                                  = 0,
-    VK_OBJECT_TYPE_INSTANCE                                 = 1,
-    VK_OBJECT_TYPE_PHYSICAL_DEVICE                          = 2,
-    VK_OBJECT_TYPE_DEVICE                                   = 3,
-    VK_OBJECT_TYPE_QUEUE                                    = 4,
-    VK_OBJECT_TYPE_SEMAPHORE                                = 5,
-    VK_OBJECT_TYPE_COMMAND_BUFFER                           = 6,
-    VK_OBJECT_TYPE_FENCE                                    = 7,
-    VK_OBJECT_TYPE_DEVICE_MEMORY                            = 8,
-    VK_OBJECT_TYPE_BUFFER                                   = 9,
-    VK_OBJECT_TYPE_IMAGE                                    = 10,
-    VK_OBJECT_TYPE_EVENT                                    = 11,
-    VK_OBJECT_TYPE_QUERY_POOL                               = 12,
-    VK_OBJECT_TYPE_BUFFER_VIEW                              = 13,
-    VK_OBJECT_TYPE_IMAGE_VIEW                               = 14,
-    VK_OBJECT_TYPE_SHADER_MODULE                            = 15,
-    VK_OBJECT_TYPE_PIPELINE_CACHE                           = 16,
-    VK_OBJECT_TYPE_PIPELINE_LAYOUT                          = 17,
-    VK_OBJECT_TYPE_RENDER_PASS                              = 18,
-    VK_OBJECT_TYPE_PIPELINE                                 = 19,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT                    = 20,
-    VK_OBJECT_TYPE_SAMPLER                                  = 21,
-    VK_OBJECT_TYPE_DESCRIPTOR_POOL                          = 22,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET                           = 23,
-    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,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_OBJECT_TYPE_SWAPCHAIN_KHR                            = 1000001000,
-
-    //@extension("VK_KHR_display") // 3
-    VK_OBJECT_TYPE_DISPLAY_KHR                              = 1000002000,
-    VK_OBJECT_TYPE_DISPLAY_MODE_KHR                         = 1000002001,
-
-    //@extension("VK_KHR_debug_report") // 12
-    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT                = 1000011000,
-
-    //@extension("VK_KHR_descriptor_update_template") // 86
-    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR           = 1000085000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_OBJECT_TYPE_OBJECT_TABLE_NVX                         = 1000086000,
-    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX             = 1000086001,
-
-    //@extension("VK_EXT_debug_utils") // 129
-    VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT                = 1000128000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR             = 1000156000,
-
-    //@extension("VK_EXT_validation_cache") // 161
-    VK_OBJECT_TYPE_VALIDATION_CACHE_EXT                     = 1000160000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV                = 1000165000,
-}
-
-
-//@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,
-}
-
-enum VkVendorId {
-    VK_VENDOR_ID_VIV                                        = 0x10001,
-    VK_VENDOR_ID_VSI                                        = 0x10002,
-    VK_VENDOR_ID_KAZAN                                      = 0x10003,
-}
-
-@extension("VK_KHR_surface") // 1
-enum VkPresentModeKHR {
-    VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
-    VK_PRESENT_MODE_MAILBOX_KHR                             = 0x00000001,
-    VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
-    VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR               = 1000111000,
-    VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR           = 1000111001,
-}
-
-@extension("VK_KHR_surface") // 1
-enum VkColorSpaceKHR {
-    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR                       = 0x00000000,
-
-    //@extension("VK_EXT_swapchain_colorspace") // 105
-    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT                 = 1000104001,
-    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT                 = 1000104002,
-    VK_COLOR_SPACE_DCI_P3_LINEAR_EXT                        = 1000104003,
-    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT                     = 1000104004,
-    VK_COLOR_SPACE_BT709_LINEAR_EXT                         = 1000104005,
-    VK_COLOR_SPACE_BT709_NONLINEAR_EXT                      = 1000104006,
-    VK_COLOR_SPACE_BT2020_LINEAR_EXT                        = 1000104007,
-    VK_COLOR_SPACE_HDR10_ST2084_EXT                         = 1000104008,
-    VK_COLOR_SPACE_DOLBYVISION_EXT                          = 1000104009,
-    VK_COLOR_SPACE_HDR10_HLG_EXT                            = 1000104010,
-    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT                      = 1000104011,
-    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT                   = 1000104012,
-    VK_COLOR_SPACE_PASS_THROUGH_EXT                         = 1000104013,
-    VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT              = 1000104014,
-}
-
-@extension("VK_EXT_debug_report") // 12
-enum VkDebugReportObjectTypeEXT {
-    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT                 = 0,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT                = 1,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT         = 2,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT                  = 3,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT                   = 4,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT               = 5,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT          = 6,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT                   = 7,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT           = 8,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT                  = 9,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT                   = 10,
-    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT                   = 11,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT              = 12,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT             = 13,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT              = 14,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT           = 15,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT          = 16,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT         = 17,
-    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT             = 18,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT                = 19,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT   = 20,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT                 = 21,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT         = 22,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT          = 23,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT             = 24,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT            = 25,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT             = 26,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT           = 27,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT             = 29,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT        = 30,
-    VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT        = 31,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
-
-    //extension("VK_EXT_validation_cache") // 161
-    VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT    = 33,
-
-    //extension("VK_KHR_descriptor_update_template") // 86
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT   = 1000165000,
-}
-
-@extension("VK_AMD_rasterization_order") // 19
-enum VkRasterizationOrderAMD {
-    VK_RASTERIZATION_ORDER_STRICT_AMD                       = 0,
-    VK_RASTERIZATION_ORDER_RELAXED_AMD                      = 1,
-}
-
-@extension("VK_AMD_shader_info") // 43
-enum VkShaderInfoTypeAMD {
-    VK_SHADER_INFO_TYPE_STATISTICS_AMD                      = 0,
-    VK_SHADER_INFO_TYPE_BINARY_AMD                          = 1,
-    VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD                     = 2,
-}
-
-@extension("VK_EXT_validation_flags") // 62
-enum VkValidationCheckEXT {
-    VK_VALIDATION_CHECK_ALL_EXT                             = 0,
-    VK_VALIDATION_CHECK_SHADERS_EXT                         = 1,
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-enum VkDescriptorUpdateTemplateTypeKHR {
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR   = 0,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX            = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX      = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX        = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX       = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX       = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX        = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX                = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX            = 7,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-enum VkObjectEntryTypeNVX {
-    VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX                 = 0,
-    VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX                       = 1,
-    VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX                   = 2,
-    VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX                  = 3,
-    VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX                  = 4,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDisplayPowerStateEXT {
-    VK_DISPLAY_POWER_STATE_OFF_EXT                          = 0,
-    VK_DISPLAY_POWER_STATE_SUSPEND_EXT                      = 1,
-    VK_DISPLAY_POWER_STATE_ON_EXT                           = 2,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDeviceEventTypeEXT {
-    VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT                = 0,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDisplayEventTypeEXT {
-    VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT               = 0,
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-enum VkViewportCoordinateSwizzleNV {
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV            = 0,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV            = 1,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV            = 2,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV            = 3,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV            = 4,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV            = 5,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV            = 6,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV            = 7,
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-enum VkDiscardRectangleModeEXT {
-    VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
-    VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-enum VkConservativeRasterizationModeEXT {
-    VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT         = 0,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT     = 1,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT    = 2,
-}
-
-@extension("VK_KHR_maintenance2") // 118
-enum VkPointClippingBehaviorKHR {
-    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR          = 0,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR    = 1,
-}
-
-@extension("VK_KHR_maintenance2") // 118
-enum VkTessellationDomainOriginKHR {
-    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR            = 0,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR            = 1,
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-enum VkSamplerReductionModeEXT {
-    VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT          = 0,
-    VK_SAMPLER_REDUCTION_MODE_MIN_EXT                       = 1,
-    VK_SAMPLER_REDUCTION_MODE_MAX_EXT                       = 2,
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-enum VkBlendOverlapEXT {
-    VK_BLEND_OVERLAP_UNCORRELATED_EXT                       = 0,
-    VK_BLEND_OVERLAP_DISJOINT_EXT                           = 1,
-    VK_BLEND_OVERLAP_CONJOINT_EXT                           = 2,
-}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-enum VkCoverageModulationModeNV {
-    VK_COVERAGE_MODULATION_MODE_NONE_NV                     = 0,
-    VK_COVERAGE_MODULATION_MODE_RGB_NV                      = 1,
-    VK_COVERAGE_MODULATION_MODE_ALPHA_NV                    = 2,
-    VK_COVERAGE_MODULATION_MODE_RGBA_NV                     = 3,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-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,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-enum VkSamplerYcbcrRangeKHR {
-    VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR                     = 0,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR                   = 1,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-enum VkChromaLocationKHR {
-    VK_CHROMA_LOCATION_COSITED_EVEN_KHR                     = 0,
-    VK_CHROMA_LOCATION_MIDPOINT_KHR                         = 1,
-}
-
-@extension("VK_EXT_validation_cache") // 161
-enum VkValidationCacheHeaderVersionEXT {
-    VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT              = 1,
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-enum VkShadingRatePaletteEntryNV {
-    VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV                 = 0,
-    VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV       = 1,
-    VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV        = 2,
-    VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV        = 3,
-    VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV        = 4,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV         = 5,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV    = 6,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV    = 7,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV    = 8,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV    = 9,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV    = 10,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV    = 11,
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-enum VkCoarseSampleOrderTypeNV {
-    VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV                  = 0,
-    VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV                   = 1,
-    VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV              = 2,
-    VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV             = 3,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkRayTracingShaderGroupTypeNV {
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV                 = 0,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV     = 1,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV    = 2,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkGeometryTypeNV {
-    VK_GEOMETRY_TYPE_TRIANGLES_NV                           = 0,
-    VK_GEOMETRY_TYPE_AABBS_NV                               = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkAccelerationStructureTypeNV {
-    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV             = 0,
-    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV          = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkCopyAccelerationStructureModeNV {
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV            = 0,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV          = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkAccelerationStructureMemoryRequirementsTypeNV {
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV            = 0,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV     = 1,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV    = 2,
-}
-
-@extension("VK_EXT_global_priority") // 175
-enum VkQueueGlobalPriorityEXT {
-    VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT                        = 128,
-    VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT                     = 256,
-    VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT                       = 512,
-    VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT                   = 1024,
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-enum VkTimeDomainEXT {
-    VK_TIME_DOMAIN_DEVICE_EXT                               = 0,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT                      = 1,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT                  = 2,
-    VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT            = 3,
-}
-
-@extension("VK_AMD_memory_overallocation_behavior") // 190
-enum VkMemoryOverallocationBehaviorAMD {
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD           = 0,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD           = 1,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD        = 2,
-}
-
-@extension("VK_KHR_driver_properties") // 197
-enum VkDriverIdKHR {
-    VK_DRIVER_ID_AMD_PROPRIETARY_KHR                        = 1,
-    VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR                        = 2,
-    VK_DRIVER_ID_MESA_RADV_KHR                              = 3,
-    VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR                     = 4,
-    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR              = 5,
-    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR                 = 6,
-    VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR                = 7,
-    VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR                   = 8,
-    VK_DRIVER_ID_ARM_PROPRIETARY_KHR                        = 9,
-    VK_DRIVER_ID_GOOGLE_PASTEL_KHR                          = 10,
-}
-
-/////////////////
-//  Bitfields  //
-/////////////////
-
-/// Queue capabilities
-type VkFlags VkQueueFlags
-bitfield VkQueueFlagBits {
-    VK_QUEUE_GRAPHICS_BIT                                   = 0x00000001,    /// Queue supports graphics operations
-    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().
-type VkFlags VkMemoryPropertyFlags
-bitfield VkMemoryPropertyFlagBits {
-    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT                     = 0x00000001,
-    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT                     = 0x00000002,
-    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
-type VkFlags VkMemoryHeapFlags
-bitfield VkMemoryHeapFlagBits {
-    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT                         = 0x00000001,
-
-    //@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
-type VkFlags VkAccessFlags
-bitfield VkAccessFlagBits {
-    VK_ACCESS_INDIRECT_COMMAND_READ_BIT                     = 0x00000001,
-    VK_ACCESS_INDEX_READ_BIT                                = 0x00000002,
-    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT                     = 0x00000004,
-    VK_ACCESS_UNIFORM_READ_BIT                              = 0x00000008,
-    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT                     = 0x00000010,
-    VK_ACCESS_SHADER_READ_BIT                               = 0x00000020,
-    VK_ACCESS_SHADER_WRITE_BIT                              = 0x00000040,
-    VK_ACCESS_COLOR_ATTACHMENT_READ_BIT                     = 0x00000080,
-    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT                    = 0x00000100,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT             = 0x00000200,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT            = 0x00000400,
-    VK_ACCESS_TRANSFER_READ_BIT                             = 0x00000800,
-    VK_ACCESS_TRANSFER_WRITE_BIT                            = 0x00001000,
-    VK_ACCESS_HOST_READ_BIT                                 = 0x00002000,
-    VK_ACCESS_HOST_WRITE_BIT                                = 0x00004000,
-    VK_ACCESS_MEMORY_READ_BIT                               = 0x00008000,
-    VK_ACCESS_MEMORY_WRITE_BIT                              = 0x00010000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX                  = 0x00020000,
-    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX                 = 0x00040000,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT     = 0x00080000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT            = 0x00100000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV                = 0x00800000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV            = 0x00200000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV           = 0x00400000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT             = 0x01000000,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT              = 0x02000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT       = 0x04000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT      = 0x08000000,
-}
-
-/// Buffer usage flags
-type VkFlags VkBufferUsageFlags
-bitfield VkBufferUsageFlagBits {
-    VK_BUFFER_USAGE_TRANSFER_SRC_BIT                        = 0x00000001,    /// Can be used as a source of transfer operations
-    VK_BUFFER_USAGE_TRANSFER_DST_BIT                        = 0x00000002,    /// Can be used as a destination of transfer operations
-    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT                = 0x00000004,    /// Can be used as TBO
-    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT                = 0x00000008,    /// Can be used as IBO
-    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT                      = 0x00000010,    /// Can be used as UBO
-    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT                      = 0x00000020,    /// Can be used as SSBO
-    VK_BUFFER_USAGE_INDEX_BUFFER_BIT                        = 0x00000040,    /// Can be used as source of fixed function index fetch (index buffer)
-    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT                       = 0x00000080,    /// Can be used as source of fixed function vertex fetch (VBO)
-    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT                     = 0x00000100,    /// Can be the source of indirect parameters (e.g. indirect buffer, parameter buffer)
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT           = 0x00000200,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_BUFFER_USAGE_RAY_TRACING_BIT_NV                      = 0x00000400,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT           = 0x00000800,
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT   = 0x00001000,
-}
-
-/// Buffer creation flags
-type VkFlags VkBufferCreateFlags
-bitfield VkBufferCreateFlagBits {
-    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
-type VkFlags VkShaderStageFlags
-bitfield VkShaderStageFlagBits {
-    VK_SHADER_STAGE_VERTEX_BIT                              = 0x00000001,
-    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT                = 0x00000002,
-    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT             = 0x00000004,
-    VK_SHADER_STAGE_GEOMETRY_BIT                            = 0x00000008,
-    VK_SHADER_STAGE_FRAGMENT_BIT                            = 0x00000010,
-    VK_SHADER_STAGE_COMPUTE_BIT                             = 0x00000020,
-    VK_SHADER_STAGE_ALL_GRAPHICS                            = 0x0000001F,
-
-    VK_SHADER_STAGE_ALL                                     = 0x7FFFFFFF,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_SHADER_STAGE_RAYGEN_BIT_NV                           = 0x00000100,
-    VK_SHADER_STAGE_ANY_HIT_BIT_NV                          = 0x00000200,
-    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV                      = 0x00000400,
-    VK_SHADER_STAGE_MISS_BIT_NV                             = 0x00000800,
-    VK_SHADER_STAGE_INTERSECTION_BIT_NV                     = 0x00001000,
-    VK_SHADER_STAGE_CALLABLE_BIT_NV                         = 0x00002000,
-
-    //@extension("VK_NV_mesh_shader") // 203
-    VK_SHADER_STAGE_TASK_BIT_NV                             = 0x00000040,
-    VK_SHADER_STAGE_MESH_BIT_NV                             = 0x00000080,
-}
-
-/// Descriptor pool create flags
-type VkFlags VkDescriptorPoolCreateFlags
-bitfield VkDescriptorPoolCreateFlagBits {
-    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT       = 0x00000001,
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT     = 0x00000002,
-}
-
-/// Descriptor pool reset flags
-type VkFlags VkDescriptorPoolResetFlags
-//bitfield VkDescriptorPoolResetFlagBits {
-//}
-
-/// Image usage flags
-type VkFlags VkImageUsageFlags
-bitfield VkImageUsageFlagBits {
-    VK_IMAGE_USAGE_TRANSFER_SRC_BIT                         = 0x00000001,    /// Can be used as a source of transfer operations
-    VK_IMAGE_USAGE_TRANSFER_DST_BIT                         = 0x00000002,    /// Can be used as a destination of transfer operations
-    VK_IMAGE_USAGE_SAMPLED_BIT                              = 0x00000004,    /// Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
-    VK_IMAGE_USAGE_STORAGE_BIT                              = 0x00000008,    /// Can be used as storage image (STORAGE_IMAGE descriptor type)
-    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT                     = 0x00000010,    /// Can be used as framebuffer color attachment
-    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT             = 0x00000020,    /// Can be used as framebuffer depth/stencil attachment
-    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,    /// Image data not needed outside of rendering
-    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT                     = 0x00000080,    /// Can be used as framebuffer input attachment
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV                = 0x00000100,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT             = 0x00000200,
-}
-
-/// Image creation flags
-type VkFlags VkImageCreateFlags
-bitfield VkImageCreateFlagBits {
-    VK_IMAGE_CREATE_SPARSE_BINDING_BIT                      = 0x00000001,    /// Image should support sparse backing
-    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT                    = 0x00000002,    /// Image should support sparse backing with partial residency
-    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT                      = 0x00000004,    /// Image should support constent data access to physical memory blocks mapped into multiple locations of sparse images
-    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_SPLIT_INSTANCE_BIND_REGIONS_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_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,
-    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR                  = 0x00000100,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_IMAGE_CREATE_DISJOINT_BIT_KHR                        = 0x00000200,
-
-    //@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,
-
-    //@extension("VK_NV_corner_sampled_image") // 51
-    VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV                   = 0x00002000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT                      = 0x00004000,
-}
-
-/// Image view creation flags
-type VkFlags VkImageViewCreateFlags
-bitfield VkImageViewCreateFlagBits {
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT   = 0x00000001,
-}
-
-/// Pipeline creation flags
-type VkFlags VkPipelineCreateFlags
-bitfield VkPipelineCreateFlagBits {
-    VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT             = 0x00000001,
-    VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT                = 0x00000002,
-    VK_PIPELINE_CREATE_DERIVATIVE_BIT                       = 0x00000004,
-
-    //@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,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV                 = 0x00000020,
-}
-
-/// Color component flags
-type VkFlags VkColorComponentFlags
-bitfield VkColorComponentFlagBits {
-    VK_COLOR_COMPONENT_R_BIT                                = 0x00000001,
-    VK_COLOR_COMPONENT_G_BIT                                = 0x00000002,
-    VK_COLOR_COMPONENT_B_BIT                                = 0x00000004,
-    VK_COLOR_COMPONENT_A_BIT                                = 0x00000008,
-}
-
-/// Fence creation flags
-type VkFlags VkFenceCreateFlags
-bitfield VkFenceCreateFlagBits {
-    VK_FENCE_CREATE_SIGNALED_BIT                            = 0x00000001,
-}
-
-/// Semaphore creation flags
-type VkFlags VkSemaphoreCreateFlags
-//bitfield VkSemaphoreCreateFlagBits {
-//}
-
-/// Format capability flags
-type VkFlags VkFormatFeatureFlags
-bitfield VkFormatFeatureFlagBits {
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT                     = 0x00000001,    /// Format can be used for sampled images (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT                     = 0x00000002,    /// Format can be used for storage images (STORAGE_IMAGE descriptor type)
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT              = 0x00000004,    /// Format supports atomic operations in case it's used for storage images
-    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT              = 0x00000008,    /// Format can be used for uniform texel buffers (TBOs)
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT              = 0x00000010,    /// Format can be used for storage texel buffers (IBOs)
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT       = 0x00000020,    /// Format supports atomic operations in case it's used for storage texel buffers
-    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT                     = 0x00000040,    /// Format can be used for vertex buffers (VBOs)
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT                  = 0x00000080,    /// Format can be used for color attachment images
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT            = 0x00000100,    /// Format supports blending in case it's used for color attachment images
-    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT          = 0x00000200,    /// Format can be used for depth/stencil attachment images
-    VK_FORMAT_FEATURE_BLIT_SRC_BIT                          = 0x00000400,    /// Format can be used as the source image of blits with vkCommandBlitImage
-    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,
-
-    //@extension("VK_KHR_maintenance1") // 70
-    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR                  = 0x00004000,
-    VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR                  = 0x00008000,
-
-    //@extension("VK_EXT_sampler_filter_minmax") // 131
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT   = 0x00010000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    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,
-}
-
-/// Query control flags
-type VkFlags VkQueryControlFlags
-bitfield VkQueryControlFlagBits {
-    VK_QUERY_CONTROL_PRECISE_BIT                            = 0x00000001,
-}
-
-/// Query result flags
-type VkFlags VkQueryResultFlags
-bitfield VkQueryResultFlagBits {
-    VK_QUERY_RESULT_64_BIT                                  = 0x00000001,   /// Results of the queries are written to the destination buffer as 64-bit values
-    VK_QUERY_RESULT_WAIT_BIT                                = 0x00000002,   /// Results of the queries are waited on before proceeding with the result copy
-    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT                   = 0x00000004,   /// Besides the results of the query, the availability of the results is also written
-    VK_QUERY_RESULT_PARTIAL_BIT                             = 0x00000008,   /// Copy the partial results of the query even if the final results aren't available
-}
-
-/// Shader module creation flags
-type VkFlags VkShaderModuleCreateFlags
-//bitfield VkShaderModuleCreateFlagBits {
-//}
-
-/// Event creation flags
-type VkFlags VkEventCreateFlags
-//bitfield VkEventCreateFlagBits {
-//}
-
-/// Command buffer usage flags
-type VkFlags VkCommandBufferUsageFlags
-bitfield VkCommandBufferUsageFlagBits {
-    VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT             = 0x00000001,
-    VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT        = 0x00000002,
-    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT            = 0x00000004,
-}
-
-/// Pipeline statistics flags
-type VkFlags VkQueryPipelineStatisticFlags
-bitfield VkQueryPipelineStatisticFlagBits {
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT                     = 0x00000001,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT                   = 0x00000002,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT                   = 0x00000004,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT                 = 0x00000008,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT                  = 0x00000010,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT                        = 0x00000020,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT                         = 0x00000040,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT                 = 0x00000080,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT         = 0x00000100,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT  = 0x00000200,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT                  = 0x00000400,  /// Optional
-}
-
-/// Memory mapping flags
-type VkFlags VkMemoryMapFlags
-//bitfield VkMemoryMapFlagBits {
-//}
-
-/// Bitfield of image aspects
-type VkFlags VkImageAspectFlags
-bitfield VkImageAspectFlagBits {
-    VK_IMAGE_ASPECT_COLOR_BIT                               = 0x00000001,
-    VK_IMAGE_ASPECT_DEPTH_BIT                               = 0x00000002,
-    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,
-    VK_IMAGE_ASPECT_PLANE_2_BIT_KHR                         = 0x00000040,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT                  = 0x00000080,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT                  = 0x00000100,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT                  = 0x00000200,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT                  = 0x00000400,
-}
-
-/// Sparse memory bind flags
-type VkFlags VkSparseMemoryBindFlags
-bitfield VkSparseMemoryBindFlagBits {
-    VK_SPARSE_MEMORY_BIND_METADATA_BIT                      = 0x00000001,
-}
-
-/// Sparse image memory requirements flags
-type VkFlags VkSparseImageFormatFlags
-bitfield VkSparseImageFormatFlagBits {
-    VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT                  = 0x00000001,  /// Image uses a single miptail region for all array slices
-    VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT                = 0x00000002,  /// Image requires mip levels to be an exact multiple of the sparse iamge block size for non-mip-tail levels.
-    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT          = 0x00000004,  /// Image uses a non-standard sparse block size
-}
-
-/// Pipeline stages
-type VkFlags VkPipelineStageFlags
-bitfield VkPipelineStageFlagBits {
-    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT                       = 0x00000001,  /// Before subsequent commands are processed
-    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT                     = 0x00000002,  /// Draw/DispatchIndirect command fetch
-    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT                      = 0x00000004,  /// Vertex/index fetch
-    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT                     = 0x00000008,  /// Vertex shading
-    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT       = 0x00000010,  /// Tessellation control shading
-    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT    = 0x00000020,  /// Tessellation evaluation shading
-    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT                   = 0x00000040,  /// Geometry shading
-    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT                   = 0x00000080,  /// Fragment shading
-    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT              = 0x00000100,  /// Early fragment (depth/stencil) tests
-    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT               = 0x00000200,  /// Late fragment (depth/stencil) tests
-    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT           = 0x00000400,  /// Color attachment writes
-    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT                    = 0x00000800,  /// Compute shading
-    VK_PIPELINE_STAGE_TRANSFER_BIT                          = 0x00001000,  /// Transfer/copy operations
-    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT                    = 0x00002000,
-    VK_PIPELINE_STAGE_HOST_BIT                              = 0x00004000,  /// Indicates host (CPU) is a source/sink of the dependency
-
-    VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT                      = 0x00008000,  /// All stages of the graphics pipeline
-    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT                      = 0x00010000,  /// All graphics, compute, copy, and transition commands
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX               = 0x00020000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT         = 0x00040000,
-
-    //@extension("VK_NV_mesh_shader") // 203
-    VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV                    = 0x00080000,
-    VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV                    = 0x00100000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_STAGE_RAY_TRACING_BIT_NV                    = 0x00200000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV             = 0x00400000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT      = 0x00800000,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT            = 0x01000000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV   = 0x02000000,
-}
-
-/// Render pass attachment description flags
-type VkFlags VkAttachmentDescriptionFlags
-bitfield VkAttachmentDescriptionFlagBits {
-    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT                 = 0x00000001,  /// The attachment may alias physical memory of another attachment in the same renderpass
-}
-
-/// Subpass description flags
-type VkFlags VkSubpassDescriptionFlags
-bitfield VkSubpassDescriptionFlagBits {
-    //@extension("VK_NVX_multiview_per_view_attributes") // 98
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX      = 0x00000001,
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
-}
-
-/// Command pool creation flags
-type VkFlags VkCommandPoolCreateFlags
-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
-type VkFlags VkCommandPoolResetFlags
-bitfield VkCommandPoolResetFlagBits {
-    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT             = 0x00000001,  /// Release resources owned by the pool
-}
-
-type VkFlags VkCommandBufferResetFlags
-bitfield VkCommandBufferResetFlagBits {
-    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT           = 0x00000001,  /// Release resources owned by the buffer
-}
-
-type VkFlags VkSampleCountFlags
-bitfield VkSampleCountFlagBits {
-    VK_SAMPLE_COUNT_1_BIT                                   = 0x00000001,
-    VK_SAMPLE_COUNT_2_BIT                                   = 0x00000002,
-    VK_SAMPLE_COUNT_4_BIT                                   = 0x00000004,
-    VK_SAMPLE_COUNT_8_BIT                                   = 0x00000008,
-    VK_SAMPLE_COUNT_16_BIT                                  = 0x00000010,
-    VK_SAMPLE_COUNT_32_BIT                                  = 0x00000020,
-    VK_SAMPLE_COUNT_64_BIT                                  = 0x00000040,
-}
-
-type VkFlags VkStencilFaceFlags
-bitfield VkStencilFaceFlagBits {
-    VK_STENCIL_FACE_FRONT_BIT                               = 0x00000001,   /// Front face
-    VK_STENCIL_FACE_BACK_BIT                                = 0x00000002,   /// Back face
-    VK_STENCIL_FRONT_AND_BACK                               = 0x00000003,
-}
-
-/// Instance creation flags
-type VkFlags VkInstanceCreateFlags
-//bitfield VkInstanceCreateFlagBits {
-//}
-
-/// Device creation flags
-type VkFlags VkDeviceCreateFlags
-//bitfield VkDeviceCreateFlagBits {
-//}
-
-/// Device queue creation flags
-type VkFlags VkDeviceQueueCreateFlags
-@vulkan1_1
-bitfield VkDeviceQueueCreateFlagBits {
-    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT                    = 0x00000001,
-}
-
-/// Query pool creation flags
-type VkFlags VkQueryPoolCreateFlags
-//bitfield VkQueryPoolCreateFlagBits {
-//}
-
-/// Buffer view creation flags
-type VkFlags VkBufferViewCreateFlags
-//bitfield VkBufferViewCreateFlagBits {
-//}
-
-/// Pipeline cache creation flags
-type VkFlags VkPipelineCacheCreateFlags
-//bitfield VkPipelineCacheCreateFlagBits {
-//}
-
-/// Pipeline shader stage creation flags
-type VkFlags VkPipelineShaderStageCreateFlags
-//bitfield VkPipelineShaderStageCreateFlagBits {
-//}
-
-/// Descriptor set layout creation flags
-type VkFlags VkDescriptorSetLayoutCreateFlags
-bitfield VkDescriptorSetLayoutCreateFlagBits {
-    //@extension("VK_KHR_push_descriptor") // 81
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR     = 0x00000001,
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT  = 0x00000002,
-}
-
-/// Pipeline vertex input state creation flags
-type VkFlags VkPipelineVertexInputStateCreateFlags
-//bitfield VkPipelineVertexInputStateCreateFlagBits {
-//}
-
-/// Pipeline input assembly state creation flags
-type VkFlags VkPipelineInputAssemblyStateCreateFlags
-//bitfield VkPipelineInputAssemblyStateCreateFlagBits {
-//}
-
-/// Tessellation state creation flags
-type VkFlags VkPipelineTessellationStateCreateFlags
-//bitfield VkPipelineTessellationStateCreateFlagBits {
-//}
-
-/// Viewport state creation flags
-type VkFlags VkPipelineViewportStateCreateFlags
-//bitfield VkPipelineViewportStateCreateFlagBits {
-//}
-
-/// Rasterization state creation flags
-type VkFlags VkPipelineRasterizationStateCreateFlags
-//bitfield VkPipelineRasterizationStateCreateFlagBits {
-//}
-
-/// Multisample state creation flags
-type VkFlags VkPipelineMultisampleStateCreateFlags
-//bitfield VkPipelineMultisampleStateCreateFlagBits {
-//}
-
-/// Color blend state creation flags
-type VkFlags VkPipelineColorBlendStateCreateFlags
-//bitfield VkPipelineColorBlendStateCreateFlagBits {
-//}
-
-/// Depth/stencil state creation flags
-type VkFlags VkPipelineDepthStencilStateCreateFlags
-//bitfield VkPipelineDepthStencilStateCreateFlagBits {
-//}
-
-/// Dynamic state creation flags
-type VkFlags VkPipelineDynamicStateCreateFlags
-//bitfield VkPipelineDynamicStateCreateFlagBits {
-//}
-
-/// Pipeline layout creation flags
-type VkFlags VkPipelineLayoutCreateFlags
-//bitfield VkPipelineLayoutCreateFlagBits {
-//}
-
-/// Sampler creation flags
-type VkFlags VkSamplerCreateFlags
-bitfield VkSamplerCreateFlagBits {
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT                        = 0x00000001,
-    VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT  = 0x00000002,
-}
-
-/// Render pass creation flags
-type VkFlags VkRenderPassCreateFlags
-//bitfield VkRenderPassCreateFlagBits {
-//}
-
-/// Framebuffer creation flags
-type VkFlags VkFramebufferCreateFlags
-//bitfield VkFramebufferCreateFlagBits {
-//}
-
-/// Dependency flags
-type VkFlags VkDependencyFlags
-bitfield VkDependencyFlagBits {
-    VK_DEPENDENCY_BY_REGION_BIT                             = 0x00000001,
-
-    //@vulkan1_1
-    VK_DEPENDENCY_DEVICE_GROUP_BIT                          = 0x00000004,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT                            = 0x00000002,
-
-    //@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
-type VkFlags VkCullModeFlags
-bitfield VkCullModeFlagBits {
-    VK_CULL_MODE_NONE                                       = 0x00000000,
-    VK_CULL_MODE_FRONT_BIT                                  = 0x00000001,
-    VK_CULL_MODE_BACK_BIT                                   = 0x00000002,
-    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,
-
-    //@extension("VK_NV_shader_subgroup_partitioned") // 199
-    VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV                  = 0x00000100,
-}
-
-/// 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,
-
-    //@extension("VK_EXT_external_memory_host") // 179
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT              = 0x00000080,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT   = 0x00000100,
-
-    //@extension("VK_EXT_external_memory_dma_buf") // 126
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT                      = 0x00000200,
-
-    //@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID  = 0x00000400,
-}
-
-/// 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
-bitfield VkSurfaceTransformFlagBitsKHR {
-    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR                       = 0x00000001,
-    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR                      = 0x00000002,
-    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR                     = 0x00000004,
-    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR                     = 0x00000008,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR              = 0x00000010,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR    = 0x00000020,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR   = 0x00000040,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR   = 0x00000080,
-    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR                        = 0x00000100,
-}
-
-@extension("VK_KHR_surface") // 1
-type VkFlags VkCompositeAlphaFlagsKHR
-@extension("VK_KHR_surface") // 1
-bitfield VkCompositeAlphaFlagBitsKHR {
-    VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR                       = 0x00000001,
-    VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR               = 0x00000002,
-    VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR              = 0x00000004,
-    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR                      = 0x00000008,
-}
-
-@extension("VK_KHR_swapchain") // 2
-type VkFlags VkSwapchainCreateFlagsKHR
-@extension("VK_KHR_swapchain") // 2
-bitfield VkSwapchainCreateFlagBitsKHR {
-    //@vulkan1_1
-    VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
-    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR                   = 0x00000002,
-
-    //@extension("VK_KHR_swapchain_mutable_format") // 201
-    VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR              = 0x00000004,
-}
-
-@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
-type VkFlags VkDisplayPlaneAlphaFlagsKHR
-@extension("VK_KHR_display") // 3
-bitfield VkDisplayPlaneAlphaFlagBitsKHR {
-    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR                   = 0x00000001,
-    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR                   = 0x00000002,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR                = 0x00000004,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR  = 0x00000008,
-}
-
-@extension("VK_KHR_display") // 3
-type VkFlags VkDisplaySurfaceCreateFlagsKHR
-//@extension("VK_KHR_display") // 3
-//bitfield VkDisplaySurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_display") // 3
-type VkFlags VkDisplayModeCreateFlagsKHR
-//@extension("VK_KHR_display") // 3
-//bitfield VkDisplayModeCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_xlib_surface") // 5
-type VkFlags VkXlibSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xlib_surface") // 5
-//bitfield VkXlibSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_xcb_surface") // 6
-type VkFlags VkXcbSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xcb_surface") // 6
-//bitfield VkXcbSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_wayland_surface") // 7
-type VkFlags VkWaylandSurfaceCreateFlagsKHR
-//@extension("VK_KHR_wayland_surface") // 7
-//bitfield VkWaylandSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_android_surface") // 9
-type VkFlags VkAndroidSurfaceCreateFlagsKHR
-//@extension("VK_KHR_android_surface") // 9
-//bitfield VkAndroidSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_win32_surface") // 10
-type VkFlags VkWin32SurfaceCreateFlagsKHR
-//@extension("VK_KHR_win32_surface") // 10
-//bitfield VkWin32SurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_ANDROID_native_buffer") // 11
-type VkFlags VkSwapchainImageUsageFlagsANDROID
-@extension("VK_ANDROID_native_buffer") // 11
-bitfield VkSwapchainImageUsageFlagBitsANDROID {
-    VK_SWAPCHAIN_IMAGE_USAGE_FLAGS_SHARED_BIT_ANDROID = 0x00000001,
-}
-
-@extension("VK_EXT_debug_report") // 12
-type VkFlags VkDebugReportFlagsEXT
-@extension("VK_EXT_debug_report") // 12
-bitfield VkDebugReportFlagBitsEXT {
-    VK_DEBUG_REPORT_INFORMATION_BIT_EXT                     = 0x00000001,
-    VK_DEBUG_REPORT_WARNING_BIT_EXT                         = 0x00000002,
-    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT             = 0x00000004,
-    VK_DEBUG_REPORT_ERROR_BIT_EXT                           = 0x00000008,
-    VK_DEBUG_REPORT_DEBUG_BIT_EXT                           = 0x00000010,
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-type VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT
-//@extension("VK_EXT_transform_feedback") // 29
-//bitfield VkPipelineRasterizationStateStreamCreateFlagBitsEXT {
-//}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-type VkFlags VkExternalMemoryHandleTypeFlagsNV
-@extension("VK_NV_external_memory_capabilities") // 56
-bitfield VkExternalMemoryHandleTypeFlagBitsNV {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV      = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV  = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV       = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV   = 0x00000008,
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-type VkFlags VkExternalMemoryFeatureFlagsNV
-@extension("VK_NV_external_memory_capabilities") // 56
-bitfield VkExternalMemoryFeatureFlagBitsNV {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV        = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV            = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV            = 0x00000004,
-}
-
-@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_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
-type VkFlags VkViSurfaceCreateFlagsNN
-//@extension("VK_NN_vi_surface") // 63
-//bitfield VkViSurfaceCreateFlagBitsNN {
-//}
-
-@extension("VK_KHR_maintenance1") // 70
-type VkFlags VkCommandPoolTrimFlagsKHR
-//@extension("VK_KHR_maintenance1") // 70
-//bitfield VkCommandPoolTrimFlagBitsKHR {
-//}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryHandleTypeFlagsKHR
-@extension("VK_KHR_external_memory_capabilities") // 72
-bitfield 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,
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryFeatureFlagsKHR
-@extension("VK_KHR_external_memory_capabilities") // 72
-bitfield 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,
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreHandleTypeFlagsKHR
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-bitfield 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_FENCE_FD_BIT_KHR          = 0x00000010
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreFeatureFlagsKHR
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-bitfield VkExternalSemaphoreFeatureFlagBitsKHR {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR            = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR            = 0x00000002,
-}
-
-@extension("VK_KHR_external_semaphore") // 78
-type VkFlags VkSemaphoreImportFlagsKHR
-@extension("VK_KHR_external_semaphore") // 78
-bitfield VkSemaphoreImportFlagBitsKHR {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR                       = 0x00000001,
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-type VkFlags VkConditionalRenderingFlagsEXT
-@extension("VK_EXT_conditional_rendering") // 82
-bitfield VkConditionalRenderingFlagBitsEXT {
-    VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT                   = 0x00000001,
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-type VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR
-//@extension("VK_KHR_descriptor_update_template") // 86
-//bitfield VkDescriptorUpdateTemplateCreateFlagBitsKHR {
-//}
-
-@extension("VK_NVX_device_generated_commands") // 87
-type VkFlags VkIndirectCommandsLayoutUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands") // 87
-bitfield VkIndirectCommandsLayoutUsageFlagBitsNVX {
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX   = 0x00000001,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX      = 0x00000002,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX      = 0x00000004,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX     = 0x00000008,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-type VkFlags VkObjectEntryUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands") // 87
-bitfield VkObjectEntryUsageFlagBitsNVX {
-    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX                  = 0x00000001,
-    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX                   = 0x00000002,
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-type VkFlags VkSurfaceCounterFlagsEXT
-@extension("VK_EXT_display_surface_counter") // 91
-bitfield VkSurfaceCounterFlagBitsEXT {
-    VK_SURFACE_COUNTER_VBLANK_EXT                           = 0x00000001,
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-type VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV
-//@extension("VK_NV_viewport_swizzle") // 99
-//bitfield VkPipelineViewportSwizzleStateCreateFlagBitsNV {
-//}
-
-@extension("VK_EXT_discard_rectangles") // 100
-type VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT
-//@extension("VK_EXT_discard_rectangles") // 100
-//bitfield VkPipelineDiscardRectangleStateCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-type VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT
-//@extension("VK_EXT_conservative_rasterization") // 102
-//bitfield VkPipelineRasterizationConservativeStateCreateFlagBitsEXT {
-//}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-type VkFlags VkExternalFenceHandleTypeFlagsKHR
-@extension("VK_KHR_external_fence_capabilities") // 113
-bitfield 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,
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-type VkFlags VkExternalFenceFeatureFlagsKHR
-@extension("VK_KHR_external_fence_capabilities") // 113
-bitfield VkExternalFenceFeatureFlagBitsKHR {
-    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR            = 0x00000001,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR            = 0x00000002,
-}
-
-@extension("VK_KHR_external_fence") // 114
-type VkFlags VkFenceImportFlagsKHR
-@extension("VK_KHR_external_fence") // 114
-bitfield VkFenceImportFlagBitsKHR {
-    VK_FENCE_IMPORT_TEMPORARY_BIT_KHR                       = 0x00000001,
-}
-
-@extension("VK_MVK_ios_surface") // 123
-type VkFlags VkIOSSurfaceCreateFlagsMVK
-//@extension("VK_MVK_ios_surface") // 123
-//bitfield VkIOSSurfaceCreateFlagBitsMVK {
-//}
-
-@extension("VK_MVK_macos_surface") // 124
-type VkFlags VkMacOSSurfaceCreateFlagsMVK
-//@extension("VK_MVK_macos_surface") // 124
-//bitfield VkMacOSSurfaceCreateFlagBitsMVK {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT
-//@extension("VK_EXT_debug_utils") // 129
-//bitfield VkDebugUtilsMessengerCallbackDataFlagBitsEXT {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessengerCreateFlagsEXT
-//@extension("VK_EXT_debug_utils") // 129
-//bitfield VkDebugUtilsMessengerCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessageSeverityFlagsEXT
-@extension("VK_EXT_debug_utils") // 129
-bitfield VkDebugUtilsMessageSeverityFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT    = 0x00000010,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT   = 0x00001000,
-}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessageTypeFlagsEXT
-@extension("VK_EXT_debug_utils") // 129
-bitfield VkDebugUtilsMessageTypeFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT     = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT  = 0x00000002,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
-}
-
-@extension("VK_NV_fragment_coverage_to_color") // 150
-type VkFlags VkPipelineCoverageToColorStateCreateFlagsNV
-@extension("VK_NV_fragment_coverage_to_color") // 150
-//bitfield VkPipelineCoverageToColorStateCreateFlagBitsNV {
-//}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-type VkFlags VkPipelineCoverageModulationStateCreateFlagsNV
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-//bitfield VkPipelineCoverageModulationStateCreateFlagBitsNV {
-//}
-
-@extension("VK_EXT_validation_cache") // 161
-type VkFlags VkValidationCacheCreateFlagsEXT
-@extension("VK_EXT_validation_cache") // 161
-//bitfield VkValidationCacheCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-type VkFlags VkDescriptorBindingFlagsEXT
-@extension("VK_EXT_descriptor_indexing") // 162
-bitfield VkDescriptorBindingFlagBitsEXT {
-    VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT             = 0x00000001,
-    VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT   = 0x00000002,
-    VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT               = 0x00000004,
-    VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT     = 0x00000008,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkGeometryFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkGeometryFlagBitsNV {
-    VK_GEOMETRY_OPAQUE_BIT_NV                           = 0x00000001,
-    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV  = 0x00000002,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkGeometryInstanceFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkGeometryInstanceFlagBitsNV {
-    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV           = 0x00000001,
-    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
-    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV                    = 0x00000004,
-    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV                 = 0x00000008,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkBuildAccelerationStructureFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkBuildAccelerationStructureFlagBitsNV {
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV         = 0x00000001,
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV     = 0x00000002,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV    = 0x00000004,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV    = 0x00000008,
-    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV           = 0x00000010,
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-type VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA
-//@extension("VK_FUCHSIA_imagepipe_surface") // 215
-//bitfield VkImagePipeSurfaceCreateFlagBitsFUCHSIA {
-//}
-
-//////////////////
-//  Structures  //
-//////////////////
-
-class VkOffset2D {
-    s32                                         x
-    s32                                         y
-}
-
-class VkOffset3D {
-    s32                                         x
-    s32                                         y
-    s32                                         z
-}
-
-class VkExtent2D {
-    u32                                         width
-    u32                                         height
-}
-
-class VkExtent3D {
-    u32                                         width
-    u32                                         height
-    u32                                         depth
-}
-
-class VkViewport {
-    f32                                         x
-    f32                                         y
-    f32                                         width
-    f32                                         height
-    f32                                         minDepth
-    f32                                         maxDepth
-}
-
-class VkRect2D {
-    VkOffset2D                                  offset
-    VkExtent2D                                  extent
-}
-
-class VkClearRect {
-    VkRect2D                                    rect
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkComponentMapping {
-    VkComponentSwizzle                          r
-    VkComponentSwizzle                          g
-    VkComponentSwizzle                          b
-    VkComponentSwizzle                          a
-}
-
-class VkPhysicalDeviceProperties {
-    u32                                         apiVersion
-    u32                                         driverVersion
-    u32                                         vendorID
-    u32                                         deviceID
-    VkPhysicalDeviceType                        deviceType
-    char[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]      deviceName
-    u8[VK_UUID_SIZE]                            pipelineCacheUUID
-    VkPhysicalDeviceLimits                      limits
-    VkPhysicalDeviceSparseProperties            sparseProperties
-}
-
-class VkExtensionProperties {
-    char[VK_MAX_EXTENSION_NAME_SIZE]            extensionName      /// extension name
-    u32                                         specVersion        /// version of the extension specification implemented
-}
-
-class VkLayerProperties {
-    char[VK_MAX_EXTENSION_NAME_SIZE]            layerName               /// layer name
-    u32                                         specVersion             /// version of the layer specification implemented
-    u32                                         implementationVersion   /// build or release version of the layer's library
-    char[VK_MAX_DESCRIPTION_SIZE]               description             /// Free-form description of the layer
-}
-
-class VkSubmitInfo {
-    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_SUBMIT_INFO
-    const void*                                 pNext              /// Next structure in chain
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    const VkPipelineStageFlags*                 pWaitDstStageMask
-    u32                                         commandBufferCount
-    const VkCommandBuffer*                      pCommandBuffers
-    u32                                         signalSemaphoreCount
-    const VkSemaphore*                          pSignalSemaphores
-}
-
-class VkApplicationInfo {
-    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_APPLICATION_INFO
-    const void*                                 pNext              /// Next structure in chain
-    const char*                                 pApplicationName
-    u32                                         applicationVersion
-    const char*                                 pEngineName
-    u32                                         engineVersion
-    u32                                         apiVersion
-}
-
-class VkAllocationCallbacks {
-    void*                                       pUserData
-    PFN_vkAllocationFunction                    pfnAllocation
-    PFN_vkReallocationFunction                  pfnReallocation
-    PFN_vkFreeFunction                          pfnFree
-    PFN_vkInternalAllocationNotification        pfnInternalAllocation
-    PFN_vkInternalFreeNotification              pfnInternalFree
-}
-
-class VkDeviceQueueCreateInfo {
-    VkStructureType                             sStype                    /// Should be VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
-    const void*                                 pNext                     /// Pointer to next structure
-    VkDeviceQueueCreateFlags                    flags
-    u32                                         queueFamilyIndex
-    u32                                         queueCount
-    const f32*                                  pQueuePriorities
-}
-
-class VkDeviceCreateInfo {
-    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceCreateFlags                         flags
-    u32                                         queueCreateInfoCount
-    const VkDeviceQueueCreateInfo*              pQueueCreateInfos
-    u32                                         enabledLayerCount
-    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
-    u32                                         enabledExtensionCount
-    const char* const*                          ppEnabledExtensionNames
-    const VkPhysicalDeviceFeatures*             pEnabledFeatures
-}
-
-class VkInstanceCreateInfo {
-    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkInstanceCreateFlags                       flags
-    const VkApplicationInfo*                    pApplicationInfo
-    u32                                         enabledLayerCount
-    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
-    u32                                         enabledExtensionCount
-    const char* const*                          ppEnabledExtensionNames    /// Extension names to be enabled
-}
-
-class VkQueueFamilyProperties {
-    VkQueueFlags                                queueFlags                 /// Queue flags
-    u32                                         queueCount
-    u32                                         timestampValidBits
-    VkExtent3D                                  minImageTransferGranularity
-}
-
-class VkPhysicalDeviceMemoryProperties {
-    u32                                         memoryTypeCount
-    VkMemoryType[VK_MAX_MEMORY_TYPES]           memoryTypes
-    u32                                         memoryHeapCount
-    VkMemoryHeap[VK_MAX_MEMORY_HEAPS]           memoryHeaps
-}
-
-class VkMemoryAllocateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceSize                                allocationSize             /// Size of memory allocation
-    u32                                         memoryTypeIndex            /// Index of the of the memory type to allocate from
-}
-
-class VkMemoryRequirements {
-    VkDeviceSize                                size                       /// Specified in bytes
-    VkDeviceSize                                alignment                  /// Specified in bytes
-    u32                                         memoryTypeBits             /// Bitfield of the allowed memory type indices into memoryTypes[] for this object
-}
-
-class VkSparseImageFormatProperties {
-    VkImageAspectFlagBits                       aspectMask
-    VkExtent3D                                  imageGranularity
-    VkSparseImageFormatFlags                    flags
-}
-
-class VkSparseImageMemoryRequirements {
-    VkSparseImageFormatProperties               formatProperties
-    u32                                         imageMipTailFirstLod
-    VkDeviceSize                                imageMipTailSize           /// Specified in bytes, must be a multiple of image block size / alignment
-    VkDeviceSize                                imageMipTailOffset         /// Specified in bytes, must be a multiple of image block size / alignment
-    VkDeviceSize                                imageMipTailStride         /// Specified in bytes, must be a multiple of image block size / alignment
-}
-
-class VkMemoryType {
-    VkMemoryPropertyFlags                       propertyFlags              /// Memory properties of this memory type
-    u32                                         heapIndex                  /// Index of the memory heap allocations of this memory type are taken from
-}
-
-class VkMemoryHeap {
-    VkDeviceSize                                size                       /// Available memory in the heap
-    VkMemoryHeapFlags                           flags                      /// Flags for the heap
-}
-
-class VkMappedMemoryRange {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceMemory                              memory                     /// Mapped memory object
-    VkDeviceSize                                offset                     /// Offset within the mapped memory the range starts from
-    VkDeviceSize                                size                       /// Size of the range within the mapped memory
-}
-
-class VkFormatProperties {
-    VkFormatFeatureFlags                        linearTilingFeatures       /// Format features in case of linear tiling
-    VkFormatFeatureFlags                        optimalTilingFeatures      /// Format features in case of optimal tiling
-    VkFormatFeatureFlags                        bufferFeatures             /// Format features supported by buffers
-}
-
-class VkImageFormatProperties {
-    VkExtent3D                                  maxExtent                  /// max image dimensions for this resource type
-    u32                                         maxMipLevels               /// max number of mipmap levels for this resource type
-    u32                                         maxArrayLayers             /// max array layers for this resource type
-    VkSampleCountFlags                          sampleCounts               /// supported sample counts for this resource type
-    VkDeviceSize                                maxResourceSize            /// max size (in bytes) of this resource type
-}
-
-class VkDescriptorImageInfo {
-    VkSampler                                   sampler
-    VkImageView                                 imageView
-    VkImageLayout                               imageLayout
-}
-
-class VkDescriptorBufferInfo {
-    VkBuffer                                    buffer                     /// Buffer used for this descriptor when the descriptor is UNIFORM_BUFFER[_DYNAMIC]
-    VkDeviceSize                                offset                     /// Base offset from buffer start in bytes to update in the descriptor set.
-    VkDeviceSize                                range                      /// Size in bytes of the buffer resource for this descriptor update.
-}
-
-class VkWriteDescriptorSet {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDescriptorSet                             dstSet                     /// Destination descriptor set
-    u32                                         dstBinding                 /// Binding within the destination descriptor set to write
-    u32                                         dstArrayElement            /// Array element within the destination binding to write
-    u32                                         descriptorCount            /// Number of descriptors to write (determines the size of the array pointed by <pDescriptors>)
-    VkDescriptorType                            descriptorType             /// Descriptor type to write (determines which fields of the array pointed by <pDescriptors> are going to be used)
-    const VkDescriptorImageInfo*                pImageInfo
-    const VkDescriptorBufferInfo*               pBufferInfo
-    const VkBufferView*                         pTexelBufferView
-}
-
-class VkCopyDescriptorSet {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDescriptorSet                             srcSet                     /// Source descriptor set
-    u32                                         srcBinding                 /// Binding within the source descriptor set to copy from
-    u32                                         srcArrayElement            /// Array element within the source binding to copy from
-    VkDescriptorSet                             dstSet                     /// Destination descriptor set
-    u32                                         dstBinding                 /// Binding within the destination descriptor set to copy to
-    u32                                         dstArrayElement            /// Array element within the destination binding to copy to
-    u32                                         descriptorCount            /// Number of descriptors to copy
-}
-
-class VkBufferCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkBufferCreateFlags                         flags                      /// Buffer creation flags
-    VkDeviceSize                                size                       /// Specified in bytes
-    VkBufferUsageFlags                          usage                      /// Buffer usage flags
-    VkSharingMode                               sharingMode
-    u32                                         queueFamilyIndexCount
-    const u32*                                  pQueueFamilyIndices
-}
-
-class VkBufferViewCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkBufferViewCreateFlags                     flags
-    VkBuffer                                    buffer
-    VkFormat                                    format                     /// Optionally specifies format of elements
-    VkDeviceSize                                offset                     /// Specified in bytes
-    VkDeviceSize                                range                      /// View size specified in bytes
-}
-
-class VkImageSubresource {
-    VkImageAspectFlagBits                       aspectMask
-    u32                                         mipLevel
-    u32                                         arrayLayer
-}
-
-class VkImageSubresourceRange {
-    VkImageAspectFlags                          aspectMask
-    u32                                         baseMipLevel
-    u32                                         levelCount
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-}
-
-class VkBufferMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
-    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
-    VkBuffer                                    buffer                     /// Buffer to sync
-    VkDeviceSize                                offset                     /// Offset within the buffer to sync
-    VkDeviceSize                                size                       /// Amount of bytes to sync
-}
-
-class VkImageMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    VkImageLayout                               oldLayout                  /// Current layout of the image
-    VkImageLayout                               newLayout                  /// New layout to transition the image to
-    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
-    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
-    VkImage                                     image                      /// Image to sync
-    VkImageSubresourceRange                     subresourceRange           /// Subresource range to sync
-}
-
-class VkImageCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkImageCreateFlags                          flags                      /// Image creation flags
-    VkImageType                                 imageType
-    VkFormat                                    format
-    VkExtent3D                                  extent
-    u32                                         mipLevels
-    u32                                         arrayLayers
-    VkSampleCountFlagBits                       samples
-    VkImageTiling                               tiling
-    VkImageUsageFlags                           usage                      /// Image usage flags
-    VkSharingMode                               sharingMode                /// Cross-queue-family sharing mode
-    u32                                         queueFamilyIndexCount      /// Number of queue families to share across
-    const u32*                                  pQueueFamilyIndices        /// Array of queue family indices to share across
-    VkImageLayout                               initialLayout              /// Initial image layout for all subresources
-}
-
-class VkSubresourceLayout {
-    VkDeviceSize                                offset                 /// Specified in bytes
-    VkDeviceSize                                size                   /// Specified in bytes
-    VkDeviceSize                                rowPitch               /// Specified in bytes
-    VkDeviceSize                                arrayPitch             /// Specified in bytes
-    VkDeviceSize                                depthPitch             /// Specified in bytes
-}
-
-class VkImageViewCreateInfo {
-    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
-    const void*                                 pNext                  /// Pointer to next structure
-    VkImageViewCreateFlags                      flags
-    VkImage                                     image
-    VkImageViewType                             viewType
-    VkFormat                                    format
-    VkComponentMapping                          components
-    VkImageSubresourceRange                     subresourceRange
-}
-
-class VkBufferCopy {
-    VkDeviceSize                                srcOffset              /// Specified in bytes
-    VkDeviceSize                                dstOffset              /// Specified in bytes
-    VkDeviceSize                                size                   /// Specified in bytes
-}
-
-class VkSparseMemoryBind {
-    VkDeviceSize                                resourceOffset        /// Specified in bytes
-    VkDeviceSize                                size                  /// Specified in bytes
-    VkDeviceMemory                              memory
-    VkDeviceSize                                memoryOffset          /// Specified in bytes
-    VkSparseMemoryBindFlags                     flags
-}
-
-class VkSparseImageMemoryBind {
-    VkImageSubresource                          subresource
-    VkOffset3D                                  offset
-    VkExtent3D                                  extent
-    VkDeviceMemory                              memory
-    VkDeviceSize                                memoryOffset          /// Specified in bytes
-    VkSparseMemoryBindFlags                     flags
-}
-
-class VkSparseBufferMemoryBindInfo {
-    VkBuffer                                    buffer
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkSparseImageOpaqueMemoryBindInfo {
-    VkImage                                     image
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkSparseImageMemoryBindInfo {
-    VkImage                                     image
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkBindSparseInfo {
-    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_BIND_SPARSE_INFO
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    u32                                         numBufferBinds
-    const VkSparseBufferMemoryBindInfo*         pBufferBinds
-    u32                                         numImageOpaqueBinds
-    const VkSparseImageOpaqueMemoryBindInfo*    pImageOpaqueBinds
-    u32                                         numImageBinds
-    const VkSparseImageMemoryBindInfo*          pImageBinds
-    u32                                         signalSemaphoreCount
-    const VkSemaphore*                          pSignalSemaphores
-}
-
-class VkImageSubresourceLayers {
-    VkImageAspectFlags                          aspectMask
-    u32                                         mipLevel
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkImageCopy {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D                                  srcOffset             /// Specified in pixels for both compressed and uncompressed images
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D                                  dstOffset             /// Specified in pixels for both compressed and uncompressed images
-    VkExtent3D                                  extent                /// Specified in pixels for both compressed and uncompressed images
-}
-
-class VkImageBlit {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D[2]                               srcOffsets
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D[2]                               dstOffsets
-}
-
-class VkBufferImageCopy {
-    VkDeviceSize                                bufferOffset           /// Specified in bytes
-    u32                                         bufferRowLength        /// Specified in texels
-    u32                                         bufferImageHeight
-    VkImageSubresourceLayers                    imageSubresource
-    VkOffset3D                                  imageOffset            /// Specified in pixels for both compressed and uncompressed images
-    VkExtent3D                                  imageExtent            /// Specified in pixels for both compressed and uncompressed images
-}
-
-class VkImageResolve {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D                                  srcOffset
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D                                  dstOffset
-    VkExtent3D                                  extent
-}
-
-class VkShaderModuleCreateInfo {
-    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
-    const void*                                 pNext                  /// Pointer to next structure
-    VkShaderModuleCreateFlags                   flags                  /// Reserved
-    platform.size_t                             codeSize               /// Specified in bytes
-    const u32*                                  pCode                  /// Binary code of size codeSize
-}
-
-class VkDescriptorSetLayoutBinding {
-    u32                                         binding
-    VkDescriptorType                            descriptorType     /// Type of the descriptors in this binding
-    u32                                         descriptorCount    /// Number of descriptors in this binding
-    VkShaderStageFlags                          stageFlags         /// Shader stages this binding is visible to
-    const VkSampler*                            pImmutableSamplers /// Immutable samplers (used if descriptor type is SAMPLER or COMBINED_IMAGE_SAMPLER, is either NULL or contains <count> number of elements)
-}
-
-class VkDescriptorSetLayoutCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorSetLayoutCreateFlags            flags
-    u32                                         bindingCount       /// Number of bindings in the descriptor set layout
-    const VkDescriptorSetLayoutBinding*         pBindings          /// Array of descriptor set layout bindings
-}
-
-class VkDescriptorPoolSize {
-    VkDescriptorType                            type
-    u32                                         descriptorCount
-}
-
-class VkDescriptorPoolCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorPoolCreateFlags                 flags
-    u32                                         maxSets
-    u32                                         poolSizeCount
-    const VkDescriptorPoolSize*                 pPoolSizes
-}
-
-class VkDescriptorSetAllocateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorPool                            descriptorPool
-    u32                                         setCount
-    const VkDescriptorSetLayout*                pSetLayouts
-}
-
-class VkSpecializationMapEntry {
-    u32                                         constantID         /// The SpecConstant ID specified in the BIL
-    u32                                         offset             /// Offset of the value in the data block
-    platform.size_t                             size               /// Size in bytes of the SpecConstant
-}
-
-class VkSpecializationInfo {
-    u32                                         mapEntryCount      /// Number of entries in the map
-    const VkSpecializationMapEntry*             pMapEntries        /// Array of map entries
-    platform.size_t                             dataSize           /// Size in bytes of pData
-    const void*                                 pData              /// Pointer to SpecConstant data
-}
-
-class VkPipelineShaderStageCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkPipelineShaderStageCreateFlags            flags
-    VkShaderStageFlagBits                       stage
-    VkShaderModule                              module
-    const char*                                 pName
-    const VkSpecializationInfo*                 pSpecializationInfo
-}
-
-class VkComputePipelineCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkPipelineCreateFlags                       flags              /// Pipeline creation flags
-    VkPipelineShaderStageCreateInfo             stage
-    VkPipelineLayout                            layout             /// Interface layout of the pipeline
-    VkPipeline                                  basePipelineHandle /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
-    s32                                         basePipelineIndex  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
-}
-
-class VkVertexInputBindingDescription {
-    u32                                         binding               /// Vertex buffer binding id
-    u32                                         stride                /// Distance between vertices in bytes (0 = no advancement)
-    VkVertexInputRate                           inputRate             /// Rate at which binding is incremented
-}
-
-class VkVertexInputAttributeDescription {
-    u32                                         location              /// location of the shader vertex attrib
-    u32                                         binding               /// Vertex buffer binding id
-    VkFormat                                    format                /// format of source data
-    u32                                         offset                /// Offset of first element in bytes from base of vertex
-}
-
-class VkPipelineVertexInputStateCreateInfo {
-    VkStructureType                             sType                           /// Should be VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
-    const void*                                 pNext                           /// Pointer to next structure
-    VkPipelineVertexInputStateCreateFlags       flags
-    u32                                         vertexBindingDescriptionCount   /// number of bindings
-    const VkVertexInputBindingDescription*      pVertexBindingDescriptions
-    u32                                         vertexAttributeDescriptionCount /// number of attributes
-    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
-}
-
-class VkPipelineInputAssemblyStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineInputAssemblyStateCreateFlags     flags
-    VkPrimitiveTopology                         topology
-    VkBool32                                    primitiveRestartEnable
-}
-
-class VkPipelineTessellationStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineTessellationStateCreateFlags      flags
-    u32                                         patchControlPoints
-}
-
-class VkPipelineViewportStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineViewportStateCreateFlags          flags
-    u32                                         viewportCount
-    const VkViewport*                           pViewports
-    u32                                         scissorCount
-    const VkRect2D*                             pScissors
-}
-
-class VkPipelineRasterizationStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineRasterizationStateCreateFlags     flags
-    VkBool32                                    depthClampEnable
-    VkBool32                                    rasterizerDiscardEnable
-    VkPolygonMode                               polygonMode                   /// optional (GL45)
-    VkCullModeFlags                             cullMode
-    VkFrontFace                                 frontFace
-    VkBool32                                    depthBiasEnable
-    f32                                         depthBiasConstantFactor
-    f32                                         depthBiasClamp
-    f32                                         depthBiasSlopeFactor
-    f32                                         lineWidth
-}
-
-class VkPipelineMultisampleStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineMultisampleStateCreateFlags       flags
-    VkSampleCountFlagBits                       rasterizationSamples       /// Number of samples used for rasterization
-    VkBool32                                    sampleShadingEnable        /// optional (GL45)
-    f32                                         minSampleShading           /// optional (GL45)
-    const VkSampleMask*                         pSampleMask
-    VkBool32                                    alphaToCoverageEnable
-    VkBool32                                    alphaToOneEnable
-}
-
-class VkPipelineColorBlendAttachmentState {
-    VkBool32                                    blendEnable
-    VkBlendFactor                               srcColorBlendFactor
-    VkBlendFactor                               dstColorBlendFactor
-    VkBlendOp                                   colorBlendOp
-    VkBlendFactor                               srcAlphaBlendFactor
-    VkBlendFactor                               dstAlphaBlendFactor
-    VkBlendOp                                   alphaBlendOp
-    VkColorComponentFlags                       colorWriteMask
-}
-
-class VkPipelineColorBlendStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineColorBlendStateCreateFlags        flags
-    VkBool32                                    logicOpEnable
-    VkLogicOp                                   logicOp
-    u32                                         attachmentCount    /// # of pAttachments
-    const VkPipelineColorBlendAttachmentState*  pAttachments
-    f32[4]                                      blendConstants
-}
-
-class VkStencilOpState {
-    VkStencilOp                                 failOp
-    VkStencilOp                                 passOp
-    VkStencilOp                                 depthFailOp
-    VkCompareOp                                 compareOp
-    u32                                         compareMask
-    u32                                         writeMask
-    u32                                         reference
-}
-
-class VkPipelineDepthStencilStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineDepthStencilStateCreateFlags      flags
-    VkBool32                                    depthTestEnable
-    VkBool32                                    depthWriteEnable
-    VkCompareOp                                 depthCompareOp
-    VkBool32                                    depthBoundsTestEnable  /// optional (depth_bounds_test)
-    VkBool32                                    stencilTestEnable
-    VkStencilOpState                            front
-    VkStencilOpState                            back
-    f32                                         minDepthBounds
-    f32                                         maxDepthBounds
-}
-
-class VkPipelineDynamicStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineDynamicStateCreateFlags           flags
-    u32                                         dynamicStateCount
-    const VkDynamicState*                       pDynamicStates
-}
-
-class VkGraphicsPipelineCreateInfo {
-    VkStructureType                                 sType               /// Must be VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
-    const void*                                     pNext               /// Pointer to next structure
-    VkPipelineCreateFlags                           flags               /// Pipeline creation flags
-    u32                                             stageCount
-    const VkPipelineShaderStageCreateInfo*          pStages             /// One entry for each active shader stage
-    const VkPipelineVertexInputStateCreateInfo*     pVertexInputState
-    const VkPipelineInputAssemblyStateCreateInfo*   pInputAssemblyState
-    const VkPipelineTessellationStateCreateInfo*    pTessellationState
-    const VkPipelineViewportStateCreateInfo*        pViewportState
-    const VkPipelineRasterizationStateCreateInfo*   pRasterizationState
-    const VkPipelineMultisampleStateCreateInfo*     pMultisampleState
-    const VkPipelineDepthStencilStateCreateInfo*    pDepthStencilState
-    const VkPipelineColorBlendStateCreateInfo*      pColorBlendState
-    const VkPipelineDynamicStateCreateInfo*         pDynamicState
-    VkPipelineLayout                                layout              /// Interface layout of the pipeline
-    VkRenderPass                                    renderPass
-    u32                                             subpass
-    VkPipeline                                      basePipelineHandle  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
-    s32                                             basePipelineIndex   /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
-}
-
-class VkPipelineCacheCreateInfo {
-    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
-    const void*                                 pNext                 /// Pointer to next structure
-    VkPipelineCacheCreateFlags                  flags
-    platform.size_t                             initialDataSize       /// Size of initial data to populate cache, in bytes
-    const void*                                 pInitialData          /// Initial data to populate cache
-}
-
-class VkPushConstantRange {
-    VkShaderStageFlags                          stageFlags   /// Which stages use the range
-    u32                                         offset       /// Start of the range, in bytes
-    u32                                         size        /// Length of the range, in bytes
-}
-
-class VkPipelineLayoutCreateInfo {
-    VkStructureType                             sType                   /// Must be VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
-    const void*                                 pNext                   /// Pointer to next structure
-    VkPipelineLayoutCreateFlags                 flags
-    u32                                         descriptorSetCount      /// Number of descriptor sets interfaced by the pipeline
-    const VkDescriptorSetLayout*                pSetLayouts             /// Array of <setCount> number of descriptor set layout objects defining the layout of the
-    u32                                         pushConstantRangeCount  /// Number of push-constant ranges used by the pipeline
-    const VkPushConstantRange*                  pPushConstantRanges     /// Array of pushConstantRangeCount number of ranges used by various shader stages
-}
-
-class VkSamplerCreateInfo {
-    VkStructureType                             sType          /// Must be VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
-    const void*                                 pNext          /// Pointer to next structure
-    VkSamplerCreateFlags                        flags
-    VkFilter                                    magFilter      /// Filter mode for magnification
-    VkFilter                                    minFilter      /// Filter mode for minifiation
-    VkSamplerMipmapMode                         mipmapMode     /// Mipmap selection mode
-    VkSamplerAddressMode                        addressModeU
-    VkSamplerAddressMode                        addressModeV
-    VkSamplerAddressMode                        addressModeW
-    f32                                         mipLodBias
-    VkBool32                                    anisotropyEnable
-    f32                                         maxAnisotropy
-    VkBool32                                    compareEnable
-    VkCompareOp                                 compareOp
-    f32                                         minLod
-    f32                                         maxLod
-    VkBorderColor                               borderColor
-    VkBool32                                    unnormalizedCoordinates
-}
-
-class VkCommandPoolCreateInfo {
-    VkStructureType                             sType            /// Must be VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
-    const void*                                 pNext            /// Pointer to next structure
-    VkCommandPoolCreateFlags                    flags            /// Command pool creation flags
-    u32                                         queueFamilyIndex
-}
-
-class VkCommandBufferAllocateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkCommandPool                               commandPool
-    VkCommandBufferLevel                        level
-    u32                                         commandBufferCount
-}
-
-class VkCommandBufferInheritanceInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkRenderPass                                renderPass  /// Render pass for secondary command buffers
-    u32                                         subpass
-    VkFramebuffer                               framebuffer /// Framebuffer for secondary command buffers
-    VkBool32                                    occlusionQueryEnable
-    VkQueryControlFlags                         queryFlags
-    VkQueryPipelineStatisticFlags               pipelineStatistics
-}
-
-class VkCommandBufferBeginInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkCommandBufferUsageFlags                   flags       /// Command buffer usage flags
-    const VkCommandBufferInheritanceInfo*       pInheritanceInfo
-}
-
-class VkRenderPassBeginInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkRenderPass                                renderPass
-    VkFramebuffer                               framebuffer
-    VkRect2D                                    renderArea
-    u32                                         clearValueCount
-    const VkClearValue*                         pClearValues
-}
-
-@union
-/// Union allowing specification of floating point, integer, or unsigned integer color data. Actual value selected is based on image/attachment being cleared.
-class VkClearColorValue {
-    f32[4]                                      float32
-    s32[4]                                      int32
-    u32[4]                                      uint32
-}
-
-class VkClearDepthStencilValue {
-    f32                                         depth
-    u32                                         stencil
-}
-
-@union
-/// Union allowing specification of color, depth, and stencil color values. Actual value selected is based on attachment being cleared.
-class VkClearValue {
-    VkClearColorValue                           color
-    VkClearDepthStencilValue                    depthStencil
-}
-
-class VkClearAttachment {
-    VkImageAspectFlags                          aspectMask
-    u32                                         colorAttachment
-    VkClearValue                                clearValue
-}
-
-class VkAttachmentDescription {
-    VkAttachmentDescriptionFlags                flags
-    VkFormat                                    format
-    VkSampleCountFlagBits                       samples
-    VkAttachmentLoadOp                          loadOp          /// Load op for color or depth data
-    VkAttachmentStoreOp                         storeOp         /// Store op for color or depth data
-    VkAttachmentLoadOp                          stencilLoadOp   /// Load op for stencil data
-    VkAttachmentStoreOp                         stencilStoreOp  /// Store op for stencil data
-    VkImageLayout                               initialLayout
-    VkImageLayout                               finalLayout
-}
-
-class VkAttachmentReference {
-    u32                                         attachment
-    VkImageLayout                               layout
-}
-
-class VkSubpassDescription {
-    VkSubpassDescriptionFlags                   flags
-    VkPipelineBindPoint                         pipelineBindPoint  /// Must be VK_PIPELINE_BIND_POINT_GRAPHICS for now
-    u32                                         inputAttachmentCount
-    const VkAttachmentReference*                pInputAttachments
-    u32                                         colorAttachmentCount
-    const VkAttachmentReference*                pColorAttachments
-    const VkAttachmentReference*                pResolveAttachments
-    const VkAttachmentReference*                pDepthStencilAttachment
-    u32                                         preserveAttachmentCount
-    const u32*                                  pPreserveAttachments
-}
-
-class VkSubpassDependency {
-    u32                                         srcSubpass
-    u32                                         dstSubpass
-    VkPipelineStageFlags                        srcStageMask
-    VkPipelineStageFlags                        dstStageMask
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    VkDependencyFlags                           dependencyFlags
-}
-
-class VkRenderPassCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkRenderPassCreateFlags                     flags
-    u32                                         attachmentCount
-    const VkAttachmentDescription*              pAttachments
-    u32                                         subpassCount
-    const VkSubpassDescription*                 pSubpasses
-    u32                                         dependencyCount
-    const VkSubpassDependency*                  pDependencies
-}
-
-class VkEventCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_EVENT_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkEventCreateFlags                          flags      /// Event creation flags
-}
-
-class VkFenceCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkFenceCreateFlags                          flags      /// Fence creation flags
-}
-
-class VkPhysicalDeviceFeatures {
-    VkBool32                                    robustBufferAccess                        /// out of bounds buffer accesses are well defined
-    VkBool32                                    fullDrawIndexUint32                       /// full 32-bit range of indices for indexed draw calls
-    VkBool32                                    imageCubeArray                            /// image views which are arrays of cube maps
-    VkBool32                                    independentBlend                          /// blending operations are controlled per-attachment
-    VkBool32                                    geometryShader                            /// geometry stage
-    VkBool32                                    tessellationShader                        /// tessellation control and evaluation stage
-    VkBool32                                    sampleRateShading                         /// per-sample shading and interpolation
-    VkBool32                                    dualSrcBlend                              /// blend operations which take two sources
-    VkBool32                                    logicOp                                   /// logic operations
-    VkBool32                                    multiDrawIndirect                         /// multi draw indirect
-    VkBool32                                    drawIndirectFirstInstance
-    VkBool32                                    depthClamp                                /// depth clamping
-    VkBool32                                    depthBiasClamp                            /// depth bias clamping
-    VkBool32                                    fillModeNonSolid                          /// point and wireframe fill modes
-    VkBool32                                    depthBounds                               /// depth bounds test
-    VkBool32                                    wideLines                                 /// lines with width greater than 1
-    VkBool32                                    largePoints                               /// points with size greater than 1
-    VkBool32                                    alphaToOne                                /// The fragment alpha channel can be forced to maximum representable alpha value
-    VkBool32                                    multiViewport
-    VkBool32                                    samplerAnisotropy
-    VkBool32                                    textureCompressionETC2                    /// ETC texture compression formats
-    VkBool32                                    textureCompressionASTC_LDR                /// ASTC LDR texture compression formats
-    VkBool32                                    textureCompressionBC                      /// BC1-7 texture compressed formats
-    VkBool32                                    occlusionQueryPrecise
-    VkBool32                                    pipelineStatisticsQuery                   /// pipeline statistics query
-    VkBool32                                    vertexPipelineStoresAndAtomics
-    VkBool32                                    fragmentStoresAndAtomics
-    VkBool32                                    shaderTessellationAndGeometryPointSize
-    VkBool32                                    shaderImageGatherExtended                 /// texture gather with run-time values and independent offsets
-    VkBool32                                    shaderStorageImageExtendedFormats         /// the extended set of formats can be used for storage images
-    VkBool32                                    shaderStorageImageMultisample             /// multisample images can be used for storage images
-    VkBool32                                    shaderStorageImageReadWithoutFormat
-    VkBool32                                    shaderStorageImageWriteWithoutFormat
-    VkBool32                                    shaderUniformBufferArrayDynamicIndexing   /// arrays of uniform buffers can be accessed with dynamically uniform indices
-    VkBool32                                    shaderSampledImageArrayDynamicIndexing    /// arrays of sampled images can be accessed with dynamically uniform indices
-    VkBool32                                    shaderStorageBufferArrayDynamicIndexing   /// arrays of storage buffers can be accessed with dynamically uniform indices
-    VkBool32                                    shaderStorageImageArrayDynamicIndexing    /// arrays of storage images can be accessed with dynamically uniform indices
-    VkBool32                                    shaderClipDistance                        /// clip distance in shaders
-    VkBool32                                    shaderCullDistance                        /// cull distance in shaders
-    VkBool32                                    shaderFloat64                             /// 64-bit floats (doubles) in shaders
-    VkBool32                                    shaderInt64                               /// 64-bit integers in shaders
-    VkBool32                                    shaderInt16                               /// 16-bit integers in shaders
-    VkBool32                                    shaderResourceResidency                   /// shader can use texture operations that return resource residency information (requires sparseNonResident support)
-    VkBool32                                    shaderResourceMinLod                      /// shader can use texture operations that specify minimum resource LOD
-    VkBool32                                    sparseBinding                             /// Sparse resources support: Resource memory can be managed at opaque page level rather than object level
-    VkBool32                                    sparseResidencyBuffer                     /// Sparse resources support: GPU can access partially resident buffers
-    VkBool32                                    sparseResidencyImage2D                    /// Sparse resources support: GPU can access partially resident 2D (non-MSAA non-DepthStencil) images
-    VkBool32                                    sparseResidencyImage3D                    /// Sparse resources support: GPU can access partially resident 3D images
-    VkBool32                                    sparseResidency2Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 2 samples
-    VkBool32                                    sparseResidency4Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 4 samples
-    VkBool32                                    sparseResidency8Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 8 samples
-    VkBool32                                    sparseResidency16Samples                  /// Sparse resources support: GPU can access partially resident MSAA 2D images with 16 samples
-    VkBool32                                    sparseResidencyAliased                    /// Sparse resources support: GPU can correctly access data aliased into multiple locations (opt-in)
-    VkBool32                                    variableMultisampleRate
-    VkBool32                                    inheritedQueries
-}
-
-class VkPhysicalDeviceLimits {
-    /// resource maximum sizes
-    u32                                         maxImageDimension1D                       /// max 1D image dimension
-    u32                                         maxImageDimension2D                       /// max 2D image dimension
-    u32                                         maxImageDimension3D                       /// max 3D image dimension
-    u32                                         maxImageDimensionCube                     /// max cubemap image dimension
-    u32                                         maxImageArrayLayers                       /// max layers for image arrays
-    u32                                         maxTexelBufferElements
-    u32                                         maxUniformBufferRange                     /// max uniform buffer size (bytes)
-    u32                                         maxStorageBufferRange                     /// max storage buffer size (bytes)
-    u32                                         maxPushConstantsSize                      /// max size of the push constants pool (bytes)
-    /// memory limits
-    u32                                         maxMemoryAllocationCount                  /// max number of device memory allocations supported
-    u32                                         maxSamplerAllocationCount
-    VkDeviceSize                                bufferImageGranularity                    /// Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage
-    VkDeviceSize                                sparseAddressSpaceSize                    /// Total address space available for sparse allocations (bytes)
-    /// descriptor set limits
-    u32                                         maxBoundDescriptorSets                    /// max number of descriptors sets that can be bound to a pipeline
-    u32                                         maxPerStageDescriptorSamplers             /// max num of samplers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorUniformBuffers       /// max num of uniform buffers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorStorageBuffers       /// max num of storage buffers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorSampledImages        /// max num of sampled images allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorStorageImages        /// max num of storage images allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorInputAttachments
-    u32                                         maxPerStageResources
-    u32                                         maxDescriptorSetSamplers                  /// max num of samplers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetUniformBuffers            /// max num of uniform buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetUniformBuffersDynamic     /// max num of dynamic uniform buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageBuffers            /// max num of storage buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageBuffersDynamic     /// max num of dynamic storage buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetSampledImages             /// max num of sampled images allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageImages             /// max num of storage images allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetInputAttachments
-    /// vertex stage limits
-    u32                                         maxVertexInputAttributes                  /// max num of vertex input attribute slots
-    u32                                         maxVertexInputBindings                    /// max num of vertex input binding slots
-    u32                                         maxVertexInputAttributeOffset             /// max vertex input attribute offset added to vertex buffer offset
-    u32                                         maxVertexInputBindingStride               /// max vertex input binding stride
-    u32                                         maxVertexOutputComponents                 /// max num of output components written by vertex shader
-    /// tessellation control stage limits
-    u32                                         maxTessellationGenerationLevel                  /// max level supported by tess primitive generator
-    u32                                         maxTessellationPatchSize                        /// max patch size (vertices)
-    u32                                         maxTessellationControlPerVertexInputComponents  /// max num of input components per-vertex in TCS
-    u32                                         maxTessellationControlPerVertexOutputComponents /// max num of output components per-vertex in TCS
-    u32                                         maxTessellationControlPerPatchOutputComponents  /// max num of output components per-patch in TCS
-    u32                                         maxTessellationControlTotalOutputComponents     /// max total num of per-vertex and per-patch output components in TCS
-    u32                                         maxTessellationEvaluationInputComponents        /// max num of input components per vertex in TES
-    u32                                         maxTessellationEvaluationOutputComponents       /// max num of output components per vertex in TES
-    /// geometry stage limits
-    u32                                         maxGeometryShaderInvocations              /// max invocation count supported in geometry shader
-    u32                                         maxGeometryInputComponents                /// max num of input components read in geometry stage
-    u32                                         maxGeometryOutputComponents               /// max num of output components written in geometry stage
-    u32                                         maxGeometryOutputVertices                 /// max num of vertices that can be emitted in geometry stage
-    u32                                         maxGeometryTotalOutputComponents          /// max total num of components (all vertices) written in geometry stage
-    /// fragment stage limits
-    u32                                         maxFragmentInputComponents                /// max num of input compontents read in fragment stage
-    u32                                         maxFragmentOutputAttachments              /// max num of output attachments written in fragment stage
-    u32                                         maxFragmentDualSrcAttachments             /// max num of output attachments written when using dual source blending
-    u32                                         maxFragmentCombinedOutputResources        /// max total num of storage buffers, storage images and output buffers
-    /// compute stage limits
-    u32                                         maxComputeSharedMemorySize                /// max total storage size of work group local storage (bytes)
-    u32[3]                                      maxComputeWorkGroupCount                  /// max num of compute work groups that may be dispatched by a single command (x,y,z)
-    u32                                         maxComputeWorkGroupInvocations            /// max total compute invocations in a single local work group
-    u32[3]                                      maxComputeWorkGroupSize                   /// max local size of a compute work group (x,y,z)
-
-    u32                                         subPixelPrecisionBits                     /// num bits of subpixel precision in screen x and y
-    u32                                         subTexelPrecisionBits                     /// num bits of subtexel precision
-    u32                                         mipmapPrecisionBits                       /// num bits of mipmap precision
-
-    u32                                         maxDrawIndexedIndexValue                  /// max index value for indexed draw calls (for 32-bit indices)
-    u32                                         maxDrawIndirectCount
-
-    f32                                         maxSamplerLodBias                         /// max absolute sampler level of detail bias
-    f32                                         maxSamplerAnisotropy                      /// max degree of sampler anisotropy
-
-    u32                                         maxViewports                              /// max number of active viewports
-    u32[2]                                      maxViewportDimensions                     /// max viewport dimensions (x,y)
-    f32[2]                                      viewportBoundsRange                       /// viewport bounds range (min,max)
-    u32                                         viewportSubPixelBits                      /// num bits of subpixel precision for viewport
-
-    platform.size_t                             minMemoryMapAlignment                     /// min required alignment of pointers returned by MapMemory (bytes)
-    VkDeviceSize                                minTexelBufferOffsetAlignment             /// min required alignment for texel buffer offsets (bytes)
-    VkDeviceSize                                minUniformBufferOffsetAlignment           /// min required alignment for uniform buffer sizes and offsets (bytes)
-    VkDeviceSize                                minStorageBufferOffsetAlignment           /// min required alignment for storage buffer offsets (bytes)
-
-    s32                                         minTexelOffset                            /// min texel offset for OpTextureSampleOffset
-    u32                                         maxTexelOffset                            /// max texel offset for OpTextureSampleOffset
-    s32                                         minTexelGatherOffset                      /// min texel offset for OpTextureGatherOffset
-    u32                                         maxTexelGatherOffset                      /// max texel offset for OpTextureGatherOffset
-    f32                                         minInterpolationOffset                    /// furthest negative offset for interpolateAtOffset
-    f32                                         maxInterpolationOffset                    /// furthest positive offset for interpolateAtOffset
-    u32                                         subPixelInterpolationOffsetBits           /// num of subpixel bits for interpolateAtOffset
-
-    u32                                         maxFramebufferWidth                       /// max width for a framebuffer
-    u32                                         maxFramebufferHeight                      /// max height for a framebuffer
-    u32                                         maxFramebufferLayers                      /// max layer count for a layered framebuffer
-    VkSampleCountFlags                          framebufferColorSampleCounts
-    VkSampleCountFlags                          framebufferDepthSampleCounts
-    VkSampleCountFlags                          framebufferStencilSampleCounts
-    VkSampleCountFlags                          framebufferNoAttachmentSampleCounts
-    u32                                         maxColorAttachments                       /// max num of framebuffer color attachments
-
-    VkSampleCountFlags                          sampledImageColorSampleCounts
-    VkSampleCountFlags                          sampledImageIntegerSampleCounts
-    VkSampleCountFlags                          sampledImageDepthSampleCounts
-    VkSampleCountFlags                          sampledImageStencilSampleCounts
-    VkSampleCountFlags                          storageImageSampleCounts
-    u32                                         maxSampleMaskWords                        /// max num of sample mask words
-    VkBool32                                    timestampComputeAndGraphics
-
-    f32                                         timestampPeriod
-
-    u32                                         maxClipDistances                          /// max number of clip distances
-    u32                                         maxCullDistances                          /// max number of cull distances
-    u32                                         maxCombinedClipAndCullDistances           /// max combined number of user clipping
-
-    u32                                         discreteQueuePriorities
-
-    f32[2]                                      pointSizeRange                            /// range (min,max) of supported point sizes
-    f32[2]                                      lineWidthRange                            /// range (min,max) of supported line widths
-    f32                                         pointSizeGranularity                      /// granularity of supported point sizes
-    f32                                         lineWidthGranularity                      /// granularity of supported line widths
-    VkBool32                                    strictLines
-    VkBool32                                    standardSampleLocations
-
-    VkDeviceSize                                optimalBufferCopyOffsetAlignment
-    VkDeviceSize                                optimalBufferCopyRowPitchAlignment
-    VkDeviceSize                                nonCoherentAtomSize
-}
-
-class VkPhysicalDeviceSparseProperties {
-    VkBool32                                    residencyStandard2DBlockShape             /// Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyStandard2DMultisampleBlockShape  /// Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyStandard3DBlockShape             /// Sparse resources support: GPU will access all 3D sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyAlignedMipSize                   /// Sparse resources support: Images with mip-level dimensions that are NOT a multiple of the block size will be placed in the mip tail
-    VkBool32                                    residencyNonResidentStrict                /// Sparse resources support: GPU can safely access non-resident regions of a resource, all reads return as if data is 0, writes are discarded
-}
-
-class VkSemaphoreCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkSemaphoreCreateFlags                      flags      /// Semaphore creation flags
-}
-
-class VkQueryPoolCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkQueryPoolCreateFlags                      flags
-    VkQueryType                                 queryType
-    u32                                         queryCount
-    VkQueryPipelineStatisticFlags               pipelineStatistics /// Optional
-}
-
-class VkFramebufferCreateInfo {
-    VkStructureType                             sType  /// Must be VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
-    const void*                                 pNext  /// Pointer to next structure
-    VkFramebufferCreateFlags                    flags
-    VkRenderPass                                renderPass
-    u32                                         attachmentCount
-    const VkImageView*                          pAttachments
-    u32                                         width
-    u32                                         height
-    u32                                         layers
-}
-
-class VkDrawIndirectCommand {
-    u32                                         vertexCount
-    u32                                         instanceCount
-    u32                                         firstVertex
-    u32                                         firstInstance
-}
-
-class VkDrawIndexedIndirectCommand {
-    u32                                         indexCount
-    u32                                         instanceCount
-    u32                                         firstIndex
-    s32                                         vertexOffset
-    u32                                         firstInstance
-}
-
-class VkDispatchIndirectCommand {
-    u32                                         x
-    u32                                         y
-    u32                                         z
-}
-
-class VkBaseOutStructure {
-    VkStructureType                             sType
-    void*                                       pNext
-}
-
-class VkBaseInStructure {
-    VkStructureType                             sType
-    const void*                                 pNext
-}
-
-//@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                                 splitInstanceBindRegionCount
-    const VkRect2D*                     pSplitInstanceBindRegions
-}
-
-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
-    const 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
-    u32                                         maxImageCount
-    VkExtent2D                                  currentExtent
-    VkExtent2D                                  minImageExtent
-    VkExtent2D                                  maxImageExtent
-    u32                                         maxImageArrayLayers
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkSurfaceTransformFlagBitsKHR               currentTransform
-    VkCompositeAlphaFlagsKHR                    supportedCompositeAlpha
-    VkImageUsageFlags                           supportedUsageFlags
-}
-
-@extension("VK_KHR_surface") // 1
-class VkSurfaceFormatKHR {
-    VkFormat                                    format
-    VkColorSpaceKHR                             colorSpace
-}
-
-@extension("VK_KHR_swapchain") // 2
-class VkSwapchainCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainCreateFlagsKHR                   flags
-    VkSurfaceKHR                                surface
-    u32                                         minImageCount
-    VkFormat                                    imageFormat
-    VkColorSpaceKHR                             imageColorSpace
-    VkExtent2D                                  imageExtent
-    u32                                         imageArrayLayers
-    VkImageUsageFlags                           imageUsage
-    VkSharingMode                               sharingMode
-    u32                                         queueFamilyIndexCount
-    const u32*                                  pQueueFamilyIndices
-    VkSurfaceTransformFlagBitsKHR               preTransform
-    VkCompositeAlphaFlagBitsKHR                 compositeAlpha
-    VkPresentModeKHR                            presentMode
-    VkBool32                                    clipped
-    VkSwapchainKHR                              oldSwapchain
-}
-
-@extension("VK_KHR_swapchain") // 2
-class VkPresentInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    u32                                         swapchainCount
-    const VkSwapchainKHR*                       pSwapchains
-    const u32*                                  pImageIndices
-    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
-    const char*                                 displayName
-    VkExtent2D                                  physicalDimensions
-    VkExtent2D                                  physicalResolution
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkBool32                                    planeReorderPossible
-    VkBool32                                    persistentContent
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModeParametersKHR {
-    VkExtent2D                                  visibleRegion
-    u32                                         refreshRate
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModePropertiesKHR {
-    VkDisplayModeKHR                            displayMode
-    VkDisplayModeParametersKHR                  parameters
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModeCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayModeCreateFlagsKHR                 flags
-    VkDisplayModeParametersKHR                  parameters
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayPlanePropertiesKHR {
-    VkDisplayKHR                                currentDisplay
-    u32                                         currentStackIndex
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayPlaneCapabilitiesKHR {
-    VkDisplayPlaneAlphaFlagsKHR                 supportedAlpha
-    VkOffset2D                                  minSrcPosition
-    VkOffset2D                                  maxSrcPosition
-    VkExtent2D                                  minSrcExtent
-    VkExtent2D                                  maxSrcExtent
-    VkOffset2D                                  minDstPosition
-    VkOffset2D                                  maxDstPosition
-    VkExtent2D                                  minDstExtent
-    VkExtent2D                                  maxDstExtent
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplaySurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplaySurfaceCreateFlagsKHR              flags
-    VkDisplayModeKHR                            displayMode
-    u32                                         planeIndex
-    u32                                         planeStackIndex
-    VkSurfaceTransformFlagBitsKHR               transform
-    f32                                         globalAlpha
-    VkDisplayPlaneAlphaFlagBitsKHR              alphaMode
-    VkExtent2D                                  imageExtent
-}
-
-@extension("VK_KHR_display_swapchain") // 4
-class VkDisplayPresentInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkRect2D                                    srcRect
-    VkRect2D                                    dstRect
-    VkBool32                                    persistent
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-class VkXlibSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkXlibSurfaceCreateFlagsKHR                 flags
-    platform.Display*                           dpy
-    platform.Window                             window
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-class VkXcbSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkXcbSurfaceCreateFlagsKHR                  flags
-    platform.xcb_connection_t*                  connection
-    platform.xcb_window_t                       window
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-class VkWaylandSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkWaylandSurfaceCreateFlagsKHR              flags
-    platform.wl_display*                        display
-    platform.wl_surface*                        surface
-}
-
-@extension("VK_KHR_android_surface") // 9
-class VkAndroidSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkAndroidSurfaceCreateFlagsKHR              flags
-    platform.ANativeWindow*                     window
-}
-
-@extension("VK_KHR_win32_surface") // 10
-class VkWin32SurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkWin32SurfaceCreateFlagsKHR                flags
-    platform.HINSTANCE                          hinstance
-    platform.HWND                               hwnd
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@internal class Gralloc1Usage {
-    u64                                         consumer
-    u64                                         producer
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkNativeBufferANDROID {
-    VkStructureType                             sType
-    const void*                                 pNext
-    platform.buffer_handle_t                    handle
-    s32                                         stride
-    s32                                         format
-    s32                                         usage
-    Gralloc1Usage                               usage2
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkSwapchainImageCreateInfoANDROID {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainImageUsageFlagsANDROID           flags
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkPhysicalDevicePresentationPropertiesANDROID {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    sharedImage
-}
-
-@extension("VK_EXT_debug_report") // 12
-class VkDebugReportCallbackCreateInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportFlagsEXT                       flags
-    PFN_vkDebugReportCallbackEXT                pfnCallback
-    void*                                       pUserData
-}
-
-@extension("VK_AMD_rasterization_order") // 19
-class VkPipelineRasterizationStateRasterizationOrderAMD {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkRasterizationOrderAMD                     rasterizationOrder
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerObjectNameInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportObjectTypeEXT                  objectType
-    u64                                         object
-    const char*                                 pObjectName
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerObjectTagInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportObjectTypeEXT                  objectType
-    u64                                         object
-    u64                                         tagName
-    platform.size_t                             tagSize
-    const void*                                 pTag
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerMarkerInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const char*                                 pMarkerName
-    f32[4]                                      color
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationImageCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    dedicatedAllocation
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationBufferCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    dedicatedAllocation
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationMemoryAllocateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkImage                                     image
-    VkBuffer                                    buffer
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPhysicalDeviceTransformFeedbackFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    transformFeedback
-    VkBool32                                    geometryStreams
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPhysicalDeviceTransformFeedbackPropertiesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxTransformFeedbackStreams
-    u32                                         maxTransformFeedbackBuffers
-    VkDeviceSize                                maxTransformFeedbackBufferSize
-    u32                                         maxTransformFeedbackStreamDataSize
-    u32                                         maxTransformFeedbackBufferDataSize
-    u32                                         maxTransformFeedbackBufferDataStride
-    VkBool32                                    transformFeedbackQueries
-    VkBool32                                    transformFeedbackStreamsLinesTriangles
-    VkBool32                                    transformFeedbackRasterizationStreamSelect
-    VkBool32                                    transformFeedbackDraw
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPipelineRasterizationStateStreamCreateInfoEXT {
-    VkStructureType                                     sType
-    const void*                                         pNext
-    VkPipelineRasterizationStateStreamCreateFlagsEXT    flags
-    u32                                                 rasterizationStream
-}
-
-@extension("VK_AMD_texture_gather_bias_lod") // 42
-class VkTextureLODGatherFormatPropertiesAMD {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    supportsTextureGatherLODBiasAMD
-}
-
-@extension("VK_AMD_shader_info") // 43
-class VkShaderResourceUsageAMD {
-    u32                                         numUsedVgprs
-    u32                                         numUsedSgprs
-    u32                                         ldsSizePerLocalWorkGroup
-    platform.size_t                             ldsUsageSizeInBytes
-    platform.size_t                             scratchMemUsageInBytes
-}
-
-@extension("VK_AMD_shader_info") // 43
-class VkShaderStatisticsInfoAMD {
-    VkShaderStageFlags                          shaderStageMask
-    VkShaderResourceUsageAMD                    resourceUsage
-    u32                                         numPhysicalVgprs
-    u32                                         numPhysicalSgprs
-    u32                                         numAvailableVgprs
-    u32                                         numAvailableSgprs
-    u32[3]                                      computeWorkGroupSize
-}
-
-@extension("VK_NV_corner_sampled_image") // 51
-class VkPhysicalDeviceCornerSampledImageFeaturesNV {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    cornerSampledImage
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkRenderPassMultiviewCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         subpassCount
-    const u32*                                  pViewMasks
-    u32                                         dependencyCount
-    const s32*                                  pViewOffsets
-    u32                                         correlationMaskCount
-    const u32*                                  pCorrelationMasks
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkPhysicalDeviceMultiviewFeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    multiview
-    VkBool32                                    multiviewGeometryShader
-    VkBool32                                    multiviewTessellationShader
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkPhysicalDeviceMultiviewPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxMultiviewViewCount
-    u32                                         maxMultiviewInstanceIndex
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-class VkExternalImageFormatPropertiesNV {
-    VkImageFormatProperties                     imageFormatProperties
-    VkExternalMemoryFeatureFlagsNV              externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlagsNV           exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlagsNV           compatibleHandleTypes
-}
-
-@extension("VK_NV_external_memory") // 57
-class VkExternalMemoryImageCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleTypes
-}
-
-@extension("VK_NV_external_memory") // 57
-class VkExportMemoryAllocateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleTypes
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-class VkImportMemoryWin32HandleInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleType
-    platform.HANDLE                             handle
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-class VkExportMemoryWin32HandleInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-}
-
-@extension("VK_NV_win32_keyed_mutex") // 59
-class VkWin32KeyedMutexAcquireReleaseInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         acquireCount
-    const VkDeviceMemory*                       pAcquireSyncs
-    const u64*                                  pAcquireKeys
-    const u32*                                  pAcquireTimeoutMilliseconds
-    u32                                         releaseCount
-    const VkDeviceMemory*                       pReleaseSyncs
-    const u64*                                  pReleaseKeys
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceFeatures2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceFeatures                    features
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceProperties                  properties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkFormatProperties                          formatProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkImageFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkImageFormatProperties                     imageFormatProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceImageFormatInfo2KHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    format
-    VkImageType                                 type
-    VkImageTiling                               tiling
-    VkImageUsageFlags                           usage
-    VkImageCreateFlags                          flags
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkQueueFamilyProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkQueueFamilyProperties                     queueFamilyProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceMemoryProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceMemoryProperties            memoryProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkSparseImageFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkSparseImageFormatProperties               properties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceSparseImageFormatInfo2KHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    format
-    VkImageType                                 type
-    VkSampleCountFlagBits                       samples
-    VkImageUsageFlags                           usage
-    VkImageTiling                               tiling
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkMemoryAllocateFlagsInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkMemoryAllocateFlagsKHR                    flags
-    u32                                         deviceMask
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkBindBufferMemoryDeviceGroupInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceIndexCount
-    const u32*                                  pDeviceIndices
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkBindImageMemoryDeviceGroupInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceIndexCount
-    const u32*                                  pDeviceIndices
-    u32                                         SFRRectCount
-    const VkRect2D*                             pSFRRects
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupRenderPassBeginInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceMask
-    u32                                         deviceRenderAreaCount
-    const VkRect2D*                             pDeviceRenderAreas
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupCommandBufferBeginInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceMask
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupSubmitInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const u32*                                  pWaitSemaphoreDeviceIndices
-    u32                                         commandBufferCount
-    const u32*                                  pCommandBufferDeviceMasks
-    u32                                         signalSemaphoreCount
-    const u32*                                  pSignalSemaphoreDeviceIndices
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupBindSparseInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         resourceDeviceIndex
-    u32                                         memoryDeviceIndex
-}
-
-@extension("VK_EXT_validation_flags") // 62
-class VkValidationFlagsEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         disabledValidationCheckCount
-    const VkValidationCheckEXT*                 pDisabledValidationChecks
-}
-
-@extension("VK_NN_vi_surface") // 63
-class VkViSurfaceCreateInfoNN {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkViSurfaceCreateFlagsNN                    flags
-    void*                                       window
-}
-
-@extension("VK_EXT_astc_decode_mode") // 68
-class VkImageViewASTCDecodeModeEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    decodeMode
-}
-
-@extension("VK_EXT_astc_decode_mode") // 68
-class VkPhysicalDeviceASTCDecodeFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    decodeModeSharedExponent
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-class VkPhysicalDeviceGroupPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             physicalDeviceCount
-    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE]      physicalDevices
-    VkBool32                                        subsetAllocation
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-class VkDeviceGroupDeviceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         physicalDeviceCount
-    const VkPhysicalDevice*                     pPhysicalDevices
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalMemoryPropertiesKHR {
-    VkExternalMemoryFeatureFlagsKHR             externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlagsKHR          exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlagsKHR          compatibleHandleTypes
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalImageFormatInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalImageFormatPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalMemoryPropertiesKHR               externalMemoryProperties
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalBufferInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBufferCreateFlags                         flags
-    VkBufferUsageFlags                          usage
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalBufferPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalMemoryPropertiesKHR               externalMemoryProperties
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceIDPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u8[VK_UUID_SIZE]                            deviceUUID
-    u8[VK_UUID_SIZE]                            driverUUID
-    u8[VK_LUID_SIZE]                            deviceLUID
-    u32                                         deviceNodeMask
-    VkBool32                                    deviceLUIDValid
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExternalMemoryImageCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExternalMemoryBufferCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExportMemoryAllocateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkImportMemoryWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-    platform.HANDLE                             handle
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkExportMemoryWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkMemoryWin32HandlePropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         memoryTypeBits
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkMemoryGetWin32HandleInfoKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkDeviceMemory                              memory
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkImportMemoryFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-    int                                         fd
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkMemoryFdPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         memoryTypeBits
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkMemoryGetFdInfoKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkDeviceMemory                              memory
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_win32_keyed_mutex") // 76
-class VkWin32KeyedMutexAcquireReleaseInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         acquireCount
-    const VkDeviceMemory*                       pAcquireSyncs
-    const u64*                                  pAcquireKeys
-    const u32*                                  pAcquireTimeouts
-    u32                                         releaseCount
-    const VkDeviceMemory*                       pReleaseSyncs
-    const u64*                                  pReleaseKeys
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-class VkPhysicalDeviceExternalSemaphoreInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-class VkExternalSemaphorePropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalSemaphoreHandleTypeFlagsKHR       exportFromImportedHandleTypes
-    VkExternalSemaphoreHandleTypeFlagsKHR       compatibleHandleTypes
-    VkExternalSemaphoreFeatureFlagsKHR          externalSemaphoreFeatures
-}
-
-@extension("VK_KHR_external_semaphore") // 78
-class VkExportSemaphoreCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagsKHR       handleTypes
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkImportSemaphoreWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkSemaphoreImportFlagsKHR                   flags
-    VkExternalSemaphoreHandleTypeFlagsKHR       handleType
-    platform.HANDLE                             handle
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkExportSemaphoreWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkD3D12FenceSubmitInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreValuesCount
-    const u64*                                  pWaitSemaphoreValues
-    u32                                         signalSemaphoreValuesCount
-    const u64*                                  pSignalSemaphoreValues
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkSemaphoreGetWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-class VkImportSemaphoreFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkSemaphoreImportFlagsKHR                   flags
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-    s32                                         fd
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-class VkSemaphoreGetFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_push_descriptor") // 81
-class VkPhysicalDevicePushDescriptorPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxPushDescriptors
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkConditionalRenderingBeginInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBuffer                                    buffer
-    VkDeviceSize                                offset
-    VkConditionalRenderingFlagsEXT              flags
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkPhysicalDeviceConditionalRenderingFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    conditionalRendering
-    VkBool32                                    inheritedConditionalRendering
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkCommandBufferInheritanceConditionalRenderingInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    conditionalRenderingEnable
-}
-
-@extension("VK_KHR_shader_float16_int8") // 83
-class VkPhysicalDeviceFloat16Int8FeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    shaderFloat16
-    VkBool32                                    shaderInt8
-}
-
-@extension("VK_KHR_16bit_storage") // 84
-class VkPhysicalDevice16BitStorageFeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    storageBuffer16BitAccess
-    VkBool32                                    uniformAndStorageBuffer16BitAccess
-    VkBool32                                    storagePushConstant16
-    VkBool32                                    storageInputOutput16
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkRectLayerKHR {
-    VkOffset2D                                  offset
-    VkExtent2D                                  extent
-    u32                                         layer
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkPresentRegionKHR {
-    u32                                         rectangleCount
-    const VkRectLayerKHR*                       pRectangles
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkPresentRegionsKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         swapchainCount
-    const VkPresentRegionKHR*                   pRegions
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-class VkDescriptorUpdateTemplateEntryKHR {
-    u32                                         dstBinding
-    u32                                         dstArrayElement
-    u32                                         descriptorCount
-    VkDescriptorType                            descriptorType
-    platform.size_t                             offset
-    platform.size_t                             stride
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-class VkDescriptorUpdateTemplateCreateInfoKHR {
-    VkStructureType                              sType
-    void*                                        pNext
-    VkDescriptorUpdateTemplateCreateFlagsKHR     flags
-    u32                                          descriptorUpdateEntryCount
-    const VkDescriptorUpdateTemplateEntryKHR*    pDescriptorUpdateEntries
-    VkDescriptorUpdateTemplateTypeKHR            templateType
-    VkDescriptorSetLayout                        descriptorSetLayout
-    VkPipelineBindPoint                          pipelineBindPoint
-    VkPipelineLayout                             pipelineLayout
-    u32                                          set
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkDeviceGeneratedCommandsFeaturesNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    computeBindingPointSupport
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkDeviceGeneratedCommandsLimitsNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         maxIndirectCommandsLayoutTokenCount
-    u32                                         maxObjectEntryCounts
-    u32                                         minSequenceCountBufferOffsetAlignment
-    u32                                         minSequenceIndexBufferOffsetAlignment
-    u32                                         minCommandsTokenBufferOffsetAlignment
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsTokenNVX {
-    VkIndirectCommandsTokenTypeNVX              tokenType
-    VkBuffer                                    buffer
-    VkDeviceSize                                offset
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsLayoutTokenNVX {
-    VkIndirectCommandsTokenTypeNVX              tokenType
-    u32                                         bindingUnit
-    u32                                         dynamicCount
-    u32                                         divisor
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsLayoutCreateInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkPipelineBindPoint                         pipelineBindPoint
-    VkIndirectCommandsLayoutUsageFlagsNVX       flags
-    u32                                         tokenCount
-    const VkIndirectCommandsLayoutTokenNVX*     pTokens
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkCmdProcessCommandsInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkObjectTableNVX                            objectTable
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
-    u32                                         indirectCommandsTokenCount
-    const VkIndirectCommandsTokenNVX*           pIndirectCommandsTokens
-    u32                                         maxSequencesCount
-    VkCommandBuffer                             targetCommandBuffer
-    VkBuffer                                    sequencesCountBuffer
-    VkDeviceSize                                sequencesCountOffset
-    VkBuffer                                    sequencesIndexBuffer
-    VkDeviceSize                                sequencesIndexOffset
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkCmdReserveSpaceForCommandsInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkObjectTableNVX                            objectTable
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
-    u32                                         maxSequencesCount
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableCreateInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         objectCount
-    const VkObjectEntryTypeNVX*                 pObjectEntryTypes
-    const u32*                                  pObjectEntryCounts
-    const VkObjectEntryUsageFlagsNVX*           pObjectEntryUsageFlags
-    u32                                         maxUniformBuffersPerDescriptor
-    u32                                         maxStorageBuffersPerDescriptor
-    u32                                         maxStorageImagesPerDescriptor
-    u32                                         maxSampledImagesPerDescriptor
-    u32                                         maxPipelineLayouts
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTablePipelineEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipeline                                  pipeline
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableDescriptorSetEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipelineLayout                            pipelineLayout
-    VkDescriptorSet                             descriptorSet
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableVertexBufferEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkBuffer                                    buffer
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableIndexBufferEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkBuffer                                    buffer
-    VkIndexType                                 indexType
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTablePushConstantEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipelineLayout                            pipelineLayout
-    VkShaderStageFlags                          stageFlags
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-class VkViewportWScalingNV {
-    f32                                         xcoeff
-    f32                                         ycoeff
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-class VkPipelineViewportWScalingStateCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    viewportWScalingEnable
-    u32                                         viewportCount
-    const VkViewportWScalingNV*                 pViewportWScalings
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-class VkSurfaceCapabilities2EXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         minImageCount
-    u32                                         maxImageCount
-    VkExtent2D                                  currentExtent
-    VkExtent2D                                  minImageExtent
-    VkExtent2D                                  maxImageExtent
-    u32                                         maxImageArrayLayers
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkSurfaceTransformFlagBitsKHR               currentTransform
-    VkCompositeAlphaFlagsKHR                    supportedCompositeAlpha
-    VkImageUsageFlags                           supportedUsageFlags
-    VkSurfaceCounterFlagsEXT                    supportedSurfaceCounters
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDisplayPowerInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayPowerStateEXT                      powerState
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDeviceEventInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDeviceEventTypeEXT                        deviceEvent
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDisplayEventInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayEventTypeEXT                       displayEvent
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkSwapchainCounterCreateInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSurfaceCounterFlagsEXT                    surfaceCounters
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkRefreshCycleDurationGOOGLE {
-    u64                                             refreshDuration
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPastPresentationTimingGOOGLE {
-    u32                                             presentID
-    u64                                             desiredPresentTime
-    u64                                             actualPresentTime
-    u64                                             earliestPresentTime
-    u64                                             presentMargin
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPresentTimeGOOGLE {
-    u32                                             presentID
-    u64                                             desiredPresentTime
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPresentTimesInfoGOOGLE {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             swapchainCount
-    const VkPresentTimeGOOGLE*                      pTimes
-}
-
-@extension("VK_NVX_multiview_per_view_attributes") // 98
-class VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    perViewPositionAllComponents
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-class VkViewportSwizzleNV {
-    VkViewportCoordinateSwizzleNV               x
-    VkViewportCoordinateSwizzleNV               y
-    VkViewportCoordinateSwizzleNV               z
-    VkViewportCoordinateSwizzleNV               w
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-class VkPipelineViewportSwizzleStateCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkPipelineViewportSwizzleStateCreateFlagsNV flags
-    u32                                         viewportCount
-    const VkViewportSwizzleNV*                  pViewportSwizzles
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxDiscardRectangles
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-class VkPipelineDiscardRectangleStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineDiscardRectangleStateCreateFlagsEXT   flags
-    VkDiscardRectangleModeEXT                       discardRectangleMode
-    u32                                             discardRectangleCount
-    const VkRect2D*                                 pDiscardRectangles
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-class VkPhysicalDeviceConservativeRasterizationPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    f32                                             primitiveOverestimationSize
-    f32                                             maxExtraPrimitiveOverestimationSize
-    f32                                             extraPrimitiveOverestimationSizeGranularity
-    VkBool32                                        primitiveUnderestimation
-    VkBool32                                        conservativePointAndLineRasterization
-    VkBool32                                        degenerateTrianglesRasterized
-    VkBool32                                        degenerateLinesRasterized
-    VkBool32                                        fullyCoveredFragmentShaderInputVariable
-    VkBool32                                        conservativeRasterizationPostDepthCoverage
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-class VkPipelineRasterizationConservativeStateCreateInfoEXT {
-    VkStructureType                                           sType
-    const void*                                               pNext
-    VkPipelineRasterizationConservativeStateCreateFlagsEXT    flags
-    VkConservativeRasterizationModeEXT                        conservativeRasterizationMode
-    f32                                                       extraPrimitiveOverestimationSize
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-class VkXYColorEXT {
-    f32                                             x
-    f32                                             y
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-class VkHdrMetadataEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkXYColorEXT                                    displayPrimaryRed
-    VkXYColorEXT                                    displayPrimaryGreen
-    VkXYColorEXT                                    displayPrimaryBlue
-    VkXYColorEXT                                    whitePoint
-    f32                                             maxLuminance
-    f32                                             minLuminance
-    f32                                             maxContentLightLevel
-    f32                                             maxFrameAverageLightLevel
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkAttachmentDescription2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAttachmentDescriptionFlags                    flags
-    VkFormat                                        format
-    VkSampleCountFlagBits                           samples
-    VkAttachmentLoadOp                              loadOp
-    VkAttachmentStoreOp                             storeOp
-    VkAttachmentLoadOp                              stencilLoadOp
-    VkAttachmentStoreOp                             stencilStoreOp
-    VkImageLayout                                   initialLayout
-    VkImageLayout                                   finalLayout
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkAttachmentReference2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             attachment
-    VkImageLayout                                   layout
-    VkImageAspectFlags                              aspectMask
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassDescription2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSubpassDescriptionFlags                       flags
-    VkPipelineBindPoint                             pipelineBindPoint
-    u32                                             viewMask
-    u32                                             inputAttachmentCount
-    const VkAttachmentReference2KHR*                pInputAttachments
-    u32                                             colorAttachmentCount
-    const VkAttachmentReference2KHR*                pColorAttachments
-    const VkAttachmentReference2KHR*                pResolveAttachments
-    const VkAttachmentReference2KHR*                pDepthStencilAttachment
-    u32                                             preserveAttachmentCount
-    const u32*                                      pPreserveAttachments
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassDependency2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             srcSubpass
-    u32                                             dstSubpass
-    VkPipelineStageFlags                            srcStageMask
-    VkPipelineStageFlags                            dstStageMask
-    VkAccessFlags                                   srcAccessMask
-    VkAccessFlags                                   dstAccessMask
-    VkDependencyFlags                               dependencyFlags
-    s32                                             viewOffset
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkRenderPassCreateInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkRenderPassCreateFlags                         flags
-    u32                                             attachmentCount
-    const VkAttachmentDescription2KHR*              pAttachments
-    u32                                             subpassCount
-    const VkSubpassDescription2KHR*                 pSubpasses
-    u32                                             dependencyCount
-    const VkSubpassDependency2KHR*                  pDependencies
-    u32                                             correlatedViewMaskCount
-    const u32*                                      pCorrelatedViewMasks
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassBeginInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSubpassContents                               contents
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassEndInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-}
-
-@extension("VK_KHR_shared_presentable_image") // 112
-class VkSharedPresentSurfaceCapabilitiesKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               sharedPresentSupportedUsageFlags
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-class VkPhysicalDeviceExternalFenceInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-class VkExternalFencePropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExternalFenceHandleTypeFlagsKHR               exportFromImportedHandleTypes
-    VkExternalFenceHandleTypeFlagsKHR               compatibleHandleTypes
-    VkExternalFenceFeatureFlagsKHR                  externalFenceFeatures
-}
-
-@extension("VK_KHR_external_fence") // 114
-class VkExportFenceCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalFenceHandleTypeFlagsKHR               handleTypes
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkImportFenceWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkFenceImportFlagsKHR                           flags
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-    platform.HANDLE                                 handle
-    platform.LPCWSTR                                name
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkExportFenceWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    const platform.SECURITY_ATTRIBUTES*             pAttributes
-    platform.DWORD                                  dwAccess
-    platform.LPCWSTR                                name
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkFenceGetWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-class VkImportFenceFdInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkFenceImportFlagsKHR                           flags
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-    int                                             fd
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-class VkFenceGetFdInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkPhysicalDevicePointClippingPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPointClippingBehaviorKHR                      pointClippingBehavior
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkInputAttachmentAspectReferenceKHR {
-    u32                                             subpass
-    u32                                             inputAttachmentIndex
-    VkImageAspectFlags                              aspectMask
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkRenderPassInputAttachmentAspectCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             aspectReferenceCount
-    const VkInputAttachmentAspectReferenceKHR*      pAspectReferences
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkImageViewUsageCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               usage
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkPipelineTessellationDomainOriginStateCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkTessellationDomainOriginKHR                   domainOrigin
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkPhysicalDeviceSurfaceInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSurfaceKHR                                    surface
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkSurfaceCapabilities2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSurfaceCapabilitiesKHR                        surfaceCapabilities
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkSurfaceFormat2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSurfaceFormatKHR                              surfaceFormat
-}
-
-@extension("VK_KHR_variable_pointers") // 121
-class VkPhysicalDeviceVariablePointerFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        variablePointersStorageBuffer
-    VkBool32                                        variablePointers
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPropertiesKHR                          displayProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPlanePropertiesKHR                     displayPlaneProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayModeProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayModePropertiesKHR                      displayModeProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDisplayModeKHR                                mode
-    u32                                             planeIndex
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneCapabilities2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPlaneCapabilitiesKHR                   capabilities
-}
-
-@extension("VK_MVK_ios_surface") // 123
-class VkIOSSurfaceCreateInfoMVK {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkIOSSurfaceCreateFlagsMVK                      flags
-    const void*                                     pView
-}
-
-@extension("VK_MVK_macos_surface") // 124
-class VkMacOSSurfaceCreateInfoMVK {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkMacOSSurfaceCreateFlagsMVK                    flags
-    const void*                                     pView
-}
-
-@extension("VK_KHR_dedicated_allocation") // 128
-class VkMemoryDedicatedRequirementsKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        prefersDedicatedAllocation
-    VkBool32                                        requiresDedicatedAllocation
-}
-
-@extension("VK_KHR_dedicated_allocation") // 128
-class VkMemoryDedicatedAllocateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-    VkBuffer                                        buffer
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsObjectNameInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkObjectType                                    objectType
-    u64                                             objectHandle
-    const char*                                     pObjectName
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsObjectTagInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkObjectType                                    objectType
-    u64                                             objectHandle
-    u64                                             tagName
-    platform.size_t                                 tagSize
-    const void*                                     pTag
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsLabelEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    const char*                                     pLabelName
-    f32[4]                                          color
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsMessengerCallbackDataEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDebugUtilsMessengerCallbackDataFlagsEXT       flags
-    const char*                                     pMessageIdName
-    s32                                             messageIdNumber
-    const char*                                     pMessage
-    u32                                             queueLabelCount
-    const VkDebugUtilsLabelEXT*                     pQueueLabels
-    u32                                             cmdBufLabelCount
-    const VkDebugUtilsLabelEXT*                     pCmdBufLabels
-    u32                                             objectCount
-    const VkDebugUtilsObjectNameInfoEXT*            pObjects
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsMessengerCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDebugUtilsMessengerCreateFlagsEXT             flags
-    VkDebugUtilsMessageSeverityFlagsEXT             messageSeverity
-    VkDebugUtilsMessageTypeFlagsEXT                 messageTypes
-    PFN_vkDebugUtilsMessengerCallbackEXT            pfnUserCallback
-    void*                                           pUserData
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 131
-class VkAndroidHardwareBufferUsageANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             androidHardwareBufferUsage
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkAndroidHardwareBufferPropertiesANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDeviceSize                                    allocationSize
-    u32                                             memoryTypeBits
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkAndroidHardwareBufferFormatPropertiesANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkFormat                                        format
-    u64                                             externalFormat
-    VkFormatFeatureFlags                            formatFeatures
-    VkComponentMapping                              samplerYcbcrConversionComponents
-    VkSamplerYcbcrModelConversion                   suggestedYcbcrModel
-    VkSamplerYcbcrRange                             suggestedYcbcrRange
-    VkChromaLocation                                suggestedXChromaOffset
-    VkChromaLocation                                suggestedYChromaOffset
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkImportAndroidHardwareBufferInfoANDROID {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    platform.AHardwareBuffer*                       buffer
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkMemoryGetAndroidHardwareBufferInfoANDROID {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDeviceMemory                                  memory
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkExternalFormatANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             externalFormat
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-class VkSamplerReductionModeCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSamplerReductionModeEXT                       reductionMode
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-class VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        filterMinmaxSingleComponentFormats
-    VkBool32                                        filterMinmaxImageComponentMapping
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        inlineUniformBlock
-    VkBool32                                        descriptorBindingInlineUniformBlockUpdateAfterBind
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxInlineUniformBlockSize
-    u32                                             maxPerStageDescriptorInlineUniformBlocks
-    u32                                             maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks
-    u32                                             maxDescriptorSetInlineUniformBlocks
-    u32                                             maxDescriptorSetUpdateAfterBindInlineUniformBlocks
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkWriteDescriptorSetInlineUniformBlockEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             dataSize
-    const void*                                     pData
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             maxInlineUniformBlockBindings
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSampleLocationEXT {
-    f32                                             x
-    f32                                             y
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSampleLocationsInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSampleCountFlagBits                           sampleLocationsPerPixel
-    VkExtent2D                                      sampleLocationGridSize
-    u32                                             sampleLocationsCount
-    const VkSampleLocationEXT*                      pSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkAttachmentSampleLocationsEXT {
-    u32                                             attachmentIndex
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSubpassSampleLocationsEXT {
-    u32                                             subpassIndex
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkRenderPassSampleLocationsBeginInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             attachmentInitialSampleLocationsCount
-    const VkAttachmentSampleLocationsEXT*           pAttachmentInitialSampleLocations
-    u32                                             postSubpassSampleLocationsCount
-    const VkSubpassSampleLocationsEXT*              pPostSubpassSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkPipelineSampleLocationsStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        sampleLocationsEnable
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkPhysicalDeviceSampleLocationsPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSampleCountFlags                              sampleLocationSampleCounts
-    VkExtent2D                                      maxSampleLocationGridSize
-    f32[2]                                          sampleLocationCoordinateRange
-    u32                                             sampleLocationSubPixelBits
-    VkBool32                                        variableSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkMultisamplePropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      maxSampleLocationGridSize
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkBufferMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        buffer
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkImageMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkImageSparseMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkMemoryRequirements2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkMemoryRequirements                            memoryRequirements
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkSparseImageMemoryRequirements2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSparseImageMemoryRequirements                 memoryRequirements
-}
-
-@extension("VK_KHR_image_format_list") // 148
-class VkImageFormatListCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             viewFormatCount
-    const VkFormat*                                 pViewFormats
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        advancedBlendCoherentOperations
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             advancedBlendMaxColorAttachments
-    VkBool32                                        advancedBlendIndependentBlend
-    VkBool32                                        advancedBlendNonPremultipliedSrcColor
-    VkBool32                                        advancedBlendNonPremultipliedDstColor
-    VkBool32                                        advancedBlendCorrelatedOverlap
-    VkBool32                                        advancedBlendAllOperations
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPipelineColorBlendAdvancedStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        srcPremultiplied
-    VkBool32                                        dstPremultiplied
-    VkBlendOverlapEXT                               blendOverlap
-}
-
-@extension("VK_NV_fragment_coverage_to_color") // 150
-class VkPipelineCoverageToColorStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineCoverageToColorStateCreateFlagsNV     flags
-    VkBool32                                        coverageToColorEnable
-    u32                                             coverageToColorLocation
-}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-class VkPipelineCoverageModulationStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineCoverageModulationStateCreateFlagsNV  flags
-    VkCoverageModulationModeNV                      coverageModulationMode
-    VkBool32                                        coverageModulationTableEnable
-    u32                                             coverageModulationTableCount
-    const f32*                                      pCoverageModulationTable
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFormat                                        format
-    VkSamplerYcbcrModelConversionKHR                ycbcrModel
-    VkSamplerYcbcrRangeKHR                          ycbcrRange
-    VkComponentMapping                              components
-    VkChromaLocationKHR                             xChromaOffset
-    VkChromaLocationKHR                             yChromaOffset
-    VkFilter                                        chromaFilter
-    VkBool32                                        forceExplicitReconstruction
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSamplerYcbcrConversionKHR                     conversion
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkBindImagePlaneMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageAspectFlagBits                           planeAspect
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkImagePlaneMemoryRequirementsInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageAspectFlagBits                           planeAspect
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        samplerYcbcrConversion
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionImageFormatPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             combinedImageSamplerDescriptorCount
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-class VkBindBufferMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        buffer
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-class VkBindImageMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkDrmFormatModifierPropertiesEXT {
-    u64                                             drmFormatModifier
-    u32                                             drmFormatModifierPlaneCount
-    VkFormatFeatureFlags                            drmFormatModifierTilingFeatures
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkDrmFormatModifierPropertiesListEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             drmFormatModifierCount
-    VkDrmFormatModifierPropertiesEXT*               pDrmFormatModifierProperties
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkPhysicalDeviceImageDrmFormatModifierInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u64                                             drmFormatModifier
-    VkSharingMode                                   sharingMode
-    u32                                             queueFamilyIndexCount
-    const u32*                                      pQueueFamilyIndices
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierListCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             drmFormatModifierCount
-    const u64*                                      pDrmFormatModifiers
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierExplicitCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u64                                             drmFormatModifier
-    u32                                             drmFormatModifierPlaneCount
-    const VkSubresourceLayout*                      pPlaneLayouts
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             drmFormatModifier
-}
-
-@extension("VK_EXT_validation_cache") // 161
-class VkValidationCacheCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkValidationCacheCreateFlagsEXT                 flags
-    platform.size_t                                 initialDataSize
-    const void*                                     pInitialData
-}
-
-@extension("VK_EXT_validation_cache") // 161
-class VkShaderModuleValidationCacheCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkValidationCacheEXT                            validationCache
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             bindingCount
-    const VkDescriptorBindingFlagsEXT*              pBindingFlags
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkPhysicalDeviceDescriptorIndexingFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shaderInputAttachmentArrayDynamicIndexing
-    VkBool32                                        shaderUniformTexelBufferArrayDynamicIndexing
-    VkBool32                                        shaderStorageTexelBufferArrayDynamicIndexing
-    VkBool32                                        shaderUniformBufferArrayNonUniformIndexing
-    VkBool32                                        shaderSampledImageArrayNonUniformIndexing
-    VkBool32                                        shaderStorageBufferArrayNonUniformIndexing
-    VkBool32                                        shaderStorageImageArrayNonUniformIndexing
-    VkBool32                                        shaderInputAttachmentArrayNonUniformIndexing
-    VkBool32                                        shaderUniformTexelBufferArrayNonUniformIndexing
-    VkBool32                                        shaderStorageTexelBufferArrayNonUniformIndexing
-    VkBool32                                        descriptorBindingUniformBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingSampledImageUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageImageUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingUniformTexelBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageTexelBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingUpdateUnusedWhilePending
-    VkBool32                                        descriptorBindingPartiallyBound
-    VkBool32                                        descriptorBindingVariableDescriptorCount
-    VkBool32                                        runtimeDescriptorArray
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkPhysicalDeviceDescriptorIndexingPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxUpdateAfterBindDescriptorsInAllPools
-    VkBool32                                        shaderUniformBufferArrayNonUniformIndexingNative
-    VkBool32                                        shaderSampledImageArrayNonUniformIndexingNative
-    VkBool32                                        shaderStorageBufferArrayNonUniformIndexingNative
-    VkBool32                                        shaderStorageImageArrayNonUniformIndexingNative
-    VkBool32                                        shaderInputAttachmentArrayNonUniformIndexingNative
-    VkBool32                                        robustBufferAccessUpdateAfterBind
-    VkBool32                                        quadDivergentImplicitLod
-    u32                                             maxPerStageDescriptorUpdateAfterBindSamplers
-    u32                                             maxPerStageDescriptorUpdateAfterBindUniformBuffers
-    u32                                             maxPerStageDescriptorUpdateAfterBindStorageBuffers
-    u32                                             maxPerStageDescriptorUpdateAfterBindSampledImages
-    u32                                             maxPerStageDescriptorUpdateAfterBindStorageImages
-    u32                                             maxPerStageDescriptorUpdateAfterBindInputAttachments
-    u32                                             maxPerStageUpdateAfterBindResources
-    u32                                             maxDescriptorSetUpdateAfterBindSamplers
-    u32                                             maxDescriptorSetUpdateAfterBindUniformBuffers
-    u32                                             maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
-    u32                                             maxDescriptorSetUpdateAfterBindStorageBuffers
-    u32                                             maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
-    u32                                             maxDescriptorSetUpdateAfterBindSampledImages
-    u32                                             maxDescriptorSetUpdateAfterBindStorageImages
-    u32                                             maxDescriptorSetUpdateAfterBindInputAttachments
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             descriptorSetCount
-    const u32*                                      pDescriptorCounts
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxVariableDescriptorCount
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkShadingRatePaletteNV {
-    u32                                             shadingRatePaletteEntryCount
-    const VkShadingRatePaletteEntryNV*              pShadingRatePaletteEntries
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPipelineViewportShadingRateImageStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        shadingRateImageEnable
-    u32                                             viewportCount
-    const VkShadingRatePaletteNV*                   pShadingRatePalettes
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPhysicalDeviceShadingRateImageFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shadingRateImage
-    VkBool32                                        shadingRateCoarseSampleOrder
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPhysicalDeviceShadingRateImagePropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      shadingRateTexelSize
-    u32                                             shadingRatePaletteSize
-    u32                                             shadingRateMaxCoarseSamples
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkCoarseSampleLocationNV {
-    u32                                             pixelX
-    u32                                             pixelY
-    u32                                             sample
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkCoarseSampleOrderCustomNV {
-    VkShadingRatePaletteEntryNV                     shadingRate
-    u32                                             sampleCount
-    u32                                             sampleLocationCount
-    const VkCoarseSampleLocationNV*                 pSampleLocations
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkCoarseSampleOrderTypeNV                       sampleOrderType
-    u32                                             customSampleOrderCount
-    const VkCoarseSampleOrderCustomNV*              pCustomSampleOrders
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkRayTracingShaderGroupCreateInfoNV {
-    VkStructureType                  sType
-    const void*                      pNext
-    VkRayTracingShaderGroupTypeNV    type
-    u32                              generalShader
-    u32                              closestHitShader
-    u32                              anyHitShader
-    u32                              intersectionShader
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkRayTracingPipelineCreateInfoNV {
-    VkStructureType                               sType
-    const void*                                   pNext
-    VkPipelineCreateFlags                         flags
-    u32                                           stageCount
-    const VkPipelineShaderStageCreateInfo*        pStages
-    u32                                           groupCount
-    const VkRayTracingShaderGroupCreateInfoNV*    pGroups
-    u32                                           maxRecursionDepth
-    VkPipelineLayout                              layout
-    VkPipeline                                    basePipelineHandle
-    s32                                           basePipelineIndex
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryTrianglesNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        vertexData
-    VkDeviceSize                                    vertexOffset
-    u32                                             vertexCount
-    VkDeviceSize                                    vertexStride
-    VkFormat                                        vertexFormat
-    VkBuffer                                        indexData
-    VkDeviceSize                                    indexOffset
-    u32                                             indexCount
-    VkIndexType                                     indexType
-    VkBuffer                                        transformData
-    VkDeviceSize                                    transformOffset
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryAABBNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        aabbData
-    u32                                             numAABBs
-    u32                                             stride
-    VkDeviceSize                                    offset
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryDataNV {
-    VkGeometryTrianglesNV                           triangles
-    VkGeometryAABBNV                                aabbs
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkGeometryTypeNV                                geometryType
-    VkGeometryDataNV                                geometry
-    VkGeometryFlagsNV                               flags
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureTypeNV                   type
-    VkBuildAccelerationStructureFlagsNV             flags
-    u32                                             instanceCount
-    u32                                             geometryCount
-    const VkGeometryNV*                             pGeometries
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDeviceSize                                    compactedSize
-    VkAccelerationStructureInfoNV                   info
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkBindAccelerationStructureMemoryInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureNV                       accelerationStructure
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-    u32                                             deviceIndexCount
-    const u32*                                      pDeviceIndices
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkDescriptorAccelerationStructureInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             accelerationStructureCount
-    const VkAccelerationStructureNV*                pAccelerationStructures
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureMemoryRequirementsInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureMemoryRequirementsTypeNV type
-    VkAccelerationStructureNV                       accelerationStructure
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkPhysicalDeviceRaytracingPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             shaderGroupHandleSize
-    u32                                             maxRecursionDepth
-    u32                                             maxShaderGroupStride
-    u32                                             shaderGroupBaseAlignment
-    u64                                             maxGeometryCount
-    u64                                             maxInstanceCount
-    u64                                             maxTriangleCount
-    u32                                             maxDescriptorSetAccelerationStructures
-}
-
-@extension("VK_NV_representative_fragment_test") // 167
-class VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        representativeFragmentTest
-}
-
-@extension("VK_NV_representative_fragment_test") // 167
-class VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        representativeFragmentTestEnable
-}
-
-@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
-}
-
-@extension("VK_EXT_global_priority") // 175
-class VkDeviceQueueGlobalPriorityCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkQueueGlobalPriorityEXT                        globalPriority
-}
-
-@extension("VK_KHR_8bit_storage") // 178
-class VkPhysicalDevice8BitStorageFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        storageBuffer8BitAccess
-    VkBool32                                        uniformAndStorageBuffer8BitAccess
-    VkBool32                                        storagePushConstant8
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkImportMemoryHostPointerInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalMemoryHandleTypeFlagBits              handleType
-    void*                                           pHostPointer
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkMemoryHostPointerPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             memoryTypeBits
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkPhysicalDeviceExternalMemoryHostPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDeviceSize                                    minImportedHostPointerAlignment
-}
-
-@extension("VK_KHR_shader_atomic_int64") // 181
-class VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shaderBufferInt64Atomics
-    VkBool32                                        shaderSharedInt64Atomics
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-class VkCalibratedTimestampInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkTimeDomainEXT                                 timeDomain
-}
-
-@extension("VK_AMD_shader_core_properties") // 186
-class VkPhysicalDeviceShaderCorePropertiesAMD {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             shaderEngineCount
-    u32                                             shaderArraysPerEngineCount
-    u32                                             computeUnitsPerShaderArray
-    u32                                             simdPerComputeUnit
-    u32                                             wavefrontsPerSimd
-    u32                                             wavefrontSize
-    u32                                             sgprsPerSimd
-    u32                                             minSgprAllocation
-    u32                                             maxSgprAllocation
-    u32                                             sgprAllocationGranularity
-    u32                                             vgprsPerSimd
-    u32                                             minVgprAllocation
-    u32                                             maxVgprAllocation
-    u32                                             vgprAllocationGranularity
-}
-
-@extension("VK_AMD_memory_overallocation_behavior") // 190
-class VkDeviceMemoryOverallocationCreateInfoAMD {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkMemoryOverallocationBehaviorAMD               overallocationBehavior
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxVertexAttribDivisor
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkVertexInputBindingDivisorDescriptionEXT {
-    u32                                             binding
-    u32                                             divisor
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPipelineVertexInputDivisorStateCreateInfoEXT {
-    VkStructureType                                     sType
-    const void*                                         pNext
-    u32                                                 vertexBindingDivisorCount
-    const VkVertexInputBindingDivisorDescriptionEXT*    pVertexBindingDivisors
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        vertexAttributeInstanceRateDivisor
-    VkBool32                                        vertexAttributeInstanceRateZeroDivisor
-}
-
-@extension("VK_KHR_driver_properties") // 197
-class VkConformanceVersionKHR {
-    u8                                              major
-    u8                                              minor
-    u8                                              subminor
-    u8                                              patch
-}
-
-@extension("VK_KHR_driver_properties") // 197
-class VkPhysicalDeviceDriverPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDriverIdKHR                                   driverID
-    char[VK_MAX_DRIVER_NAME_SIZE_KHR]               driverName
-    char[VK_MAX_DRIVER_INFO_SIZE_KHR]               driverInfo
-    VkConformanceVersionKHR                         conformanceVersion
-}
-
-@extension("VK_KHR_shader_float_controls") // 198
-class VkPhysicalDeviceFloatControlsPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        separateDenormSettings
-    VkBool32                                        separateRoundingModeSettings
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat16
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat32
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat64
-    VkBool32                                        shaderDenormPreserveFloat16
-    VkBool32                                        shaderDenormPreserveFloat32
-    VkBool32                                        shaderDenormPreserveFloat64
-    VkBool32                                        shaderDenormFlushToZeroFloat16
-    VkBool32                                        shaderDenormFlushToZeroFloat32
-    VkBool32                                        shaderDenormFlushToZeroFloat64
-    VkBool32                                        shaderRoundingModeRTEFloat16
-    VkBool32                                        shaderRoundingModeRTEFloat32
-    VkBool32                                        shaderRoundingModeRTEFloat64
-    VkBool32                                        shaderRoundingModeRTZFloat16
-    VkBool32                                        shaderRoundingModeRTZFloat32
-    VkBool32                                        shaderRoundingModeRTZFloat64
-}
-
-@extension("VK_NV_compute_shader_derivatives") // 202
-class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        computeDerivativeGroupQuads
-    VkBool32                                        computeDerivativeGroupLinear
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkPhysicalDeviceMeshShaderFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        taskShader
-    VkBool32                                        meshShader
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkPhysicalDeviceMeshShaderPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxDrawMeshTasksCount
-    u32                                             maxTaskWorkGroupInvocations
-    u32[3]                                          maxTaskWorkGroupSize
-    u32                                             maxTaskTotalMemorySize
-    u32                                             maxTaskOutputCount
-    u32                                             maxMeshWorkGroupInvocations
-    u32[3]                                          maxMeshWorkGroupSize
-    u32                                             maxMeshTotalMemorySize
-    u32                                             maxMeshOutputVertices
-    u32                                             maxMeshOutputPrimitives
-    u32                                             maxMeshMultiviewViewCount
-    u32                                             meshOutputPerVertexGranularity
-    u32                                             meshOutputPerPrimitiveGranularity
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkDrawMeshTasksIndirectCommandNV {
-    u32                                             taskCount
-    u32                                             firstTask
-}
-
-@extension("VK_NV_fragment_shader_barycentric") // 204
-class VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        fragmentShaderBarycentric
-}
-
-@extension("VK_NV_shader_image_footprint") // 205
-class VkPhysicalDeviceShaderImageFootprintFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        imageFootprint
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-class VkPipelineViewportExclusiveScissorStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             exclusiveScissorCount
-    const VkRect2D*                                 pExclusiveScissors
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-class VkPhysicalDeviceExclusiveScissorFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        exclusiveScissor
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-class VkQueueFamilyCheckpointPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPipelineStageFlags                            checkpointExecutionStageMask
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-class VkCheckpointDataNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPipelineStageFlagBits                         stage
-    void*                                           pCheckpointMarker
-}
-
-@extension("VK_KHR_vulkan_memory_model") // 212
-class VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        vulkanMemoryModel
-    VkBool32                                        vulkanMemoryModelDeviceScope
-}
-
-@extension("VK_EXT_pci_bus_info") // 213
-class VkPhysicalDevicePCIBusInfoPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             pciDomain
-    u32                                             pciBus
-    u32                                             pciDevice
-    u32                                             pciFunction
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-class VkImagePipeSurfaceCreateInfoFUCHSIA {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImagePipeSurfaceCreateFlagsFUCHSIA            flags
-    platform.zx_handle_t                            imagePipeHandle
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        fragmentDensityMap
-    VkBool32                                        fragmentDensityMapDynamic
-    VkBool32                                        fragmentDensityMapNonSubsampledImages
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      minFragmentDensityTexelSize
-    VkExtent2D                                      maxFragmentDensityTexelSize
-    VkBool32                                        fragmentDensityInvocations
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkRenderPassFragmentDensityMapCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAttachmentReference                           fragmentDensityMapAttachment
-}
-
-@extension("VK_EXT_scalar_block_layout") // 222
-class VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        scalarBlockLayout
-}
-
-@extension("VK_EXT_separate_stencil_usage") // 247
-class VkImageStencilUsageCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               stencilUsage
-}
-
-
-////////////////
-//  Commands  //
-////////////////
-
-// Function pointers. TODO: add support for function pointers.
-
-@external type void* PFN_vkVoidFunction
-@pfn cmd void vkVoidFunction() {
-}
-
-@external type void* PFN_vkAllocationFunction
-@pfn cmd void* vkAllocationFunction(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        platform.size_t                             alignment,
-        VkSystemAllocationScope                     allocationScope) {
-    return ?
-}
-
-@external type void* PFN_vkReallocationFunction
-@pfn cmd void* vkReallocationFunction(
-        void*                                       pUserData,
-        void*                                       pOriginal,
-        platform.size_t                             size,
-        platform.size_t                             alignment,
-        VkSystemAllocationScope                     allocationScope) {
-    return ?
-}
-
-@external type void* PFN_vkFreeFunction
-@pfn cmd void vkFreeFunction(
-        void*                                       pUserData,
-        void*                                       pMemory) {
-}
-
-@external type void* PFN_vkInternalAllocationNotification
-@pfn cmd void vkInternalAllocationNotification(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        VkInternalAllocationType                    allocationType,
-        VkSystemAllocationScope                     allocationScope) {
-}
-
-@external type void* PFN_vkInternalFreeNotification
-@pfn cmd void vkInternalFreeNotification(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        VkInternalAllocationType                    allocationType,
-        VkSystemAllocationScope                     allocationScope) {
-}
-
-// Global functions
-
-@threadSafety("system")
-cmd VkResult vkCreateInstance(
-        const VkInstanceCreateInfo*                 pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkInstance*                                 pInstance) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
-
-    instance := ?
-    pInstance[0] = instance
-    State.Instances[instance] = new!InstanceObject()
-
-    layers := pCreateInfo.ppEnabledLayerNames[0:pCreateInfo.enabledLayerCount]
-    extensions := pCreateInfo.ppEnabledExtensionNames[0:pCreateInfo.enabledExtensionCount]
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyInstance(
-        VkInstance                                  instance,
-        const VkAllocationCallbacks*                pAllocator) {
-    instanceObject := GetInstance(instance)
-
-    State.Instances[instance] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkEnumeratePhysicalDevices(
-        VkInstance                                  instance,
-        u32*                                        pPhysicalDeviceCount,
-        VkPhysicalDevice*                           pPhysicalDevices) {
-    instanceObject := GetInstance(instance)
-
-    physicalDeviceCount := as!u32(?)
-    pPhysicalDeviceCount[0] = physicalDeviceCount
-    physicalDevices := pPhysicalDevices[0:physicalDeviceCount]
-
-    for i in (0 .. physicalDeviceCount) {
-        physicalDevice := ?
-        physicalDevices[i] = physicalDevice
-        if !(physicalDevice in State.PhysicalDevices) {
-            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
-        }
-    }
-
-    return ?
-}
-
-cmd PFN_vkVoidFunction vkGetDeviceProcAddr(
-        VkDevice                                    device,
-        const char*                                 pName) {
-    if device != NULL_HANDLE {
-        device := GetDevice(device)
-    }
-
-    return ?
-}
-
-cmd PFN_vkVoidFunction vkGetInstanceProcAddr(
-        VkInstance                                  instance,
-        const char*                                 pName) {
-    if instance != NULL_HANDLE {
-        instanceObject := GetInstance(instance)
-    }
-
-    return ?
-}
-
-cmd void vkGetPhysicalDeviceProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceProperties*                 pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    properties := ?
-    pProperties[0] = properties
-}
-
-cmd void vkGetPhysicalDeviceQueueFamilyProperties(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pQueueFamilyPropertyCount,
-        VkQueueFamilyProperties*                    pQueueFamilyProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    // TODO: Figure out how to express fetch-count-or-properties
-    // This version fails 'apic validate' with 'fence not allowed in
-    // *semantic.Branch'. Other attempts have failed with the same or other
-    // errors.
-    // if pQueueFamilyProperties != null {
-    //     queuesProperties := pQueueFamilyProperties[0:pCount[0]]
-    //     for i in (0 .. pCount[0]) {
-    //         queueProperties := as!VkQueueFamilyProperties(?)
-    //         queuesProperties[i] = queueProperties
-    //    }
-    // } else {
-    //     count := ?
-    //     pCount[0] = count
-    // }
-}
-
-cmd void vkGetPhysicalDeviceMemoryProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceMemoryProperties*           pMemoryProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    memoryProperties := ?
-    pMemoryProperties[0] = memoryProperties
-}
-
-cmd void vkGetPhysicalDeviceFeatures(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceFeatures*                   pFeatures) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    features := ?
-    pFeatures[0] = features
-}
-
-cmd void vkGetPhysicalDeviceFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkFormatProperties*                         pFormatProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    formatProperties := ?
-    pFormatProperties[0] = formatProperties
-}
-
-cmd VkResult vkGetPhysicalDeviceImageFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkImageTiling                               tiling,
-        VkImageUsageFlags                           usage,
-        VkImageCreateFlags                          flags,
-        VkImageFormatProperties*                    pImageFormatProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    imageFormatProperties := ?
-    pImageFormatProperties[0] = imageFormatProperties
-
-    return ?
-}
-
-
-// Device functions
-
-@threadSafety("system")
-cmd VkResult vkCreateDevice(
-        VkPhysicalDevice                            physicalDevice,
-        const VkDeviceCreateInfo*                   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDevice*                                   pDevice) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    device := ?
-    pDevice[0] = device
-    State.Devices[device] = new!DeviceObject(physicalDevice: physicalDevice)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDevice(
-        VkDevice                                    device,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-
-    State.Devices[device] = null
-}
-
-
-// Extension discovery functions
-
-cmd VkResult vkEnumerateInstanceLayerProperties(
-        u32*                                        pPropertyCount,
-        VkLayerProperties*                          pProperties) {
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateInstanceExtensionProperties(
-        const char*                                 pLayerName,
-        u32*                                        pPropertyCount,
-        VkExtensionProperties*                      pProperties) {
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateDeviceLayerProperties(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkLayerProperties*                          pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateDeviceExtensionProperties(
-        VkPhysicalDevice                            physicalDevice,
-        const char*                                 pLayerName,
-        u32*                                        pPropertyCount,
-        VkExtensionProperties*                      pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-
-// Queue functions
-
-@threadSafety("system")
-cmd void vkGetDeviceQueue(
-        VkDevice                                    device,
-        u32                                         queueFamilyIndex,
-        u32                                         queueIndex,
-        VkQueue*                                    pQueue) {
-    deviceObject := GetDevice(device)
-
-    queue := ?
-    pQueue[0] = queue
-
-    if !(queue in State.Queues) {
-        State.Queues[queue] = new!QueueObject(device: device)
-    }
-}
-
-@threadSafety("app")
-cmd VkResult vkQueueSubmit(
-        VkQueue                                     queue,
-        u32                                         submitCount,
-        const VkSubmitInfo*                         pSubmits,
-        VkFence                                     fence) {
-    queueObject := GetQueue(queue)
-
-    if fence != NULL_HANDLE {
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == queueObject.device)
-    }
-
-    // commandBuffers := pcommandBuffers[0:commandBufferCount]
-    // for i in (0 .. commandBufferCount) {
-    //    commandBuffer := commandBuffers[i]
-    //    commandBufferObject := GetCommandBuffer(commandBuffer)
-    //    assert(commandBufferObject.device == queueObject.device)
-    //
-    //    validate("QueueCheck", commandBufferObject.queueFlags in queueObject.flags,
-    //        "vkQueueSubmit: enqueued commandBuffer requires missing queue capabilities.")
-    // }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkQueueWaitIdle(
-        VkQueue                                     queue) {
-    queueObject := GetQueue(queue)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkDeviceWaitIdle(
-        VkDevice                                    device) {
-    deviceObject := GetDevice(device)
-
-    return ?
-}
-
-
-// Memory functions
-
-@threadSafety("system")
-cmd VkResult vkAllocateMemory(
-        VkDevice                                    device,
-        const VkMemoryAllocateInfo*                 pAllocateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDeviceMemory*                             pMemory) {
-    assert(pAllocateInfo.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
-    deviceObject := GetDevice(device)
-
-    memory := ?
-    pMemory[0] = memory
-    State.DeviceMemories[memory] = new!DeviceMemoryObject(
-        device: device,
-        allocationSize: pAllocateInfo[0].allocationSize)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkFreeMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-
-    // Check that no objects are still bound before freeing.
-    validate("MemoryCheck", len(memoryObject.boundObjects) == 0,
-        "vkFreeMemory: objects still bound")
-    validate("MemoryCheck", len(memoryObject.boundCommandBuffers) == 0,
-        "vkFreeMemory: commandBuffers still bound")
-    State.DeviceMemories[memory] = null
-}
-
-@threadSafety("app")
-cmd VkResult vkMapMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                offset,
-        VkDeviceSize                                size,
-        VkMemoryMapFlags                            flags,
-        void**                                      ppData) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-
-    assert(flags == as!VkMemoryMapFlags(0))
-    assert((offset + size) <= memoryObject.allocationSize)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd void vkUnmapMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-}
-
-cmd VkResult vkFlushMappedMemoryRanges(
-        VkDevice                                    device,
-        u32                                         memoryRangeCount
-        const VkMappedMemoryRange*                  pMemoryRanges) {
-    deviceObject := GetDevice(device)
-
-    memoryRanges := pMemoryRanges[0:memoryRangeCount]
-    for i in (0 .. memoryRangeCount) {
-        memoryRange := memoryRanges[i]
-        memoryObject := GetDeviceMemory(memoryRange.memory)
-        assert(memoryObject.device == device)
-        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
-    }
-
-    return ?
-}
-
-cmd VkResult vkInvalidateMappedMemoryRanges(
-        VkDevice                                    device,
-        u32                                         memoryRangeCount,
-        const VkMappedMemoryRange*                  pMemoryRanges) {
-    deviceObject := GetDevice(device)
-
-    memoryRanges := pMemoryRanges[0:memoryRangeCount]
-    for i in (0 .. memoryRangeCount) {
-        memoryRange := memoryRanges[i]
-        memoryObject := GetDeviceMemory(memoryRange.memory)
-        assert(memoryObject.device == device)
-        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
-    }
-
-    return ?
-}
-
-
-// Memory management API functions
-
-cmd void vkGetDeviceMemoryCommitment(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkDeviceSize*                               pCommittedMemoryInBytes) {
-    deviceObject := GetDevice(device)
-
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-    }
-
-    committedMemoryInBytes := ?
-    pCommittedMemoryInBytes[0] = committedMemoryInBytes
-}
-
-cmd void vkGetBufferMemoryRequirements(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        VkMemoryRequirements*                       pMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-}
-
-cmd VkResult vkBindBufferMemory(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                memoryOffset) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-
-    // Unbind buffer from previous memory object, if not VK_NULL_HANDLE.
-    if bufferObject.memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(bufferObject.memory)
-        memoryObject.boundObjects[as!u64(buffer)] = null
-    }
-
-    // Bind buffer to given memory object, if not VK_NULL_HANDLE.
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-        memoryObject.boundObjects[as!u64(buffer)] = memoryOffset
-    }
-    bufferObject.memory = memory
-    bufferObject.memoryOffset = memoryOffset
-
-    return ?
-}
-
-cmd void vkGetImageMemoryRequirements(
-        VkDevice                                    device,
-        VkImage                                     image,
-        VkMemoryRequirements*                       pMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-cmd VkResult vkBindImageMemory(
-        VkDevice                                    device,
-        VkImage                                     image,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                memoryOffset) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-
-    // Unbind image from previous memory object, if not VK_NULL_HANDLE.
-    if imageObject.memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(imageObject.memory)
-        memoryObject.boundObjects[as!u64(image)] = null
-    }
-
-    // Bind image to given memory object, if not VK_NULL_HANDLE.
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-        memoryObject.boundObjects[as!u64(image)] = memoryOffset
-    }
-    imageObject.memory = memory
-    imageObject.memoryOffset = memoryOffset
-
-    return ?
-}
-
-cmd void vkGetImageSparseMemoryRequirements(
-        VkDevice                                    device,
-        VkImage                                     image,
-        u32*                                        pSparseMemoryRequirementCount,
-        VkSparseImageMemoryRequirements*            pSparseMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-cmd void vkGetPhysicalDeviceSparseImageFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkSampleCountFlagBits                       samples,
-        VkImageUsageFlags                           usage,
-        VkImageTiling                               tiling,
-        u32*                                        pPropertyCount,
-        VkSparseImageFormatProperties*              pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-}
-
-cmd VkResult vkQueueBindSparse(
-        VkQueue                                     queue,
-        u32                                         bindInfoCount,
-        const VkBindSparseInfo*                     pBindInfo,
-        VkFence                                     fence) {
-    queueObject := GetQueue(queue)
-
-    return ?
-}
-
-
-// Fence functions
-
-@threadSafety("system")
-cmd VkResult vkCreateFence(
-        VkDevice                                    device,
-        const VkFenceCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    fence := ?
-    pFence[0] = fence
-    State.Fences[fence] = new!FenceObject(
-        device: device, signaled: (pCreateInfo.flags == as!VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT)))
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyFence(
-        VkDevice                                    device,
-        VkFence                                     fence,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    fenceObject := GetFence(fence)
-    assert(fenceObject.device == device)
-
-    State.Fences[fence] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkResetFences(
-        VkDevice                                    device,
-        u32                                         fenceCount,
-        const VkFence*                              pFences) {
-    deviceObject := GetDevice(device)
-
-    fences := pFences[0:fenceCount]
-    for i in (0 .. fenceCount) {
-        fence := fences[i]
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == device)
-        fenceObject.signaled = false
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkGetFenceStatus(
-        VkDevice                                    device,
-        VkFence                                     fence) {
-    deviceObject := GetDevice(device)
-    fenceObject := GetFence(fence)
-    assert(fenceObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkWaitForFences(
-        VkDevice                                    device,
-        u32                                         fenceCount,
-        const VkFence*                              pFences,
-        VkBool32                                    waitAll,
-        u64                                         timeout) {  /// timeout in nanoseconds
-    deviceObject := GetDevice(device)
-
-    fences := pFences[0:fenceCount]
-    for i in (0 .. fenceCount) {
-        fence := fences[i]
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == device)
-    }
-
-    return ?
-}
-
-
-// Queue semaphore functions
-
-@threadSafety("system")
-cmd VkResult vkCreateSemaphore(
-        VkDevice                                    device,
-        const VkSemaphoreCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSemaphore*                                pSemaphore) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    semaphore := ?
-    pSemaphore[0] = semaphore
-    State.Semaphores[semaphore] = new!SemaphoreObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroySemaphore(
-        VkDevice                                    device,
-        VkSemaphore                                 semaphore,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    semaphoreObject := GetSemaphore(semaphore)
-    assert(semaphoreObject.device == device)
-
-    State.Semaphores[semaphore] = null
-}
-
-
-// Event functions
-
-@threadSafety("system")
-cmd VkResult vkCreateEvent(
-        VkDevice                                    device,
-        const VkEventCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkEvent*                                    pEvent) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_EVENT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    event := ?
-    pEvent[0] = event
-    State.Events[event] = new!EventObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyEvent(
-        VkDevice                                    device,
-        VkEvent                                     event,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    State.Events[event] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkGetEventStatus(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkSetEvent(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkResetEvent(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-
-// Query functions
-
-@threadSafety("system")
-cmd VkResult vkCreateQueryPool(
-        VkDevice                                    device,
-        const VkQueryPoolCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkQueryPool*                                pQueryPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    queryPool := ?
-    pQueryPool[0] = queryPool
-    State.QueryPools[queryPool] = new!QueryPoolObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyQueryPool(
-        VkDevice                                    device,
-        VkQueryPool                                 queryPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(queryPoolObject.device == device)
-
-    State.QueryPools[queryPool] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkGetQueryPoolResults(
-        VkDevice                                    device,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount,
-        platform.size_t                             dataSize,
-        void*                                       pData,
-        VkDeviceSize                                stride,
-        VkQueryResultFlags                          flags) {
-    deviceObject := GetDevice(device)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(queryPoolObject.device == device)
-
-    data := pData[0:dataSize]
-
-    return ?
-}
-
-// Buffer functions
-
-@threadSafety("system")
-cmd VkResult vkCreateBuffer(
-        VkDevice                                    device,
-        const VkBufferCreateInfo*                   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkBuffer*                                   pBuffer) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    buffer := ?
-    pBuffer[0] = buffer
-    State.Buffers[buffer] = new!BufferObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyBuffer(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-
-    assert(bufferObject.memory == 0)
-    State.Buffers[buffer] = null
-}
-
-
-// Buffer view functions
-
-@threadSafety("system")
-cmd VkResult vkCreateBufferView(
-        VkDevice                                    device,
-        const VkBufferViewCreateInfo*               pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkBufferView*                               pView) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    bufferObject := GetBuffer(pCreateInfo.buffer)
-    assert(bufferObject.device == device)
-
-    view := ?
-    pView[0] = view
-    State.BufferViews[view] = new!BufferViewObject(device: device, buffer: pCreateInfo.buffer)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyBufferView(
-        VkDevice                                    device,
-        VkBufferView                                bufferView,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    bufferViewObject := GetBufferView(bufferView)
-    assert(bufferViewObject.device == device)
-
-    State.BufferViews[bufferView] = null
-}
-
-
-// Image functions
-
-@threadSafety("system")
-cmd VkResult vkCreateImage(
-        VkDevice                                    device,
-        const VkImageCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkImage*                                    pImage) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    image := ?
-    pImage[0] = image
-    State.Images[image] = new!ImageObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyImage(
-        VkDevice                                    device,
-        VkImage                                     image,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-
-    assert(imageObject.memory == 0)
-    State.Images[image] = null
-}
-
-cmd void vkGetImageSubresourceLayout(
-        VkDevice                                    device,
-        VkImage                                     image,
-        const VkImageSubresource*                   pSubresource,
-        VkSubresourceLayout*                        pLayout) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-
-// Image view functions
-
-@threadSafety("system")
-cmd VkResult vkCreateImageView(
-        VkDevice                                    device,
-        const VkImageViewCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkImageView*                                pView) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    imageObject := GetImage(pCreateInfo.image)
-    assert(imageObject.device == device)
-
-    view := ?
-    pView[0] = view
-    State.ImageViews[view] = new!ImageViewObject(device: device, image: pCreateInfo.image)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyImageView(
-        VkDevice                                    device,
-        VkImageView                                 imageView,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    imageViewObject := GetImageView(imageView)
-    assert(imageViewObject.device == device)
-
-    State.ImageViews[imageView] = null
-}
-
-
-// Shader functions
-
-cmd VkResult vkCreateShaderModule(
-        VkDevice                                    device,
-        const VkShaderModuleCreateInfo*             pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkShaderModule*                             pShaderModule) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    shaderModule := ?
-    pShaderModule[0] = shaderModule
-    State.ShaderModules[shaderModule] = new!ShaderModuleObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyShaderModule(
-        VkDevice                                    device,
-        VkShaderModule                              shaderModule,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    shaderModuleObject := GetShaderModule(shaderModule)
-    assert(shaderModuleObject.device == device)
-
-    State.ShaderModules[shaderModule] = null
-}
-
-
-// Pipeline functions
-
-cmd VkResult vkCreatePipelineCache(
-        VkDevice                                    device,
-        const VkPipelineCacheCreateInfo*            pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipelineCache*                            pPipelineCache) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    pipelineCache := ?
-    pPipelineCache[0] = pipelineCache
-    State.PipelineCaches[pipelineCache] = new!PipelineCacheObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyPipelineCache(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineCacheObject := GetPipelineCache(pipelineCache)
-    assert(pipelineCacheObject.device == device)
-
-    State.PipelineCaches[pipelineCache] = null
-}
-
-cmd VkResult vkGetPipelineCacheData(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        platform.size_t*                            pDataSize,
-        void*                                       pData) {
-    deviceObject := GetDevice(device)
-    pipelineCacheObject := GetPipelineCache(pipelineCache)
-    assert(pipelineCacheObject.device == device)
-
-    return ?
-}
-
-cmd VkResult vkMergePipelineCaches(
-        VkDevice                                    device,
-        VkPipelineCache                             dstCache,
-        u32                                         srcCacheCount,
-        const VkPipelineCache*                      pSrcCaches) {
-    deviceObject := GetDevice(device)
-    dstCacheObject := GetPipelineCache(dstCache)
-    assert(dstCacheObject.device == device)
-
-    srcCaches := pSrcCaches[0:srcCacheCount]
-    for i in (0 .. srcCacheCount) {
-        srcCache := srcCaches[i]
-        srcCacheObject := GetPipelineCache(srcCache)
-        assert(srcCacheObject.device == device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkCreateGraphicsPipelines(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkGraphicsPipelineCreateInfo*         pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    deviceObject := GetDevice(device)
-    if pipelineCache != NULL_HANDLE {
-        pipelineCacheObject := GetPipelineCache(pipelineCache)
-        assert(pipelineCacheObject.device == device)
-    }
-
-    createInfos := pCreateInfos[0:createInfoCount]
-    pipelines := pPipelines[0:createInfoCount]
-    for i in (0 .. createInfoCount) {
-        pipeline := ?
-        pipelines[i] = pipeline
-        State.Pipelines[pipeline] = new!PipelineObject(device: device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkCreateComputePipelines(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkComputePipelineCreateInfo*          pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    deviceObject := GetDevice(device)
-    if pipelineCache != NULL_HANDLE {
-        pipelineCacheObject := GetPipelineCache(pipelineCache)
-        assert(pipelineCacheObject.device == device)
-    }
-
-    createInfos := pCreateInfos[0:createInfoCount]
-    pipelines := pPipelines[0:createInfoCount]
-    for i in (0 .. createInfoCount) {
-        pipeline := ?
-        pipelines[i] = pipeline
-        State.Pipelines[pipeline] = new!PipelineObject(device: device)
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyPipeline(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineObjects := GetPipeline(pipeline)
-    assert(pipelineObjects.device == device)
-
-    State.Pipelines[pipeline] = null
-}
-
-
-// Pipeline layout functions
-
-@threadSafety("system")
-cmd VkResult vkCreatePipelineLayout(
-        VkDevice                                    device,
-        const VkPipelineLayoutCreateInfo*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipelineLayout*                           pPipelineLayout) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    pipelineLayout := ?
-    pPipelineLayout[0] = pipelineLayout
-    State.PipelineLayouts[pipelineLayout] = new!PipelineLayoutObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyPipelineLayout(
-        VkDevice                                    device,
-        VkPipelineLayout                            pipelineLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineLayoutObjects := GetPipelineLayout(pipelineLayout)
-    assert(pipelineLayoutObjects.device == device)
-
-    State.PipelineLayouts[pipelineLayout] = null
-}
-
-
-// Sampler functions
-
-@threadSafety("system")
-cmd VkResult vkCreateSampler(
-        VkDevice                                    device,
-        const VkSamplerCreateInfo*                  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSampler*                                  pSampler) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    sampler := ?
-    pSampler[0] = sampler
-    State.Samplers[sampler] = new!SamplerObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroySampler(
-        VkDevice                                    device,
-        VkSampler                                   sampler,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    samplerObject := GetSampler(sampler)
-    assert(samplerObject.device == device)
-
-    State.Samplers[sampler] = null
-}
-
-
-// Descriptor set functions
-
-@threadSafety("system")
-cmd VkResult vkCreateDescriptorSetLayout(
-        VkDevice                                    device,
-        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorSetLayout*                      pSetLayout) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    setLayout := ?
-    pSetLayout[0] = setLayout
-    State.DescriptorSetLayouts[setLayout] = new!DescriptorSetLayoutObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDescriptorSetLayout(
-        VkDevice                                    device,
-        VkDescriptorSetLayout                       descriptorSetLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    descriptorSetLayoutObject := GetDescriptorSetLayout(descriptorSetLayout)
-    assert(descriptorSetLayoutObject.device == device)
-
-    State.DescriptorSetLayouts[descriptorSetLayout] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkCreateDescriptorPool(
-        VkDevice                                    device,
-        const VkDescriptorPoolCreateInfo*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorPool*                           pDescriptorPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    descriptorPool := ?
-    pDescriptorPool[0] = descriptorPool
-    State.DescriptorPools[descriptorPool] = new!DescriptorPoolObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDescriptorPool(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-    assert(descriptorPoolObject.device == device)
-
-    State.DescriptorPools[descriptorPool] = null
-}
-
-@threadSafety("app")
-cmd VkResult vkResetDescriptorPool(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        VkDescriptorPoolResetFlags                  flags) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-    assert(descriptorPoolObject.device == device)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkAllocateDescriptorSets(
-        VkDevice                                    device,
-        const VkDescriptorSetAllocateInfo*          pAllocateInfo,
-        VkDescriptorSet*                            pDescriptorSets) {
-    deviceObject := GetDevice(device)
-    allocInfo := pAllocateInfo[0]
-    descriptorPoolObject := GetDescriptorPool(allocInfo.descriptorPool)
-
-    setLayouts := allocInfo.pSetLayouts[0:allocInfo.setCount]
-    for i in (0 .. allocInfo.setCount) {
-        setLayout := setLayouts[i]
-        setLayoutObject := GetDescriptorSetLayout(setLayout)
-        assert(setLayoutObject.device == device)
-    }
-
-    descriptorSets := pDescriptorSets[0:allocInfo.setCount]
-    for i in (0 .. allocInfo.setCount) {
-        descriptorSet := ?
-        descriptorSets[i] = descriptorSet
-        State.DescriptorSets[descriptorSet] = new!DescriptorSetObject(device: device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkFreeDescriptorSets(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        u32                                         descriptorSetCount,
-        const VkDescriptorSet*                      pDescriptorSets) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-
-    descriptorSets := pDescriptorSets[0:descriptorSetCount]
-    for i in (0 .. descriptorSetCount) {
-        descriptorSet := descriptorSets[i]
-        descriptorSetObject := GetDescriptorSet(descriptorSet)
-        assert(descriptorSetObject.device == device)
-        State.DescriptorSets[descriptorSet] = null
-    }
-
-    return ?
-}
-
-cmd void vkUpdateDescriptorSets(
-        VkDevice                                    device,
-        u32                                         descriptorWriteCount,
-        const VkWriteDescriptorSet*                 pDescriptorWrites,
-        u32                                         descriptorCopyCount,
-        const VkCopyDescriptorSet*                  pDescriptorCopies) {
-    deviceObject := GetDevice(device)
-
-    descriptorWrites := pDescriptorWrites[0:descriptorWriteCount]
-    for i in (0 .. descriptorWriteCount) {
-        descriptorWrite := descriptorWrites[i]
-        descriptorWriteObject := GetDescriptorSet(descriptorWrite.dstSet)
-        assert(descriptorWriteObject.device == device)
-    }
-
-    descriptorCopies := pDescriptorCopies[0:descriptorCopyCount]
-    for i in (0 .. descriptorCopyCount) {
-        descriptorCopy := descriptorCopies[i]
-        descriptorCopyObject := GetDescriptorSet(descriptorCopy.dstSet)
-        assert(descriptorCopyObject.device == device)
-    }
-}
-
-
-// Framebuffer functions
-
-@threadSafety("system")
-cmd VkResult vkCreateFramebuffer(
-        VkDevice                                    device,
-        const VkFramebufferCreateInfo*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFramebuffer*                              pFramebuffer) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    framebuffer := ?
-    pFramebuffer[0] = framebuffer
-    State.Framebuffers[framebuffer] = new!FramebufferObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyFramebuffer(
-        VkDevice                                    device,
-        VkFramebuffer                               framebuffer,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    framebufferObject := GetFramebuffer(framebuffer)
-    assert(framebufferObject.device == device)
-
-    State.Framebuffers[framebuffer] = null
-}
-
-
-// Renderpass functions
-
-@threadSafety("system")
-cmd VkResult vkCreateRenderPass(
-        VkDevice                                    device,
-        const VkRenderPassCreateInfo*               pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkRenderPass*                               pRenderPass) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    renderpass := ?
-    pRenderPass[0] = renderpass
-    State.RenderPasses[renderpass] = new!RenderPassObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyRenderPass(
-        VkDevice                                    device,
-        VkRenderPass                                renderPass,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    renderPassObject := GetRenderPass(renderPass)
-    assert(renderPassObject.device == device)
-
-    State.RenderPasses[renderPass] = null
-}
-
-cmd void vkGetRenderAreaGranularity(
-        VkDevice                                    device,
-        VkRenderPass                                renderPass,
-        VkExtent2D*                                 pGranularity) {
-    deviceObject := GetDevice(device)
-    renderPassObject := GetRenderPass(renderPass)
-
-    granularity := ?
-    pGranularity[0] = granularity
-}
-
-// Command pool functions
-
-cmd VkResult vkCreateCommandPool(
-        VkDevice                                    device,
-        const VkCommandPoolCreateInfo*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkCommandPool*                              pCommandPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    commandPool := ?
-    pCommandPool[0] = commandPool
-    State.CommandPools[commandPool] = new!CommandPoolObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyCommandPool(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    commandPoolObject := GetCommandPool(commandPool)
-    assert(commandPoolObject.device == device)
-
-    State.CommandPools[commandPool] = null
-}
-
-cmd VkResult vkResetCommandPool(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        VkCommandPoolResetFlags                     flags) {
-    deviceObject := GetDevice(device)
-    commandPoolObject := GetCommandPool(commandPool)
-    assert(commandPoolObject.device == device)
-
-    return ?
-}
-
-// Command buffer functions
-
-macro void bindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
-    memoryObject := GetDeviceMemory(memory)
-    memoryObject.boundCommandBuffers[commandBuffer] = commandBuffer
-
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.boundObjects[as!u64(obj)] = memory
-}
-
-macro void unbindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
-    memoryObject := GetDeviceMemory(memory)
-    memoryObject.boundCommandBuffers[commandBuffer] = null
-
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.boundObjects[as!u64(obj)] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkAllocateCommandBuffers(
-        VkDevice                                    device,
-        const VkCommandBufferAllocateInfo*          pAllocateInfo,
-        VkCommandBuffer*                            pCommandBuffers) {
-    assert(pAllocateInfo[0].sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
-
-    count := pAllocateInfo[0].commandBufferCount
-    commandBuffers := pCommandBuffers[0:count]
-    for i in (0 .. count) {
-        commandBuffer := ?
-        commandBuffers[i] = commandBuffer
-        State.CommandBuffers[commandBuffer] = new!CommandBufferObject(device: device)
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkFreeCommandBuffers(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        u32                                         commandBufferCount,
-        const VkCommandBuffer*                      pCommandBuffers) {
-    deviceObject := GetDevice(device)
-
-    commandBuffers := pCommandBuffers[0:commandBufferCount]
-    for i in (0 .. commandBufferCount) {
-        commandBufferObject := GetCommandBuffer(commandBuffers[i])
-        assert(commandBufferObject.device == device)
-        // TODO: iterate over boundObjects and clear memory bindings
-        State.CommandBuffers[commandBuffers[i]] = null
-    }
-}
-
-@threadSafety("app")
-cmd VkResult vkBeginCommandBuffer(
-        VkCommandBuffer                             commandBuffer,
-        const VkCommandBufferBeginInfo*             pBeginInfo) {
-    assert(pBeginInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: iterate over boundObjects and clear memory bindings
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkEndCommandBuffer(
-        VkCommandBuffer                             commandBuffer) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkResetCommandBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkCommandBufferResetFlags                   flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: iterate over boundObjects and clear memory bindings
-
-    return ?
-}
-
-
-// Command buffer building functions
-
-@threadSafety("app")
-cmd void vkCmdBindPipeline(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipeline                                  pipeline) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    pipelineObject := GetPipeline(pipeline)
-    assert(commandBufferObject.device == pipelineObject.device)
-
-    queue := switch (pipelineBindPoint) {
-        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
-        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
-    }
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetViewport(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkViewport*                           pViewports) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetScissor(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstScissor,
-        u32                                         scissorCount,
-        const VkRect2D*                             pScissors) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetLineWidth(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         lineWidth) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetDepthBias(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         depthBiasConstantFactor,
-        f32                                         depthBiasClamp,
-        f32                                         depthBiasSlopeFactor) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetBlendConstants(
-        VkCommandBuffer                             commandBuffer,
-        // TODO(jessehall): apic only supports 'const' on pointer types. Using
-        // an annotation as a quick hack to pass this to the template without
-        // having to modify the AST and semantic model.
-        @readonly f32[4]                            blendConstants) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetDepthBounds(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         minDepthBounds,
-        f32                                         maxDepthBounds) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilCompareMask(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         compareMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilWriteMask(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         writeMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilReference(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         reference) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindDescriptorSets(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipelineLayout                            layout,
-        u32                                         firstSet,
-        u32                                         descriptorSetCount,
-        const VkDescriptorSet*                      pDescriptorSets,
-        u32                                         dynamicOffsetCount,
-        const u32*                                  pDynamicOffsets) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    descriptorSets := pDescriptorSets[0:descriptorSetCount]
-    for i in (0 .. descriptorSetCount) {
-        descriptorSet := descriptorSets[i]
-        descriptorSetObject := GetDescriptorSet(descriptorSet)
-        assert(commandBufferObject.device == descriptorSetObject.device)
-    }
-
-    dynamicOffsets := pDynamicOffsets[0:dynamicOffsetCount]
-    for i in (0 .. dynamicOffsetCount) {
-        dynamicOffset := dynamicOffsets[i]
-    }
-
-    queue := switch (pipelineBindPoint) {
-        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
-        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
-    }
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindIndexBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkIndexType                                 indexType) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindVertexBuffers(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstBinding,
-        u32                                         bindingCount,
-        const VkBuffer*                             pBuffers,
-        const VkDeviceSize*                         pOffsets) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: check if not [firstBinding:firstBinding+bindingCount]
-    buffers := pBuffers[0:bindingCount]
-    offsets := pOffsets[0:bindingCount]
-    for i in (0 .. bindingCount) {
-        buffer := buffers[i]
-        offset := offsets[i]
-        bufferObject := GetBuffer(buffer)
-        assert(commandBufferObject.device == bufferObject.device)
-
-        bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-    }
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDraw(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         vertexCount,
-        u32                                         instanceCount,
-        u32                                         firstVertex,
-        u32                                         firstInstance) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndexed(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         indexCount,
-        u32                                         instanceCount,
-        u32                                         firstIndex,
-        s32                                         vertexOffset,
-        u32                                         firstInstance) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndexedIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDispatch(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         groupCountX,
-        u32                                         groupCountY,
-        u32                                         groupCountZ) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDispatchIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    srcBuffer,
-        VkBuffer                                    dstBuffer,
-        u32                                         regionCount,
-        const VkBufferCopy*                         pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcBufferObject := GetBuffer(srcBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == srcBufferObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageCopy*                          pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBlitImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageBlit*                          pRegions,
-        VkFilter                                    filter) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyBufferToImage(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    srcBuffer,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkBufferImageCopy*                    pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcBufferObject := GetBuffer(srcBuffer)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcBufferObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyImageToBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkBuffer                                    dstBuffer,
-        u32                                         regionCount,
-        const VkBufferImageCopy*                    pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdUpdateBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                dataSize,
-        const void*                                 pData) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    data := pData[0:dataSize]
-
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdFillBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                size,
-        u32                                         data) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearColorImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     image,
-        VkImageLayout                               imageLayout,
-        const VkClearColorValue*                    pColor,
-        u32                                         rangeCount,
-        const VkImageSubresourceRange*              pRanges) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    imageObject := GetImage(image)
-    assert(commandBufferObject.device == imageObject.device)
-
-    ranges := pRanges[0:rangeCount]
-    for i in (0 .. rangeCount) {
-        range := ranges[i]
-    }
-
-    bindCommandBuffer(commandBuffer, image, imageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearDepthStencilImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     image,
-        VkImageLayout                               imageLayout,
-        const VkClearDepthStencilValue*             pDepthStencil,
-        u32                                         rangeCount,
-        const VkImageSubresourceRange*              pRanges) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    imageObject := GetImage(image)
-    assert(commandBufferObject.device == imageObject.device)
-
-    ranges := pRanges[0:rangeCount]
-    for i in (0 .. rangeCount) {
-        range := ranges[i]
-    }
-
-    bindCommandBuffer(commandBuffer, image, imageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearAttachments(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         attachmentCount,
-        const VkClearAttachment*                    pAttachments,
-        u32                                         rectCount,
-        const VkClearRect*                          pRects) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    rects := pRects[0:rectCount]
-    for i in (0 .. rectCount) {
-        rect := rects[i]
-    }
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdResolveImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageResolve*                       pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetEvent(
-        VkCommandBuffer                             commandBuffer,
-        VkEvent                                     event,
-        VkPipelineStageFlags                        stageMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    eventObject := GetEvent(event)
-    assert(commandBufferObject.device == eventObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdResetEvent(
-        VkCommandBuffer                             commandBuffer,
-        VkEvent                                     event,
-        VkPipelineStageFlags                        stageMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    eventObject := GetEvent(event)
-    assert(commandBufferObject.device == eventObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdWaitEvents(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         eventCount,
-        const VkEvent*                              pEvents,
-        VkPipelineStageFlags                        srcStageMask,
-        VkPipelineStageFlags                        dstStageMask,
-        u32                                         memoryBarrierCount,
-        const VkMemoryBarrier*                      pMemoryBarriers,
-        u32                                         bufferMemoryBarrierCount,
-        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-        u32                                         imageMemoryBarrierCount,
-        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    events := pEvents[0:eventCount]
-    for i in (0 .. eventCount) {
-        event := events[i]
-        eventObject := GetEvent(event)
-        assert(commandBufferObject.device == eventObject.device)
-    }
-
-    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
-    for i in (0 .. memoryBarrierCount) {
-        memoryBarrier := memoryBarriers[i]
-    }
-    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
-    for i in (0 .. bufferMemoryBarrierCount) {
-        bufferMemoryBarrier := bufferMemoryBarriers[i]
-        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
-        assert(bufferObject.device == commandBufferObject.device)
-    }
-    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
-    for i in (0 .. imageMemoryBarrierCount) {
-        imageMemoryBarrier := imageMemoryBarriers[i]
-        imageObject := GetImage(imageMemoryBarrier.image)
-        assert(imageObject.device == commandBufferObject.device)
-    }
-}
-
-@threadSafety("app")
-cmd void vkCmdPipelineBarrier(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlags                        srcStageMask,
-        VkPipelineStageFlags                        dstStageMask,
-        VkDependencyFlags                           dependencyFlags,
-        u32                                         memoryBarrierCount,
-        const VkMemoryBarrier*                      pMemoryBarriers,
-        u32                                         bufferMemoryBarrierCount,
-        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-        u32                                         imageMemoryBarrierCount,
-        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
-    for i in (0 .. memoryBarrierCount) {
-        memoryBarrier := memoryBarriers[i]
-    }
-    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
-    for i in (0 .. bufferMemoryBarrierCount) {
-        bufferMemoryBarrier := bufferMemoryBarriers[i]
-        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
-        assert(bufferObject.device == commandBufferObject.device)
-    }
-    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
-    for i in (0 .. imageMemoryBarrierCount) {
-        imageMemoryBarrier := imageMemoryBarriers[i]
-        imageObject := GetImage(imageMemoryBarrier.image)
-        assert(imageObject.device == commandBufferObject.device)
-    }
-}
-
-@threadSafety("app")
-cmd void vkCmdBeginQuery(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        VkQueryControlFlags                         flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdEndQuery(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdResetQueryPool(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdWriteTimestamp(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlagBits                     pipelineStage,
-        VkQueryPool                                 queryPool,
-        u32                                         query) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyQueryPoolResults(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                stride,
-        VkQueryResultFlags                          flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == queryPoolObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-}
-
-cmd void vkCmdPushConstants(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineLayout                            layout,
-        VkShaderStageFlags                          stageFlags,
-        u32                                         offset,
-        u32                                         size,
-        const void*                                 pValues) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    layoutObject := GetPipelineLayout(layout)
-    assert(commandBufferObject.device == layoutObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdBeginRenderPass(
-        VkCommandBuffer                             commandBuffer,
-        const VkRenderPassBeginInfo*                pRenderPassBegin,
-        VkSubpassContents                           contents) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    renderPassObject := GetRenderPass(pRenderPassBegin.renderPass)
-    framebufferObject := GetFramebuffer(pRenderPassBegin.framebuffer)
-    assert(commandBufferObject.device == renderPassObject.device)
-    assert(commandBufferObject.device == framebufferObject.device)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-cmd void vkCmdNextSubpass(
-        VkCommandBuffer                             commandBuffer,
-        VkSubpassContents                           contents) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-}
-
-@threadSafety("app")
-cmd void vkCmdEndRenderPass(
-        VkCommandBuffer                             commandBuffer) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-cmd void vkCmdExecuteCommands(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         commandBufferCount,
-        const VkCommandBuffer*                      pCommandBuffers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBuffers := pCommandBuffers[0:commandBufferCount]
-    for i in (0 .. commandBufferCount) {
-        secondaryCommandBuffer := commandBuffers[i]
-        secondaryCommandBufferObject := GetCommandBuffer(secondaryCommandBuffer)
-        assert(commandBufferObject.device == secondaryCommandBufferObject.device)
-    }
-}
-
-//@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,
-        VkSurfaceKHR                                surface,
-        const VkAllocationCallbacks*                pAllocator) {
-    instanceObject := GetInstance(instance)
-    surfaceObject := GetSurface(surface)
-    assert(surfaceObject.instance == instance)
-
-    State.Surfaces[surface] = null
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceSupportKHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32                                         queueFamilyIndex,
-        VkSurfaceKHR                                surface,
-        VkBool32*                                   pSupported) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    surfaceCapabilities := ?
-    pSurfaceCapabilities[0] = surfaceCapabilities
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pSurfaceFormatCount,
-        VkSurfaceFormatKHR*                         pSurfaceFormats) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pSurfaceFormatCount[0] = count
-    surfaceFormats := pSurfaceFormats[0:count]
-
-    for i in (0 .. count) {
-        surfaceFormat := ?
-        surfaceFormats[i] = surfaceFormat
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pPresentModeCount,
-        VkPresentModeKHR*                           pPresentModes) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pPresentModeCount[0] = count
-    presentModes := pPresentModes[0:count]
-
-    for i in (0 .. count) {
-        presentMode := ?
-        presentModes[i] = presentMode
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkCreateSwapchainKHR(
-        VkDevice                                 device,
-        const VkSwapchainCreateInfoKHR*          pCreateInfo,
-        const VkAllocationCallbacks*             pAllocator,
-        VkSwapchainKHR*                          pSwapchain) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR)
-    deviceObject := GetDevice(device)
-
-    swapchain := ?
-    pSwapchain[0] = swapchain
-    State.Swapchains[swapchain] = new!SwapchainObject(device: device)
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd void vkDestroySwapchainKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        const VkAllocationCallbacks*             pAllocator) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-    assert(swapchainObject.device == device)
-
-    State.Swapchains[swapchain] = null
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkGetSwapchainImagesKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        u32*                                     pSwapchainImageCount,
-        VkImage*                                 pSwapchainImages) {
-    deviceObject := GetDevice(device)
-
-    count := as!u32(?)
-    pSwapchainImageCount[0] = count
-    swapchainImages := pSwapchainImages[0:count]
-
-    for i in (0 .. count) {
-        swapchainImage := ?
-        swapchainImages[i] = swapchainImage
-        State.Images[swapchainImage] = new!ImageObject(device: device)
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkAcquireNextImageKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        u64                                      timeout,
-        VkSemaphore                              semaphore,
-        VkFence                                  fence,
-        u32*                                     pImageIndex) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-
-    imageIndex := ?
-    pImageIndex[0] = imageIndex
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkQueuePresentKHR(
-        VkQueue                                  queue,
-        const VkPresentInfoKHR*                  pPresentInfo) {
-    queueObject := GetQueue(queue)
-
-    presentInfo := ?
-    pPresentInfo[0] = presentInfo
-
-    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,
-        u32*                                    pPropertyCount,
-        VkDisplayPropertiesKHR*                 pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32*                                    pPropertyCount,
-        VkDisplayPlanePropertiesKHR*            pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayPlaneSupportedDisplaysKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     planeIndex,
-        u32*                                    pDisplayCount,
-        VkDisplayKHR*                           pDisplays) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayModePropertiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayKHR                            display,
-        u32*                                    pPropertyCount,
-        VkDisplayModePropertiesKHR*             pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkCreateDisplayModeKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayKHR                            display,
-        const VkDisplayModeCreateInfoKHR*       pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkDisplayModeKHR*                       pMode) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayPlaneCapabilitiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayModeKHR                        mode,
-        u32                                     planeIndex,
-        VkDisplayPlaneCapabilitiesKHR*          pCapabilities) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkCreateDisplayPlaneSurfaceKHR(
-        VkInstance                              instance,
-        const VkDisplaySurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    return ?
-}
-
-@extension("VK_KHR_display_swapchain") // 4
-cmd VkResult vkCreateSharedSwapchainsKHR(
-        VkDevice                                device,
-        u32                                     swapchainCount,
-        const VkSwapchainCreateInfoKHR*         pCreateInfos,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSwapchainKHR*                         pSwapchains) {
-    return ?
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-cmd VkResult vkCreateXlibSurfaceKHR(
-        VkInstance                              instance,
-        const VkXlibSurfaceCreateInfoKHR*       pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-cmd VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.Display*                       dpy,
-        platform.VisualID                       visualID) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-cmd VkResult vkCreateXcbSurfaceKHR(
-        VkInstance                              instance,
-        const VkXcbSurfaceCreateInfoKHR*        pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-cmd VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.xcb_connection_t*              connection,
-        platform.xcb_visualid_t                 visual_id) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-cmd VkResult vkCreateWaylandSurfaceKHR(
-        VkInstance                              instance,
-        const VkWaylandSurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-cmd VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.wl_display*                    display) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_android_surface") // 9
-cmd VkResult vkCreateAndroidSurfaceKHR(
-        VkInstance                              instance,
-        const VkAndroidSurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_win32_surface") // 10
-cmd VkResult vkCreateWin32SurfaceKHR(
-        VkInstance                              instance,
-        const VkWin32SurfaceCreateInfoKHR*      pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_win32_surface") // 10
-cmd VkResult vkGetPhysicalDeviceWin32PresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@optional
-cmd VkResult vkGetSwapchainGrallocUsageANDROID(
-        VkDevice                                device,
-        VkFormat                                format,
-        VkImageUsageFlags                       imageUsage,
-        s32*                                    grallocUsage) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@optional
-cmd VkResult vkGetSwapchainGrallocUsage2ANDROID(
-        VkDevice                                device,
-        VkFormat                                format,
-        VkImageUsageFlags                       imageUsage,
-        VkSwapchainImageUsageFlagsANDROID       swapchainImageUsage,
-        u64*                                    grallocConsumerUsage,
-        u64*                                    grallocProducerUsage) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-cmd VkResult vkAcquireImageANDROID(
-        VkDevice                                device,
-        VkImage                                 image,
-        int                                     nativeFenceFd,
-        VkSemaphore                             semaphore,
-        VkFence                                 fence) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-cmd VkResult vkQueueSignalReleaseImageANDROID(
-        VkQueue                                 queue,
-        u32                                     waitSemaphoreCount,
-        const VkSemaphore*                      pWaitSemaphores,
-        VkImage                                 image,
-        int*                                    pNativeFenceFd) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-@external type void* PFN_vkDebugReportCallbackEXT
-@extension("VK_EXT_debug_report") // 12
-@pfn cmd VkBool32 vkDebugReportCallbackEXT(
-        VkDebugReportFlagsEXT                   flags,
-        VkDebugReportObjectTypeEXT              objectType,
-        u64                                     object,
-        platform.size_t                         location,
-        s32                                     messageCode,
-        const char*                             pLayerPrefix,
-        const char*                             pMessage,
-        void*                                   pUserData) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd VkResult vkCreateDebugReportCallbackEXT(
-        VkInstance                                  instance,
-        const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDebugReportCallbackEXT*                   pCallback) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd void vkDestroyDebugReportCallbackEXT(
-        VkInstance                                  instance,
-        VkDebugReportCallbackEXT                    callback,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd void vkDebugReportMessageEXT(
-        VkInstance                                  instance,
-        VkDebugReportFlagsEXT                       flags,
-        VkDebugReportObjectTypeEXT                  objectType,
-        u64                                         object,
-        platform.size_t                             location,
-        s32                                         messageCode,
-        const char*                                 pLayerPrefix,
-        const char*                                 pMessage) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd VkResult vkDebugMarkerSetObjectTagEXT(
-        VkDevice                                    device,
-        const VkDebugMarkerObjectTagInfoEXT*        pTagInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd VkResult vkDebugMarkerSetObjectNameEXT(
-        VkDevice                                    device,
-        const VkDebugMarkerObjectNameInfoEXT*       pNameInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerBeginEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerEndEXT(
-        VkCommandBuffer                             commandBuffer) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerInsertEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBindTransformFeedbackBuffersEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstBinding,
-        u32                                         bindingCount,
-        const VkBuffer*                             pBuffers,
-        const VkDeviceSize*                         pOffsets,
-        const VkDeviceSize*                         pSizes) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBeginTransformFeedbackEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstCounterBuffer,
-        u32                                         counterBufferCount,
-        const VkBuffer*                             pCounterBuffers,
-        const VkDeviceSize*                         pCounterBufferOffsets) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdEndTransformFeedbackEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstCounterBuffer,
-        u32                                         counterBufferCount,
-        const VkBuffer*                             pCounterBuffers,
-        const VkDeviceSize*                         pCounterBufferOffsets) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBeginQueryIndexedEXT(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        VkQueryControlFlags                         flags,
-        u32                                         index) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdEndQueryIndexedEXT(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        u32                                         index) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdDrawIndirectByteCountEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         instanceCount,
-        u32                                         firstInstance,
-        VkBuffer                                    counterBuffer,
-        VkDeviceSize                                counterBufferOffset,
-        u32                                         counterOffset,
-        u32                                         vertexStride) {
-}
-
-@extension("VK_AMD_draw_indirect_count") // 34
-cmd void vkCmdDrawIndirectCountAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_AMD_draw_indirect_count") // 34
-cmd void vkCmdDrawIndexedIndirectCountAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_AMD_shader_info") // 43
-cmd VkResult vkGetShaderInfoAMD(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        VkShaderStageFlagBits                       shaderStage,
-        VkShaderInfoTypeAMD                         infoType,
-        platform.size_t*                            pInfoSize,
-        void*                                       pInfo) {
-    return ?
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-cmd VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkImageTiling                               tiling,
-        VkImageUsageFlags                           usage,
-        VkImageCreateFlags                          flags,
-        VkExternalMemoryHandleTypeFlagsNV           externalHandleType,
-        VkExternalImageFormatPropertiesNV*          pExternalImageFormatProperties) {
-    return ?
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-cmd VkResult vkGetMemoryWin32HandleNV(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkExternalMemoryHandleTypeFlagsNV           handleType,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceFeatures2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceFeatures2KHR*               pFeatures) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceProperties2KHR*             pProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceFormatProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkFormatProperties2KHR*                     pFormatProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd VkResult vkGetPhysicalDeviceImageFormatProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceImageFormatInfo2KHR*  pImageFormatInfo,
-        VkImageFormatProperties2KHR*                pImageFormatProperties) {
-    return ?
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceQueueFamilyProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pQueueFamilyPropertyCount,
-        VkQueueFamilyProperties2KHR*                pQueueFamilyProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceMemoryProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceMemoryProperties2KHR*       pMemoryProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
-        VkPhysicalDevice                                    physicalDevice,
-        const VkPhysicalDeviceSparseImageFormatInfo2KHR*    pFormatInfo,
-        u32*                                                pPropertyCount,
-        VkSparseImageFormatProperties2KHR*                  pProperties) {
-}
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkGetDeviceGroupPeerMemoryFeaturesKHR(
-        VkDevice                                    device,
-        u32                                         heapIndex,
-        u32                                         localDeviceIndex,
-        u32                                         remoteDeviceIndex,
-        VkPeerMemoryFeatureFlagsKHR*                pPeerMemoryFeatures) {
-}
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkCmdSetDeviceMaskKHR(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         deviceMask) {
-}
-
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkCmdDispatchBaseKHR(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         baseGroupX,
-        u32                                         baseGroupY,
-        u32                                         baseGroupZ,
-        u32                                         groupCountX,
-        u32                                         groupCountY,
-        u32                                         groupCountZ) {
-}
-
-@extension("VK_NN_vi_surface") // 63
-cmd VkResult vkCreateViSurfaceNN(
-        VkInstance                                  instance,
-        const VkViSurfaceCreateInfoNN*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_KHR_maintenance1") // 70
-cmd void vkTrimCommandPoolKHR(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        VkCommandPoolTrimFlagsKHR                   flags) {
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-@threadSafety("system")
-cmd VkResult vkEnumeratePhysicalDeviceGroupsKHR(
-        VkInstance                                  instance,
-        u32*                                        pPhysicalDeviceGroupCount,
-        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 ?
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-cmd void vkGetPhysicalDeviceExternalBufferPropertiesKHR(
-        VkPhysicalDevice                                physicalDevice,
-        const VkPhysicalDeviceExternalBufferInfoKHR*    pExternalBufferInfo,
-        VkExternalBufferPropertiesKHR*                  pExternalBufferProperties) {
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandleKHR(
-        VkDevice                                    device,
-        const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandlePropertiesKHR(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
-        platform.HANDLE                             handle,
-        VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdKHR(
-        VkDevice                                    device,
-        const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
-        s32*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdPropertiesKHR(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
-        s32                                         fd,
-        VkMemoryFdPropertiesKHR*                    pMemoryFdProperties) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-cmd void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
-        VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties) {
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-cmd VkResult vkImportSemaphoreWin32HandleKHR(
-        VkDevice                                    device,
-        const VkImportSemaphoreWin32HandleInfoKHR*  pImportSemaphoreWin32HandleInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-cmd VkResult vkGetSemaphoreWin32HandleKHR(
-        VkDevice                                    device,
-        const VkSemaphoreGetWin32HandleInfoKHR*     pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-cmd VkResult vkImportSemaphoreFdKHR(
-        VkDevice                                    device,
-        const VkImportSemaphoreFdInfoKHR*           pImportSemaphoreFdInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-cmd VkResult vkGetSemaphoreFdKHR(
-        VkDevice                                    device,
-        const VkSemaphoreGetFdInfoKHR*              pGetFdInfo,
-        s32*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_push_descriptor") // 81
-cmd void vkCmdPushDescriptorSetKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipelineLayout                            layout,
-        u32                                         set,
-        u32                                         descriptorWriteCount,
-        const VkWriteDescriptorSet*                 pDescriptorWrites) {
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-cmd void vkCmdBeginConditionalRenderingEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkConditionalRenderingBeginInfoEXT*   pConditionalRenderingBegin) {
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-cmd void vkCmdEndConditionalRenderingEXT(
-        VkCommandBuffer                             commandBuffer) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd VkResult vkCreateDescriptorUpdateTemplateKHR(
-        VkDevice                                    device,
-        const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorUpdateTemplateKHR*              pDescriptorUpdateTemplate) {
-    return ?
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkDestroyDescriptorUpdateTemplateKHR(
-        VkDevice                                    device,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkUpdateDescriptorSetWithTemplateKHR(
-        VkDevice                                    device,
-        VkDescriptorSet                             descriptorSet,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        const void*                                 pData) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkCmdPushDescriptorSetWithTemplateKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        VkPipelineLayout                            layout,
-        u32                                         set,
-        const void*                                 pData) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkCmdProcessCommandsNVX(
-        VkCommandBuffer                             commandBuffer,
-        const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkCmdReserveSpaceForCommandsNVX(
-        VkCommandBuffer                             commandBuffer,
-        const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkCreateIndirectCommandsLayoutNVX(
-        VkDevice                                    device,
-        const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkDestroyIndirectCommandsLayoutNVX(
-        VkDevice                                    device,
-        VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkCreateObjectTableNVX(
-        VkDevice                                    device,
-        const VkObjectTableCreateInfoNVX*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkObjectTableNVX*                           pObjectTable) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkDestroyObjectTableNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkRegisterObjectsNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        u32                                         objectCount,
-        const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
-        const u32*                                  pObjectIndices) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkUnregisterObjectsNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        u32                                         objectCount,
-        const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
-        const u32*                                  pObjectIndices) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
-        VkPhysicalDevice                            physicalDevice,
-        VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
-        VkDeviceGeneratedCommandsLimitsNVX*         pLimits) {
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-cmd void vkCmdSetViewportWScalingNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkViewportWScalingNV*                 pViewportWScalings) {
-}
-
-@extension("VK_EXT_direct_mode_display") // 89
-cmd VkResult vkReleaseDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkDisplayKHR                                display) {
-    return ?
-}
-
-@extension("VK_EXT_acquire_xlib_display") // 90
-cmd VkResult vkAcquireXlibDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        platform.Display*                           dpy,
-        VkDisplayKHR                                display) {
-    return ?
-}
-
-@extension("VK_EXT_acquire_xlib_display") // 90
-cmd VkResult vkGetRandROutputDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        platform.Display*                           dpy,
-        platform.RROutput                           rrOutput,
-        VkDisplayKHR*                               pDisplay) {
-    return ?
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2EXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        VkSurfaceCapabilities2EXT*                  pSurfaceCapabilities) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkDisplayPowerControlEXT(
-        VkDevice                                    device,
-        VkDisplayKHR                                display,
-        const VkDisplayPowerInfoEXT*                pDisplayPowerInfo) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkRegisterDeviceEventEXT(
-        VkDevice                                    device,
-        const VkDeviceEventInfoEXT*                 pDeviceEventInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkRegisterDisplayEventEXT(
-        VkDevice                                    device,
-        VkDisplayKHR                                display,
-        const VkDisplayEventInfoEXT*                pDisplayEventInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkGetSwapchainCounterEXT(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        VkSurfaceCounterFlagBitsEXT                 counter,
-        u64*                                        pCounterValue) {
-    return ?
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-cmd VkResult vkGetRefreshCycleDurationGOOGLE(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        VkRefreshCycleDurationGOOGLE*               pDisplayTimingProperties) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-
-    displayTimingProperties := ?
-    pDisplayTimingProperties[0] = displayTimingProperties
-
-    return ?
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-cmd VkResult vkGetPastPresentationTimingGOOGLE(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        u32*                                        pPresentationTimingCount,
-        VkPastPresentationTimingGOOGLE*             pPresentationTimings) {
-    return ?
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-cmd void vkCmdSetDiscardRectangleEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstDiscardRectangle,
-        u32                                         discardRectangleCount,
-        const VkRect2D*                             pDiscardRectangles) {
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-cmd void vkSetHdrMetadataEXT(
-        VkDevice                                    device,
-        u32                                         swapchainCount,
-        const VkSwapchainKHR*                       pSwapchains,
-        const VkHdrMetadataEXT*                     pMetadata) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd VkResult vkCreateRenderPass2KHR(
-        VkDevice                                    device,
-        const VkRenderPassCreateInfo2KHR*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkRenderPass*                               pRenderPass) {
-    return ?
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdBeginRenderPass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkRenderPassBeginInfo*                pRenderPassBegin,
-        const VkSubpassBeginInfoKHR*                pSubpassBeginInfo) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdNextSubpass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkSubpassBeginInfoKHR*                pSubpassBeginInfo,
-        const VkSubpassEndInfoKHR*                  pSubpassEndInfo) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdEndRenderPass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkSubpassEndInfoKHR*                  pSubpassEndInfo) {
-}
-
-@extension("VK_KHR_shared_presentable_image") // 112
-cmd VkResult vkGetSwapchainStatusKHR(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-cmd void vkGetPhysicalDeviceExternalFencePropertiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
-        VkExternalFencePropertiesKHR*               pExternalFenceProperties) {
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-cmd VkResult vkImportFenceWin32HandleKHR(
-        VkDevice                                    device,
-        const VkImportFenceWin32HandleInfoKHR*      pImportFenceWin32HandleInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-cmd VkResult vkGetFenceWin32HandleKHR(
-        VkDevice                                    device,
-        const VkFenceGetWin32HandleInfoKHR*         pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-cmd VkResult vkImportFenceFdKHR(
-        VkDevice                                    device,
-        const VkImportFenceFdInfoKHR*               pImportFenceFdInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-cmd VkResult vkGetFenceFdKHR(
-        VkDevice                                    device,
-        const VkFenceGetFdInfoKHR*                  pGetFdInfo,
-        int*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-        VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities) {
-    return ?
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-        u32*                                        pSurfaceFormatCount,
-        VkSurfaceFormat2KHR*                        pSurfaceFormats) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetPhysicalDeviceDisplayProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkDisplayProperties2KHR*                    pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkDisplayPlaneProperties2KHR*               pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetDisplayModeProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkDisplayKHR                                display,
-        u32*                                        pPropertyCount,
-        VkDisplayModeProperties2KHR*                pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetDisplayPlaneCapabilities2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkDisplayPlaneInfo2KHR*               pDisplayPlaneInfo,
-        VkDisplayPlaneCapabilities2KHR*             pCapabilities) {
-    return ?
-}
-
-@extension("VK_MVK_ios_surface") // 123
-cmd VkResult vkCreateIOSSurfaceMVK(
-        VkInstance                                  instance,
-        const VkIOSSurfaceCreateInfoMVK*            pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_MVK_macos_surface") // 124
-cmd VkResult vkCreateMacOSSurfaceMVK(
-        VkInstance                                  instance,
-        const VkMacOSSurfaceCreateInfoMVK*          pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-@external type void* PFN_vkDebugUtilsMessengerCallbackEXT
-@extension("VK_EXT_debug_utils") // 129
-@pfn cmd VkBool32 vkDebugUtilsMessengerCallbackEXT(
-        VkDebugUtilsMessageSeverityFlagBitsEXT      messageSeverity,
-        VkDebugUtilsMessageTypeFlagsEXT             messageType,
-        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
-        void*                                       pUserData) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkSetDebugUtilsObjectNameEXT(
-        VkDevice                                    device,
-        const VkDebugUtilsObjectNameInfoEXT*        pNameInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkSetDebugUtilsObjectTagEXT(
-        VkDevice                                    device,
-        const VkDebugUtilsObjectTagInfoEXT*         pTagInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueBeginDebugUtilsLabelEXT(
-        VkQueue                                     queue,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueEndDebugUtilsLabelEXT(VkQueue       queue) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueInsertDebugUtilsLabelEXT(
-        VkQueue                                     queue,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdBeginDebugUtilsLabelEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdInsertDebugUtilsLabelEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkCreateDebugUtilsMessengerEXT(
-        VkInstance                                  instance,
-        const VkDebugUtilsMessengerCreateInfoEXT*   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDebugUtilsMessengerEXT*                   pMessenger) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkDestroyDebugUtilsMessengerEXT(
-        VkInstance                                  instance,
-        VkDebugUtilsMessengerEXT                    messenger,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkSubmitDebugUtilsMessageEXT(
-        VkInstance                                  instance,
-        VkDebugUtilsMessageSeverityFlagBitsEXT      messageSeverity,
-        VkDebugUtilsMessageTypeFlagsEXT             messageTypes,
-        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData) {
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-@vulkan1_1 // extension requires 1.1, and should become non-optional when 1.1 does
-cmd VkResult vkGetAndroidHardwareBufferPropertiesANDROID(
-        VkDevice                                    device,
-        const platform.AHardwareBuffer*             buffer,
-        VkAndroidHardwareBufferPropertiesANDROID*   pProperties) {
-    return ?
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-@vulkan1_1 // extension requires 1.1, and should become non-optional when 1.1 does
-cmd VkResult vkGetMemoryAndroidHardwareBufferANDROID(
-        VkDevice                                            device,
-        const VkMemoryGetAndroidHardwareBufferInfoANDROID*  pInfo,
-        platform.AHardwareBuffer**                          pBuffer) {
-    return ?
-}
-
-@extension("VK_EXT_sample_locations") // 144
-cmd void vkCmdSetSampleLocationsEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkSampleLocationsInfoEXT*             pSampleLocationsInfo) {
-}
-
-@extension("VK_EXT_sample_locations") // 144
-cmd void vkGetPhysicalDeviceMultisamplePropertiesEXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkSampleCountFlagBits                       samples,
-        VkMultisamplePropertiesEXT*                 pMultisampleProperties) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetImageMemoryRequirements2KHR(
-        VkDevice                                    device,
-        const VkImageMemoryRequirementsInfo2KHR*    pInfo,
-        VkMemoryRequirements2KHR*                   pMemoryRequirements) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetBufferMemoryRequirements2KHR(
-        VkDevice                                    device,
-        const VkBufferMemoryRequirementsInfo2KHR*   pInfo,
-        VkMemoryRequirements2KHR*                   pMemoryRequirements) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetImageSparseMemoryRequirements2KHR(
-        VkDevice                                        device,
-        const VkImageSparseMemoryRequirementsInfo2KHR*  pInfo,
-        u32*                                            pSparseMemoryRequirementCount,
-        VkSparseImageMemoryRequirements2KHR*            pSparseMemoryRequirements) {
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-cmd VkResult vkCreateSamplerYcbcrConversionKHR(
-        VkDevice                                        device,
-        const VkSamplerYcbcrConversionCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*                    pAllocator,
-        VkSamplerYcbcrConversionKHR*                    pYcbcrConversion) {
-    return ?
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-cmd void vkDestroySamplerYcbcrConversionKHR(
-        VkDevice                                        device,
-        VkSamplerYcbcrConversionKHR                     ycbcrConversion,
-        const VkAllocationCallbacks*                    pAllocator) {
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-cmd VkResult vkBindBufferMemory2KHR(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindBufferMemoryInfoKHR*                pBindInfos) {
-    return ?
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-cmd VkResult vkBindImageMemory2KHR(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindImageMemoryInfoKHR*                 pBindInfos) {
-    return ?
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-cmd VkResult vkGetImageDrmFormatModifierPropertiesEXT(
-        VkDevice                                        device,
-        VkImage                                         image,
-        VkImageDrmFormatModifierPropertiesEXT*          pProperties) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkCreateValidationCacheEXT(
-        VkDevice                                    device,
-        const VkValidationCacheCreateInfoEXT*       pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkValidationCacheEXT*                       pValidationCache) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd void vkDestroyValidationCacheEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        validationCache,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkMergeValidationCachesEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        dstCache,
-        u32                                         srcCacheCount,
-        const VkValidationCacheEXT*                 pSrcCaches) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkGetValidationCacheDataEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        validationCache,
-        platform.size_t*                            pDataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdBindShadingRateImageNV(
-        VkCommandBuffer                             commandBuffer,
-        VkImageView                                 imageView,
-        VkImageLayout                               imageLayout) {
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdSetViewportShadingRatePaletteNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkShadingRatePaletteNV*               pShadingRatePalettes) {
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdSetCoarseSampleOrderNV(
-        VkCommandBuffer                             commandBuffer,
-        VkCoarseSampleOrderTypeNV                   sampleOrderType,
-        u32                                         customSampleOrderCount,
-        const VkCoarseSampleOrderCustomNV*          pCustomSampleOrders) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCreateAccelerationStructureNV(
-        VkDevice                                    device,
-        const VkAccelerationStructureCreateInfoNV*  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkAccelerationStructureNV*                  pAccelerationStructure) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkDestroyAccelerationStructureNV(
-        VkDevice                                    device,
-        VkAccelerationStructureNV                   accelerationStructure,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkGetAccelerationStructureMemoryRequirementsNV(
-        VkDevice                                                device,
-        const VkAccelerationStructureMemoryRequirementsInfoNV*  pInfo,
-        VkMemoryRequirements2KHR*                               pMemoryRequirements) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkBindAccelerationStructureMemoryNV(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindAccelerationStructureMemoryInfoNV*  pBindInfos) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdBuildAccelerationStructureNV(
-        VkCommandBuffer                             commandBuffer,
-        const VkAccelerationStructureInfoNV*        pInfo,
-        VkBuffer                                    instanceData,
-        VkDeviceSize                                instanceOffset,
-        VkBool32                                    update,
-        VkAccelerationStructureNV                   dst,
-        VkAccelerationStructureNV                   src,
-        VkBuffer                                    scratch,
-        VkDeviceSize                                scratchOffset) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdCopyAccelerationStructureNV(
-        VkCommandBuffer                             commandBuffer,
-        VkAccelerationStructureNV                   dst,
-        VkAccelerationStructureNV                   src,
-        VkCopyAccelerationStructureModeNV           mode) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdTraceRaysNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    raygenShaderBindingTableBuffer,
-        VkDeviceSize                                raygenShaderBindingOffset,
-        VkBuffer                                    missShaderBindingTableBuffer,
-        VkDeviceSize                                missShaderBindingOffset,
-        VkDeviceSize                                missShaderBindingStride,
-        VkBuffer                                    hitShaderBindingTableBuffer,
-        VkDeviceSize                                hitShaderBindingOffset,
-        VkDeviceSize                                hitShaderBindingStride,
-        VkBuffer                                    callableShaderBindingTableBuffer,
-        VkDeviceSize                                callableShaderBindingOffset,
-        VkDeviceSize                                callableShaderBindingStride,
-        u32                                         width,
-        u32                                         height,
-        u32                                         depth) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCreateRaytracingPipelinesNV(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkRayTracingPipelineCreateInfoNV*     pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkGetRaytracingShaderHandlesNV(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        u32                                         firstGroup,
-        u32                                         groupCount,
-        platform.size_t                             dataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkGetAccelerationStructureHandleNV(
-        VkDevice                                    device,
-        VkAccelerationStructureNV                   accelerationStructure,
-        platform.size_t                             dataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdWriteAccelerationStructurePropertiesNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         accelerationStructureCount,
-        const VkAccelerationStructureNV*            pAccelerationStructures,
-        VkQueryType                                 queryType,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCompileDeferredNV(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        u32                                         shader) {
-    return ?
-}
-
-@extension("VK_KHR_maintenance3") // 169
-cmd void vkGetDescriptorSetLayoutSupportKHR(
-        VkDevice                                    device,
-        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-        VkDescriptorSetLayoutSupportKHR*            pSupport) {
-}
-
-@extension("VK_KHR_draw_indirect_count") // 170
-cmd void vkCmdDrawIndirectCountKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_KHR_draw_indirect_count") // 170
-cmd void vkCmdDrawIndexedIndirectCountKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-cmd VkResult vkGetMemoryHostPointerPropertiesEXT(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBits          handleType,
-        const void*                                 pHostPointer,
-        VkMemoryHostPointerPropertiesEXT*           pMemoryHostPointerProperties) {
-    return ?
-}
-
-@extension("VK_AMD_buffer_marker") // 180
-cmd void vkCmdWriteBufferMarkerAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlagBits                     pipelineStage,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        u32                                         marker) {
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-cmd VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pTimeDomainCount,
-        VkTimeDomainEXT*                            pTimeDomains) {
-    return ?
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-cmd VkResult vkGetCalibratedTimestampsEXT(
-        VkDevice                                    device,
-        u32                                         timestampCount,
-        const VkCalibratedTimestampInfoEXT*         pTimestampInfos,
-        u64*                                        pTimestamps,
-        u64*                                        pMaxDeviation) {
-    return ?
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         taskCount,
-        u32                                         firstTask) {
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksIndirectNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksIndirectCountNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-cmd void vkCmdSetExclusiveScissorNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstExclusiveScissor,
-        u32                                         exclusiveScissorCount,
-        const VkRect2D*                             pExclusiveScissors) {
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-cmd void vkCmdSetCheckpointNV(
-        VkCommandBuffer                             commandBuffer,
-        const void*                                 pCheckpointMarker) {
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-cmd void vkGetQueueCheckpointDataNV(
-        VkQueue                                     queue,
-        u32*                                        pCheckpointDataCount,
-        VkCheckpointDataNV*                         pCheckpointData) {
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-cmd VkResult vkCreateImagePipeSurfaceFUCHSIA(
-        VkInstance                                  instance,
-        const VkImagePipeSurfaceCreateInfoFUCHSIA*  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-
-////////////////
-// Validation //
-////////////////
-
-extern void validate(string layerName, bool condition, string message)
-
-
-/////////////////////////////
-// Internal State Tracking //
-/////////////////////////////
-
-StateObject State
-
-@internal class StateObject {
-    // Dispatchable objects.
-    map!(VkInstance,       ref!InstanceObject)       Instances
-    map!(VkPhysicalDevice, ref!PhysicalDeviceObject) PhysicalDevices
-    map!(VkDevice,         ref!DeviceObject)         Devices
-    map!(VkQueue,          ref!QueueObject)          Queues
-    map!(VkCommandBuffer,  ref!CommandBufferObject)  CommandBuffers
-
-    // Non-dispatchable objects.
-    map!(VkDeviceMemory,             ref!DeviceMemoryObject)             DeviceMemories
-    map!(VkBuffer,                   ref!BufferObject)                   Buffers
-    map!(VkBufferView,               ref!BufferViewObject)               BufferViews
-    map!(VkImage,                    ref!ImageObject)                    Images
-    map!(VkImageView,                ref!ImageViewObject)                ImageViews
-    map!(VkShaderModule,             ref!ShaderModuleObject)             ShaderModules
-    map!(VkPipeline,                 ref!PipelineObject)                 Pipelines
-    map!(VkPipelineLayout,           ref!PipelineLayoutObject)           PipelineLayouts
-    map!(VkSampler,                  ref!SamplerObject)                  Samplers
-    map!(VkDescriptorSet,            ref!DescriptorSetObject)            DescriptorSets
-    map!(VkDescriptorSetLayout,      ref!DescriptorSetLayoutObject)      DescriptorSetLayouts
-    map!(VkDescriptorPool,           ref!DescriptorPoolObject)           DescriptorPools
-    map!(VkFence,                    ref!FenceObject)                    Fences
-    map!(VkSemaphore,                ref!SemaphoreObject)                Semaphores
-    map!(VkEvent,                    ref!EventObject)                    Events
-    map!(VkQueryPool,                ref!QueryPoolObject)                QueryPools
-    map!(VkFramebuffer,              ref!FramebufferObject)              Framebuffers
-    map!(VkRenderPass,               ref!RenderPassObject)               RenderPasses
-    map!(VkPipelineCache,            ref!PipelineCacheObject)            PipelineCaches
-    map!(VkCommandPool,              ref!CommandPoolObject)              CommandPools
-    map!(VkSurfaceKHR,               ref!SurfaceObject)                  Surfaces
-    map!(VkSwapchainKHR,             ref!SwapchainObject)                Swapchains
-}
-
-@internal class InstanceObject {
-}
-
-@internal class PhysicalDeviceObject {
-    VkInstance instance
-}
-
-@internal class DeviceObject {
-    VkPhysicalDevice physicalDevice
-}
-
-@internal class QueueObject {
-    VkDevice      device
-    VkQueueFlags  flags
-}
-
-@internal class CommandBufferObject {
-    VkDevice                  device
-    map!(u64, VkDeviceMemory) boundObjects
-    VkQueueFlags              queueFlags
-}
-
-@internal class DeviceMemoryObject {
-    VkDevice                                device
-    VkDeviceSize                            allocationSize
-    map!(u64, VkDeviceSize)                 boundObjects
-    map!(VkCommandBuffer, VkCommandBuffer)  boundCommandBuffers
-}
-
-@internal class BufferObject {
-    VkDevice              device
-    VkDeviceMemory        memory
-    VkDeviceSize          memoryOffset
-}
-
-@internal class BufferViewObject {
-    VkDevice      device
-    VkBuffer      buffer
-}
-
-@internal class ImageObject {
-    VkDevice              device
-    VkDeviceMemory        memory
-    VkDeviceSize          memoryOffset
-}
-
-@internal class ImageViewObject {
-    VkDevice      device
-    VkImage       image
-}
-
-@internal class ShaderObject {
-    VkDevice      device
-}
-
-@internal class ShaderModuleObject {
-    VkDevice      device
-}
-
-@internal class PipelineObject {
-    VkDevice      device
-}
-
-@internal class PipelineLayoutObject {
-    VkDevice      device
-}
-
-@internal class SamplerObject {
-    VkDevice      device
-}
-
-@internal class DescriptorSetObject {
-    VkDevice      device
-}
-
-@internal class DescriptorSetLayoutObject {
-    VkDevice      device
-}
-
-@internal class DescriptorPoolObject {
-    VkDevice      device
-}
-
-@internal class FenceObject {
-    VkDevice      device
-    bool          signaled
-}
-
-@internal class SemaphoreObject {
-    VkDevice      device
-}
-
-@internal class EventObject {
-    VkDevice      device
-}
-
-@internal class QueryPoolObject {
-    VkDevice      device
-}
-
-@internal class FramebufferObject {
-    VkDevice      device
-}
-
-@internal class RenderPassObject {
-    VkDevice      device
-}
-
-@internal class PipelineCacheObject {
-    VkDevice      device
-}
-
-@internal class CommandPoolObject {
-    VkDevice      device
-}
-
-@internal class SurfaceObject {
-    VkInstance    instance
-}
-
-@internal class SwapchainObject {
-    VkDevice      device
-}
-
-macro ref!InstanceObject GetInstance(VkInstance instance) {
-    assert(instance in State.Instances)
-    return State.Instances[instance]
-}
-
-macro ref!PhysicalDeviceObject GetPhysicalDevice(VkPhysicalDevice physicalDevice) {
-    assert(physicalDevice in State.PhysicalDevices)
-    return State.PhysicalDevices[physicalDevice]
-}
-
-macro ref!DeviceObject GetDevice(VkDevice device) {
-    assert(device in State.Devices)
-    return State.Devices[device]
-}
-
-macro ref!QueueObject GetQueue(VkQueue queue) {
-    assert(queue in State.Queues)
-    return State.Queues[queue]
-}
-
-macro ref!CommandBufferObject GetCommandBuffer(VkCommandBuffer commandBuffer) {
-    assert(commandBuffer in State.CommandBuffers)
-    return State.CommandBuffers[commandBuffer]
-}
-
-macro ref!DeviceMemoryObject GetDeviceMemory(VkDeviceMemory memory) {
-    assert(memory in State.DeviceMemories)
-    return State.DeviceMemories[memory]
-}
-
-macro ref!BufferObject GetBuffer(VkBuffer buffer) {
-    assert(buffer in State.Buffers)
-    return State.Buffers[buffer]
-}
-
-macro ref!BufferViewObject GetBufferView(VkBufferView bufferView) {
-    assert(bufferView in State.BufferViews)
-    return State.BufferViews[bufferView]
-}
-
-macro ref!ImageObject GetImage(VkImage image) {
-    assert(image in State.Images)
-    return State.Images[image]
-}
-
-macro ref!ImageViewObject GetImageView(VkImageView imageView) {
-    assert(imageView in State.ImageViews)
-    return State.ImageViews[imageView]
-}
-
-macro ref!ShaderModuleObject GetShaderModule(VkShaderModule shaderModule) {
-    assert(shaderModule in State.ShaderModules)
-    return State.ShaderModules[shaderModule]
-}
-
-macro ref!PipelineObject GetPipeline(VkPipeline pipeline) {
-    assert(pipeline in State.Pipelines)
-    return State.Pipelines[pipeline]
-}
-
-macro ref!PipelineLayoutObject GetPipelineLayout(VkPipelineLayout pipelineLayout) {
-    assert(pipelineLayout in State.PipelineLayouts)
-    return State.PipelineLayouts[pipelineLayout]
-}
-
-macro ref!SamplerObject GetSampler(VkSampler sampler) {
-    assert(sampler in State.Samplers)
-    return State.Samplers[sampler]
-}
-
-macro ref!DescriptorSetObject GetDescriptorSet(VkDescriptorSet descriptorSet) {
-    assert(descriptorSet in State.DescriptorSets)
-    return State.DescriptorSets[descriptorSet]
-}
-
-macro ref!DescriptorSetLayoutObject GetDescriptorSetLayout(VkDescriptorSetLayout descriptorSetLayout) {
-    assert(descriptorSetLayout in State.DescriptorSetLayouts)
-    return State.DescriptorSetLayouts[descriptorSetLayout]
-}
-
-macro ref!DescriptorPoolObject GetDescriptorPool(VkDescriptorPool descriptorPool) {
-    assert(descriptorPool in State.DescriptorPools)
-    return State.DescriptorPools[descriptorPool]
-}
-
-macro ref!FenceObject GetFence(VkFence fence) {
-    assert(fence in State.Fences)
-    return State.Fences[fence]
-}
-
-macro ref!SemaphoreObject GetSemaphore(VkSemaphore semaphore) {
-    assert(semaphore in State.Semaphores)
-    return State.Semaphores[semaphore]
-}
-
-macro ref!EventObject GetEvent(VkEvent event) {
-    assert(event in State.Events)
-    return State.Events[event]
-}
-
-macro ref!QueryPoolObject GetQueryPool(VkQueryPool queryPool) {
-    assert(queryPool in State.QueryPools)
-    return State.QueryPools[queryPool]
-}
-
-macro ref!FramebufferObject GetFramebuffer(VkFramebuffer framebuffer) {
-    assert(framebuffer in State.Framebuffers)
-    return State.Framebuffers[framebuffer]
-}
-
-macro ref!RenderPassObject GetRenderPass(VkRenderPass renderPass) {
-    assert(renderPass in State.RenderPasses)
-    return State.RenderPasses[renderPass]
-}
-
-macro ref!PipelineCacheObject GetPipelineCache(VkPipelineCache pipelineCache) {
-    assert(pipelineCache in State.PipelineCaches)
-    return State.PipelineCaches[pipelineCache]
-}
-
-macro ref!CommandPoolObject GetCommandPool(VkCommandPool commandPool) {
-    assert(commandPool in State.CommandPools)
-    return State.CommandPools[commandPool]
-}
-
-macro ref!SurfaceObject GetSurface(VkSurfaceKHR surface) {
-    assert(surface in State.Surfaces)
-    return State.Surfaces[surface]
-}
-
-macro ref!SwapchainObject GetSwapchain(VkSwapchainKHR swapchain) {
-    assert(swapchain in State.Swapchains)
-    return State.Swapchains[swapchain]
-}
-
-macro VkQueueFlags AddQueueFlag(VkQueueFlags flags, VkQueueFlagBits bit) {
-    return as!VkQueueFlags(as!u32(flags) | as!u32(bit))
-}
diff --git a/vulkan/include/vulkan/NOTICE b/vulkan/include/vulkan/NOTICE
deleted file mode 100644
index c958fba..0000000
--- a/vulkan/include/vulkan/NOTICE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright (c) 2015-2016 The Khronos Group Inc.
-
-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.
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index d3e5f0f..9ffe83b 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -37,7 +37,17 @@
  * backwards-compatibility support is temporary, and will likely be removed in
  * (along with all gralloc0 support) in a future release.
  */
-#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     7
+/* NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 8
+ *
+ * This version of the extension doesn't introduce new types or structs, but is
+ * to accommodate the new struct VkBindImageMemorySwapchainInfoKHR added in
+ * VK_KHR_swapchain spec version 69. When VkBindImageMemorySwapchainInfoKHR is
+ * chained in the pNext chain of VkBindImageMemoryInfo, a VkNativeBufferANDROID
+ * that holds the correct gralloc handle according to the imageIndex specified
+ * in VkBindImageMemorySwapchainInfoKHR will be additionally chained to the
+ * pNext chain of VkBindImageMemoryInfo and passed down to the driver.
+ */
+#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     8
 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME   "VK_ANDROID_native_buffer"
 
 #define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id)    ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
@@ -52,6 +62,11 @@
 typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
 
 typedef struct {
+    uint64_t consumer;
+    uint64_t producer;
+} VkNativeBufferUsage2ANDROID;
+
+typedef struct {
     VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
     const void*                 pNext;
 
@@ -63,10 +78,7 @@
     int                         format;
     int                         usage; // DEPRECATED in SPEC_VERSION 6
     // -- Added in SPEC_VERSION 6 --
-    struct {
-        uint64_t                consumer;
-        uint64_t                producer;
-    } usage2;
+    VkNativeBufferUsage2ANDROID usage2;
 } VkNativeBufferANDROID;
 
 typedef struct {
diff --git a/vulkan/include/vulkan/vk_platform.h b/vulkan/include/vulkan/vk_platform.h
deleted file mode 100644
index 7289299..0000000
--- a/vulkan/include/vulkan/vk_platform.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// File: vk_platform.h
-//
-/*
-** Copyright (c) 2014-2017 The Khronos Group Inc.
-**
-** 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 VK_PLATFORM_H_
-#define VK_PLATFORM_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif // __cplusplus
-
-/*
-***************************************************************************************************
-*   Platform-specific directives and type declarations
-***************************************************************************************************
-*/
-
-/* Platform-specific calling convention macros.
- *
- * Platforms should define these so that Vulkan clients call Vulkan commands
- * with the same calling conventions that the Vulkan implementation expects.
- *
- * VKAPI_ATTR - Placed before the return type in function declarations.
- *              Useful for C++11 and GCC/Clang-style function attribute syntax.
- * VKAPI_CALL - Placed after the return type in function declarations.
- *              Useful for MSVC-style calling convention syntax.
- * VKAPI_PTR  - Placed between the '(' and '*' in function pointer types.
- *
- * Function declaration:  VKAPI_ATTR void VKAPI_CALL vkCommand(void);
- * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
- */
-#if defined(_WIN32)
-    // On Windows, Vulkan commands use the stdcall convention
-    #define VKAPI_ATTR
-    #define VKAPI_CALL __stdcall
-    #define VKAPI_PTR  VKAPI_CALL
-#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
-    #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
-#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
-    // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
-    // calling convention, i.e. float parameters are passed in registers. This
-    // is true even if the rest of the application passes floats on the stack,
-    // as it does by default when compiling for the armeabi-v7a NDK ABI.
-    #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
-    #define VKAPI_CALL
-    #define VKAPI_PTR  VKAPI_ATTR
-#else
-    // On other platforms, use the default calling convention
-    #define VKAPI_ATTR
-    #define VKAPI_CALL
-    #define VKAPI_PTR
-#endif
-
-#include <stddef.h>
-
-#if !defined(VK_NO_STDINT_H)
-    #if defined(_MSC_VER) && (_MSC_VER < 1600)
-        typedef signed   __int8  int8_t;
-        typedef unsigned __int8  uint8_t;
-        typedef signed   __int16 int16_t;
-        typedef unsigned __int16 uint16_t;
-        typedef signed   __int32 int32_t;
-        typedef unsigned __int32 uint32_t;
-        typedef signed   __int64 int64_t;
-        typedef unsigned __int64 uint64_t;
-    #else
-        #include <stdint.h>
-    #endif
-#endif // !defined(VK_NO_STDINT_H)
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
deleted file mode 100644
index 77da637..0000000
--- a/vulkan/include/vulkan/vulkan.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef VULKAN_H_
-#define VULKAN_H_ 1
-
-/*
-** Copyright (c) 2015-2018 The Khronos Group Inc.
-**
-** 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 "vk_platform.h"
-#include "vulkan_core.h"
-
-#ifdef VK_USE_PLATFORM_ANDROID_KHR
-#include "vulkan_android.h"
-#endif
-
-#ifdef VK_USE_PLATFORM_FUCHSIA
-#include <zircon/types.h>
-#include "vulkan_fuchsia.h"
-#endif
-
-#ifdef VK_USE_PLATFORM_IOS_MVK
-#include "vulkan_ios.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_MACOS_MVK
-#include "vulkan_macos.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_VI_NN
-#include "vulkan_vi.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_WAYLAND_KHR
-#include <wayland-client.h>
-#include "vulkan_wayland.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_WIN32_KHR
-#include <windows.h>
-#include "vulkan_win32.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_XCB_KHR
-#include <xcb/xcb.h>
-#include "vulkan_xcb.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_XLIB_KHR
-#include <X11/Xlib.h>
-#include "vulkan_xlib.h"
-#endif
-
-
-#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
-#include <X11/Xlib.h>
-#include <X11/extensions/Xrandr.h>
-#include "vulkan_xlib_xrandr.h"
-#endif
-
-#endif // VULKAN_H_
diff --git a/vulkan/include/vulkan/vulkan_android.h b/vulkan/include/vulkan/vulkan_android.h
deleted file mode 100644
index 07aaeda..0000000
--- a/vulkan/include/vulkan/vulkan_android.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef VULKAN_ANDROID_H_
-#define VULKAN_ANDROID_H_ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Copyright (c) 2015-2018 The Khronos Group Inc.
-**
-** 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 header is generated from the Khronos Vulkan XML API Registry.
-**
-*/
-
-
-#define VK_KHR_android_surface 1
-struct ANativeWindow;
-
-#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
-#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
-
-typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
-
-typedef struct VkAndroidSurfaceCreateInfoKHR {
-    VkStructureType                   sType;
-    const void*                       pNext;
-    VkAndroidSurfaceCreateFlagsKHR    flags;
-    struct ANativeWindow*             window;
-} VkAndroidSurfaceCreateInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
-    VkInstance                                  instance,
-    const VkAndroidSurfaceCreateInfoKHR*        pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSurfaceKHR*                               pSurface);
-#endif
-
-#define VK_ANDROID_external_memory_android_hardware_buffer 1
-struct AHardwareBuffer;
-
-#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
-#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
-
-typedef struct VkAndroidHardwareBufferUsageANDROID {
-    VkStructureType    sType;
-    void*              pNext;
-    uint64_t           androidHardwareBufferUsage;
-} VkAndroidHardwareBufferUsageANDROID;
-
-typedef struct VkAndroidHardwareBufferPropertiesANDROID {
-    VkStructureType    sType;
-    void*              pNext;
-    VkDeviceSize       allocationSize;
-    uint32_t           memoryTypeBits;
-} VkAndroidHardwareBufferPropertiesANDROID;
-
-typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkFormat                         format;
-    uint64_t                         externalFormat;
-    VkFormatFeatureFlags             formatFeatures;
-    VkComponentMapping               samplerYcbcrConversionComponents;
-    VkSamplerYcbcrModelConversion    suggestedYcbcrModel;
-    VkSamplerYcbcrRange              suggestedYcbcrRange;
-    VkChromaLocation                 suggestedXChromaOffset;
-    VkChromaLocation                 suggestedYChromaOffset;
-} VkAndroidHardwareBufferFormatPropertiesANDROID;
-
-typedef struct VkImportAndroidHardwareBufferInfoANDROID {
-    VkStructureType            sType;
-    const void*                pNext;
-    struct AHardwareBuffer*    buffer;
-} VkImportAndroidHardwareBufferInfoANDROID;
-
-typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkDeviceMemory     memory;
-} VkMemoryGetAndroidHardwareBufferInfoANDROID;
-
-typedef struct VkExternalFormatANDROID {
-    VkStructureType    sType;
-    void*              pNext;
-    uint64_t           externalFormat;
-} VkExternalFormatANDROID;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(
-    VkDevice                                    device,
-    const struct AHardwareBuffer*               buffer,
-    VkAndroidHardwareBufferPropertiesANDROID*   pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(
-    VkDevice                                    device,
-    const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
-    struct AHardwareBuffer**                    pBuffer);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
deleted file mode 100644
index 72542c7..0000000
--- a/vulkan/include/vulkan/vulkan_core.h
+++ /dev/null
@@ -1,8945 +0,0 @@
-#ifndef VULKAN_CORE_H_
-#define VULKAN_CORE_H_ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** Copyright (c) 2015-2018 The Khronos Group Inc.
-**
-** 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 header is generated from the Khronos Vulkan XML API Registry.
-**
-*/
-
-
-#define VK_VERSION_1_0 1
-#include "vk_platform.h"
-
-#define VK_MAKE_VERSION(major, minor, patch) \
-    (((major) << 22) | ((minor) << 12) | (patch))
-
-// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.
-//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0
-
-// Vulkan 1.0 version number
-#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0
-
-#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
-#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
-#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
-// Version of this file
-#define VK_HEADER_VERSION 96
-
-
-#define VK_NULL_HANDLE 0
-
-
-#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
-
-
-#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
-#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
-        #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
-#else
-        #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
-#endif
-#endif
-
-
-typedef uint32_t VkFlags;
-typedef uint32_t VkBool32;
-typedef uint64_t VkDeviceSize;
-typedef uint32_t VkSampleMask;
-
-VK_DEFINE_HANDLE(VkInstance)
-VK_DEFINE_HANDLE(VkPhysicalDevice)
-VK_DEFINE_HANDLE(VkDevice)
-VK_DEFINE_HANDLE(VkQueue)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
-VK_DEFINE_HANDLE(VkCommandBuffer)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
-
-#define VK_LOD_CLAMP_NONE                 1000.0f
-#define VK_REMAINING_MIP_LEVELS           (~0U)
-#define VK_REMAINING_ARRAY_LAYERS         (~0U)
-#define VK_WHOLE_SIZE                     (~0ULL)
-#define VK_ATTACHMENT_UNUSED              (~0U)
-#define VK_TRUE                           1
-#define VK_FALSE                          0
-#define VK_QUEUE_FAMILY_IGNORED           (~0U)
-#define VK_SUBPASS_EXTERNAL               (~0U)
-#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE  256
-#define VK_UUID_SIZE                      16
-#define VK_MAX_MEMORY_TYPES               32
-#define VK_MAX_MEMORY_HEAPS               16
-#define VK_MAX_EXTENSION_NAME_SIZE        256
-#define VK_MAX_DESCRIPTION_SIZE           256
-
-
-typedef enum VkPipelineCacheHeaderVersion {
-    VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
-    VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
-    VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
-    VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1),
-    VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF
-} VkPipelineCacheHeaderVersion;
-
-typedef enum VkResult {
-    VK_SUCCESS = 0,
-    VK_NOT_READY = 1,
-    VK_TIMEOUT = 2,
-    VK_EVENT_SET = 3,
-    VK_EVENT_RESET = 4,
-    VK_INCOMPLETE = 5,
-    VK_ERROR_OUT_OF_HOST_MEMORY = -1,
-    VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
-    VK_ERROR_INITIALIZATION_FAILED = -3,
-    VK_ERROR_DEVICE_LOST = -4,
-    VK_ERROR_MEMORY_MAP_FAILED = -5,
-    VK_ERROR_LAYER_NOT_PRESENT = -6,
-    VK_ERROR_EXTENSION_NOT_PRESENT = -7,
-    VK_ERROR_FEATURE_NOT_PRESENT = -8,
-    VK_ERROR_INCOMPATIBLE_DRIVER = -9,
-    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,
-    VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
-    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
-    VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
-    VK_ERROR_INVALID_SHADER_NV = -1000012000,
-    VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000,
-    VK_ERROR_FRAGMENTATION_EXT = -1000161000,
-    VK_ERROR_NOT_PERMITTED_EXT = -1000174001,
-    VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY,
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE,
-    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),
-    VK_RESULT_MAX_ENUM = 0x7FFFFFFF
-} VkResult;
-
-typedef enum VkStructureType {
-    VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
-    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2,
-    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3,
-    VK_STRUCTURE_TYPE_SUBMIT_INFO = 4,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5,
-    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6,
-    VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7,
-    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8,
-    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9,
-    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10,
-    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11,
-    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12,
-    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13,
-    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15,
-    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16,
-    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17,
-    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19,
-    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23,
-    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24,
-    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25,
-    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26,
-    VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27,
-    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28,
-    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29,
-    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30,
-    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35,
-    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36,
-    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38,
-    VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42,
-    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45,
-    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_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
-    VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
-    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,
-    VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
-    VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
-    VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
-    VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
-    VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
-    VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002,
-    VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
-    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_VALIDATION_FLAGS_EXT = 1000061000,
-    VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
-    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,
-    VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003,
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000,
-    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_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,
-    VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003,
-    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_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
-    VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = 1000082000,
-    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
-    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,
-    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000,
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000,
-    VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
-    VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001,
-    VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002,
-    VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003,
-    VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000,
-    VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
-    VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
-    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = 1000109000,
-    VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = 1000109001,
-    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = 1000109002,
-    VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = 1000109003,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = 1000109004,
-    VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = 1000109005,
-    VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = 1000109006,
-    VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
-    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_SURFACE_INFO_2_KHR = 1000119000,
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
-    VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
-    VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001,
-    VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004,
-    VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
-    VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002,
-    VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003,
-    VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004,
-    VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
-    VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
-    VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
-    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_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_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000,
-    VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005,
-    VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
-    VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = 1000161000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = 1000161001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
-    VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001,
-    VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
-    VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004,
-    VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005,
-    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009,
-    VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
-    VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = 1000177000,
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
-    VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
-    VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
-    VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002,
-    VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
-    VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001,
-    VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = 1000221000,
-    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = 1000246000,
-    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
-    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
-    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES,
-    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
-    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
-    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO,
-    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT,
-    VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
-    VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
-    VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
-    VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkStructureType;
-
-typedef enum VkSystemAllocationScope {
-    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
-    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
-    VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
-    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
-    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
-    VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND,
-    VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE,
-    VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1),
-    VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF
-} VkSystemAllocationScope;
-
-typedef enum VkInternalAllocationType {
-    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
-    VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
-    VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
-    VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1),
-    VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkInternalAllocationType;
-
-typedef enum VkFormat {
-    VK_FORMAT_UNDEFINED = 0,
-    VK_FORMAT_R4G4_UNORM_PACK8 = 1,
-    VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
-    VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
-    VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
-    VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
-    VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
-    VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
-    VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
-    VK_FORMAT_R8_UNORM = 9,
-    VK_FORMAT_R8_SNORM = 10,
-    VK_FORMAT_R8_USCALED = 11,
-    VK_FORMAT_R8_SSCALED = 12,
-    VK_FORMAT_R8_UINT = 13,
-    VK_FORMAT_R8_SINT = 14,
-    VK_FORMAT_R8_SRGB = 15,
-    VK_FORMAT_R8G8_UNORM = 16,
-    VK_FORMAT_R8G8_SNORM = 17,
-    VK_FORMAT_R8G8_USCALED = 18,
-    VK_FORMAT_R8G8_SSCALED = 19,
-    VK_FORMAT_R8G8_UINT = 20,
-    VK_FORMAT_R8G8_SINT = 21,
-    VK_FORMAT_R8G8_SRGB = 22,
-    VK_FORMAT_R8G8B8_UNORM = 23,
-    VK_FORMAT_R8G8B8_SNORM = 24,
-    VK_FORMAT_R8G8B8_USCALED = 25,
-    VK_FORMAT_R8G8B8_SSCALED = 26,
-    VK_FORMAT_R8G8B8_UINT = 27,
-    VK_FORMAT_R8G8B8_SINT = 28,
-    VK_FORMAT_R8G8B8_SRGB = 29,
-    VK_FORMAT_B8G8R8_UNORM = 30,
-    VK_FORMAT_B8G8R8_SNORM = 31,
-    VK_FORMAT_B8G8R8_USCALED = 32,
-    VK_FORMAT_B8G8R8_SSCALED = 33,
-    VK_FORMAT_B8G8R8_UINT = 34,
-    VK_FORMAT_B8G8R8_SINT = 35,
-    VK_FORMAT_B8G8R8_SRGB = 36,
-    VK_FORMAT_R8G8B8A8_UNORM = 37,
-    VK_FORMAT_R8G8B8A8_SNORM = 38,
-    VK_FORMAT_R8G8B8A8_USCALED = 39,
-    VK_FORMAT_R8G8B8A8_SSCALED = 40,
-    VK_FORMAT_R8G8B8A8_UINT = 41,
-    VK_FORMAT_R8G8B8A8_SINT = 42,
-    VK_FORMAT_R8G8B8A8_SRGB = 43,
-    VK_FORMAT_B8G8R8A8_UNORM = 44,
-    VK_FORMAT_B8G8R8A8_SNORM = 45,
-    VK_FORMAT_B8G8R8A8_USCALED = 46,
-    VK_FORMAT_B8G8R8A8_SSCALED = 47,
-    VK_FORMAT_B8G8R8A8_UINT = 48,
-    VK_FORMAT_B8G8R8A8_SINT = 49,
-    VK_FORMAT_B8G8R8A8_SRGB = 50,
-    VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51,
-    VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52,
-    VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53,
-    VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54,
-    VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55,
-    VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56,
-    VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57,
-    VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58,
-    VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59,
-    VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60,
-    VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61,
-    VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62,
-    VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63,
-    VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64,
-    VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65,
-    VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66,
-    VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67,
-    VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68,
-    VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69,
-    VK_FORMAT_R16_UNORM = 70,
-    VK_FORMAT_R16_SNORM = 71,
-    VK_FORMAT_R16_USCALED = 72,
-    VK_FORMAT_R16_SSCALED = 73,
-    VK_FORMAT_R16_UINT = 74,
-    VK_FORMAT_R16_SINT = 75,
-    VK_FORMAT_R16_SFLOAT = 76,
-    VK_FORMAT_R16G16_UNORM = 77,
-    VK_FORMAT_R16G16_SNORM = 78,
-    VK_FORMAT_R16G16_USCALED = 79,
-    VK_FORMAT_R16G16_SSCALED = 80,
-    VK_FORMAT_R16G16_UINT = 81,
-    VK_FORMAT_R16G16_SINT = 82,
-    VK_FORMAT_R16G16_SFLOAT = 83,
-    VK_FORMAT_R16G16B16_UNORM = 84,
-    VK_FORMAT_R16G16B16_SNORM = 85,
-    VK_FORMAT_R16G16B16_USCALED = 86,
-    VK_FORMAT_R16G16B16_SSCALED = 87,
-    VK_FORMAT_R16G16B16_UINT = 88,
-    VK_FORMAT_R16G16B16_SINT = 89,
-    VK_FORMAT_R16G16B16_SFLOAT = 90,
-    VK_FORMAT_R16G16B16A16_UNORM = 91,
-    VK_FORMAT_R16G16B16A16_SNORM = 92,
-    VK_FORMAT_R16G16B16A16_USCALED = 93,
-    VK_FORMAT_R16G16B16A16_SSCALED = 94,
-    VK_FORMAT_R16G16B16A16_UINT = 95,
-    VK_FORMAT_R16G16B16A16_SINT = 96,
-    VK_FORMAT_R16G16B16A16_SFLOAT = 97,
-    VK_FORMAT_R32_UINT = 98,
-    VK_FORMAT_R32_SINT = 99,
-    VK_FORMAT_R32_SFLOAT = 100,
-    VK_FORMAT_R32G32_UINT = 101,
-    VK_FORMAT_R32G32_SINT = 102,
-    VK_FORMAT_R32G32_SFLOAT = 103,
-    VK_FORMAT_R32G32B32_UINT = 104,
-    VK_FORMAT_R32G32B32_SINT = 105,
-    VK_FORMAT_R32G32B32_SFLOAT = 106,
-    VK_FORMAT_R32G32B32A32_UINT = 107,
-    VK_FORMAT_R32G32B32A32_SINT = 108,
-    VK_FORMAT_R32G32B32A32_SFLOAT = 109,
-    VK_FORMAT_R64_UINT = 110,
-    VK_FORMAT_R64_SINT = 111,
-    VK_FORMAT_R64_SFLOAT = 112,
-    VK_FORMAT_R64G64_UINT = 113,
-    VK_FORMAT_R64G64_SINT = 114,
-    VK_FORMAT_R64G64_SFLOAT = 115,
-    VK_FORMAT_R64G64B64_UINT = 116,
-    VK_FORMAT_R64G64B64_SINT = 117,
-    VK_FORMAT_R64G64B64_SFLOAT = 118,
-    VK_FORMAT_R64G64B64A64_UINT = 119,
-    VK_FORMAT_R64G64B64A64_SINT = 120,
-    VK_FORMAT_R64G64B64A64_SFLOAT = 121,
-    VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122,
-    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123,
-    VK_FORMAT_D16_UNORM = 124,
-    VK_FORMAT_X8_D24_UNORM_PACK32 = 125,
-    VK_FORMAT_D32_SFLOAT = 126,
-    VK_FORMAT_S8_UINT = 127,
-    VK_FORMAT_D16_UNORM_S8_UINT = 128,
-    VK_FORMAT_D24_UNORM_S8_UINT = 129,
-    VK_FORMAT_D32_SFLOAT_S8_UINT = 130,
-    VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131,
-    VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132,
-    VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133,
-    VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134,
-    VK_FORMAT_BC2_UNORM_BLOCK = 135,
-    VK_FORMAT_BC2_SRGB_BLOCK = 136,
-    VK_FORMAT_BC3_UNORM_BLOCK = 137,
-    VK_FORMAT_BC3_SRGB_BLOCK = 138,
-    VK_FORMAT_BC4_UNORM_BLOCK = 139,
-    VK_FORMAT_BC4_SNORM_BLOCK = 140,
-    VK_FORMAT_BC5_UNORM_BLOCK = 141,
-    VK_FORMAT_BC5_SNORM_BLOCK = 142,
-    VK_FORMAT_BC6H_UFLOAT_BLOCK = 143,
-    VK_FORMAT_BC6H_SFLOAT_BLOCK = 144,
-    VK_FORMAT_BC7_UNORM_BLOCK = 145,
-    VK_FORMAT_BC7_SRGB_BLOCK = 146,
-    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147,
-    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148,
-    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149,
-    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150,
-    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151,
-    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152,
-    VK_FORMAT_EAC_R11_UNORM_BLOCK = 153,
-    VK_FORMAT_EAC_R11_SNORM_BLOCK = 154,
-    VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155,
-    VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156,
-    VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157,
-    VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158,
-    VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159,
-    VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160,
-    VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161,
-    VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162,
-    VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163,
-    VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164,
-    VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165,
-    VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166,
-    VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167,
-    VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168,
-    VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169,
-    VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170,
-    VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171,
-    VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172,
-    VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173,
-    VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174,
-    VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175,
-    VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176,
-    VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177,
-    VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178,
-    VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179,
-    VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180,
-    VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181,
-    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,
-    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003,
-    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004,
-    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 = VK_FORMAT_G8B8G8R8_422_UNORM,
-    VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM,
-    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
-    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
-    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
-    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
-    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
-    VK_FORMAT_R10X6_UNORM_PACK16_KHR = VK_FORMAT_R10X6_UNORM_PACK16,
-    VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
-    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
-    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
-    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
-    VK_FORMAT_R12X4_UNORM_PACK16_KHR = VK_FORMAT_R12X4_UNORM_PACK16,
-    VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
-    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
-    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
-    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
-    VK_FORMAT_G16B16G16R16_422_UNORM_KHR = VK_FORMAT_G16B16G16R16_422_UNORM,
-    VK_FORMAT_B16G16R16G16_422_UNORM_KHR = VK_FORMAT_B16G16R16G16_422_UNORM,
-    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
-    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
-    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
-    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
-    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
-    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),
-    VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
-} VkFormat;
-
-typedef enum VkImageType {
-    VK_IMAGE_TYPE_1D = 0,
-    VK_IMAGE_TYPE_2D = 1,
-    VK_IMAGE_TYPE_3D = 2,
-    VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D,
-    VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D,
-    VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1),
-    VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkImageType;
-
-typedef enum VkImageTiling {
-    VK_IMAGE_TILING_OPTIMAL = 0,
-    VK_IMAGE_TILING_LINEAR = 1,
-    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000,
-    VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL,
-    VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR,
-    VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1),
-    VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
-} VkImageTiling;
-
-typedef enum VkPhysicalDeviceType {
-    VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
-    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
-    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
-    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
-    VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
-    VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER,
-    VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU,
-    VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1),
-    VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkPhysicalDeviceType;
-
-typedef enum VkQueryType {
-    VK_QUERY_TYPE_OCCLUSION = 0,
-    VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
-    VK_QUERY_TYPE_TIMESTAMP = 2,
-    VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
-    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000,
-    VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
-    VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
-    VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
-    VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkQueryType;
-
-typedef enum VkSharingMode {
-    VK_SHARING_MODE_EXCLUSIVE = 0,
-    VK_SHARING_MODE_CONCURRENT = 1,
-    VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE,
-    VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT,
-    VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1),
-    VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF
-} VkSharingMode;
-
-typedef enum VkImageLayout {
-    VK_IMAGE_LAYOUT_UNDEFINED = 0,
-    VK_IMAGE_LAYOUT_GENERAL = 1,
-    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2,
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3,
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4,
-    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5,
-    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_SHADING_RATE_OPTIMAL_NV = 1000164003,
-    VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000,
-    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
-    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
-    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),
-    VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF
-} VkImageLayout;
-
-typedef enum VkImageViewType {
-    VK_IMAGE_VIEW_TYPE_1D = 0,
-    VK_IMAGE_VIEW_TYPE_2D = 1,
-    VK_IMAGE_VIEW_TYPE_3D = 2,
-    VK_IMAGE_VIEW_TYPE_CUBE = 3,
-    VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
-    VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
-    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
-    VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D,
-    VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
-    VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1),
-    VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkImageViewType;
-
-typedef enum VkComponentSwizzle {
-    VK_COMPONENT_SWIZZLE_IDENTITY = 0,
-    VK_COMPONENT_SWIZZLE_ZERO = 1,
-    VK_COMPONENT_SWIZZLE_ONE = 2,
-    VK_COMPONENT_SWIZZLE_R = 3,
-    VK_COMPONENT_SWIZZLE_G = 4,
-    VK_COMPONENT_SWIZZLE_B = 5,
-    VK_COMPONENT_SWIZZLE_A = 6,
-    VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY,
-    VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A,
-    VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1),
-    VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF
-} VkComponentSwizzle;
-
-typedef enum VkVertexInputRate {
-    VK_VERTEX_INPUT_RATE_VERTEX = 0,
-    VK_VERTEX_INPUT_RATE_INSTANCE = 1,
-    VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX,
-    VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE,
-    VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1),
-    VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF
-} VkVertexInputRate;
-
-typedef enum VkPrimitiveTopology {
-    VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
-    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
-    VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
-    VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
-    VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1),
-    VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
-} VkPrimitiveTopology;
-
-typedef enum VkPolygonMode {
-    VK_POLYGON_MODE_FILL = 0,
-    VK_POLYGON_MODE_LINE = 1,
-    VK_POLYGON_MODE_POINT = 2,
-    VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000,
-    VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL,
-    VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT,
-    VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1),
-    VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF
-} VkPolygonMode;
-
-typedef enum VkFrontFace {
-    VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
-    VK_FRONT_FACE_CLOCKWISE = 1,
-    VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE,
-    VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE,
-    VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1),
-    VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF
-} VkFrontFace;
-
-typedef enum VkCompareOp {
-    VK_COMPARE_OP_NEVER = 0,
-    VK_COMPARE_OP_LESS = 1,
-    VK_COMPARE_OP_EQUAL = 2,
-    VK_COMPARE_OP_LESS_OR_EQUAL = 3,
-    VK_COMPARE_OP_GREATER = 4,
-    VK_COMPARE_OP_NOT_EQUAL = 5,
-    VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
-    VK_COMPARE_OP_ALWAYS = 7,
-    VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER,
-    VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS,
-    VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1),
-    VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
-} VkCompareOp;
-
-typedef enum VkStencilOp {
-    VK_STENCIL_OP_KEEP = 0,
-    VK_STENCIL_OP_ZERO = 1,
-    VK_STENCIL_OP_REPLACE = 2,
-    VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3,
-    VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
-    VK_STENCIL_OP_INVERT = 5,
-    VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
-    VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
-    VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP,
-    VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP,
-    VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1),
-    VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
-} VkStencilOp;
-
-typedef enum VkLogicOp {
-    VK_LOGIC_OP_CLEAR = 0,
-    VK_LOGIC_OP_AND = 1,
-    VK_LOGIC_OP_AND_REVERSE = 2,
-    VK_LOGIC_OP_COPY = 3,
-    VK_LOGIC_OP_AND_INVERTED = 4,
-    VK_LOGIC_OP_NO_OP = 5,
-    VK_LOGIC_OP_XOR = 6,
-    VK_LOGIC_OP_OR = 7,
-    VK_LOGIC_OP_NOR = 8,
-    VK_LOGIC_OP_EQUIVALENT = 9,
-    VK_LOGIC_OP_INVERT = 10,
-    VK_LOGIC_OP_OR_REVERSE = 11,
-    VK_LOGIC_OP_COPY_INVERTED = 12,
-    VK_LOGIC_OP_OR_INVERTED = 13,
-    VK_LOGIC_OP_NAND = 14,
-    VK_LOGIC_OP_SET = 15,
-    VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR,
-    VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET,
-    VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1),
-    VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF
-} VkLogicOp;
-
-typedef enum VkBlendFactor {
-    VK_BLEND_FACTOR_ZERO = 0,
-    VK_BLEND_FACTOR_ONE = 1,
-    VK_BLEND_FACTOR_SRC_COLOR = 2,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3,
-    VK_BLEND_FACTOR_DST_COLOR = 4,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5,
-    VK_BLEND_FACTOR_SRC_ALPHA = 6,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7,
-    VK_BLEND_FACTOR_DST_ALPHA = 8,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9,
-    VK_BLEND_FACTOR_CONSTANT_COLOR = 10,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11,
-    VK_BLEND_FACTOR_CONSTANT_ALPHA = 12,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13,
-    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14,
-    VK_BLEND_FACTOR_SRC1_COLOR = 15,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
-    VK_BLEND_FACTOR_SRC1_ALPHA = 17,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
-    VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO,
-    VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
-    VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1),
-    VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF
-} VkBlendFactor;
-
-typedef enum VkBlendOp {
-    VK_BLEND_OP_ADD = 0,
-    VK_BLEND_OP_SUBTRACT = 1,
-    VK_BLEND_OP_REVERSE_SUBTRACT = 2,
-    VK_BLEND_OP_MIN = 3,
-    VK_BLEND_OP_MAX = 4,
-    VK_BLEND_OP_ZERO_EXT = 1000148000,
-    VK_BLEND_OP_SRC_EXT = 1000148001,
-    VK_BLEND_OP_DST_EXT = 1000148002,
-    VK_BLEND_OP_SRC_OVER_EXT = 1000148003,
-    VK_BLEND_OP_DST_OVER_EXT = 1000148004,
-    VK_BLEND_OP_SRC_IN_EXT = 1000148005,
-    VK_BLEND_OP_DST_IN_EXT = 1000148006,
-    VK_BLEND_OP_SRC_OUT_EXT = 1000148007,
-    VK_BLEND_OP_DST_OUT_EXT = 1000148008,
-    VK_BLEND_OP_SRC_ATOP_EXT = 1000148009,
-    VK_BLEND_OP_DST_ATOP_EXT = 1000148010,
-    VK_BLEND_OP_XOR_EXT = 1000148011,
-    VK_BLEND_OP_MULTIPLY_EXT = 1000148012,
-    VK_BLEND_OP_SCREEN_EXT = 1000148013,
-    VK_BLEND_OP_OVERLAY_EXT = 1000148014,
-    VK_BLEND_OP_DARKEN_EXT = 1000148015,
-    VK_BLEND_OP_LIGHTEN_EXT = 1000148016,
-    VK_BLEND_OP_COLORDODGE_EXT = 1000148017,
-    VK_BLEND_OP_COLORBURN_EXT = 1000148018,
-    VK_BLEND_OP_HARDLIGHT_EXT = 1000148019,
-    VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020,
-    VK_BLEND_OP_DIFFERENCE_EXT = 1000148021,
-    VK_BLEND_OP_EXCLUSION_EXT = 1000148022,
-    VK_BLEND_OP_INVERT_EXT = 1000148023,
-    VK_BLEND_OP_INVERT_RGB_EXT = 1000148024,
-    VK_BLEND_OP_LINEARDODGE_EXT = 1000148025,
-    VK_BLEND_OP_LINEARBURN_EXT = 1000148026,
-    VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027,
-    VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028,
-    VK_BLEND_OP_PINLIGHT_EXT = 1000148029,
-    VK_BLEND_OP_HARDMIX_EXT = 1000148030,
-    VK_BLEND_OP_HSL_HUE_EXT = 1000148031,
-    VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032,
-    VK_BLEND_OP_HSL_COLOR_EXT = 1000148033,
-    VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034,
-    VK_BLEND_OP_PLUS_EXT = 1000148035,
-    VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036,
-    VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037,
-    VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038,
-    VK_BLEND_OP_MINUS_EXT = 1000148039,
-    VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040,
-    VK_BLEND_OP_CONTRAST_EXT = 1000148041,
-    VK_BLEND_OP_INVERT_OVG_EXT = 1000148042,
-    VK_BLEND_OP_RED_EXT = 1000148043,
-    VK_BLEND_OP_GREEN_EXT = 1000148044,
-    VK_BLEND_OP_BLUE_EXT = 1000148045,
-    VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD,
-    VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX,
-    VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1),
-    VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF
-} VkBlendOp;
-
-typedef enum VkDynamicState {
-    VK_DYNAMIC_STATE_VIEWPORT = 0,
-    VK_DYNAMIC_STATE_SCISSOR = 1,
-    VK_DYNAMIC_STATE_LINE_WIDTH = 2,
-    VK_DYNAMIC_STATE_DEPTH_BIAS = 3,
-    VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4,
-    VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5,
-    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
-    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
-    VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
-    VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
-    VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
-    VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000,
-    VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004,
-    VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006,
-    VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001,
-    VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
-    VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
-    VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
-    VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF
-} VkDynamicState;
-
-typedef enum VkFilter {
-    VK_FILTER_NEAREST = 0,
-    VK_FILTER_LINEAR = 1,
-    VK_FILTER_CUBIC_IMG = 1000015000,
-    VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST,
-    VK_FILTER_END_RANGE = VK_FILTER_LINEAR,
-    VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1),
-    VK_FILTER_MAX_ENUM = 0x7FFFFFFF
-} VkFilter;
-
-typedef enum VkSamplerMipmapMode {
-    VK_SAMPLER_MIPMAP_MODE_NEAREST = 0,
-    VK_SAMPLER_MIPMAP_MODE_LINEAR = 1,
-    VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST,
-    VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR,
-    VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1),
-    VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
-} VkSamplerMipmapMode;
-
-typedef enum VkSamplerAddressMode {
-    VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
-    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
-    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
-    VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT,
-    VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
-    VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1),
-    VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF
-} VkSamplerAddressMode;
-
-typedef enum VkBorderColor {
-    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
-    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
-    VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
-    VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
-    VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
-    VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE,
-    VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1),
-    VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
-} VkBorderColor;
-
-typedef enum VkDescriptorType {
-    VK_DESCRIPTOR_TYPE_SAMPLER = 0,
-    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
-    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
-    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
-    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
-    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
-    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
-    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
-    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
-    VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
-    VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
-    VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
-    VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkDescriptorType;
-
-typedef enum VkAttachmentLoadOp {
-    VK_ATTACHMENT_LOAD_OP_LOAD = 0,
-    VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
-    VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
-    VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD,
-    VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
-    VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1),
-    VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF
-} VkAttachmentLoadOp;
-
-typedef enum VkAttachmentStoreOp {
-    VK_ATTACHMENT_STORE_OP_STORE = 0,
-    VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
-    VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE,
-    VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE,
-    VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1),
-    VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF
-} VkAttachmentStoreOp;
-
-typedef enum VkPipelineBindPoint {
-    VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
-    VK_PIPELINE_BIND_POINT_COMPUTE = 1,
-    VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000,
-    VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
-    VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
-    VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
-    VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF
-} VkPipelineBindPoint;
-
-typedef enum VkCommandBufferLevel {
-    VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
-    VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
-    VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
-    VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
-    VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1),
-    VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
-} VkCommandBufferLevel;
-
-typedef enum VkIndexType {
-    VK_INDEX_TYPE_UINT16 = 0,
-    VK_INDEX_TYPE_UINT32 = 1,
-    VK_INDEX_TYPE_NONE_NV = 1000165000,
-    VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
-    VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
-    VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
-    VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkIndexType;
-
-typedef enum VkSubpassContents {
-    VK_SUBPASS_CONTENTS_INLINE = 0,
-    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1,
-    VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE,
-    VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
-    VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1),
-    VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
-} VkSubpassContents;
-
-typedef enum VkObjectType {
-    VK_OBJECT_TYPE_UNKNOWN = 0,
-    VK_OBJECT_TYPE_INSTANCE = 1,
-    VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
-    VK_OBJECT_TYPE_DEVICE = 3,
-    VK_OBJECT_TYPE_QUEUE = 4,
-    VK_OBJECT_TYPE_SEMAPHORE = 5,
-    VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
-    VK_OBJECT_TYPE_FENCE = 7,
-    VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
-    VK_OBJECT_TYPE_BUFFER = 9,
-    VK_OBJECT_TYPE_IMAGE = 10,
-    VK_OBJECT_TYPE_EVENT = 11,
-    VK_OBJECT_TYPE_QUERY_POOL = 12,
-    VK_OBJECT_TYPE_BUFFER_VIEW = 13,
-    VK_OBJECT_TYPE_IMAGE_VIEW = 14,
-    VK_OBJECT_TYPE_SHADER_MODULE = 15,
-    VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
-    VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
-    VK_OBJECT_TYPE_RENDER_PASS = 18,
-    VK_OBJECT_TYPE_PIPELINE = 19,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
-    VK_OBJECT_TYPE_SAMPLER = 21,
-    VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
-    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_OBJECT_TABLE_NVX = 1000086000,
-    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
-    VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
-    VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
-    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
-    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
-    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
-    VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
-    VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
-    VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1),
-    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkObjectType;
-
-typedef enum VkVendorId {
-    VK_VENDOR_ID_VIV = 0x10001,
-    VK_VENDOR_ID_VSI = 0x10002,
-    VK_VENDOR_ID_KAZAN = 0x10003,
-    VK_VENDOR_ID_BEGIN_RANGE = VK_VENDOR_ID_VIV,
-    VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_KAZAN,
-    VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_KAZAN - VK_VENDOR_ID_VIV + 1),
-    VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF
-} VkVendorId;
-
-typedef VkFlags VkInstanceCreateFlags;
-
-typedef enum VkFormatFeatureFlagBits {
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
-    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
-    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
-    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
-    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_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000,
-    VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000,
-    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT,
-    VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
-    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,
-    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,
-    VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT,
-    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT,
-    VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkFormatFeatureFlagBits;
-typedef VkFlags VkFormatFeatureFlags;
-
-typedef enum VkImageUsageFlagBits {
-    VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,
-    VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,
-    VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
-    VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
-    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
-    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
-    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
-    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
-    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
-    VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200,
-    VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkImageUsageFlagBits;
-typedef VkFlags VkImageUsageFlags;
-
-typedef enum VkImageCreateFlagBits {
-    VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001,
-    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
-    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
-    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
-    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
-    VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400,
-    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_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_CORNER_SAMPLED_BIT_NV = 0x00002000,
-    VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
-    VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000,
-    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
-    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
-    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,
-    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
-    VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT,
-    VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT,
-    VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkImageCreateFlagBits;
-typedef VkFlags VkImageCreateFlags;
-
-typedef enum VkSampleCountFlagBits {
-    VK_SAMPLE_COUNT_1_BIT = 0x00000001,
-    VK_SAMPLE_COUNT_2_BIT = 0x00000002,
-    VK_SAMPLE_COUNT_4_BIT = 0x00000004,
-    VK_SAMPLE_COUNT_8_BIT = 0x00000008,
-    VK_SAMPLE_COUNT_16_BIT = 0x00000010,
-    VK_SAMPLE_COUNT_32_BIT = 0x00000020,
-    VK_SAMPLE_COUNT_64_BIT = 0x00000040,
-    VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSampleCountFlagBits;
-typedef VkFlags VkSampleCountFlags;
-
-typedef enum VkQueueFlagBits {
-    VK_QUEUE_GRAPHICS_BIT = 0x00000001,
-    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;
-
-typedef enum VkMemoryPropertyFlagBits {
-    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
-    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
-    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 = 0x00000002,
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
-    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 {
-    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
-    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
-    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
-    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
-    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
-    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
-    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
-    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
-    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
-    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
-    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
-    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
-    VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
-    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000,
-    VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
-    VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
-    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
-    VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
-    VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
-    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
-    VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
-    VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = 0x00200000,
-    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
-    VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
-    VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
-    VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
-    VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkPipelineStageFlagBits;
-typedef VkFlags VkPipelineStageFlags;
-typedef VkFlags VkMemoryMapFlags;
-
-typedef enum VkImageAspectFlagBits {
-    VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001,
-    VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
-    VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
-    VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
-    VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010,
-    VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020,
-    VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400,
-    VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT,
-    VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT,
-    VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT,
-    VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkImageAspectFlagBits;
-typedef VkFlags VkImageAspectFlags;
-
-typedef enum VkSparseImageFormatFlagBits {
-    VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001,
-    VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
-    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004,
-    VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSparseImageFormatFlagBits;
-typedef VkFlags VkSparseImageFormatFlags;
-
-typedef enum VkSparseMemoryBindFlagBits {
-    VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001,
-    VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSparseMemoryBindFlagBits;
-typedef VkFlags VkSparseMemoryBindFlags;
-
-typedef enum VkFenceCreateFlagBits {
-    VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
-    VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkFenceCreateFlagBits;
-typedef VkFlags VkFenceCreateFlags;
-typedef VkFlags VkSemaphoreCreateFlags;
-typedef VkFlags VkEventCreateFlags;
-typedef VkFlags VkQueryPoolCreateFlags;
-
-typedef enum VkQueryPipelineStatisticFlagBits {
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001,
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002,
-    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004,
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008,
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010,
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020,
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040,
-    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080,
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
-    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
-    VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkQueryPipelineStatisticFlagBits;
-typedef VkFlags VkQueryPipelineStatisticFlags;
-
-typedef enum VkQueryResultFlagBits {
-    VK_QUERY_RESULT_64_BIT = 0x00000001,
-    VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
-    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
-    VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
-    VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkQueryResultFlagBits;
-typedef VkFlags VkQueryResultFlags;
-
-typedef enum VkBufferCreateFlagBits {
-    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;
-
-typedef enum VkBufferUsageFlagBits {
-    VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001,
-    VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002,
-    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
-    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
-    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
-    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
-    VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
-    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
-    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800,
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000,
-    VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
-    VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
-    VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkBufferUsageFlagBits;
-typedef VkFlags VkBufferUsageFlags;
-typedef VkFlags VkBufferViewCreateFlags;
-
-typedef enum VkImageViewCreateFlagBits {
-    VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001,
-    VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkImageViewCreateFlagBits;
-typedef VkFlags VkImageViewCreateFlags;
-typedef VkFlags VkShaderModuleCreateFlags;
-typedef VkFlags VkPipelineCacheCreateFlags;
-
-typedef enum VkPipelineCreateFlagBits {
-    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 = 0x00000008,
-    VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
-    VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020,
-    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
-    VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE,
-    VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkPipelineCreateFlagBits;
-typedef VkFlags VkPipelineCreateFlags;
-typedef VkFlags VkPipelineShaderStageCreateFlags;
-
-typedef enum VkShaderStageFlagBits {
-    VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
-    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002,
-    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004,
-    VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
-    VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
-    VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
-    VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
-    VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
-    VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100,
-    VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
-    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
-    VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800,
-    VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000,
-    VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000,
-    VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
-    VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
-    VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkShaderStageFlagBits;
-typedef VkFlags VkPipelineVertexInputStateCreateFlags;
-typedef VkFlags VkPipelineInputAssemblyStateCreateFlags;
-typedef VkFlags VkPipelineTessellationStateCreateFlags;
-typedef VkFlags VkPipelineViewportStateCreateFlags;
-typedef VkFlags VkPipelineRasterizationStateCreateFlags;
-
-typedef enum VkCullModeFlagBits {
-    VK_CULL_MODE_NONE = 0,
-    VK_CULL_MODE_FRONT_BIT = 0x00000001,
-    VK_CULL_MODE_BACK_BIT = 0x00000002,
-    VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
-    VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkCullModeFlagBits;
-typedef VkFlags VkCullModeFlags;
-typedef VkFlags VkPipelineMultisampleStateCreateFlags;
-typedef VkFlags VkPipelineDepthStencilStateCreateFlags;
-typedef VkFlags VkPipelineColorBlendStateCreateFlags;
-
-typedef enum VkColorComponentFlagBits {
-    VK_COLOR_COMPONENT_R_BIT = 0x00000001,
-    VK_COLOR_COMPONENT_G_BIT = 0x00000002,
-    VK_COLOR_COMPONENT_B_BIT = 0x00000004,
-    VK_COLOR_COMPONENT_A_BIT = 0x00000008,
-    VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkColorComponentFlagBits;
-typedef VkFlags VkColorComponentFlags;
-typedef VkFlags VkPipelineDynamicStateCreateFlags;
-typedef VkFlags VkPipelineLayoutCreateFlags;
-typedef VkFlags VkShaderStageFlags;
-
-typedef enum VkSamplerCreateFlagBits {
-    VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001,
-    VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002,
-    VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSamplerCreateFlagBits;
-typedef VkFlags VkSamplerCreateFlags;
-
-typedef enum VkDescriptorSetLayoutCreateFlagBits {
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = 0x00000002,
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkDescriptorSetLayoutCreateFlagBits;
-typedef VkFlags VkDescriptorSetLayoutCreateFlags;
-
-typedef enum VkDescriptorPoolCreateFlagBits {
-    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
-    VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = 0x00000002,
-    VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkDescriptorPoolCreateFlagBits;
-typedef VkFlags VkDescriptorPoolCreateFlags;
-typedef VkFlags VkDescriptorPoolResetFlags;
-typedef VkFlags VkFramebufferCreateFlags;
-typedef VkFlags VkRenderPassCreateFlags;
-
-typedef enum VkAttachmentDescriptionFlagBits {
-    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001,
-    VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkAttachmentDescriptionFlagBits;
-typedef VkFlags VkAttachmentDescriptionFlags;
-
-typedef enum VkSubpassDescriptionFlagBits {
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001,
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
-    VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkSubpassDescriptionFlagBits;
-typedef VkFlags VkSubpassDescriptionFlags;
-
-typedef enum VkAccessFlagBits {
-    VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
-    VK_ACCESS_INDEX_READ_BIT = 0x00000002,
-    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
-    VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
-    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
-    VK_ACCESS_SHADER_READ_BIT = 0x00000020,
-    VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
-    VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
-    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
-    VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
-    VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
-    VK_ACCESS_HOST_READ_BIT = 0x00002000,
-    VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
-    VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
-    VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000,
-    VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
-    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
-    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
-    VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
-    VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
-    VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
-    VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkAccessFlagBits;
-typedef VkFlags VkAccessFlags;
-
-typedef enum VkDependencyFlagBits {
-    VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
-    VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT,
-    VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT,
-    VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkDependencyFlagBits;
-typedef VkFlags VkDependencyFlags;
-
-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;
-
-typedef enum VkCommandPoolResetFlagBits {
-    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
-    VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkCommandPoolResetFlagBits;
-typedef VkFlags VkCommandPoolResetFlags;
-
-typedef enum VkCommandBufferUsageFlagBits {
-    VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
-    VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
-    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
-    VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkCommandBufferUsageFlagBits;
-typedef VkFlags VkCommandBufferUsageFlags;
-
-typedef enum VkQueryControlFlagBits {
-    VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
-    VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkQueryControlFlagBits;
-typedef VkFlags VkQueryControlFlags;
-
-typedef enum VkCommandBufferResetFlagBits {
-    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
-    VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkCommandBufferResetFlagBits;
-typedef VkFlags VkCommandBufferResetFlags;
-
-typedef enum VkStencilFaceFlagBits {
-    VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
-    VK_STENCIL_FACE_BACK_BIT = 0x00000002,
-    VK_STENCIL_FRONT_AND_BACK = 0x00000003,
-    VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkStencilFaceFlagBits;
-typedef VkFlags VkStencilFaceFlags;
-
-typedef struct VkApplicationInfo {
-    VkStructureType    sType;
-    const void*        pNext;
-    const char*        pApplicationName;
-    uint32_t           applicationVersion;
-    const char*        pEngineName;
-    uint32_t           engineVersion;
-    uint32_t           apiVersion;
-} VkApplicationInfo;
-
-typedef struct VkInstanceCreateInfo {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkInstanceCreateFlags       flags;
-    const VkApplicationInfo*    pApplicationInfo;
-    uint32_t                    enabledLayerCount;
-    const char* const*          ppEnabledLayerNames;
-    uint32_t                    enabledExtensionCount;
-    const char* const*          ppEnabledExtensionNames;
-} VkInstanceCreateInfo;
-
-typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)(
-    void*                                       pUserData,
-    size_t                                      size,
-    size_t                                      alignment,
-    VkSystemAllocationScope                     allocationScope);
-
-typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
-    void*                                       pUserData,
-    void*                                       pOriginal,
-    size_t                                      size,
-    size_t                                      alignment,
-    VkSystemAllocationScope                     allocationScope);
-
-typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
-    void*                                       pUserData,
-    void*                                       pMemory);
-
-typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
-    void*                                       pUserData,
-    size_t                                      size,
-    VkInternalAllocationType                    allocationType,
-    VkSystemAllocationScope                     allocationScope);
-
-typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
-    void*                                       pUserData,
-    size_t                                      size,
-    VkInternalAllocationType                    allocationType,
-    VkSystemAllocationScope                     allocationScope);
-
-typedef struct VkAllocationCallbacks {
-    void*                                   pUserData;
-    PFN_vkAllocationFunction                pfnAllocation;
-    PFN_vkReallocationFunction              pfnReallocation;
-    PFN_vkFreeFunction                      pfnFree;
-    PFN_vkInternalAllocationNotification    pfnInternalAllocation;
-    PFN_vkInternalFreeNotification          pfnInternalFree;
-} VkAllocationCallbacks;
-
-typedef struct VkPhysicalDeviceFeatures {
-    VkBool32    robustBufferAccess;
-    VkBool32    fullDrawIndexUint32;
-    VkBool32    imageCubeArray;
-    VkBool32    independentBlend;
-    VkBool32    geometryShader;
-    VkBool32    tessellationShader;
-    VkBool32    sampleRateShading;
-    VkBool32    dualSrcBlend;
-    VkBool32    logicOp;
-    VkBool32    multiDrawIndirect;
-    VkBool32    drawIndirectFirstInstance;
-    VkBool32    depthClamp;
-    VkBool32    depthBiasClamp;
-    VkBool32    fillModeNonSolid;
-    VkBool32    depthBounds;
-    VkBool32    wideLines;
-    VkBool32    largePoints;
-    VkBool32    alphaToOne;
-    VkBool32    multiViewport;
-    VkBool32    samplerAnisotropy;
-    VkBool32    textureCompressionETC2;
-    VkBool32    textureCompressionASTC_LDR;
-    VkBool32    textureCompressionBC;
-    VkBool32    occlusionQueryPrecise;
-    VkBool32    pipelineStatisticsQuery;
-    VkBool32    vertexPipelineStoresAndAtomics;
-    VkBool32    fragmentStoresAndAtomics;
-    VkBool32    shaderTessellationAndGeometryPointSize;
-    VkBool32    shaderImageGatherExtended;
-    VkBool32    shaderStorageImageExtendedFormats;
-    VkBool32    shaderStorageImageMultisample;
-    VkBool32    shaderStorageImageReadWithoutFormat;
-    VkBool32    shaderStorageImageWriteWithoutFormat;
-    VkBool32    shaderUniformBufferArrayDynamicIndexing;
-    VkBool32    shaderSampledImageArrayDynamicIndexing;
-    VkBool32    shaderStorageBufferArrayDynamicIndexing;
-    VkBool32    shaderStorageImageArrayDynamicIndexing;
-    VkBool32    shaderClipDistance;
-    VkBool32    shaderCullDistance;
-    VkBool32    shaderFloat64;
-    VkBool32    shaderInt64;
-    VkBool32    shaderInt16;
-    VkBool32    shaderResourceResidency;
-    VkBool32    shaderResourceMinLod;
-    VkBool32    sparseBinding;
-    VkBool32    sparseResidencyBuffer;
-    VkBool32    sparseResidencyImage2D;
-    VkBool32    sparseResidencyImage3D;
-    VkBool32    sparseResidency2Samples;
-    VkBool32    sparseResidency4Samples;
-    VkBool32    sparseResidency8Samples;
-    VkBool32    sparseResidency16Samples;
-    VkBool32    sparseResidencyAliased;
-    VkBool32    variableMultisampleRate;
-    VkBool32    inheritedQueries;
-} VkPhysicalDeviceFeatures;
-
-typedef struct VkFormatProperties {
-    VkFormatFeatureFlags    linearTilingFeatures;
-    VkFormatFeatureFlags    optimalTilingFeatures;
-    VkFormatFeatureFlags    bufferFeatures;
-} VkFormatProperties;
-
-typedef struct VkExtent3D {
-    uint32_t    width;
-    uint32_t    height;
-    uint32_t    depth;
-} VkExtent3D;
-
-typedef struct VkImageFormatProperties {
-    VkExtent3D            maxExtent;
-    uint32_t              maxMipLevels;
-    uint32_t              maxArrayLayers;
-    VkSampleCountFlags    sampleCounts;
-    VkDeviceSize          maxResourceSize;
-} VkImageFormatProperties;
-
-typedef struct VkPhysicalDeviceLimits {
-    uint32_t              maxImageDimension1D;
-    uint32_t              maxImageDimension2D;
-    uint32_t              maxImageDimension3D;
-    uint32_t              maxImageDimensionCube;
-    uint32_t              maxImageArrayLayers;
-    uint32_t              maxTexelBufferElements;
-    uint32_t              maxUniformBufferRange;
-    uint32_t              maxStorageBufferRange;
-    uint32_t              maxPushConstantsSize;
-    uint32_t              maxMemoryAllocationCount;
-    uint32_t              maxSamplerAllocationCount;
-    VkDeviceSize          bufferImageGranularity;
-    VkDeviceSize          sparseAddressSpaceSize;
-    uint32_t              maxBoundDescriptorSets;
-    uint32_t              maxPerStageDescriptorSamplers;
-    uint32_t              maxPerStageDescriptorUniformBuffers;
-    uint32_t              maxPerStageDescriptorStorageBuffers;
-    uint32_t              maxPerStageDescriptorSampledImages;
-    uint32_t              maxPerStageDescriptorStorageImages;
-    uint32_t              maxPerStageDescriptorInputAttachments;
-    uint32_t              maxPerStageResources;
-    uint32_t              maxDescriptorSetSamplers;
-    uint32_t              maxDescriptorSetUniformBuffers;
-    uint32_t              maxDescriptorSetUniformBuffersDynamic;
-    uint32_t              maxDescriptorSetStorageBuffers;
-    uint32_t              maxDescriptorSetStorageBuffersDynamic;
-    uint32_t              maxDescriptorSetSampledImages;
-    uint32_t              maxDescriptorSetStorageImages;
-    uint32_t              maxDescriptorSetInputAttachments;
-    uint32_t              maxVertexInputAttributes;
-    uint32_t              maxVertexInputBindings;
-    uint32_t              maxVertexInputAttributeOffset;
-    uint32_t              maxVertexInputBindingStride;
-    uint32_t              maxVertexOutputComponents;
-    uint32_t              maxTessellationGenerationLevel;
-    uint32_t              maxTessellationPatchSize;
-    uint32_t              maxTessellationControlPerVertexInputComponents;
-    uint32_t              maxTessellationControlPerVertexOutputComponents;
-    uint32_t              maxTessellationControlPerPatchOutputComponents;
-    uint32_t              maxTessellationControlTotalOutputComponents;
-    uint32_t              maxTessellationEvaluationInputComponents;
-    uint32_t              maxTessellationEvaluationOutputComponents;
-    uint32_t              maxGeometryShaderInvocations;
-    uint32_t              maxGeometryInputComponents;
-    uint32_t              maxGeometryOutputComponents;
-    uint32_t              maxGeometryOutputVertices;
-    uint32_t              maxGeometryTotalOutputComponents;
-    uint32_t              maxFragmentInputComponents;
-    uint32_t              maxFragmentOutputAttachments;
-    uint32_t              maxFragmentDualSrcAttachments;
-    uint32_t              maxFragmentCombinedOutputResources;
-    uint32_t              maxComputeSharedMemorySize;
-    uint32_t              maxComputeWorkGroupCount[3];
-    uint32_t              maxComputeWorkGroupInvocations;
-    uint32_t              maxComputeWorkGroupSize[3];
-    uint32_t              subPixelPrecisionBits;
-    uint32_t              subTexelPrecisionBits;
-    uint32_t              mipmapPrecisionBits;
-    uint32_t              maxDrawIndexedIndexValue;
-    uint32_t              maxDrawIndirectCount;
-    float                 maxSamplerLodBias;
-    float                 maxSamplerAnisotropy;
-    uint32_t              maxViewports;
-    uint32_t              maxViewportDimensions[2];
-    float                 viewportBoundsRange[2];
-    uint32_t              viewportSubPixelBits;
-    size_t                minMemoryMapAlignment;
-    VkDeviceSize          minTexelBufferOffsetAlignment;
-    VkDeviceSize          minUniformBufferOffsetAlignment;
-    VkDeviceSize          minStorageBufferOffsetAlignment;
-    int32_t               minTexelOffset;
-    uint32_t              maxTexelOffset;
-    int32_t               minTexelGatherOffset;
-    uint32_t              maxTexelGatherOffset;
-    float                 minInterpolationOffset;
-    float                 maxInterpolationOffset;
-    uint32_t              subPixelInterpolationOffsetBits;
-    uint32_t              maxFramebufferWidth;
-    uint32_t              maxFramebufferHeight;
-    uint32_t              maxFramebufferLayers;
-    VkSampleCountFlags    framebufferColorSampleCounts;
-    VkSampleCountFlags    framebufferDepthSampleCounts;
-    VkSampleCountFlags    framebufferStencilSampleCounts;
-    VkSampleCountFlags    framebufferNoAttachmentsSampleCounts;
-    uint32_t              maxColorAttachments;
-    VkSampleCountFlags    sampledImageColorSampleCounts;
-    VkSampleCountFlags    sampledImageIntegerSampleCounts;
-    VkSampleCountFlags    sampledImageDepthSampleCounts;
-    VkSampleCountFlags    sampledImageStencilSampleCounts;
-    VkSampleCountFlags    storageImageSampleCounts;
-    uint32_t              maxSampleMaskWords;
-    VkBool32              timestampComputeAndGraphics;
-    float                 timestampPeriod;
-    uint32_t              maxClipDistances;
-    uint32_t              maxCullDistances;
-    uint32_t              maxCombinedClipAndCullDistances;
-    uint32_t              discreteQueuePriorities;
-    float                 pointSizeRange[2];
-    float                 lineWidthRange[2];
-    float                 pointSizeGranularity;
-    float                 lineWidthGranularity;
-    VkBool32              strictLines;
-    VkBool32              standardSampleLocations;
-    VkDeviceSize          optimalBufferCopyOffsetAlignment;
-    VkDeviceSize          optimalBufferCopyRowPitchAlignment;
-    VkDeviceSize          nonCoherentAtomSize;
-} VkPhysicalDeviceLimits;
-
-typedef struct VkPhysicalDeviceSparseProperties {
-    VkBool32    residencyStandard2DBlockShape;
-    VkBool32    residencyStandard2DMultisampleBlockShape;
-    VkBool32    residencyStandard3DBlockShape;
-    VkBool32    residencyAlignedMipSize;
-    VkBool32    residencyNonResidentStrict;
-} VkPhysicalDeviceSparseProperties;
-
-typedef struct VkPhysicalDeviceProperties {
-    uint32_t                            apiVersion;
-    uint32_t                            driverVersion;
-    uint32_t                            vendorID;
-    uint32_t                            deviceID;
-    VkPhysicalDeviceType                deviceType;
-    char                                deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
-    uint8_t                             pipelineCacheUUID[VK_UUID_SIZE];
-    VkPhysicalDeviceLimits              limits;
-    VkPhysicalDeviceSparseProperties    sparseProperties;
-} VkPhysicalDeviceProperties;
-
-typedef struct VkQueueFamilyProperties {
-    VkQueueFlags    queueFlags;
-    uint32_t        queueCount;
-    uint32_t        timestampValidBits;
-    VkExtent3D      minImageTransferGranularity;
-} VkQueueFamilyProperties;
-
-typedef struct VkMemoryType {
-    VkMemoryPropertyFlags    propertyFlags;
-    uint32_t                 heapIndex;
-} VkMemoryType;
-
-typedef struct VkMemoryHeap {
-    VkDeviceSize         size;
-    VkMemoryHeapFlags    flags;
-} VkMemoryHeap;
-
-typedef struct VkPhysicalDeviceMemoryProperties {
-    uint32_t        memoryTypeCount;
-    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
-    uint32_t        memoryHeapCount;
-    VkMemoryHeap    memoryHeaps[VK_MAX_MEMORY_HEAPS];
-} VkPhysicalDeviceMemoryProperties;
-
-typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void);
-typedef struct VkDeviceQueueCreateInfo {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkDeviceQueueCreateFlags    flags;
-    uint32_t                    queueFamilyIndex;
-    uint32_t                    queueCount;
-    const float*                pQueuePriorities;
-} VkDeviceQueueCreateInfo;
-
-typedef struct VkDeviceCreateInfo {
-    VkStructureType                    sType;
-    const void*                        pNext;
-    VkDeviceCreateFlags                flags;
-    uint32_t                           queueCreateInfoCount;
-    const VkDeviceQueueCreateInfo*     pQueueCreateInfos;
-    uint32_t                           enabledLayerCount;
-    const char* const*                 ppEnabledLayerNames;
-    uint32_t                           enabledExtensionCount;
-    const char* const*                 ppEnabledExtensionNames;
-    const VkPhysicalDeviceFeatures*    pEnabledFeatures;
-} VkDeviceCreateInfo;
-
-typedef struct VkExtensionProperties {
-    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
-    uint32_t    specVersion;
-} VkExtensionProperties;
-
-typedef struct VkLayerProperties {
-    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];
-    uint32_t    specVersion;
-    uint32_t    implementationVersion;
-    char        description[VK_MAX_DESCRIPTION_SIZE];
-} VkLayerProperties;
-
-typedef struct VkSubmitInfo {
-    VkStructureType                sType;
-    const void*                    pNext;
-    uint32_t                       waitSemaphoreCount;
-    const VkSemaphore*             pWaitSemaphores;
-    const VkPipelineStageFlags*    pWaitDstStageMask;
-    uint32_t                       commandBufferCount;
-    const VkCommandBuffer*         pCommandBuffers;
-    uint32_t                       signalSemaphoreCount;
-    const VkSemaphore*             pSignalSemaphores;
-} VkSubmitInfo;
-
-typedef struct VkMemoryAllocateInfo {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkDeviceSize       allocationSize;
-    uint32_t           memoryTypeIndex;
-} VkMemoryAllocateInfo;
-
-typedef struct VkMappedMemoryRange {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkDeviceMemory     memory;
-    VkDeviceSize       offset;
-    VkDeviceSize       size;
-} VkMappedMemoryRange;
-
-typedef struct VkMemoryRequirements {
-    VkDeviceSize    size;
-    VkDeviceSize    alignment;
-    uint32_t        memoryTypeBits;
-} VkMemoryRequirements;
-
-typedef struct VkSparseImageFormatProperties {
-    VkImageAspectFlags          aspectMask;
-    VkExtent3D                  imageGranularity;
-    VkSparseImageFormatFlags    flags;
-} VkSparseImageFormatProperties;
-
-typedef struct VkSparseImageMemoryRequirements {
-    VkSparseImageFormatProperties    formatProperties;
-    uint32_t                         imageMipTailFirstLod;
-    VkDeviceSize                     imageMipTailSize;
-    VkDeviceSize                     imageMipTailOffset;
-    VkDeviceSize                     imageMipTailStride;
-} VkSparseImageMemoryRequirements;
-
-typedef struct VkSparseMemoryBind {
-    VkDeviceSize               resourceOffset;
-    VkDeviceSize               size;
-    VkDeviceMemory             memory;
-    VkDeviceSize               memoryOffset;
-    VkSparseMemoryBindFlags    flags;
-} VkSparseMemoryBind;
-
-typedef struct VkSparseBufferMemoryBindInfo {
-    VkBuffer                     buffer;
-    uint32_t                     bindCount;
-    const VkSparseMemoryBind*    pBinds;
-} VkSparseBufferMemoryBindInfo;
-
-typedef struct VkSparseImageOpaqueMemoryBindInfo {
-    VkImage                      image;
-    uint32_t                     bindCount;
-    const VkSparseMemoryBind*    pBinds;
-} VkSparseImageOpaqueMemoryBindInfo;
-
-typedef struct VkImageSubresource {
-    VkImageAspectFlags    aspectMask;
-    uint32_t              mipLevel;
-    uint32_t              arrayLayer;
-} VkImageSubresource;
-
-typedef struct VkOffset3D {
-    int32_t    x;
-    int32_t    y;
-    int32_t    z;
-} VkOffset3D;
-
-typedef struct VkSparseImageMemoryBind {
-    VkImageSubresource         subresource;
-    VkOffset3D                 offset;
-    VkExtent3D                 extent;
-    VkDeviceMemory             memory;
-    VkDeviceSize               memoryOffset;
-    VkSparseMemoryBindFlags    flags;
-} VkSparseImageMemoryBind;
-
-typedef struct VkSparseImageMemoryBindInfo {
-    VkImage                           image;
-    uint32_t                          bindCount;
-    const VkSparseImageMemoryBind*    pBinds;
-} VkSparseImageMemoryBindInfo;
-
-typedef struct VkBindSparseInfo {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    uint32_t                                    waitSemaphoreCount;
-    const VkSemaphore*                          pWaitSemaphores;
-    uint32_t                                    bufferBindCount;
-    const VkSparseBufferMemoryBindInfo*         pBufferBinds;
-    uint32_t                                    imageOpaqueBindCount;
-    const VkSparseImageOpaqueMemoryBindInfo*    pImageOpaqueBinds;
-    uint32_t                                    imageBindCount;
-    const VkSparseImageMemoryBindInfo*          pImageBinds;
-    uint32_t                                    signalSemaphoreCount;
-    const VkSemaphore*                          pSignalSemaphores;
-} VkBindSparseInfo;
-
-typedef struct VkFenceCreateInfo {
-    VkStructureType       sType;
-    const void*           pNext;
-    VkFenceCreateFlags    flags;
-} VkFenceCreateInfo;
-
-typedef struct VkSemaphoreCreateInfo {
-    VkStructureType           sType;
-    const void*               pNext;
-    VkSemaphoreCreateFlags    flags;
-} VkSemaphoreCreateInfo;
-
-typedef struct VkEventCreateInfo {
-    VkStructureType       sType;
-    const void*           pNext;
-    VkEventCreateFlags    flags;
-} VkEventCreateInfo;
-
-typedef struct VkQueryPoolCreateInfo {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkQueryPoolCreateFlags           flags;
-    VkQueryType                      queryType;
-    uint32_t                         queryCount;
-    VkQueryPipelineStatisticFlags    pipelineStatistics;
-} VkQueryPoolCreateInfo;
-
-typedef struct VkBufferCreateInfo {
-    VkStructureType        sType;
-    const void*            pNext;
-    VkBufferCreateFlags    flags;
-    VkDeviceSize           size;
-    VkBufferUsageFlags     usage;
-    VkSharingMode          sharingMode;
-    uint32_t               queueFamilyIndexCount;
-    const uint32_t*        pQueueFamilyIndices;
-} VkBufferCreateInfo;
-
-typedef struct VkBufferViewCreateInfo {
-    VkStructureType            sType;
-    const void*                pNext;
-    VkBufferViewCreateFlags    flags;
-    VkBuffer                   buffer;
-    VkFormat                   format;
-    VkDeviceSize               offset;
-    VkDeviceSize               range;
-} VkBufferViewCreateInfo;
-
-typedef struct VkImageCreateInfo {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkImageCreateFlags       flags;
-    VkImageType              imageType;
-    VkFormat                 format;
-    VkExtent3D               extent;
-    uint32_t                 mipLevels;
-    uint32_t                 arrayLayers;
-    VkSampleCountFlagBits    samples;
-    VkImageTiling            tiling;
-    VkImageUsageFlags        usage;
-    VkSharingMode            sharingMode;
-    uint32_t                 queueFamilyIndexCount;
-    const uint32_t*          pQueueFamilyIndices;
-    VkImageLayout            initialLayout;
-} VkImageCreateInfo;
-
-typedef struct VkSubresourceLayout {
-    VkDeviceSize    offset;
-    VkDeviceSize    size;
-    VkDeviceSize    rowPitch;
-    VkDeviceSize    arrayPitch;
-    VkDeviceSize    depthPitch;
-} VkSubresourceLayout;
-
-typedef struct VkComponentMapping {
-    VkComponentSwizzle    r;
-    VkComponentSwizzle    g;
-    VkComponentSwizzle    b;
-    VkComponentSwizzle    a;
-} VkComponentMapping;
-
-typedef struct VkImageSubresourceRange {
-    VkImageAspectFlags    aspectMask;
-    uint32_t              baseMipLevel;
-    uint32_t              levelCount;
-    uint32_t              baseArrayLayer;
-    uint32_t              layerCount;
-} VkImageSubresourceRange;
-
-typedef struct VkImageViewCreateInfo {
-    VkStructureType            sType;
-    const void*                pNext;
-    VkImageViewCreateFlags     flags;
-    VkImage                    image;
-    VkImageViewType            viewType;
-    VkFormat                   format;
-    VkComponentMapping         components;
-    VkImageSubresourceRange    subresourceRange;
-} VkImageViewCreateInfo;
-
-typedef struct VkShaderModuleCreateInfo {
-    VkStructureType              sType;
-    const void*                  pNext;
-    VkShaderModuleCreateFlags    flags;
-    size_t                       codeSize;
-    const uint32_t*              pCode;
-} VkShaderModuleCreateInfo;
-
-typedef struct VkPipelineCacheCreateInfo {
-    VkStructureType               sType;
-    const void*                   pNext;
-    VkPipelineCacheCreateFlags    flags;
-    size_t                        initialDataSize;
-    const void*                   pInitialData;
-} VkPipelineCacheCreateInfo;
-
-typedef struct VkSpecializationMapEntry {
-    uint32_t    constantID;
-    uint32_t    offset;
-    size_t      size;
-} VkSpecializationMapEntry;
-
-typedef struct VkSpecializationInfo {
-    uint32_t                           mapEntryCount;
-    const VkSpecializationMapEntry*    pMapEntries;
-    size_t                             dataSize;
-    const void*                        pData;
-} VkSpecializationInfo;
-
-typedef struct VkPipelineShaderStageCreateInfo {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    VkPipelineShaderStageCreateFlags    flags;
-    VkShaderStageFlagBits               stage;
-    VkShaderModule                      module;
-    const char*                         pName;
-    const VkSpecializationInfo*         pSpecializationInfo;
-} VkPipelineShaderStageCreateInfo;
-
-typedef struct VkVertexInputBindingDescription {
-    uint32_t             binding;
-    uint32_t             stride;
-    VkVertexInputRate    inputRate;
-} VkVertexInputBindingDescription;
-
-typedef struct VkVertexInputAttributeDescription {
-    uint32_t    location;
-    uint32_t    binding;
-    VkFormat    format;
-    uint32_t    offset;
-} VkVertexInputAttributeDescription;
-
-typedef struct VkPipelineVertexInputStateCreateInfo {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkPipelineVertexInputStateCreateFlags       flags;
-    uint32_t                                    vertexBindingDescriptionCount;
-    const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
-    uint32_t                                    vertexAttributeDescriptionCount;
-    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
-} VkPipelineVertexInputStateCreateInfo;
-
-typedef struct VkPipelineInputAssemblyStateCreateInfo {
-    VkStructureType                            sType;
-    const void*                                pNext;
-    VkPipelineInputAssemblyStateCreateFlags    flags;
-    VkPrimitiveTopology                        topology;
-    VkBool32                                   primitiveRestartEnable;
-} VkPipelineInputAssemblyStateCreateInfo;
-
-typedef struct VkPipelineTessellationStateCreateInfo {
-    VkStructureType                           sType;
-    const void*                               pNext;
-    VkPipelineTessellationStateCreateFlags    flags;
-    uint32_t                                  patchControlPoints;
-} VkPipelineTessellationStateCreateInfo;
-
-typedef struct VkViewport {
-    float    x;
-    float    y;
-    float    width;
-    float    height;
-    float    minDepth;
-    float    maxDepth;
-} VkViewport;
-
-typedef struct VkOffset2D {
-    int32_t    x;
-    int32_t    y;
-} VkOffset2D;
-
-typedef struct VkExtent2D {
-    uint32_t    width;
-    uint32_t    height;
-} VkExtent2D;
-
-typedef struct VkRect2D {
-    VkOffset2D    offset;
-    VkExtent2D    extent;
-} VkRect2D;
-
-typedef struct VkPipelineViewportStateCreateInfo {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkPipelineViewportStateCreateFlags    flags;
-    uint32_t                              viewportCount;
-    const VkViewport*                     pViewports;
-    uint32_t                              scissorCount;
-    const VkRect2D*                       pScissors;
-} VkPipelineViewportStateCreateInfo;
-
-typedef struct VkPipelineRasterizationStateCreateInfo {
-    VkStructureType                            sType;
-    const void*                                pNext;
-    VkPipelineRasterizationStateCreateFlags    flags;
-    VkBool32                                   depthClampEnable;
-    VkBool32                                   rasterizerDiscardEnable;
-    VkPolygonMode                              polygonMode;
-    VkCullModeFlags                            cullMode;
-    VkFrontFace                                frontFace;
-    VkBool32                                   depthBiasEnable;
-    float                                      depthBiasConstantFactor;
-    float                                      depthBiasClamp;
-    float                                      depthBiasSlopeFactor;
-    float                                      lineWidth;
-} VkPipelineRasterizationStateCreateInfo;
-
-typedef struct VkPipelineMultisampleStateCreateInfo {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkPipelineMultisampleStateCreateFlags    flags;
-    VkSampleCountFlagBits                    rasterizationSamples;
-    VkBool32                                 sampleShadingEnable;
-    float                                    minSampleShading;
-    const VkSampleMask*                      pSampleMask;
-    VkBool32                                 alphaToCoverageEnable;
-    VkBool32                                 alphaToOneEnable;
-} VkPipelineMultisampleStateCreateInfo;
-
-typedef struct VkStencilOpState {
-    VkStencilOp    failOp;
-    VkStencilOp    passOp;
-    VkStencilOp    depthFailOp;
-    VkCompareOp    compareOp;
-    uint32_t       compareMask;
-    uint32_t       writeMask;
-    uint32_t       reference;
-} VkStencilOpState;
-
-typedef struct VkPipelineDepthStencilStateCreateInfo {
-    VkStructureType                           sType;
-    const void*                               pNext;
-    VkPipelineDepthStencilStateCreateFlags    flags;
-    VkBool32                                  depthTestEnable;
-    VkBool32                                  depthWriteEnable;
-    VkCompareOp                               depthCompareOp;
-    VkBool32                                  depthBoundsTestEnable;
-    VkBool32                                  stencilTestEnable;
-    VkStencilOpState                          front;
-    VkStencilOpState                          back;
-    float                                     minDepthBounds;
-    float                                     maxDepthBounds;
-} VkPipelineDepthStencilStateCreateInfo;
-
-typedef struct VkPipelineColorBlendAttachmentState {
-    VkBool32                 blendEnable;
-    VkBlendFactor            srcColorBlendFactor;
-    VkBlendFactor            dstColorBlendFactor;
-    VkBlendOp                colorBlendOp;
-    VkBlendFactor            srcAlphaBlendFactor;
-    VkBlendFactor            dstAlphaBlendFactor;
-    VkBlendOp                alphaBlendOp;
-    VkColorComponentFlags    colorWriteMask;
-} VkPipelineColorBlendAttachmentState;
-
-typedef struct VkPipelineColorBlendStateCreateInfo {
-    VkStructureType                               sType;
-    const void*                                   pNext;
-    VkPipelineColorBlendStateCreateFlags          flags;
-    VkBool32                                      logicOpEnable;
-    VkLogicOp                                     logicOp;
-    uint32_t                                      attachmentCount;
-    const VkPipelineColorBlendAttachmentState*    pAttachments;
-    float                                         blendConstants[4];
-} VkPipelineColorBlendStateCreateInfo;
-
-typedef struct VkPipelineDynamicStateCreateInfo {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkPipelineDynamicStateCreateFlags    flags;
-    uint32_t                             dynamicStateCount;
-    const VkDynamicState*                pDynamicStates;
-} VkPipelineDynamicStateCreateInfo;
-
-typedef struct VkGraphicsPipelineCreateInfo {
-    VkStructureType                                  sType;
-    const void*                                      pNext;
-    VkPipelineCreateFlags                            flags;
-    uint32_t                                         stageCount;
-    const VkPipelineShaderStageCreateInfo*           pStages;
-    const VkPipelineVertexInputStateCreateInfo*      pVertexInputState;
-    const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState;
-    const VkPipelineTessellationStateCreateInfo*     pTessellationState;
-    const VkPipelineViewportStateCreateInfo*         pViewportState;
-    const VkPipelineRasterizationStateCreateInfo*    pRasterizationState;
-    const VkPipelineMultisampleStateCreateInfo*      pMultisampleState;
-    const VkPipelineDepthStencilStateCreateInfo*     pDepthStencilState;
-    const VkPipelineColorBlendStateCreateInfo*       pColorBlendState;
-    const VkPipelineDynamicStateCreateInfo*          pDynamicState;
-    VkPipelineLayout                                 layout;
-    VkRenderPass                                     renderPass;
-    uint32_t                                         subpass;
-    VkPipeline                                       basePipelineHandle;
-    int32_t                                          basePipelineIndex;
-} VkGraphicsPipelineCreateInfo;
-
-typedef struct VkComputePipelineCreateInfo {
-    VkStructureType                    sType;
-    const void*                        pNext;
-    VkPipelineCreateFlags              flags;
-    VkPipelineShaderStageCreateInfo    stage;
-    VkPipelineLayout                   layout;
-    VkPipeline                         basePipelineHandle;
-    int32_t                            basePipelineIndex;
-} VkComputePipelineCreateInfo;
-
-typedef struct VkPushConstantRange {
-    VkShaderStageFlags    stageFlags;
-    uint32_t              offset;
-    uint32_t              size;
-} VkPushConstantRange;
-
-typedef struct VkPipelineLayoutCreateInfo {
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkPipelineLayoutCreateFlags     flags;
-    uint32_t                        setLayoutCount;
-    const VkDescriptorSetLayout*    pSetLayouts;
-    uint32_t                        pushConstantRangeCount;
-    const VkPushConstantRange*      pPushConstantRanges;
-} VkPipelineLayoutCreateInfo;
-
-typedef struct VkSamplerCreateInfo {
-    VkStructureType         sType;
-    const void*             pNext;
-    VkSamplerCreateFlags    flags;
-    VkFilter                magFilter;
-    VkFilter                minFilter;
-    VkSamplerMipmapMode     mipmapMode;
-    VkSamplerAddressMode    addressModeU;
-    VkSamplerAddressMode    addressModeV;
-    VkSamplerAddressMode    addressModeW;
-    float                   mipLodBias;
-    VkBool32                anisotropyEnable;
-    float                   maxAnisotropy;
-    VkBool32                compareEnable;
-    VkCompareOp             compareOp;
-    float                   minLod;
-    float                   maxLod;
-    VkBorderColor           borderColor;
-    VkBool32                unnormalizedCoordinates;
-} VkSamplerCreateInfo;
-
-typedef struct VkDescriptorSetLayoutBinding {
-    uint32_t              binding;
-    VkDescriptorType      descriptorType;
-    uint32_t              descriptorCount;
-    VkShaderStageFlags    stageFlags;
-    const VkSampler*      pImmutableSamplers;
-} VkDescriptorSetLayoutBinding;
-
-typedef struct VkDescriptorSetLayoutCreateInfo {
-    VkStructureType                        sType;
-    const void*                            pNext;
-    VkDescriptorSetLayoutCreateFlags       flags;
-    uint32_t                               bindingCount;
-    const VkDescriptorSetLayoutBinding*    pBindings;
-} VkDescriptorSetLayoutCreateInfo;
-
-typedef struct VkDescriptorPoolSize {
-    VkDescriptorType    type;
-    uint32_t            descriptorCount;
-} VkDescriptorPoolSize;
-
-typedef struct VkDescriptorPoolCreateInfo {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkDescriptorPoolCreateFlags    flags;
-    uint32_t                       maxSets;
-    uint32_t                       poolSizeCount;
-    const VkDescriptorPoolSize*    pPoolSizes;
-} VkDescriptorPoolCreateInfo;
-
-typedef struct VkDescriptorSetAllocateInfo {
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkDescriptorPool                descriptorPool;
-    uint32_t                        descriptorSetCount;
-    const VkDescriptorSetLayout*    pSetLayouts;
-} VkDescriptorSetAllocateInfo;
-
-typedef struct VkDescriptorImageInfo {
-    VkSampler        sampler;
-    VkImageView      imageView;
-    VkImageLayout    imageLayout;
-} VkDescriptorImageInfo;
-
-typedef struct VkDescriptorBufferInfo {
-    VkBuffer        buffer;
-    VkDeviceSize    offset;
-    VkDeviceSize    range;
-} VkDescriptorBufferInfo;
-
-typedef struct VkWriteDescriptorSet {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkDescriptorSet                  dstSet;
-    uint32_t                         dstBinding;
-    uint32_t                         dstArrayElement;
-    uint32_t                         descriptorCount;
-    VkDescriptorType                 descriptorType;
-    const VkDescriptorImageInfo*     pImageInfo;
-    const VkDescriptorBufferInfo*    pBufferInfo;
-    const VkBufferView*              pTexelBufferView;
-} VkWriteDescriptorSet;
-
-typedef struct VkCopyDescriptorSet {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkDescriptorSet    srcSet;
-    uint32_t           srcBinding;
-    uint32_t           srcArrayElement;
-    VkDescriptorSet    dstSet;
-    uint32_t           dstBinding;
-    uint32_t           dstArrayElement;
-    uint32_t           descriptorCount;
-} VkCopyDescriptorSet;
-
-typedef struct VkFramebufferCreateInfo {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkFramebufferCreateFlags    flags;
-    VkRenderPass                renderPass;
-    uint32_t                    attachmentCount;
-    const VkImageView*          pAttachments;
-    uint32_t                    width;
-    uint32_t                    height;
-    uint32_t                    layers;
-} VkFramebufferCreateInfo;
-
-typedef struct VkAttachmentDescription {
-    VkAttachmentDescriptionFlags    flags;
-    VkFormat                        format;
-    VkSampleCountFlagBits           samples;
-    VkAttachmentLoadOp              loadOp;
-    VkAttachmentStoreOp             storeOp;
-    VkAttachmentLoadOp              stencilLoadOp;
-    VkAttachmentStoreOp             stencilStoreOp;
-    VkImageLayout                   initialLayout;
-    VkImageLayout                   finalLayout;
-} VkAttachmentDescription;
-
-typedef struct VkAttachmentReference {
-    uint32_t         attachment;
-    VkImageLayout    layout;
-} VkAttachmentReference;
-
-typedef struct VkSubpassDescription {
-    VkSubpassDescriptionFlags       flags;
-    VkPipelineBindPoint             pipelineBindPoint;
-    uint32_t                        inputAttachmentCount;
-    const VkAttachmentReference*    pInputAttachments;
-    uint32_t                        colorAttachmentCount;
-    const VkAttachmentReference*    pColorAttachments;
-    const VkAttachmentReference*    pResolveAttachments;
-    const VkAttachmentReference*    pDepthStencilAttachment;
-    uint32_t                        preserveAttachmentCount;
-    const uint32_t*                 pPreserveAttachments;
-} VkSubpassDescription;
-
-typedef struct VkSubpassDependency {
-    uint32_t                srcSubpass;
-    uint32_t                dstSubpass;
-    VkPipelineStageFlags    srcStageMask;
-    VkPipelineStageFlags    dstStageMask;
-    VkAccessFlags           srcAccessMask;
-    VkAccessFlags           dstAccessMask;
-    VkDependencyFlags       dependencyFlags;
-} VkSubpassDependency;
-
-typedef struct VkRenderPassCreateInfo {
-    VkStructureType                   sType;
-    const void*                       pNext;
-    VkRenderPassCreateFlags           flags;
-    uint32_t                          attachmentCount;
-    const VkAttachmentDescription*    pAttachments;
-    uint32_t                          subpassCount;
-    const VkSubpassDescription*       pSubpasses;
-    uint32_t                          dependencyCount;
-    const VkSubpassDependency*        pDependencies;
-} VkRenderPassCreateInfo;
-
-typedef struct VkCommandPoolCreateInfo {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkCommandPoolCreateFlags    flags;
-    uint32_t                    queueFamilyIndex;
-} VkCommandPoolCreateInfo;
-
-typedef struct VkCommandBufferAllocateInfo {
-    VkStructureType         sType;
-    const void*             pNext;
-    VkCommandPool           commandPool;
-    VkCommandBufferLevel    level;
-    uint32_t                commandBufferCount;
-} VkCommandBufferAllocateInfo;
-
-typedef struct VkCommandBufferInheritanceInfo {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkRenderPass                     renderPass;
-    uint32_t                         subpass;
-    VkFramebuffer                    framebuffer;
-    VkBool32                         occlusionQueryEnable;
-    VkQueryControlFlags              queryFlags;
-    VkQueryPipelineStatisticFlags    pipelineStatistics;
-} VkCommandBufferInheritanceInfo;
-
-typedef struct VkCommandBufferBeginInfo {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkCommandBufferUsageFlags                flags;
-    const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
-} VkCommandBufferBeginInfo;
-
-typedef struct VkBufferCopy {
-    VkDeviceSize    srcOffset;
-    VkDeviceSize    dstOffset;
-    VkDeviceSize    size;
-} VkBufferCopy;
-
-typedef struct VkImageSubresourceLayers {
-    VkImageAspectFlags    aspectMask;
-    uint32_t              mipLevel;
-    uint32_t              baseArrayLayer;
-    uint32_t              layerCount;
-} VkImageSubresourceLayers;
-
-typedef struct VkImageCopy {
-    VkImageSubresourceLayers    srcSubresource;
-    VkOffset3D                  srcOffset;
-    VkImageSubresourceLayers    dstSubresource;
-    VkOffset3D                  dstOffset;
-    VkExtent3D                  extent;
-} VkImageCopy;
-
-typedef struct VkImageBlit {
-    VkImageSubresourceLayers    srcSubresource;
-    VkOffset3D                  srcOffsets[2];
-    VkImageSubresourceLayers    dstSubresource;
-    VkOffset3D                  dstOffsets[2];
-} VkImageBlit;
-
-typedef struct VkBufferImageCopy {
-    VkDeviceSize                bufferOffset;
-    uint32_t                    bufferRowLength;
-    uint32_t                    bufferImageHeight;
-    VkImageSubresourceLayers    imageSubresource;
-    VkOffset3D                  imageOffset;
-    VkExtent3D                  imageExtent;
-} VkBufferImageCopy;
-
-typedef union VkClearColorValue {
-    float       float32[4];
-    int32_t     int32[4];
-    uint32_t    uint32[4];
-} VkClearColorValue;
-
-typedef struct VkClearDepthStencilValue {
-    float       depth;
-    uint32_t    stencil;
-} VkClearDepthStencilValue;
-
-typedef union VkClearValue {
-    VkClearColorValue           color;
-    VkClearDepthStencilValue    depthStencil;
-} VkClearValue;
-
-typedef struct VkClearAttachment {
-    VkImageAspectFlags    aspectMask;
-    uint32_t              colorAttachment;
-    VkClearValue          clearValue;
-} VkClearAttachment;
-
-typedef struct VkClearRect {
-    VkRect2D    rect;
-    uint32_t    baseArrayLayer;
-    uint32_t    layerCount;
-} VkClearRect;
-
-typedef struct VkImageResolve {
-    VkImageSubresourceLayers    srcSubresource;
-    VkOffset3D                  srcOffset;
-    VkImageSubresourceLayers    dstSubresource;
-    VkOffset3D                  dstOffset;
-    VkExtent3D                  extent;
-} VkImageResolve;
-
-typedef struct VkMemoryBarrier {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkAccessFlags      srcAccessMask;
-    VkAccessFlags      dstAccessMask;
-} VkMemoryBarrier;
-
-typedef struct VkBufferMemoryBarrier {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkAccessFlags      srcAccessMask;
-    VkAccessFlags      dstAccessMask;
-    uint32_t           srcQueueFamilyIndex;
-    uint32_t           dstQueueFamilyIndex;
-    VkBuffer           buffer;
-    VkDeviceSize       offset;
-    VkDeviceSize       size;
-} VkBufferMemoryBarrier;
-
-typedef struct VkImageMemoryBarrier {
-    VkStructureType            sType;
-    const void*                pNext;
-    VkAccessFlags              srcAccessMask;
-    VkAccessFlags              dstAccessMask;
-    VkImageLayout              oldLayout;
-    VkImageLayout              newLayout;
-    uint32_t                   srcQueueFamilyIndex;
-    uint32_t                   dstQueueFamilyIndex;
-    VkImage                    image;
-    VkImageSubresourceRange    subresourceRange;
-} VkImageMemoryBarrier;
-
-typedef struct VkRenderPassBeginInfo {
-    VkStructureType        sType;
-    const void*            pNext;
-    VkRenderPass           renderPass;
-    VkFramebuffer          framebuffer;
-    VkRect2D               renderArea;
-    uint32_t               clearValueCount;
-    const VkClearValue*    pClearValues;
-} VkRenderPassBeginInfo;
-
-typedef struct VkDispatchIndirectCommand {
-    uint32_t    x;
-    uint32_t    y;
-    uint32_t    z;
-} VkDispatchIndirectCommand;
-
-typedef struct VkDrawIndexedIndirectCommand {
-    uint32_t    indexCount;
-    uint32_t    instanceCount;
-    uint32_t    firstIndex;
-    int32_t     vertexOffset;
-    uint32_t    firstInstance;
-} VkDrawIndexedIndirectCommand;
-
-typedef struct VkDrawIndirectCommand {
-    uint32_t    vertexCount;
-    uint32_t    instanceCount;
-    uint32_t    firstVertex;
-    uint32_t    firstInstance;
-} VkDrawIndirectCommand;
-
-typedef struct VkBaseOutStructure {
-    VkStructureType               sType;
-    struct VkBaseOutStructure*    pNext;
-} VkBaseOutStructure;
-
-typedef struct VkBaseInStructure {
-    VkStructureType                    sType;
-    const struct VkBaseInStructure*    pNext;
-} VkBaseInStructure;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
-typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
-typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
-typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
-typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
-typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
-typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
-typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue);
-typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device);
-typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
-typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
-typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory);
-typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
-typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
-typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
-typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
-typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
-typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
-typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
-typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence);
-typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore);
-typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent);
-typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event);
-typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event);
-typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
-typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
-typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView);
-typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage);
-typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView);
-typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);
-typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
-typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData);
-typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
-typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
-typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
-typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
-typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
-typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
-typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
-typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
-typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer);
-typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
-typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
-typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
-typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
-typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
-typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer);
-typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
-typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
-typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports);
-typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors);
-typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth);
-typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
-typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]);
-typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
-typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask);
-typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask);
-typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference);
-typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
-typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
-typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
-typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
-typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
-typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
-typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
-typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
-typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
-typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects);
-typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
-typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
-typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
-typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
-typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
-typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query);
-typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
-typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
-typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
-typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents);
-typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer);
-typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
-    const VkInstanceCreateInfo*                 pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkInstance*                                 pInstance);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
-    VkInstance                                  instance,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
-    VkInstance                                  instance,
-    uint32_t*                                   pPhysicalDeviceCount,
-    VkPhysicalDevice*                           pPhysicalDevices);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceFeatures*                   pFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
-    VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
-    VkFormatProperties*                         pFormatProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(
-    VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
-    VkImageType                                 type,
-    VkImageTiling                               tiling,
-    VkImageUsageFlags                           usage,
-    VkImageCreateFlags                          flags,
-    VkImageFormatProperties*                    pImageFormatProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceProperties*                 pProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pQueueFamilyPropertyCount,
-    VkQueueFamilyProperties*                    pQueueFamilyProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceMemoryProperties*           pMemoryProperties);
-
-VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(
-    VkInstance                                  instance,
-    const char*                                 pName);
-
-VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
-    VkDevice                                    device,
-    const char*                                 pName);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
-    VkPhysicalDevice                            physicalDevice,
-    const VkDeviceCreateInfo*                   pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDevice*                                   pDevice);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(
-    VkDevice                                    device,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
-    const char*                                 pLayerName,
-    uint32_t*                                   pPropertyCount,
-    VkExtensionProperties*                      pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
-    VkPhysicalDevice                            physicalDevice,
-    const char*                                 pLayerName,
-    uint32_t*                                   pPropertyCount,
-    VkExtensionProperties*                      pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
-    uint32_t*                                   pPropertyCount,
-    VkLayerProperties*                          pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pPropertyCount,
-    VkLayerProperties*                          pProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
-    VkDevice                                    device,
-    uint32_t                                    queueFamilyIndex,
-    uint32_t                                    queueIndex,
-    VkQueue*                                    pQueue);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(
-    VkQueue                                     queue,
-    uint32_t                                    submitCount,
-    const VkSubmitInfo*                         pSubmits,
-    VkFence                                     fence);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(
-    VkQueue                                     queue);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(
-    VkDevice                                    device);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(
-    VkDevice                                    device,
-    const VkMemoryAllocateInfo*                 pAllocateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDeviceMemory*                             pMemory);
-
-VKAPI_ATTR void VKAPI_CALL vkFreeMemory(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory,
-    VkDeviceSize                                offset,
-    VkDeviceSize                                size,
-    VkMemoryMapFlags                            flags,
-    void**                                      ppData);
-
-VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges(
-    VkDevice                                    device,
-    uint32_t                                    memoryRangeCount,
-    const VkMappedMemoryRange*                  pMemoryRanges);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(
-    VkDevice                                    device,
-    uint32_t                                    memoryRangeCount,
-    const VkMappedMemoryRange*                  pMemoryRanges);
-
-VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory,
-    VkDeviceSize*                               pCommittedMemoryInBytes);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(
-    VkDevice                                    device,
-    VkBuffer                                    buffer,
-    VkDeviceMemory                              memory,
-    VkDeviceSize                                memoryOffset);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(
-    VkDevice                                    device,
-    VkImage                                     image,
-    VkDeviceMemory                              memory,
-    VkDeviceSize                                memoryOffset);
-
-VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(
-    VkDevice                                    device,
-    VkBuffer                                    buffer,
-    VkMemoryRequirements*                       pMemoryRequirements);
-
-VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(
-    VkDevice                                    device,
-    VkImage                                     image,
-    VkMemoryRequirements*                       pMemoryRequirements);
-
-VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(
-    VkDevice                                    device,
-    VkImage                                     image,
-    uint32_t*                                   pSparseMemoryRequirementCount,
-    VkSparseImageMemoryRequirements*            pSparseMemoryRequirements);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(
-    VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
-    VkImageType                                 type,
-    VkSampleCountFlagBits                       samples,
-    VkImageUsageFlags                           usage,
-    VkImageTiling                               tiling,
-    uint32_t*                                   pPropertyCount,
-    VkSparseImageFormatProperties*              pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(
-    VkQueue                                     queue,
-    uint32_t                                    bindInfoCount,
-    const VkBindSparseInfo*                     pBindInfo,
-    VkFence                                     fence);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(
-    VkDevice                                    device,
-    const VkFenceCreateInfo*                    pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkFence*                                    pFence);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyFence(
-    VkDevice                                    device,
-    VkFence                                     fence,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(
-    VkDevice                                    device,
-    uint32_t                                    fenceCount,
-    const VkFence*                              pFences);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(
-    VkDevice                                    device,
-    VkFence                                     fence);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(
-    VkDevice                                    device,
-    uint32_t                                    fenceCount,
-    const VkFence*                              pFences,
-    VkBool32                                    waitAll,
-    uint64_t                                    timeout);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(
-    VkDevice                                    device,
-    const VkSemaphoreCreateInfo*                pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSemaphore*                                pSemaphore);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(
-    VkDevice                                    device,
-    VkSemaphore                                 semaphore,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(
-    VkDevice                                    device,
-    const VkEventCreateInfo*                    pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkEvent*                                    pEvent);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(
-    VkDevice                                    device,
-    VkEvent                                     event,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(
-    VkDevice                                    device,
-    VkEvent                                     event);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(
-    VkDevice                                    device,
-    VkEvent                                     event);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(
-    VkDevice                                    device,
-    VkEvent                                     event);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(
-    VkDevice                                    device,
-    const VkQueryPoolCreateInfo*                pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkQueryPool*                                pQueryPool);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(
-    VkDevice                                    device,
-    VkQueryPool                                 queryPool,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(
-    VkDevice                                    device,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    firstQuery,
-    uint32_t                                    queryCount,
-    size_t                                      dataSize,
-    void*                                       pData,
-    VkDeviceSize                                stride,
-    VkQueryResultFlags                          flags);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(
-    VkDevice                                    device,
-    const VkBufferCreateInfo*                   pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkBuffer*                                   pBuffer);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(
-    VkDevice                                    device,
-    VkBuffer                                    buffer,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(
-    VkDevice                                    device,
-    const VkBufferViewCreateInfo*               pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkBufferView*                               pView);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(
-    VkDevice                                    device,
-    VkBufferView                                bufferView,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(
-    VkDevice                                    device,
-    const VkImageCreateInfo*                    pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkImage*                                    pImage);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyImage(
-    VkDevice                                    device,
-    VkImage                                     image,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
-    VkDevice                                    device,
-    VkImage                                     image,
-    const VkImageSubresource*                   pSubresource,
-    VkSubresourceLayout*                        pLayout);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(
-    VkDevice                                    device,
-    const VkImageViewCreateInfo*                pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkImageView*                                pView);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(
-    VkDevice                                    device,
-    VkImageView                                 imageView,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(
-    VkDevice                                    device,
-    const VkShaderModuleCreateInfo*             pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkShaderModule*                             pShaderModule);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(
-    VkDevice                                    device,
-    VkShaderModule                              shaderModule,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(
-    VkDevice                                    device,
-    const VkPipelineCacheCreateInfo*            pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkPipelineCache*                            pPipelineCache);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(
-    VkDevice                                    device,
-    VkPipelineCache                             pipelineCache,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(
-    VkDevice                                    device,
-    VkPipelineCache                             pipelineCache,
-    size_t*                                     pDataSize,
-    void*                                       pData);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(
-    VkDevice                                    device,
-    VkPipelineCache                             dstCache,
-    uint32_t                                    srcCacheCount,
-    const VkPipelineCache*                      pSrcCaches);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(
-    VkDevice                                    device,
-    VkPipelineCache                             pipelineCache,
-    uint32_t                                    createInfoCount,
-    const VkGraphicsPipelineCreateInfo*         pCreateInfos,
-    const VkAllocationCallbacks*                pAllocator,
-    VkPipeline*                                 pPipelines);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(
-    VkDevice                                    device,
-    VkPipelineCache                             pipelineCache,
-    uint32_t                                    createInfoCount,
-    const VkComputePipelineCreateInfo*          pCreateInfos,
-    const VkAllocationCallbacks*                pAllocator,
-    VkPipeline*                                 pPipelines);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(
-    VkDevice                                    device,
-    VkPipeline                                  pipeline,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout(
-    VkDevice                                    device,
-    const VkPipelineLayoutCreateInfo*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkPipelineLayout*                           pPipelineLayout);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(
-    VkDevice                                    device,
-    VkPipelineLayout                            pipelineLayout,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(
-    VkDevice                                    device,
-    const VkSamplerCreateInfo*                  pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSampler*                                  pSampler);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroySampler(
-    VkDevice                                    device,
-    VkSampler                                   sampler,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(
-    VkDevice                                    device,
-    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDescriptorSetLayout*                      pSetLayout);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout(
-    VkDevice                                    device,
-    VkDescriptorSetLayout                       descriptorSetLayout,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool(
-    VkDevice                                    device,
-    const VkDescriptorPoolCreateInfo*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDescriptorPool*                           pDescriptorPool);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(
-    VkDevice                                    device,
-    VkDescriptorPool                            descriptorPool,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(
-    VkDevice                                    device,
-    VkDescriptorPool                            descriptorPool,
-    VkDescriptorPoolResetFlags                  flags);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets(
-    VkDevice                                    device,
-    const VkDescriptorSetAllocateInfo*          pAllocateInfo,
-    VkDescriptorSet*                            pDescriptorSets);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(
-    VkDevice                                    device,
-    VkDescriptorPool                            descriptorPool,
-    uint32_t                                    descriptorSetCount,
-    const VkDescriptorSet*                      pDescriptorSets);
-
-VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets(
-    VkDevice                                    device,
-    uint32_t                                    descriptorWriteCount,
-    const VkWriteDescriptorSet*                 pDescriptorWrites,
-    uint32_t                                    descriptorCopyCount,
-    const VkCopyDescriptorSet*                  pDescriptorCopies);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(
-    VkDevice                                    device,
-    const VkFramebufferCreateInfo*              pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkFramebuffer*                              pFramebuffer);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(
-    VkDevice                                    device,
-    VkFramebuffer                               framebuffer,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(
-    VkDevice                                    device,
-    const VkRenderPassCreateInfo*               pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkRenderPass*                               pRenderPass);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(
-    VkDevice                                    device,
-    VkRenderPass                                renderPass,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity(
-    VkDevice                                    device,
-    VkRenderPass                                renderPass,
-    VkExtent2D*                                 pGranularity);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(
-    VkDevice                                    device,
-    const VkCommandPoolCreateInfo*              pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkCommandPool*                              pCommandPool);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(
-    VkDevice                                    device,
-    VkCommandPool                               commandPool,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(
-    VkDevice                                    device,
-    VkCommandPool                               commandPool,
-    VkCommandPoolResetFlags                     flags);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(
-    VkDevice                                    device,
-    const VkCommandBufferAllocateInfo*          pAllocateInfo,
-    VkCommandBuffer*                            pCommandBuffers);
-
-VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(
-    VkDevice                                    device,
-    VkCommandPool                               commandPool,
-    uint32_t                                    commandBufferCount,
-    const VkCommandBuffer*                      pCommandBuffers);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(
-    VkCommandBuffer                             commandBuffer,
-    const VkCommandBufferBeginInfo*             pBeginInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(
-    VkCommandBuffer                             commandBuffer);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkCommandBufferResetFlags                   flags);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineBindPoint                         pipelineBindPoint,
-    VkPipeline                                  pipeline);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstViewport,
-    uint32_t                                    viewportCount,
-    const VkViewport*                           pViewports);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstScissor,
-    uint32_t                                    scissorCount,
-    const VkRect2D*                             pScissors);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(
-    VkCommandBuffer                             commandBuffer,
-    float                                       lineWidth);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(
-    VkCommandBuffer                             commandBuffer,
-    float                                       depthBiasConstantFactor,
-    float                                       depthBiasClamp,
-    float                                       depthBiasSlopeFactor);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(
-    VkCommandBuffer                             commandBuffer,
-    const float                                 blendConstants[4]);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(
-    VkCommandBuffer                             commandBuffer,
-    float                                       minDepthBounds,
-    float                                       maxDepthBounds);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(
-    VkCommandBuffer                             commandBuffer,
-    VkStencilFaceFlags                          faceMask,
-    uint32_t                                    compareMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(
-    VkCommandBuffer                             commandBuffer,
-    VkStencilFaceFlags                          faceMask,
-    uint32_t                                    writeMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(
-    VkCommandBuffer                             commandBuffer,
-    VkStencilFaceFlags                          faceMask,
-    uint32_t                                    reference);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineBindPoint                         pipelineBindPoint,
-    VkPipelineLayout                            layout,
-    uint32_t                                    firstSet,
-    uint32_t                                    descriptorSetCount,
-    const VkDescriptorSet*                      pDescriptorSets,
-    uint32_t                                    dynamicOffsetCount,
-    const uint32_t*                             pDynamicOffsets);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkIndexType                                 indexType);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstBinding,
-    uint32_t                                    bindingCount,
-    const VkBuffer*                             pBuffers,
-    const VkDeviceSize*                         pOffsets);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDraw(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    vertexCount,
-    uint32_t                                    instanceCount,
-    uint32_t                                    firstVertex,
-    uint32_t                                    firstInstance);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    indexCount,
-    uint32_t                                    instanceCount,
-    uint32_t                                    firstIndex,
-    int32_t                                     vertexOffset,
-    uint32_t                                    firstInstance);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    uint32_t                                    drawCount,
-    uint32_t                                    stride);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    uint32_t                                    drawCount,
-    uint32_t                                    stride);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    groupCountX,
-    uint32_t                                    groupCountY,
-    uint32_t                                    groupCountZ);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    srcBuffer,
-    VkBuffer                                    dstBuffer,
-    uint32_t                                    regionCount,
-    const VkBufferCopy*                         pRegions);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkImage                                     dstImage,
-    VkImageLayout                               dstImageLayout,
-    uint32_t                                    regionCount,
-    const VkImageCopy*                          pRegions);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkImage                                     dstImage,
-    VkImageLayout                               dstImageLayout,
-    uint32_t                                    regionCount,
-    const VkImageBlit*                          pRegions,
-    VkFilter                                    filter);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    srcBuffer,
-    VkImage                                     dstImage,
-    VkImageLayout                               dstImageLayout,
-    uint32_t                                    regionCount,
-    const VkBufferImageCopy*                    pRegions);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkBuffer                                    dstBuffer,
-    uint32_t                                    regionCount,
-    const VkBufferImageCopy*                    pRegions);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    dstBuffer,
-    VkDeviceSize                                dstOffset,
-    VkDeviceSize                                dataSize,
-    const void*                                 pData);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    dstBuffer,
-    VkDeviceSize                                dstOffset,
-    VkDeviceSize                                size,
-    uint32_t                                    data);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     image,
-    VkImageLayout                               imageLayout,
-    const VkClearColorValue*                    pColor,
-    uint32_t                                    rangeCount,
-    const VkImageSubresourceRange*              pRanges);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     image,
-    VkImageLayout                               imageLayout,
-    const VkClearDepthStencilValue*             pDepthStencil,
-    uint32_t                                    rangeCount,
-    const VkImageSubresourceRange*              pRanges);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    attachmentCount,
-    const VkClearAttachment*                    pAttachments,
-    uint32_t                                    rectCount,
-    const VkClearRect*                          pRects);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkImage                                     dstImage,
-    VkImageLayout                               dstImageLayout,
-    uint32_t                                    regionCount,
-    const VkImageResolve*                       pRegions);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(
-    VkCommandBuffer                             commandBuffer,
-    VkEvent                                     event,
-    VkPipelineStageFlags                        stageMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(
-    VkCommandBuffer                             commandBuffer,
-    VkEvent                                     event,
-    VkPipelineStageFlags                        stageMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    eventCount,
-    const VkEvent*                              pEvents,
-    VkPipelineStageFlags                        srcStageMask,
-    VkPipelineStageFlags                        dstStageMask,
-    uint32_t                                    memoryBarrierCount,
-    const VkMemoryBarrier*                      pMemoryBarriers,
-    uint32_t                                    bufferMemoryBarrierCount,
-    const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-    uint32_t                                    imageMemoryBarrierCount,
-    const VkImageMemoryBarrier*                 pImageMemoryBarriers);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineStageFlags                        srcStageMask,
-    VkPipelineStageFlags                        dstStageMask,
-    VkDependencyFlags                           dependencyFlags,
-    uint32_t                                    memoryBarrierCount,
-    const VkMemoryBarrier*                      pMemoryBarriers,
-    uint32_t                                    bufferMemoryBarrierCount,
-    const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-    uint32_t                                    imageMemoryBarrierCount,
-    const VkImageMemoryBarrier*                 pImageMemoryBarriers);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    query,
-    VkQueryControlFlags                         flags);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    query);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    firstQuery,
-    uint32_t                                    queryCount);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineStageFlagBits                     pipelineStage,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    query);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    firstQuery,
-    uint32_t                                    queryCount,
-    VkBuffer                                    dstBuffer,
-    VkDeviceSize                                dstOffset,
-    VkDeviceSize                                stride,
-    VkQueryResultFlags                          flags);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineLayout                            layout,
-    VkShaderStageFlags                          stageFlags,
-    uint32_t                                    offset,
-    uint32_t                                    size,
-    const void*                                 pValues);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(
-    VkCommandBuffer                             commandBuffer,
-    const VkRenderPassBeginInfo*                pRenderPassBegin,
-    VkSubpassContents                           contents);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(
-    VkCommandBuffer                             commandBuffer,
-    VkSubpassContents                           contents);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(
-    VkCommandBuffer                             commandBuffer);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    commandBufferCount,
-    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_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
-    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_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
-    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_RGB_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020,
-    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_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
-    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_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN,
-    VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT,
-    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_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
-    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_PARTITIONED_BIT_NV = 0x00000100,
-    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_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT,
-    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT,
-    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT,
-    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_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,
-    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_DMA_BUF_BIT_EXT = 0x00000200,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
-    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_DEDICATED_ONLY_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
-    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_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
-    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_EXPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT,
-    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_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT,
-    VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VkFenceImportFlagBits;
-typedef VkFlags VkFenceImportFlags;
-
-typedef enum VkSemaphoreImportFlagBits {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
-    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_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
-    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_EXPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT,
-    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           splitInstanceBindRegionCount;
-    const VkRect2D*    pSplitInstanceBindRegions;
-} 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 VkMemoryRequirements2 VkMemoryRequirements2KHR;
-
-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;
-    const 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_EXTENSION_NAME     "VK_KHR_surface"
-
-
-typedef enum VkColorSpaceKHR {
-    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
-    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
-    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
-    VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
-    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
-    VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
-    VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
-    VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
-    VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
-    VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
-    VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
-    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
-    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
-    VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
-    VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014,
-    VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
-    VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
-    VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
-    VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
-    VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkColorSpaceKHR;
-
-typedef enum VkPresentModeKHR {
-    VK_PRESENT_MODE_IMMEDIATE_KHR = 0,
-    VK_PRESENT_MODE_MAILBOX_KHR = 1,
-    VK_PRESENT_MODE_FIFO_KHR = 2,
-    VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
-    VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000,
-    VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001,
-    VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR,
-    VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
-    VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1),
-    VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkPresentModeKHR;
-
-
-typedef enum VkSurfaceTransformFlagBitsKHR {
-    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001,
-    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,
-    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004,
-    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,
-    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
-    VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSurfaceTransformFlagBitsKHR;
-typedef VkFlags VkSurfaceTransformFlagsKHR;
-
-typedef enum VkCompositeAlphaFlagBitsKHR {
-    VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
-    VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
-    VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004,
-    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
-    VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkCompositeAlphaFlagBitsKHR;
-typedef VkFlags VkCompositeAlphaFlagsKHR;
-
-typedef struct VkSurfaceCapabilitiesKHR {
-    uint32_t                         minImageCount;
-    uint32_t                         maxImageCount;
-    VkExtent2D                       currentExtent;
-    VkExtent2D                       minImageExtent;
-    VkExtent2D                       maxImageExtent;
-    uint32_t                         maxImageArrayLayers;
-    VkSurfaceTransformFlagsKHR       supportedTransforms;
-    VkSurfaceTransformFlagBitsKHR    currentTransform;
-    VkCompositeAlphaFlagsKHR         supportedCompositeAlpha;
-    VkImageUsageFlags                supportedUsageFlags;
-} VkSurfaceCapabilitiesKHR;
-
-typedef struct VkSurfaceFormatKHR {
-    VkFormat           format;
-    VkColorSpaceKHR    colorSpace;
-} VkSurfaceFormatKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
-    VkInstance                                  instance,
-    VkSurfaceKHR                                surface,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t                                    queueFamilyIndex,
-    VkSurfaceKHR                                surface,
-    VkBool32*                                   pSupported);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkSurfaceKHR                                surface,
-    VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkSurfaceKHR                                surface,
-    uint32_t*                                   pSurfaceFormatCount,
-    VkSurfaceFormatKHR*                         pSurfaceFormats);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkSurfaceKHR                                surface,
-    uint32_t*                                   pPresentModeCount,
-    VkPresentModeKHR*                           pPresentModes);
-#endif
-
-#define VK_KHR_swapchain 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
-
-#define VK_KHR_SWAPCHAIN_SPEC_VERSION     70
-#define VK_KHR_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_swapchain"
-
-
-typedef enum VkSwapchainCreateFlagBitsKHR {
-    VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
-    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
-    VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004,
-    VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSwapchainCreateFlagBitsKHR;
-typedef VkFlags VkSwapchainCreateFlagsKHR;
-
-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 VkSwapchainCreateInfoKHR {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkSwapchainCreateFlagsKHR        flags;
-    VkSurfaceKHR                     surface;
-    uint32_t                         minImageCount;
-    VkFormat                         imageFormat;
-    VkColorSpaceKHR                  imageColorSpace;
-    VkExtent2D                       imageExtent;
-    uint32_t                         imageArrayLayers;
-    VkImageUsageFlags                imageUsage;
-    VkSharingMode                    imageSharingMode;
-    uint32_t                         queueFamilyIndexCount;
-    const uint32_t*                  pQueueFamilyIndices;
-    VkSurfaceTransformFlagBitsKHR    preTransform;
-    VkCompositeAlphaFlagBitsKHR      compositeAlpha;
-    VkPresentModeKHR                 presentMode;
-    VkBool32                         clipped;
-    VkSwapchainKHR                   oldSwapchain;
-} VkSwapchainCreateInfoKHR;
-
-typedef struct VkPresentInfoKHR {
-    VkStructureType          sType;
-    const void*              pNext;
-    uint32_t                 waitSemaphoreCount;
-    const VkSemaphore*       pWaitSemaphores;
-    uint32_t                 swapchainCount;
-    const VkSwapchainKHR*    pSwapchains;
-    const uint32_t*          pImageIndices;
-    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(
-    VkDevice                                    device,
-    const VkSwapchainCreateInfoKHR*             pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSwapchainKHR*                             pSwapchain);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    uint32_t*                                   pSwapchainImageCount,
-    VkImage*                                    pSwapchainImages);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    uint64_t                                    timeout,
-    VkSemaphore                                 semaphore,
-    VkFence                                     fence,
-    uint32_t*                                   pImageIndex);
-
-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
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR)
-
-#define VK_KHR_DISPLAY_SPEC_VERSION       21
-#define VK_KHR_DISPLAY_EXTENSION_NAME     "VK_KHR_display"
-
-
-typedef enum VkDisplayPlaneAlphaFlagBitsKHR {
-    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
-    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
-    VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkDisplayPlaneAlphaFlagBitsKHR;
-typedef VkFlags VkDisplayPlaneAlphaFlagsKHR;
-typedef VkFlags VkDisplayModeCreateFlagsKHR;
-typedef VkFlags VkDisplaySurfaceCreateFlagsKHR;
-
-typedef struct VkDisplayPropertiesKHR {
-    VkDisplayKHR                  display;
-    const char*                   displayName;
-    VkExtent2D                    physicalDimensions;
-    VkExtent2D                    physicalResolution;
-    VkSurfaceTransformFlagsKHR    supportedTransforms;
-    VkBool32                      planeReorderPossible;
-    VkBool32                      persistentContent;
-} VkDisplayPropertiesKHR;
-
-typedef struct VkDisplayModeParametersKHR {
-    VkExtent2D    visibleRegion;
-    uint32_t      refreshRate;
-} VkDisplayModeParametersKHR;
-
-typedef struct VkDisplayModePropertiesKHR {
-    VkDisplayModeKHR              displayMode;
-    VkDisplayModeParametersKHR    parameters;
-} VkDisplayModePropertiesKHR;
-
-typedef struct VkDisplayModeCreateInfoKHR {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkDisplayModeCreateFlagsKHR    flags;
-    VkDisplayModeParametersKHR     parameters;
-} VkDisplayModeCreateInfoKHR;
-
-typedef struct VkDisplayPlaneCapabilitiesKHR {
-    VkDisplayPlaneAlphaFlagsKHR    supportedAlpha;
-    VkOffset2D                     minSrcPosition;
-    VkOffset2D                     maxSrcPosition;
-    VkExtent2D                     minSrcExtent;
-    VkExtent2D                     maxSrcExtent;
-    VkOffset2D                     minDstPosition;
-    VkOffset2D                     maxDstPosition;
-    VkExtent2D                     minDstExtent;
-    VkExtent2D                     maxDstExtent;
-} VkDisplayPlaneCapabilitiesKHR;
-
-typedef struct VkDisplayPlanePropertiesKHR {
-    VkDisplayKHR    currentDisplay;
-    uint32_t        currentStackIndex;
-} VkDisplayPlanePropertiesKHR;
-
-typedef struct VkDisplaySurfaceCreateInfoKHR {
-    VkStructureType                   sType;
-    const void*                       pNext;
-    VkDisplaySurfaceCreateFlagsKHR    flags;
-    VkDisplayModeKHR                  displayMode;
-    uint32_t                          planeIndex;
-    uint32_t                          planeStackIndex;
-    VkSurfaceTransformFlagBitsKHR     transform;
-    float                             globalAlpha;
-    VkDisplayPlaneAlphaFlagBitsKHR    alphaMode;
-    VkExtent2D                        imageExtent;
-} VkDisplaySurfaceCreateInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayPropertiesKHR*                     pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayPlanePropertiesKHR*                pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t                                    planeIndex,
-    uint32_t*                                   pDisplayCount,
-    VkDisplayKHR*                               pDisplays);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkDisplayKHR                                display,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayModePropertiesKHR*                 pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkDisplayKHR                                display,
-    const VkDisplayModeCreateInfoKHR*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDisplayModeKHR*                           pMode);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkDisplayModeKHR                            mode,
-    uint32_t                                    planeIndex,
-    VkDisplayPlaneCapabilitiesKHR*              pCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
-    VkInstance                                  instance,
-    const VkDisplaySurfaceCreateInfoKHR*        pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSurfaceKHR*                               pSurface);
-#endif
-
-#define VK_KHR_display_swapchain 1
-#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 9
-#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain"
-
-typedef struct VkDisplayPresentInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkRect2D           srcRect;
-    VkRect2D           dstRect;
-    VkBool32           persistent;
-} VkDisplayPresentInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
-    VkDevice                                    device,
-    uint32_t                                    swapchainCount,
-    const VkSwapchainCreateInfoKHR*             pCreateInfos,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSwapchainKHR*                             pSwapchains);
-#endif
-
-#define VK_KHR_sampler_mirror_clamp_to_edge 1
-#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1
-#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
-
-
-#define VK_KHR_multiview 1
-#define VK_KHR_MULTIVIEW_SPEC_VERSION     1
-#define VK_KHR_MULTIVIEW_EXTENSION_NAME   "VK_KHR_multiview"
-
-typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR;
-
-typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR;
-
-typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR;
-
-
-
-#define VK_KHR_get_physical_device_properties2 1
-#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"
-
-typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR;
-
-typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR;
-
-typedef VkFormatProperties2 VkFormatProperties2KHR;
-
-typedef VkImageFormatProperties2 VkImageFormatProperties2KHR;
-
-typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR;
-
-typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR;
-
-typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
-
-typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR;
-
-typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
-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_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
-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,
-    VkPhysicalDeviceFeatures2*                  pFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceProperties2*                pProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
-    VkFormatProperties2*                        pFormatProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceImageFormatInfo2*     pImageFormatInfo,
-    VkImageFormatProperties2*                   pImageFormatProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pQueueFamilyPropertyCount,
-    VkQueueFamilyProperties2*                   pQueueFamilyProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
-    uint32_t*                                   pPropertyCount,
-    VkSparseImageFormatProperties2*             pProperties);
-#endif
-
-#define VK_KHR_device_group 1
-#define VK_KHR_DEVICE_GROUP_SPEC_VERSION  3
-#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
-
-typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;
-
-typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
-
-typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;
-
-typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
-
-
-typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
-
-typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR;
-
-typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR;
-
-typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR;
-
-typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR;
-
-typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR;
-
-typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
-typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
-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);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR(
-    VkDevice                                    device,
-    uint32_t                                    heapIndex,
-    uint32_t                                    localDeviceIndex,
-    uint32_t                                    remoteDeviceIndex,
-    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    deviceMask);
-
-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);
-#endif
-
-#define VK_KHR_shader_draw_parameters 1
-#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
-#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
-
-
-#define VK_KHR_maintenance1 1
-#define VK_KHR_MAINTENANCE1_SPEC_VERSION  2
-#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
-
-typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
-
-
-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,
-    VkCommandPoolTrimFlags                      flags);
-#endif
-
-#define VK_KHR_device_group_creation 1
-#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
-
-typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR;
-
-typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR;
-
-
-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_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
-#define VK_LUID_SIZE_KHR                  VK_LUID_SIZE
-
-typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR;
-
-typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR;
-
-typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR;
-
-typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR;
-
-
-typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR;
-
-typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR;
-
-typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR;
-
-typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR;
-
-typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR;
-
-typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR;
-
-
-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 VkPhysicalDeviceExternalBufferInfo*   pExternalBufferInfo,
-    VkExternalBufferProperties*                 pExternalBufferProperties);
-#endif
-
-#define VK_KHR_external_memory 1
-#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      VK_QUEUE_FAMILY_EXTERNAL
-
-typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR;
-
-typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR;
-
-typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
-
-
-
-#define VK_KHR_external_memory_fd 1
-#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
-
-typedef struct VkImportMemoryFdInfoKHR {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagBits    handleType;
-    int                                   fd;
-} VkImportMemoryFdInfoKHR;
-
-typedef struct VkMemoryFdPropertiesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           memoryTypeBits;
-} VkMemoryFdPropertiesKHR;
-
-typedef struct VkMemoryGetFdInfoKHR {
-    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, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR(
-    VkDevice                                    device,
-    const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
-    int*                                        pFd);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(
-    VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBits          handleType,
-    int                                         fd,
-    VkMemoryFdPropertiesKHR*                    pMemoryFdProperties);
-#endif
-
-#define VK_KHR_external_semaphore_capabilities 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
-
-typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR;
-
-typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR;
-
-typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR;
-
-typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR;
-
-
-typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR;
-
-typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR;
-
-
-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 VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
-    VkExternalSemaphoreProperties*              pExternalSemaphoreProperties);
-#endif
-
-#define VK_KHR_external_semaphore 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
-
-typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
-
-typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
-
-
-typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
-
-
-
-#define VK_KHR_external_semaphore_fd 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
-
-typedef struct VkImportSemaphoreFdInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkSemaphore                              semaphore;
-    VkSemaphoreImportFlags                   flags;
-    VkExternalSemaphoreHandleTypeFlagBits    handleType;
-    int                                      fd;
-} VkImportSemaphoreFdInfoKHR;
-
-typedef struct VkSemaphoreGetFdInfoKHR {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkSemaphore                              semaphore;
-    VkExternalSemaphoreHandleTypeFlagBits    handleType;
-} VkSemaphoreGetFdInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR(
-    VkDevice                                    device,
-    const VkImportSemaphoreFdInfoKHR*           pImportSemaphoreFdInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR(
-    VkDevice                                    device,
-    const VkSemaphoreGetFdInfoKHR*              pGetFdInfo,
-    int*                                        pFd);
-#endif
-
-#define VK_KHR_push_descriptor 1
-#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
-#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
-
-typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxPushDescriptors;
-} VkPhysicalDevicePushDescriptorPropertiesKHR;
-
-
-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(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineBindPoint                         pipelineBindPoint,
-    VkPipelineLayout                            layout,
-    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_shader_float16_int8 1
-#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
-#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
-
-typedef struct VkPhysicalDeviceFloat16Int8FeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           shaderFloat16;
-    VkBool32           shaderInt8;
-} VkPhysicalDeviceFloat16Int8FeaturesKHR;
-
-
-
-#define VK_KHR_16bit_storage 1
-#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
-#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
-
-typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR;
-
-
-
-#define VK_KHR_incremental_present 1
-#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
-
-typedef struct VkRectLayerKHR {
-    VkOffset2D    offset;
-    VkExtent2D    extent;
-    uint32_t      layer;
-} VkRectLayerKHR;
-
-typedef struct VkPresentRegionKHR {
-    uint32_t                 rectangleCount;
-    const VkRectLayerKHR*    pRectangles;
-} VkPresentRegionKHR;
-
-typedef struct VkPresentRegionsKHR {
-    VkStructureType              sType;
-    const void*                  pNext;
-    uint32_t                     swapchainCount;
-    const VkPresentRegionKHR*    pRegions;
-} VkPresentRegionsKHR;
-
-
-
-#define VK_KHR_descriptor_update_template 1
-typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR;
-
-
-#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
-#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
-
-typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
-
-
-typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
-
-
-typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
-
-typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
-
-
-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 VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDescriptorUpdateTemplate*                 pDescriptorUpdateTemplate);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR(
-    VkDevice                                    device,
-    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR(
-    VkDevice                                    device,
-    VkDescriptorSet                             descriptorSet,
-    VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
-    const void*                                 pData);
-#endif
-
-#define VK_KHR_create_renderpass2 1
-#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1
-#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2"
-
-typedef struct VkAttachmentDescription2KHR {
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkAttachmentDescriptionFlags    flags;
-    VkFormat                        format;
-    VkSampleCountFlagBits           samples;
-    VkAttachmentLoadOp              loadOp;
-    VkAttachmentStoreOp             storeOp;
-    VkAttachmentLoadOp              stencilLoadOp;
-    VkAttachmentStoreOp             stencilStoreOp;
-    VkImageLayout                   initialLayout;
-    VkImageLayout                   finalLayout;
-} VkAttachmentDescription2KHR;
-
-typedef struct VkAttachmentReference2KHR {
-    VkStructureType       sType;
-    const void*           pNext;
-    uint32_t              attachment;
-    VkImageLayout         layout;
-    VkImageAspectFlags    aspectMask;
-} VkAttachmentReference2KHR;
-
-typedef struct VkSubpassDescription2KHR {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    VkSubpassDescriptionFlags           flags;
-    VkPipelineBindPoint                 pipelineBindPoint;
-    uint32_t                            viewMask;
-    uint32_t                            inputAttachmentCount;
-    const VkAttachmentReference2KHR*    pInputAttachments;
-    uint32_t                            colorAttachmentCount;
-    const VkAttachmentReference2KHR*    pColorAttachments;
-    const VkAttachmentReference2KHR*    pResolveAttachments;
-    const VkAttachmentReference2KHR*    pDepthStencilAttachment;
-    uint32_t                            preserveAttachmentCount;
-    const uint32_t*                     pPreserveAttachments;
-} VkSubpassDescription2KHR;
-
-typedef struct VkSubpassDependency2KHR {
-    VkStructureType         sType;
-    const void*             pNext;
-    uint32_t                srcSubpass;
-    uint32_t                dstSubpass;
-    VkPipelineStageFlags    srcStageMask;
-    VkPipelineStageFlags    dstStageMask;
-    VkAccessFlags           srcAccessMask;
-    VkAccessFlags           dstAccessMask;
-    VkDependencyFlags       dependencyFlags;
-    int32_t                 viewOffset;
-} VkSubpassDependency2KHR;
-
-typedef struct VkRenderPassCreateInfo2KHR {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkRenderPassCreateFlags               flags;
-    uint32_t                              attachmentCount;
-    const VkAttachmentDescription2KHR*    pAttachments;
-    uint32_t                              subpassCount;
-    const VkSubpassDescription2KHR*       pSubpasses;
-    uint32_t                              dependencyCount;
-    const VkSubpassDependency2KHR*        pDependencies;
-    uint32_t                              correlatedViewMaskCount;
-    const uint32_t*                       pCorrelatedViewMasks;
-} VkRenderPassCreateInfo2KHR;
-
-typedef struct VkSubpassBeginInfoKHR {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkSubpassContents    contents;
-} VkSubpassBeginInfoKHR;
-
-typedef struct VkSubpassEndInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-} VkSubpassEndInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2KHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo*      pRenderPassBegin, const VkSubpassBeginInfoKHR*      pSubpassBeginInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR*      pSubpassBeginInfo, const VkSubpassEndInfoKHR*        pSubpassEndInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR*        pSubpassEndInfo);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR(
-    VkDevice                                    device,
-    const VkRenderPassCreateInfo2KHR*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkRenderPass*                               pRenderPass);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(
-    VkCommandBuffer                             commandBuffer,
-    const VkRenderPassBeginInfo*                pRenderPassBegin,
-    const VkSubpassBeginInfoKHR*                pSubpassBeginInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR(
-    VkCommandBuffer                             commandBuffer,
-    const VkSubpassBeginInfoKHR*                pSubpassBeginInfo,
-    const VkSubpassEndInfoKHR*                  pSubpassEndInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR(
-    VkCommandBuffer                             commandBuffer,
-    const VkSubpassEndInfoKHR*                  pSubpassEndInfo);
-#endif
-
-#define VK_KHR_shared_presentable_image 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
-    VkStructureType      sType;
-    void*                pNext;
-    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
-} VkSharedPresentSurfaceCapabilitiesKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain);
-#endif
-
-#define VK_KHR_external_fence_capabilities 1
-#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
-
-typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR;
-
-typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR;
-
-typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR;
-
-typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR;
-
-
-typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR;
-
-typedef VkExternalFenceProperties VkExternalFencePropertiesKHR;
-
-
-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 VkPhysicalDeviceExternalFenceInfo*    pExternalFenceInfo,
-    VkExternalFenceProperties*                  pExternalFenceProperties);
-#endif
-
-#define VK_KHR_external_fence 1
-#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
-
-typedef VkFenceImportFlags VkFenceImportFlagsKHR;
-
-typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
-
-
-typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
-
-
-
-#define VK_KHR_external_fence_fd 1
-#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1
-#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
-
-typedef struct VkImportFenceFdInfoKHR {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkFence                              fence;
-    VkFenceImportFlags                   flags;
-    VkExternalFenceHandleTypeFlagBits    handleType;
-    int                                  fd;
-} VkImportFenceFdInfoKHR;
-
-typedef struct VkFenceGetFdInfoKHR {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkFence                              fence;
-    VkExternalFenceHandleTypeFlagBits    handleType;
-} VkFenceGetFdInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR(
-    VkDevice                                    device,
-    const VkImportFenceFdInfoKHR*               pImportFenceFdInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR(
-    VkDevice                                    device,
-    const VkFenceGetFdInfoKHR*                  pGetFdInfo,
-    int*                                        pFd);
-#endif
-
-#define VK_KHR_maintenance2 1
-#define VK_KHR_MAINTENANCE2_SPEC_VERSION  1
-#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
-
-typedef VkPointClippingBehavior VkPointClippingBehaviorKHR;
-
-typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR;
-
-
-typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR;
-
-typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR;
-
-typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR;
-
-typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR;
-
-typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR;
-
-
-
-#define VK_KHR_get_surface_capabilities2 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
-
-typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSurfaceKHR       surface;
-} VkPhysicalDeviceSurfaceInfo2KHR;
-
-typedef struct VkSurfaceCapabilities2KHR {
-    VkStructureType             sType;
-    void*                       pNext;
-    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
-} VkSurfaceCapabilities2KHR;
-
-typedef struct VkSurfaceFormat2KHR {
-    VkStructureType       sType;
-    void*                 pNext;
-    VkSurfaceFormatKHR    surfaceFormat;
-} VkSurfaceFormat2KHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    uint32_t*                                   pSurfaceFormatCount,
-    VkSurfaceFormat2KHR*                        pSurfaceFormats);
-#endif
-
-#define VK_KHR_variable_pointers 1
-#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
-#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
-
-typedef VkPhysicalDeviceVariablePointerFeatures VkPhysicalDeviceVariablePointerFeaturesKHR;
-
-
-
-#define VK_KHR_get_display_properties2 1
-#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
-#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
-
-typedef struct VkDisplayProperties2KHR {
-    VkStructureType           sType;
-    void*                     pNext;
-    VkDisplayPropertiesKHR    displayProperties;
-} VkDisplayProperties2KHR;
-
-typedef struct VkDisplayPlaneProperties2KHR {
-    VkStructureType                sType;
-    void*                          pNext;
-    VkDisplayPlanePropertiesKHR    displayPlaneProperties;
-} VkDisplayPlaneProperties2KHR;
-
-typedef struct VkDisplayModeProperties2KHR {
-    VkStructureType               sType;
-    void*                         pNext;
-    VkDisplayModePropertiesKHR    displayModeProperties;
-} VkDisplayModeProperties2KHR;
-
-typedef struct VkDisplayPlaneInfo2KHR {
-    VkStructureType     sType;
-    const void*         pNext;
-    VkDisplayModeKHR    mode;
-    uint32_t            planeIndex;
-} VkDisplayPlaneInfo2KHR;
-
-typedef struct VkDisplayPlaneCapabilities2KHR {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkDisplayPlaneCapabilitiesKHR    capabilities;
-} VkDisplayPlaneCapabilities2KHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayProperties2KHR*                    pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayPlaneProperties2KHR*               pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    VkDisplayKHR                                display,
-    uint32_t*                                   pPropertyCount,
-    VkDisplayModeProperties2KHR*                pProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkDisplayPlaneInfo2KHR*               pDisplayPlaneInfo,
-    VkDisplayPlaneCapabilities2KHR*             pCapabilities);
-#endif
-
-#define VK_KHR_dedicated_allocation 1
-#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
-#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
-
-typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR;
-
-typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
-
-
-
-#define VK_KHR_storage_buffer_storage_class 1
-#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1
-#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class"
-
-
-#define VK_KHR_relaxed_block_layout 1
-#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1
-#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout"
-
-
-#define VK_KHR_get_memory_requirements2 1
-#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1
-#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
-
-typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR;
-
-typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR;
-
-typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
-
-typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* 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 VkImageMemoryRequirementsInfo2*       pInfo,
-    VkMemoryRequirements2*                      pMemoryRequirements);
-
-VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR(
-    VkDevice                                    device,
-    const VkBufferMemoryRequirementsInfo2*      pInfo,
-    VkMemoryRequirements2*                      pMemoryRequirements);
-
-VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR(
-    VkDevice                                    device,
-    const VkImageSparseMemoryRequirementsInfo2* pInfo,
-    uint32_t*                                   pSparseMemoryRequirementCount,
-    VkSparseImageMemoryRequirements2*           pSparseMemoryRequirements);
-#endif
-
-#define VK_KHR_image_format_list 1
-#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1
-#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list"
-
-typedef struct VkImageFormatListCreateInfoKHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           viewFormatCount;
-    const VkFormat*    pViewFormats;
-} VkImageFormatListCreateInfoKHR;
-
-
-
-#define VK_KHR_sampler_ycbcr_conversion 1
-typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR;
-
-
-#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1
-#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
-
-typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR;
-
-typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR;
-
-typedef VkChromaLocation VkChromaLocationKHR;
-
-
-typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR;
-
-typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR;
-
-typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR;
-
-typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR;
-
-typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
-
-typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR;
-
-
-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 VkSamplerYcbcrConversionCreateInfo*   pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSamplerYcbcrConversion*                   pYcbcrConversion);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR(
-    VkDevice                                    device,
-    VkSamplerYcbcrConversion                    ycbcrConversion,
-    const VkAllocationCallbacks*                pAllocator);
-#endif
-
-#define VK_KHR_bind_memory2 1
-#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1
-#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2"
-
-typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR;
-
-typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR;
-
-
-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 VkBindBufferMemoryInfo*               pBindInfos);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR(
-    VkDevice                                    device,
-    uint32_t                                    bindInfoCount,
-    const VkBindImageMemoryInfo*                pBindInfos);
-#endif
-
-#define VK_KHR_maintenance3 1
-#define VK_KHR_MAINTENANCE3_SPEC_VERSION  1
-#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
-
-typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR;
-
-typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
-
-
-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_KHR_draw_indirect_count 1
-#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
-
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkBuffer                                    countBuffer,
-    VkDeviceSize                                countBufferOffset,
-    uint32_t                                    maxDrawCount,
-    uint32_t                                    stride);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkBuffer                                    countBuffer,
-    VkDeviceSize                                countBufferOffset,
-    uint32_t                                    maxDrawCount,
-    uint32_t                                    stride);
-#endif
-
-#define VK_KHR_8bit_storage 1
-#define VK_KHR_8BIT_STORAGE_SPEC_VERSION  1
-#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
-
-typedef struct VkPhysicalDevice8BitStorageFeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           storageBuffer8BitAccess;
-    VkBool32           uniformAndStorageBuffer8BitAccess;
-    VkBool32           storagePushConstant8;
-} VkPhysicalDevice8BitStorageFeaturesKHR;
-
-
-
-#define VK_KHR_shader_atomic_int64 1
-#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
-#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
-
-typedef struct VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           shaderBufferInt64Atomics;
-    VkBool32           shaderSharedInt64Atomics;
-} VkPhysicalDeviceShaderAtomicInt64FeaturesKHR;
-
-
-
-#define VK_KHR_driver_properties 1
-#define VK_MAX_DRIVER_NAME_SIZE_KHR       256
-#define VK_MAX_DRIVER_INFO_SIZE_KHR       256
-#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
-#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
-
-
-typedef enum VkDriverIdKHR {
-    VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
-    VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
-    VK_DRIVER_ID_MESA_RADV_KHR = 3,
-    VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
-    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
-    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
-    VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
-    VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
-    VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
-    VK_DRIVER_ID_GOOGLE_PASTEL_KHR = 10,
-    VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR,
-    VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_GOOGLE_PASTEL_KHR,
-    VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_GOOGLE_PASTEL_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
-    VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkDriverIdKHR;
-
-typedef struct VkConformanceVersionKHR {
-    uint8_t    major;
-    uint8_t    minor;
-    uint8_t    subminor;
-    uint8_t    patch;
-} VkConformanceVersionKHR;
-
-typedef struct VkPhysicalDeviceDriverPropertiesKHR {
-    VkStructureType            sType;
-    void*                      pNext;
-    VkDriverIdKHR              driverID;
-    char                       driverName[VK_MAX_DRIVER_NAME_SIZE_KHR];
-    char                       driverInfo[VK_MAX_DRIVER_INFO_SIZE_KHR];
-    VkConformanceVersionKHR    conformanceVersion;
-} VkPhysicalDeviceDriverPropertiesKHR;
-
-
-
-#define VK_KHR_shader_float_controls 1
-#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
-#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
-
-typedef struct VkPhysicalDeviceFloatControlsPropertiesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           separateDenormSettings;
-    VkBool32           separateRoundingModeSettings;
-    VkBool32           shaderSignedZeroInfNanPreserveFloat16;
-    VkBool32           shaderSignedZeroInfNanPreserveFloat32;
-    VkBool32           shaderSignedZeroInfNanPreserveFloat64;
-    VkBool32           shaderDenormPreserveFloat16;
-    VkBool32           shaderDenormPreserveFloat32;
-    VkBool32           shaderDenormPreserveFloat64;
-    VkBool32           shaderDenormFlushToZeroFloat16;
-    VkBool32           shaderDenormFlushToZeroFloat32;
-    VkBool32           shaderDenormFlushToZeroFloat64;
-    VkBool32           shaderRoundingModeRTEFloat16;
-    VkBool32           shaderRoundingModeRTEFloat32;
-    VkBool32           shaderRoundingModeRTEFloat64;
-    VkBool32           shaderRoundingModeRTZFloat16;
-    VkBool32           shaderRoundingModeRTZFloat32;
-    VkBool32           shaderRoundingModeRTZFloat64;
-} VkPhysicalDeviceFloatControlsPropertiesKHR;
-
-
-
-#define VK_KHR_swapchain_mutable_format 1
-#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
-#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
-
-
-#define VK_KHR_vulkan_memory_model 1
-#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
-#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
-
-typedef struct VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           vulkanMemoryModel;
-    VkBool32           vulkanMemoryModelDeviceScope;
-} VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
-
-
-
-#define VK_EXT_debug_report 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
-
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  9
-#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
-
-
-typedef enum VkDebugReportObjectTypeEXT {
-    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10,
-    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17,
-    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
-    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_EXT = 33,
-    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_ACCELERATION_STRUCTURE_NV_EXT = 1000165000,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
-    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_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
-    VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDebugReportObjectTypeEXT;
-
-
-typedef enum VkDebugReportFlagBitsEXT {
-    VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001,
-    VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002,
-    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004,
-    VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008,
-    VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010,
-    VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDebugReportFlagBitsEXT;
-typedef VkFlags VkDebugReportFlagsEXT;
-
-typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)(
-    VkDebugReportFlagsEXT                       flags,
-    VkDebugReportObjectTypeEXT                  objectType,
-    uint64_t                                    object,
-    size_t                                      location,
-    int32_t                                     messageCode,
-    const char*                                 pLayerPrefix,
-    const char*                                 pMessage,
-    void*                                       pUserData);
-
-typedef struct VkDebugReportCallbackCreateInfoEXT {
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkDebugReportFlagsEXT           flags;
-    PFN_vkDebugReportCallbackEXT    pfnCallback;
-    void*                           pUserData;
-} VkDebugReportCallbackCreateInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
-typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
-    VkInstance                                  instance,
-    const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDebugReportCallbackEXT*                   pCallback);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
-    VkInstance                                  instance,
-    VkDebugReportCallbackEXT                    callback,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
-    VkInstance                                  instance,
-    VkDebugReportFlagsEXT                       flags,
-    VkDebugReportObjectTypeEXT                  objectType,
-    uint64_t                                    object,
-    size_t                                      location,
-    int32_t                                     messageCode,
-    const char*                                 pLayerPrefix,
-    const char*                                 pMessage);
-#endif
-
-#define VK_NV_glsl_shader 1
-#define VK_NV_GLSL_SHADER_SPEC_VERSION    1
-#define VK_NV_GLSL_SHADER_EXTENSION_NAME  "VK_NV_glsl_shader"
-
-
-#define VK_EXT_depth_range_unrestricted 1
-#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1
-#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted"
-
-
-#define VK_IMG_filter_cubic 1
-#define VK_IMG_FILTER_CUBIC_SPEC_VERSION  1
-#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic"
-
-
-#define VK_AMD_rasterization_order 1
-#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1
-#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order"
-
-
-typedef enum VkRasterizationOrderAMD {
-    VK_RASTERIZATION_ORDER_STRICT_AMD = 0,
-    VK_RASTERIZATION_ORDER_RELAXED_AMD = 1,
-    VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD,
-    VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD,
-    VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1),
-    VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF
-} VkRasterizationOrderAMD;
-
-typedef struct VkPipelineRasterizationStateRasterizationOrderAMD {
-    VkStructureType            sType;
-    const void*                pNext;
-    VkRasterizationOrderAMD    rasterizationOrder;
-} VkPipelineRasterizationStateRasterizationOrderAMD;
-
-
-
-#define VK_AMD_shader_trinary_minmax 1
-#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1
-#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax"
-
-
-#define VK_AMD_shader_explicit_vertex_parameter 1
-#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1
-#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
-
-
-#define VK_EXT_debug_marker 1
-#define VK_EXT_DEBUG_MARKER_SPEC_VERSION  4
-#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker"
-
-typedef struct VkDebugMarkerObjectNameInfoEXT {
-    VkStructureType               sType;
-    const void*                   pNext;
-    VkDebugReportObjectTypeEXT    objectType;
-    uint64_t                      object;
-    const char*                   pObjectName;
-} VkDebugMarkerObjectNameInfoEXT;
-
-typedef struct VkDebugMarkerObjectTagInfoEXT {
-    VkStructureType               sType;
-    const void*                   pNext;
-    VkDebugReportObjectTypeEXT    objectType;
-    uint64_t                      object;
-    uint64_t                      tagName;
-    size_t                        tagSize;
-    const void*                   pTag;
-} VkDebugMarkerObjectTagInfoEXT;
-
-typedef struct VkDebugMarkerMarkerInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    const char*        pMarkerName;
-    float              color[4];
-} VkDebugMarkerMarkerInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer);
-typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT(
-    VkDevice                                    device,
-    const VkDebugMarkerObjectTagInfoEXT*        pTagInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT(
-    VkDevice                                    device,
-    const VkDebugMarkerObjectNameInfoEXT*       pNameInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT(
-    VkCommandBuffer                             commandBuffer);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo);
-#endif
-
-#define VK_AMD_gcn_shader 1
-#define VK_AMD_GCN_SHADER_SPEC_VERSION    1
-#define VK_AMD_GCN_SHADER_EXTENSION_NAME  "VK_AMD_gcn_shader"
-
-
-#define VK_NV_dedicated_allocation 1
-#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1
-#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation"
-
-typedef struct VkDedicatedAllocationImageCreateInfoNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           dedicatedAllocation;
-} VkDedicatedAllocationImageCreateInfoNV;
-
-typedef struct VkDedicatedAllocationBufferCreateInfoNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           dedicatedAllocation;
-} VkDedicatedAllocationBufferCreateInfoNV;
-
-typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkImage            image;
-    VkBuffer           buffer;
-} VkDedicatedAllocationMemoryAllocateInfoNV;
-
-
-
-#define VK_EXT_transform_feedback 1
-#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1
-#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback"
-
-typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT;
-
-typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           transformFeedback;
-    VkBool32           geometryStreams;
-} VkPhysicalDeviceTransformFeedbackFeaturesEXT;
-
-typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxTransformFeedbackStreams;
-    uint32_t           maxTransformFeedbackBuffers;
-    VkDeviceSize       maxTransformFeedbackBufferSize;
-    uint32_t           maxTransformFeedbackStreamDataSize;
-    uint32_t           maxTransformFeedbackBufferDataSize;
-    uint32_t           maxTransformFeedbackBufferDataStride;
-    VkBool32           transformFeedbackQueries;
-    VkBool32           transformFeedbackStreamsLinesTriangles;
-    VkBool32           transformFeedbackRasterizationStreamSelect;
-    VkBool32           transformFeedbackDraw;
-} VkPhysicalDeviceTransformFeedbackPropertiesEXT;
-
-typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT {
-    VkStructureType                                     sType;
-    const void*                                         pNext;
-    VkPipelineRasterizationStateStreamCreateFlagsEXT    flags;
-    uint32_t                                            rasterizationStream;
-} VkPipelineRasterizationStateStreamCreateInfoEXT;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets);
-typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index);
-typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstBinding,
-    uint32_t                                    bindingCount,
-    const VkBuffer*                             pBuffers,
-    const VkDeviceSize*                         pOffsets,
-    const VkDeviceSize*                         pSizes);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstCounterBuffer,
-    uint32_t                                    counterBufferCount,
-    const VkBuffer*                             pCounterBuffers,
-    const VkDeviceSize*                         pCounterBufferOffsets);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstCounterBuffer,
-    uint32_t                                    counterBufferCount,
-    const VkBuffer*                             pCounterBuffers,
-    const VkDeviceSize*                         pCounterBufferOffsets);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    query,
-    VkQueryControlFlags                         flags,
-    uint32_t                                    index);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT(
-    VkCommandBuffer                             commandBuffer,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    query,
-    uint32_t                                    index);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    instanceCount,
-    uint32_t                                    firstInstance,
-    VkBuffer                                    counterBuffer,
-    VkDeviceSize                                counterBufferOffset,
-    uint32_t                                    counterOffset,
-    uint32_t                                    vertexStride);
-#endif
-
-#define VK_AMD_draw_indirect_count 1
-#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
-
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkBuffer                                    countBuffer,
-    VkDeviceSize                                countBufferOffset,
-    uint32_t                                    maxDrawCount,
-    uint32_t                                    stride);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkBuffer                                    countBuffer,
-    VkDeviceSize                                countBufferOffset,
-    uint32_t                                    maxDrawCount,
-    uint32_t                                    stride);
-#endif
-
-#define VK_AMD_negative_viewport_height 1
-#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
-#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
-
-
-#define VK_AMD_gpu_shader_half_float 1
-#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
-#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
-
-
-#define VK_AMD_shader_ballot 1
-#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
-#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
-
-
-#define VK_AMD_texture_gather_bias_lod 1
-#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1
-#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
-
-typedef struct VkTextureLODGatherFormatPropertiesAMD {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           supportsTextureGatherLODBiasAMD;
-} VkTextureLODGatherFormatPropertiesAMD;
-
-
-
-#define VK_AMD_shader_info 1
-#define VK_AMD_SHADER_INFO_SPEC_VERSION   1
-#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info"
-
-
-typedef enum VkShaderInfoTypeAMD {
-    VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0,
-    VK_SHADER_INFO_TYPE_BINARY_AMD = 1,
-    VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2,
-    VK_SHADER_INFO_TYPE_BEGIN_RANGE_AMD = VK_SHADER_INFO_TYPE_STATISTICS_AMD,
-    VK_SHADER_INFO_TYPE_END_RANGE_AMD = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD,
-    VK_SHADER_INFO_TYPE_RANGE_SIZE_AMD = (VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD - VK_SHADER_INFO_TYPE_STATISTICS_AMD + 1),
-    VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF
-} VkShaderInfoTypeAMD;
-
-typedef struct VkShaderResourceUsageAMD {
-    uint32_t    numUsedVgprs;
-    uint32_t    numUsedSgprs;
-    uint32_t    ldsSizePerLocalWorkGroup;
-    size_t      ldsUsageSizeInBytes;
-    size_t      scratchMemUsageInBytes;
-} VkShaderResourceUsageAMD;
-
-typedef struct VkShaderStatisticsInfoAMD {
-    VkShaderStageFlags          shaderStageMask;
-    VkShaderResourceUsageAMD    resourceUsage;
-    uint32_t                    numPhysicalVgprs;
-    uint32_t                    numPhysicalSgprs;
-    uint32_t                    numAvailableVgprs;
-    uint32_t                    numAvailableSgprs;
-    uint32_t                    computeWorkGroupSize[3];
-} VkShaderStatisticsInfoAMD;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD(
-    VkDevice                                    device,
-    VkPipeline                                  pipeline,
-    VkShaderStageFlagBits                       shaderStage,
-    VkShaderInfoTypeAMD                         infoType,
-    size_t*                                     pInfoSize,
-    void*                                       pInfo);
-#endif
-
-#define VK_AMD_shader_image_load_store_lod 1
-#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
-#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
-
-
-#define VK_NV_corner_sampled_image 1
-#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
-#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
-
-typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           cornerSampledImage;
-} VkPhysicalDeviceCornerSampledImageFeaturesNV;
-
-
-
-#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"
-
-
-#define VK_NV_external_memory_capabilities 1
-#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
-
-
-typedef enum VkExternalMemoryHandleTypeFlagBitsNV {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkExternalMemoryHandleTypeFlagBitsNV;
-typedef VkFlags VkExternalMemoryHandleTypeFlagsNV;
-
-typedef enum VkExternalMemoryFeatureFlagBitsNV {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
-    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkExternalMemoryFeatureFlagBitsNV;
-typedef VkFlags VkExternalMemoryFeatureFlagsNV;
-
-typedef struct VkExternalImageFormatPropertiesNV {
-    VkImageFormatProperties              imageFormatProperties;
-    VkExternalMemoryFeatureFlagsNV       externalMemoryFeatures;
-    VkExternalMemoryHandleTypeFlagsNV    exportFromImportedHandleTypes;
-    VkExternalMemoryHandleTypeFlagsNV    compatibleHandleTypes;
-} VkExternalImageFormatPropertiesNV;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
-    VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
-    VkImageType                                 type,
-    VkImageTiling                               tiling,
-    VkImageUsageFlags                           usage,
-    VkImageCreateFlags                          flags,
-    VkExternalMemoryHandleTypeFlagsNV           externalHandleType,
-    VkExternalImageFormatPropertiesNV*          pExternalImageFormatProperties);
-#endif
-
-#define VK_NV_external_memory 1
-#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
-#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
-
-typedef struct VkExternalMemoryImageCreateInfoNV {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
-} VkExternalMemoryImageCreateInfoNV;
-
-typedef struct VkExportMemoryAllocateInfoNV {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
-} VkExportMemoryAllocateInfoNV;
-
-
-
-#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"
-
-
-typedef enum VkValidationCheckEXT {
-    VK_VALIDATION_CHECK_ALL_EXT = 0,
-    VK_VALIDATION_CHECK_SHADERS_EXT = 1,
-    VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
-    VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT,
-    VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1),
-    VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkValidationCheckEXT;
-
-typedef struct VkValidationFlagsEXT {
-    VkStructureType                sType;
-    const void*                    pNext;
-    uint32_t                       disabledValidationCheckCount;
-    const VkValidationCheckEXT*    pDisabledValidationChecks;
-} VkValidationFlagsEXT;
-
-
-
-#define VK_EXT_shader_subgroup_ballot 1
-#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
-#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
-
-
-#define VK_EXT_shader_subgroup_vote 1
-#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
-#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
-
-
-#define VK_EXT_astc_decode_mode 1
-#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
-#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
-
-typedef struct VkImageViewASTCDecodeModeEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkFormat           decodeMode;
-} VkImageViewASTCDecodeModeEXT;
-
-typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           decodeModeSharedExponent;
-} VkPhysicalDeviceASTCDecodeFeaturesEXT;
-
-
-
-#define VK_EXT_conditional_rendering 1
-#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
-#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
-
-
-typedef enum VkConditionalRenderingFlagBitsEXT {
-    VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001,
-    VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkConditionalRenderingFlagBitsEXT;
-typedef VkFlags VkConditionalRenderingFlagsEXT;
-
-typedef struct VkConditionalRenderingBeginInfoEXT {
-    VkStructureType                   sType;
-    const void*                       pNext;
-    VkBuffer                          buffer;
-    VkDeviceSize                      offset;
-    VkConditionalRenderingFlagsEXT    flags;
-} VkConditionalRenderingBeginInfoEXT;
-
-typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           conditionalRendering;
-    VkBool32           inheritedConditionalRendering;
-} VkPhysicalDeviceConditionalRenderingFeaturesEXT;
-
-typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           conditionalRenderingEnable;
-} VkCommandBufferInheritanceConditionalRenderingInfoEXT;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin);
-typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkConditionalRenderingBeginInfoEXT*   pConditionalRenderingBegin);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT(
-    VkCommandBuffer                             commandBuffer);
-#endif
-
-#define VK_NVX_device_generated_commands 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
-
-#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
-#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
-
-
-typedef enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1),
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkIndirectCommandsTokenTypeNVX;
-
-typedef enum VkObjectEntryTypeNVX {
-    VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0,
-    VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1,
-    VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2,
-    VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3,
-    VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4,
-    VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX,
-    VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX,
-    VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1),
-    VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkObjectEntryTypeNVX;
-
-
-typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX {
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkIndirectCommandsLayoutUsageFlagBitsNVX;
-typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX;
-
-typedef enum VkObjectEntryUsageFlagBitsNVX {
-    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
-    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
-    VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkObjectEntryUsageFlagBitsNVX;
-typedef VkFlags VkObjectEntryUsageFlagsNVX;
-
-typedef struct VkDeviceGeneratedCommandsFeaturesNVX {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           computeBindingPointSupport;
-} VkDeviceGeneratedCommandsFeaturesNVX;
-
-typedef struct VkDeviceGeneratedCommandsLimitsNVX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           maxIndirectCommandsLayoutTokenCount;
-    uint32_t           maxObjectEntryCounts;
-    uint32_t           minSequenceCountBufferOffsetAlignment;
-    uint32_t           minSequenceIndexBufferOffsetAlignment;
-    uint32_t           minCommandsTokenBufferOffsetAlignment;
-} VkDeviceGeneratedCommandsLimitsNVX;
-
-typedef struct VkIndirectCommandsTokenNVX {
-    VkIndirectCommandsTokenTypeNVX    tokenType;
-    VkBuffer                          buffer;
-    VkDeviceSize                      offset;
-} VkIndirectCommandsTokenNVX;
-
-typedef struct VkIndirectCommandsLayoutTokenNVX {
-    VkIndirectCommandsTokenTypeNVX    tokenType;
-    uint32_t                          bindingUnit;
-    uint32_t                          dynamicCount;
-    uint32_t                          divisor;
-} VkIndirectCommandsLayoutTokenNVX;
-
-typedef struct VkIndirectCommandsLayoutCreateInfoNVX {
-    VkStructureType                            sType;
-    const void*                                pNext;
-    VkPipelineBindPoint                        pipelineBindPoint;
-    VkIndirectCommandsLayoutUsageFlagsNVX      flags;
-    uint32_t                                   tokenCount;
-    const VkIndirectCommandsLayoutTokenNVX*    pTokens;
-} VkIndirectCommandsLayoutCreateInfoNVX;
-
-typedef struct VkCmdProcessCommandsInfoNVX {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkObjectTableNVX                     objectTable;
-    VkIndirectCommandsLayoutNVX          indirectCommandsLayout;
-    uint32_t                             indirectCommandsTokenCount;
-    const VkIndirectCommandsTokenNVX*    pIndirectCommandsTokens;
-    uint32_t                             maxSequencesCount;
-    VkCommandBuffer                      targetCommandBuffer;
-    VkBuffer                             sequencesCountBuffer;
-    VkDeviceSize                         sequencesCountOffset;
-    VkBuffer                             sequencesIndexBuffer;
-    VkDeviceSize                         sequencesIndexOffset;
-} VkCmdProcessCommandsInfoNVX;
-
-typedef struct VkCmdReserveSpaceForCommandsInfoNVX {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkObjectTableNVX               objectTable;
-    VkIndirectCommandsLayoutNVX    indirectCommandsLayout;
-    uint32_t                       maxSequencesCount;
-} VkCmdReserveSpaceForCommandsInfoNVX;
-
-typedef struct VkObjectTableCreateInfoNVX {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    uint32_t                             objectCount;
-    const VkObjectEntryTypeNVX*          pObjectEntryTypes;
-    const uint32_t*                      pObjectEntryCounts;
-    const VkObjectEntryUsageFlagsNVX*    pObjectEntryUsageFlags;
-    uint32_t                             maxUniformBuffersPerDescriptor;
-    uint32_t                             maxStorageBuffersPerDescriptor;
-    uint32_t                             maxStorageImagesPerDescriptor;
-    uint32_t                             maxSampledImagesPerDescriptor;
-    uint32_t                             maxPipelineLayouts;
-} VkObjectTableCreateInfoNVX;
-
-typedef struct VkObjectTableEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-} VkObjectTableEntryNVX;
-
-typedef struct VkObjectTablePipelineEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipeline                    pipeline;
-} VkObjectTablePipelineEntryNVX;
-
-typedef struct VkObjectTableDescriptorSetEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipelineLayout              pipelineLayout;
-    VkDescriptorSet               descriptorSet;
-} VkObjectTableDescriptorSetEntryNVX;
-
-typedef struct VkObjectTableVertexBufferEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkBuffer                      buffer;
-} VkObjectTableVertexBufferEntryNVX;
-
-typedef struct VkObjectTableIndexBufferEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkBuffer                      buffer;
-    VkIndexType                   indexType;
-} VkObjectTableIndexBufferEntryNVX;
-
-typedef struct VkObjectTablePushConstantEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipelineLayout              pipelineLayout;
-    VkShaderStageFlags            stageFlags;
-} VkObjectTablePushConstantEntryNVX;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
-typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable);
-typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const*    ppObjectTableEntries, const uint32_t* pObjectIndices);
-typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX(
-    VkCommandBuffer                             commandBuffer,
-    const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX(
-    VkCommandBuffer                             commandBuffer,
-    const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX(
-    VkDevice                                    device,
-    const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX(
-    VkDevice                                    device,
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX(
-    VkDevice                                    device,
-    const VkObjectTableCreateInfoNVX*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkObjectTableNVX*                           pObjectTable);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    uint32_t                                    objectCount,
-    const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
-    const uint32_t*                             pObjectIndices);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    uint32_t                                    objectCount,
-    const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
-    const uint32_t*                             pObjectIndices);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
-    VkPhysicalDevice                            physicalDevice,
-    VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
-    VkDeviceGeneratedCommandsLimitsNVX*         pLimits);
-#endif
-
-#define VK_NV_clip_space_w_scaling 1
-#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
-#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
-
-typedef struct VkViewportWScalingNV {
-    float    xcoeff;
-    float    ycoeff;
-} VkViewportWScalingNV;
-
-typedef struct VkPipelineViewportWScalingStateCreateInfoNV {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkBool32                       viewportWScalingEnable;
-    uint32_t                       viewportCount;
-    const VkViewportWScalingNV*    pViewportWScalings;
-} VkPipelineViewportWScalingStateCreateInfoNV;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstViewport,
-    uint32_t                                    viewportCount,
-    const VkViewportWScalingNV*                 pViewportWScalings);
-#endif
-
-#define VK_EXT_direct_mode_display 1
-#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
-#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
-
-typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT(
-    VkPhysicalDevice                            physicalDevice,
-    VkDisplayKHR                                display);
-#endif
-
-#define VK_EXT_display_surface_counter 1
-#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
-#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-
-
-typedef enum VkSurfaceCounterFlagBitsEXT {
-    VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001,
-    VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkSurfaceCounterFlagBitsEXT;
-typedef VkFlags VkSurfaceCounterFlagsEXT;
-
-typedef struct VkSurfaceCapabilities2EXT {
-    VkStructureType                  sType;
-    void*                            pNext;
-    uint32_t                         minImageCount;
-    uint32_t                         maxImageCount;
-    VkExtent2D                       currentExtent;
-    VkExtent2D                       minImageExtent;
-    VkExtent2D                       maxImageExtent;
-    uint32_t                         maxImageArrayLayers;
-    VkSurfaceTransformFlagsKHR       supportedTransforms;
-    VkSurfaceTransformFlagBitsKHR    currentTransform;
-    VkCompositeAlphaFlagsKHR         supportedCompositeAlpha;
-    VkImageUsageFlags                supportedUsageFlags;
-    VkSurfaceCounterFlagsEXT         supportedSurfaceCounters;
-} VkSurfaceCapabilities2EXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
-    VkPhysicalDevice                            physicalDevice,
-    VkSurfaceKHR                                surface,
-    VkSurfaceCapabilities2EXT*                  pSurfaceCapabilities);
-#endif
-
-#define VK_EXT_display_control 1
-#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
-#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control"
-
-
-typedef enum VkDisplayPowerStateEXT {
-    VK_DISPLAY_POWER_STATE_OFF_EXT = 0,
-    VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1,
-    VK_DISPLAY_POWER_STATE_ON_EXT = 2,
-    VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT,
-    VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT,
-    VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1),
-    VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDisplayPowerStateEXT;
-
-typedef enum VkDeviceEventTypeEXT {
-    VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
-    VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
-    VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
-    VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1),
-    VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDeviceEventTypeEXT;
-
-typedef enum VkDisplayEventTypeEXT {
-    VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
-    VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
-    VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
-    VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1),
-    VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDisplayEventTypeEXT;
-
-typedef struct VkDisplayPowerInfoEXT {
-    VkStructureType           sType;
-    const void*               pNext;
-    VkDisplayPowerStateEXT    powerState;
-} VkDisplayPowerInfoEXT;
-
-typedef struct VkDeviceEventInfoEXT {
-    VkStructureType         sType;
-    const void*             pNext;
-    VkDeviceEventTypeEXT    deviceEvent;
-} VkDeviceEventInfoEXT;
-
-typedef struct VkDisplayEventInfoEXT {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkDisplayEventTypeEXT    displayEvent;
-} VkDisplayEventInfoEXT;
-
-typedef struct VkSwapchainCounterCreateInfoEXT {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkSurfaceCounterFlagsEXT    surfaceCounters;
-} VkSwapchainCounterCreateInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
-typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT(
-    VkDevice                                    device,
-    VkDisplayKHR                                display,
-    const VkDisplayPowerInfoEXT*                pDisplayPowerInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT(
-    VkDevice                                    device,
-    const VkDeviceEventInfoEXT*                 pDeviceEventInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkFence*                                    pFence);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT(
-    VkDevice                                    device,
-    VkDisplayKHR                                display,
-    const VkDisplayEventInfoEXT*                pDisplayEventInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkFence*                                    pFence);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    VkSurfaceCounterFlagBitsEXT                 counter,
-    uint64_t*                                   pCounterValue);
-#endif
-
-#define VK_GOOGLE_display_timing 1
-#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
-#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
-
-typedef struct VkRefreshCycleDurationGOOGLE {
-    uint64_t    refreshDuration;
-} VkRefreshCycleDurationGOOGLE;
-
-typedef struct VkPastPresentationTimingGOOGLE {
-    uint32_t    presentID;
-    uint64_t    desiredPresentTime;
-    uint64_t    actualPresentTime;
-    uint64_t    earliestPresentTime;
-    uint64_t    presentMargin;
-} VkPastPresentationTimingGOOGLE;
-
-typedef struct VkPresentTimeGOOGLE {
-    uint32_t    presentID;
-    uint64_t    desiredPresentTime;
-} VkPresentTimeGOOGLE;
-
-typedef struct VkPresentTimesInfoGOOGLE {
-    VkStructureType               sType;
-    const void*                   pNext;
-    uint32_t                      swapchainCount;
-    const VkPresentTimeGOOGLE*    pTimes;
-} VkPresentTimesInfoGOOGLE;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    VkRefreshCycleDurationGOOGLE*               pDisplayTimingProperties);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain,
-    uint32_t*                                   pPresentationTimingCount,
-    VkPastPresentationTimingGOOGLE*             pPresentationTimings);
-#endif
-
-#define VK_NV_sample_mask_override_coverage 1
-#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
-#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
-
-
-#define VK_NV_geometry_shader_passthrough 1
-#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
-#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
-
-
-#define VK_NV_viewport_array2 1
-#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
-#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
-
-
-#define VK_NVX_multiview_per_view_attributes 1
-#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
-#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
-
-typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           perViewPositionAllComponents;
-} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX;
-
-
-
-#define VK_NV_viewport_swizzle 1
-#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
-#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
-
-
-typedef enum VkViewportCoordinateSwizzleNV {
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1),
-    VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkViewportCoordinateSwizzleNV;
-
-typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV;
-
-typedef struct VkViewportSwizzleNV {
-    VkViewportCoordinateSwizzleNV    x;
-    VkViewportCoordinateSwizzleNV    y;
-    VkViewportCoordinateSwizzleNV    z;
-    VkViewportCoordinateSwizzleNV    w;
-} VkViewportSwizzleNV;
-
-typedef struct VkPipelineViewportSwizzleStateCreateInfoNV {
-    VkStructureType                                sType;
-    const void*                                    pNext;
-    VkPipelineViewportSwizzleStateCreateFlagsNV    flags;
-    uint32_t                                       viewportCount;
-    const VkViewportSwizzleNV*                     pViewportSwizzles;
-} VkPipelineViewportSwizzleStateCreateInfoNV;
-
-
-
-#define VK_EXT_discard_rectangles 1
-#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
-#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
-
-
-typedef enum VkDiscardRectangleModeEXT {
-    VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
-    VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
-    VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT,
-    VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT,
-    VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1),
-    VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDiscardRectangleModeEXT;
-
-typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT;
-
-typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxDiscardRectangles;
-} VkPhysicalDeviceDiscardRectanglePropertiesEXT;
-
-typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT {
-    VkStructureType                                  sType;
-    const void*                                      pNext;
-    VkPipelineDiscardRectangleStateCreateFlagsEXT    flags;
-    VkDiscardRectangleModeEXT                        discardRectangleMode;
-    uint32_t                                         discardRectangleCount;
-    const VkRect2D*                                  pDiscardRectangles;
-} VkPipelineDiscardRectangleStateCreateInfoEXT;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstDiscardRectangle,
-    uint32_t                                    discardRectangleCount,
-    const VkRect2D*                             pDiscardRectangles);
-#endif
-
-#define VK_EXT_conservative_rasterization 1
-#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1
-#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization"
-
-
-typedef enum VkConservativeRasterizationModeEXT {
-    VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_END_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT + 1),
-    VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkConservativeRasterizationModeEXT;
-
-typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT;
-
-typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    float              primitiveOverestimationSize;
-    float              maxExtraPrimitiveOverestimationSize;
-    float              extraPrimitiveOverestimationSizeGranularity;
-    VkBool32           primitiveUnderestimation;
-    VkBool32           conservativePointAndLineRasterization;
-    VkBool32           degenerateTrianglesRasterized;
-    VkBool32           degenerateLinesRasterized;
-    VkBool32           fullyCoveredFragmentShaderInputVariable;
-    VkBool32           conservativeRasterizationPostDepthCoverage;
-} VkPhysicalDeviceConservativeRasterizationPropertiesEXT;
-
-typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT {
-    VkStructureType                                           sType;
-    const void*                                               pNext;
-    VkPipelineRasterizationConservativeStateCreateFlagsEXT    flags;
-    VkConservativeRasterizationModeEXT                        conservativeRasterizationMode;
-    float                                                     extraPrimitiveOverestimationSize;
-} VkPipelineRasterizationConservativeStateCreateInfoEXT;
-
-
-
-#define VK_EXT_swapchain_colorspace 1
-#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 3
-#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
-
-
-#define VK_EXT_hdr_metadata 1
-#define VK_EXT_HDR_METADATA_SPEC_VERSION  1
-#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
-
-typedef struct VkXYColorEXT {
-    float    x;
-    float    y;
-} VkXYColorEXT;
-
-typedef struct VkHdrMetadataEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkXYColorEXT       displayPrimaryRed;
-    VkXYColorEXT       displayPrimaryGreen;
-    VkXYColorEXT       displayPrimaryBlue;
-    VkXYColorEXT       whitePoint;
-    float              maxLuminance;
-    float              minLuminance;
-    float              maxContentLightLevel;
-    float              maxFrameAverageLightLevel;
-} VkHdrMetadataEXT;
-
-
-typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT(
-    VkDevice                                    device,
-    uint32_t                                    swapchainCount,
-    const VkSwapchainKHR*                       pSwapchains,
-    const VkHdrMetadataEXT*                     pMetadata);
-#endif
-
-#define VK_EXT_external_memory_dma_buf 1
-#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1
-#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf"
-
-
-#define VK_EXT_queue_family_foreign 1
-#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1
-#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign"
-#define VK_QUEUE_FAMILY_FOREIGN_EXT       (~0U-2)
-
-
-#define VK_EXT_debug_utils 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT)
-
-#define VK_EXT_DEBUG_UTILS_SPEC_VERSION   1
-#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
-
-typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT;
-typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT;
-
-typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDebugUtilsMessageSeverityFlagBitsEXT;
-typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT;
-
-typedef enum VkDebugUtilsMessageTypeFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDebugUtilsMessageTypeFlagBitsEXT;
-typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT;
-
-typedef struct VkDebugUtilsObjectNameInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkObjectType       objectType;
-    uint64_t           objectHandle;
-    const char*        pObjectName;
-} VkDebugUtilsObjectNameInfoEXT;
-
-typedef struct VkDebugUtilsObjectTagInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkObjectType       objectType;
-    uint64_t           objectHandle;
-    uint64_t           tagName;
-    size_t             tagSize;
-    const void*        pTag;
-} VkDebugUtilsObjectTagInfoEXT;
-
-typedef struct VkDebugUtilsLabelEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    const char*        pLabelName;
-    float              color[4];
-} VkDebugUtilsLabelEXT;
-
-typedef struct VkDebugUtilsMessengerCallbackDataEXT {
-    VkStructureType                              sType;
-    const void*                                  pNext;
-    VkDebugUtilsMessengerCallbackDataFlagsEXT    flags;
-    const char*                                  pMessageIdName;
-    int32_t                                      messageIdNumber;
-    const char*                                  pMessage;
-    uint32_t                                     queueLabelCount;
-    const VkDebugUtilsLabelEXT*                  pQueueLabels;
-    uint32_t                                     cmdBufLabelCount;
-    const VkDebugUtilsLabelEXT*                  pCmdBufLabels;
-    uint32_t                                     objectCount;
-    const VkDebugUtilsObjectNameInfoEXT*         pObjects;
-} VkDebugUtilsMessengerCallbackDataEXT;
-
-typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)(
-    VkDebugUtilsMessageSeverityFlagBitsEXT           messageSeverity,
-    VkDebugUtilsMessageTypeFlagsEXT                  messageTypes,
-    const VkDebugUtilsMessengerCallbackDataEXT*      pCallbackData,
-    void*                                            pUserData);
-
-typedef struct VkDebugUtilsMessengerCreateInfoEXT {
-    VkStructureType                         sType;
-    const void*                             pNext;
-    VkDebugUtilsMessengerCreateFlagsEXT     flags;
-    VkDebugUtilsMessageSeverityFlagsEXT     messageSeverity;
-    VkDebugUtilsMessageTypeFlagsEXT         messageType;
-    PFN_vkDebugUtilsMessengerCallbackEXT    pfnUserCallback;
-    void*                                   pUserData;
-} VkDebugUtilsMessengerCreateInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo);
-typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);
-typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue);
-typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer);
-typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger);
-typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT(
-    VkDevice                                    device,
-    const VkDebugUtilsObjectNameInfoEXT*        pNameInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT(
-    VkDevice                                    device,
-    const VkDebugUtilsObjectTagInfoEXT*         pTagInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT(
-    VkQueue                                     queue,
-    const VkDebugUtilsLabelEXT*                 pLabelInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT(
-    VkQueue                                     queue);
-
-VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT(
-    VkQueue                                     queue,
-    const VkDebugUtilsLabelEXT*                 pLabelInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkDebugUtilsLabelEXT*                 pLabelInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT(
-    VkCommandBuffer                             commandBuffer);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkDebugUtilsLabelEXT*                 pLabelInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(
-    VkInstance                                  instance,
-    const VkDebugUtilsMessengerCreateInfoEXT*   pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkDebugUtilsMessengerEXT*                   pMessenger);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(
-    VkInstance                                  instance,
-    VkDebugUtilsMessengerEXT                    messenger,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT(
-    VkInstance                                  instance,
-    VkDebugUtilsMessageSeverityFlagBitsEXT      messageSeverity,
-    VkDebugUtilsMessageTypeFlagsEXT             messageTypes,
-    const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
-#endif
-
-#define VK_EXT_sampler_filter_minmax 1
-#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1
-#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax"
-
-
-typedef enum VkSamplerReductionModeEXT {
-    VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = 0,
-    VK_SAMPLER_REDUCTION_MODE_MIN_EXT = 1,
-    VK_SAMPLER_REDUCTION_MODE_MAX_EXT = 2,
-    VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT,
-    VK_SAMPLER_REDUCTION_MODE_END_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_MAX_EXT,
-    VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE_EXT = (VK_SAMPLER_REDUCTION_MODE_MAX_EXT - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT + 1),
-    VK_SAMPLER_REDUCTION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkSamplerReductionModeEXT;
-
-typedef struct VkSamplerReductionModeCreateInfoEXT {
-    VkStructureType              sType;
-    const void*                  pNext;
-    VkSamplerReductionModeEXT    reductionMode;
-} VkSamplerReductionModeCreateInfoEXT;
-
-typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           filterMinmaxSingleComponentFormats;
-    VkBool32           filterMinmaxImageComponentMapping;
-} VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT;
-
-
-
-#define VK_AMD_gpu_shader_int16 1
-#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1
-#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16"
-
-
-#define VK_AMD_mixed_attachment_samples 1
-#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1
-#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples"
-
-
-#define VK_AMD_shader_fragment_mask 1
-#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
-#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
-
-
-#define VK_EXT_inline_uniform_block 1
-#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
-#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
-
-typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           inlineUniformBlock;
-    VkBool32           descriptorBindingInlineUniformBlockUpdateAfterBind;
-} VkPhysicalDeviceInlineUniformBlockFeaturesEXT;
-
-typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxInlineUniformBlockSize;
-    uint32_t           maxPerStageDescriptorInlineUniformBlocks;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
-    uint32_t           maxDescriptorSetInlineUniformBlocks;
-    uint32_t           maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
-} VkPhysicalDeviceInlineUniformBlockPropertiesEXT;
-
-typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           dataSize;
-    const void*        pData;
-} VkWriteDescriptorSetInlineUniformBlockEXT;
-
-typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           maxInlineUniformBlockBindings;
-} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
-
-
-
-#define VK_EXT_shader_stencil_export 1
-#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
-#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
-
-
-#define VK_EXT_sample_locations 1
-#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1
-#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations"
-
-typedef struct VkSampleLocationEXT {
-    float    x;
-    float    y;
-} VkSampleLocationEXT;
-
-typedef struct VkSampleLocationsInfoEXT {
-    VkStructureType               sType;
-    const void*                   pNext;
-    VkSampleCountFlagBits         sampleLocationsPerPixel;
-    VkExtent2D                    sampleLocationGridSize;
-    uint32_t                      sampleLocationsCount;
-    const VkSampleLocationEXT*    pSampleLocations;
-} VkSampleLocationsInfoEXT;
-
-typedef struct VkAttachmentSampleLocationsEXT {
-    uint32_t                    attachmentIndex;
-    VkSampleLocationsInfoEXT    sampleLocationsInfo;
-} VkAttachmentSampleLocationsEXT;
-
-typedef struct VkSubpassSampleLocationsEXT {
-    uint32_t                    subpassIndex;
-    VkSampleLocationsInfoEXT    sampleLocationsInfo;
-} VkSubpassSampleLocationsEXT;
-
-typedef struct VkRenderPassSampleLocationsBeginInfoEXT {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    uint32_t                                 attachmentInitialSampleLocationsCount;
-    const VkAttachmentSampleLocationsEXT*    pAttachmentInitialSampleLocations;
-    uint32_t                                 postSubpassSampleLocationsCount;
-    const VkSubpassSampleLocationsEXT*       pPostSubpassSampleLocations;
-} VkRenderPassSampleLocationsBeginInfoEXT;
-
-typedef struct VkPipelineSampleLocationsStateCreateInfoEXT {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkBool32                    sampleLocationsEnable;
-    VkSampleLocationsInfoEXT    sampleLocationsInfo;
-} VkPipelineSampleLocationsStateCreateInfoEXT;
-
-typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT {
-    VkStructureType       sType;
-    void*                 pNext;
-    VkSampleCountFlags    sampleLocationSampleCounts;
-    VkExtent2D            maxSampleLocationGridSize;
-    float                 sampleLocationCoordinateRange[2];
-    uint32_t              sampleLocationSubPixelBits;
-    VkBool32              variableSampleLocations;
-} VkPhysicalDeviceSampleLocationsPropertiesEXT;
-
-typedef struct VkMultisamplePropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkExtent2D         maxSampleLocationGridSize;
-} VkMultisamplePropertiesEXT;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT(
-    VkCommandBuffer                             commandBuffer,
-    const VkSampleLocationsInfoEXT*             pSampleLocationsInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT(
-    VkPhysicalDevice                            physicalDevice,
-    VkSampleCountFlagBits                       samples,
-    VkMultisamplePropertiesEXT*                 pMultisampleProperties);
-#endif
-
-#define VK_EXT_blend_operation_advanced 1
-#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2
-#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced"
-
-
-typedef enum VkBlendOverlapEXT {
-    VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0,
-    VK_BLEND_OVERLAP_DISJOINT_EXT = 1,
-    VK_BLEND_OVERLAP_CONJOINT_EXT = 2,
-    VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT,
-    VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT,
-    VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1),
-    VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkBlendOverlapEXT;
-
-typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           advancedBlendCoherentOperations;
-} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT;
-
-typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           advancedBlendMaxColorAttachments;
-    VkBool32           advancedBlendIndependentBlend;
-    VkBool32           advancedBlendNonPremultipliedSrcColor;
-    VkBool32           advancedBlendNonPremultipliedDstColor;
-    VkBool32           advancedBlendCorrelatedOverlap;
-    VkBool32           advancedBlendAllOperations;
-} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT;
-
-typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkBool32             srcPremultiplied;
-    VkBool32             dstPremultiplied;
-    VkBlendOverlapEXT    blendOverlap;
-} VkPipelineColorBlendAdvancedStateCreateInfoEXT;
-
-
-
-#define VK_NV_fragment_coverage_to_color 1
-#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1
-#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color"
-
-typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV;
-
-typedef struct VkPipelineCoverageToColorStateCreateInfoNV {
-    VkStructureType                                sType;
-    const void*                                    pNext;
-    VkPipelineCoverageToColorStateCreateFlagsNV    flags;
-    VkBool32                                       coverageToColorEnable;
-    uint32_t                                       coverageToColorLocation;
-} VkPipelineCoverageToColorStateCreateInfoNV;
-
-
-
-#define VK_NV_framebuffer_mixed_samples 1
-#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1
-#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples"
-
-
-typedef enum VkCoverageModulationModeNV {
-    VK_COVERAGE_MODULATION_MODE_NONE_NV = 0,
-    VK_COVERAGE_MODULATION_MODE_RGB_NV = 1,
-    VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2,
-    VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3,
-    VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV,
-    VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV,
-    VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1),
-    VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkCoverageModulationModeNV;
-
-typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV;
-
-typedef struct VkPipelineCoverageModulationStateCreateInfoNV {
-    VkStructureType                                   sType;
-    const void*                                       pNext;
-    VkPipelineCoverageModulationStateCreateFlagsNV    flags;
-    VkCoverageModulationModeNV                        coverageModulationMode;
-    VkBool32                                          coverageModulationTableEnable;
-    uint32_t                                          coverageModulationTableCount;
-    const float*                                      pCoverageModulationTable;
-} VkPipelineCoverageModulationStateCreateInfoNV;
-
-
-
-#define VK_NV_fill_rectangle 1
-#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1
-#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle"
-
-
-#define VK_EXT_post_depth_coverage 1
-#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1
-#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage"
-
-
-#define VK_EXT_image_drm_format_modifier 1
-#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
-#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
-
-typedef struct VkDrmFormatModifierPropertiesEXT {
-    uint64_t                drmFormatModifier;
-    uint32_t                drmFormatModifierPlaneCount;
-    VkFormatFeatureFlags    drmFormatModifierTilingFeatures;
-} VkDrmFormatModifierPropertiesEXT;
-
-typedef struct VkDrmFormatModifierPropertiesListEXT {
-    VkStructureType                      sType;
-    void*                                pNext;
-    uint32_t                             drmFormatModifierCount;
-    VkDrmFormatModifierPropertiesEXT*    pDrmFormatModifierProperties;
-} VkDrmFormatModifierPropertiesListEXT;
-
-typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint64_t           drmFormatModifier;
-    VkSharingMode      sharingMode;
-    uint32_t           queueFamilyIndexCount;
-    const uint32_t*    pQueueFamilyIndices;
-} VkPhysicalDeviceImageDrmFormatModifierInfoEXT;
-
-typedef struct VkImageDrmFormatModifierListCreateInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           drmFormatModifierCount;
-    const uint64_t*    pDrmFormatModifiers;
-} VkImageDrmFormatModifierListCreateInfoEXT;
-
-typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT {
-    VkStructureType               sType;
-    const void*                   pNext;
-    uint64_t                      drmFormatModifier;
-    uint32_t                      drmFormatModifierPlaneCount;
-    const VkSubresourceLayout*    pPlaneLayouts;
-} VkImageDrmFormatModifierExplicitCreateInfoEXT;
-
-typedef struct VkImageDrmFormatModifierPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint64_t           drmFormatModifier;
-} VkImageDrmFormatModifierPropertiesEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT(
-    VkDevice                                    device,
-    VkImage                                     image,
-    VkImageDrmFormatModifierPropertiesEXT*      pProperties);
-#endif
-
-#define VK_EXT_validation_cache 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT)
-
-#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
-#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-
-
-typedef enum VkValidationCacheHeaderVersionEXT {
-    VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1,
-    VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT,
-    VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT,
-    VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1),
-    VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkValidationCacheHeaderVersionEXT;
-
-typedef VkFlags VkValidationCacheCreateFlagsEXT;
-
-typedef struct VkValidationCacheCreateInfoEXT {
-    VkStructureType                    sType;
-    const void*                        pNext;
-    VkValidationCacheCreateFlagsEXT    flags;
-    size_t                             initialDataSize;
-    const void*                        pInitialData;
-} VkValidationCacheCreateInfoEXT;
-
-typedef struct VkShaderModuleValidationCacheCreateInfoEXT {
-    VkStructureType         sType;
-    const void*             pNext;
-    VkValidationCacheEXT    validationCache;
-} VkShaderModuleValidationCacheCreateInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache);
-typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches);
-typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT(
-    VkDevice                                    device,
-    const VkValidationCacheCreateInfoEXT*       pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkValidationCacheEXT*                       pValidationCache);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT(
-    VkDevice                                    device,
-    VkValidationCacheEXT                        validationCache,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT(
-    VkDevice                                    device,
-    VkValidationCacheEXT                        dstCache,
-    uint32_t                                    srcCacheCount,
-    const VkValidationCacheEXT*                 pSrcCaches);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT(
-    VkDevice                                    device,
-    VkValidationCacheEXT                        validationCache,
-    size_t*                                     pDataSize,
-    void*                                       pData);
-#endif
-
-#define VK_EXT_descriptor_indexing 1
-#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
-#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
-
-
-typedef enum VkDescriptorBindingFlagBitsEXT {
-    VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = 0x00000001,
-    VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = 0x00000002,
-    VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = 0x00000004,
-    VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008,
-    VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDescriptorBindingFlagBitsEXT;
-typedef VkFlags VkDescriptorBindingFlagsEXT;
-
-typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    uint32_t                              bindingCount;
-    const VkDescriptorBindingFlagsEXT*    pBindingFlags;
-} VkDescriptorSetLayoutBindingFlagsCreateInfoEXT;
-
-typedef struct VkPhysicalDeviceDescriptorIndexingFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           shaderInputAttachmentArrayDynamicIndexing;
-    VkBool32           shaderUniformTexelBufferArrayDynamicIndexing;
-    VkBool32           shaderStorageTexelBufferArrayDynamicIndexing;
-    VkBool32           shaderUniformBufferArrayNonUniformIndexing;
-    VkBool32           shaderSampledImageArrayNonUniformIndexing;
-    VkBool32           shaderStorageBufferArrayNonUniformIndexing;
-    VkBool32           shaderStorageImageArrayNonUniformIndexing;
-    VkBool32           shaderInputAttachmentArrayNonUniformIndexing;
-    VkBool32           shaderUniformTexelBufferArrayNonUniformIndexing;
-    VkBool32           shaderStorageTexelBufferArrayNonUniformIndexing;
-    VkBool32           descriptorBindingUniformBufferUpdateAfterBind;
-    VkBool32           descriptorBindingSampledImageUpdateAfterBind;
-    VkBool32           descriptorBindingStorageImageUpdateAfterBind;
-    VkBool32           descriptorBindingStorageBufferUpdateAfterBind;
-    VkBool32           descriptorBindingUniformTexelBufferUpdateAfterBind;
-    VkBool32           descriptorBindingStorageTexelBufferUpdateAfterBind;
-    VkBool32           descriptorBindingUpdateUnusedWhilePending;
-    VkBool32           descriptorBindingPartiallyBound;
-    VkBool32           descriptorBindingVariableDescriptorCount;
-    VkBool32           runtimeDescriptorArray;
-} VkPhysicalDeviceDescriptorIndexingFeaturesEXT;
-
-typedef struct VkPhysicalDeviceDescriptorIndexingPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxUpdateAfterBindDescriptorsInAllPools;
-    VkBool32           shaderUniformBufferArrayNonUniformIndexingNative;
-    VkBool32           shaderSampledImageArrayNonUniformIndexingNative;
-    VkBool32           shaderStorageBufferArrayNonUniformIndexingNative;
-    VkBool32           shaderStorageImageArrayNonUniformIndexingNative;
-    VkBool32           shaderInputAttachmentArrayNonUniformIndexingNative;
-    VkBool32           robustBufferAccessUpdateAfterBind;
-    VkBool32           quadDivergentImplicitLod;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindSamplers;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindUniformBuffers;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindStorageBuffers;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindSampledImages;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindStorageImages;
-    uint32_t           maxPerStageDescriptorUpdateAfterBindInputAttachments;
-    uint32_t           maxPerStageUpdateAfterBindResources;
-    uint32_t           maxDescriptorSetUpdateAfterBindSamplers;
-    uint32_t           maxDescriptorSetUpdateAfterBindUniformBuffers;
-    uint32_t           maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
-    uint32_t           maxDescriptorSetUpdateAfterBindStorageBuffers;
-    uint32_t           maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
-    uint32_t           maxDescriptorSetUpdateAfterBindSampledImages;
-    uint32_t           maxDescriptorSetUpdateAfterBindStorageImages;
-    uint32_t           maxDescriptorSetUpdateAfterBindInputAttachments;
-} VkPhysicalDeviceDescriptorIndexingPropertiesEXT;
-
-typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           descriptorSetCount;
-    const uint32_t*    pDescriptorCounts;
-} VkDescriptorSetVariableDescriptorCountAllocateInfoEXT;
-
-typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxVariableDescriptorCount;
-} VkDescriptorSetVariableDescriptorCountLayoutSupportEXT;
-
-
-
-#define VK_EXT_shader_viewport_index_layer 1
-#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
-#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
-
-
-#define VK_NV_shading_rate_image 1
-#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
-#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
-
-
-typedef enum VkShadingRatePaletteEntryNV {
-    VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
-    VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
-    VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
-    VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
-    VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
-    VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV,
-    VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV,
-    VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1),
-    VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF
-} VkShadingRatePaletteEntryNV;
-
-typedef enum VkCoarseSampleOrderTypeNV {
-    VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
-    VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
-    VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
-    VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
-    VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV,
-    VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV,
-    VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1),
-    VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkCoarseSampleOrderTypeNV;
-
-typedef struct VkShadingRatePaletteNV {
-    uint32_t                              shadingRatePaletteEntryCount;
-    const VkShadingRatePaletteEntryNV*    pShadingRatePaletteEntries;
-} VkShadingRatePaletteNV;
-
-typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkBool32                         shadingRateImageEnable;
-    uint32_t                         viewportCount;
-    const VkShadingRatePaletteNV*    pShadingRatePalettes;
-} VkPipelineViewportShadingRateImageStateCreateInfoNV;
-
-typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           shadingRateImage;
-    VkBool32           shadingRateCoarseSampleOrder;
-} VkPhysicalDeviceShadingRateImageFeaturesNV;
-
-typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkExtent2D         shadingRateTexelSize;
-    uint32_t           shadingRatePaletteSize;
-    uint32_t           shadingRateMaxCoarseSamples;
-} VkPhysicalDeviceShadingRateImagePropertiesNV;
-
-typedef struct VkCoarseSampleLocationNV {
-    uint32_t    pixelX;
-    uint32_t    pixelY;
-    uint32_t    sample;
-} VkCoarseSampleLocationNV;
-
-typedef struct VkCoarseSampleOrderCustomNV {
-    VkShadingRatePaletteEntryNV        shadingRate;
-    uint32_t                           sampleCount;
-    uint32_t                           sampleLocationCount;
-    const VkCoarseSampleLocationNV*    pSampleLocations;
-} VkCoarseSampleOrderCustomNV;
-
-typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkCoarseSampleOrderTypeNV             sampleOrderType;
-    uint32_t                              customSampleOrderCount;
-    const VkCoarseSampleOrderCustomNV*    pCustomSampleOrders;
-} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout);
-typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes);
-typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV(
-    VkCommandBuffer                             commandBuffer,
-    VkImageView                                 imageView,
-    VkImageLayout                               imageLayout);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstViewport,
-    uint32_t                                    viewportCount,
-    const VkShadingRatePaletteNV*               pShadingRatePalettes);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV(
-    VkCommandBuffer                             commandBuffer,
-    VkCoarseSampleOrderTypeNV                   sampleOrderType,
-    uint32_t                                    customSampleOrderCount,
-    const VkCoarseSampleOrderCustomNV*          pCustomSampleOrders);
-#endif
-
-#define VK_NV_ray_tracing 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV)
-
-#define VK_NV_RAY_TRACING_SPEC_VERSION    3
-#define VK_NV_RAY_TRACING_EXTENSION_NAME  "VK_NV_ray_tracing"
-#define VK_SHADER_UNUSED_NV               (~0U)
-
-
-typedef enum VkRayTracingShaderGroupTypeNV {
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1),
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkRayTracingShaderGroupTypeNV;
-
-typedef enum VkGeometryTypeNV {
-    VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
-    VK_GEOMETRY_TYPE_AABBS_NV = 1,
-    VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV,
-    VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV,
-    VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1),
-    VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryTypeNV;
-
-typedef enum VkAccelerationStructureTypeNV {
-    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
-    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
-    VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
-    VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
-    VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1),
-    VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkAccelerationStructureTypeNV;
-
-typedef enum VkCopyAccelerationStructureModeNV {
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1),
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkCopyAccelerationStructureModeNV;
-
-typedef enum VkAccelerationStructureMemoryRequirementsTypeNV {
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1),
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkAccelerationStructureMemoryRequirementsTypeNV;
-
-
-typedef enum VkGeometryFlagBitsNV {
-    VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
-    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002,
-    VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryFlagBitsNV;
-typedef VkFlags VkGeometryFlagsNV;
-
-typedef enum VkGeometryInstanceFlagBitsNV {
-    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
-    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
-    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004,
-    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008,
-    VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryInstanceFlagBitsNV;
-typedef VkFlags VkGeometryInstanceFlagsNV;
-
-typedef enum VkBuildAccelerationStructureFlagBitsNV {
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008,
-    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010,
-    VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkBuildAccelerationStructureFlagBitsNV;
-typedef VkFlags VkBuildAccelerationStructureFlagsNV;
-
-typedef struct VkRayTracingShaderGroupCreateInfoNV {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkRayTracingShaderGroupTypeNV    type;
-    uint32_t                         generalShader;
-    uint32_t                         closestHitShader;
-    uint32_t                         anyHitShader;
-    uint32_t                         intersectionShader;
-} VkRayTracingShaderGroupCreateInfoNV;
-
-typedef struct VkRayTracingPipelineCreateInfoNV {
-    VkStructureType                               sType;
-    const void*                                   pNext;
-    VkPipelineCreateFlags                         flags;
-    uint32_t                                      stageCount;
-    const VkPipelineShaderStageCreateInfo*        pStages;
-    uint32_t                                      groupCount;
-    const VkRayTracingShaderGroupCreateInfoNV*    pGroups;
-    uint32_t                                      maxRecursionDepth;
-    VkPipelineLayout                              layout;
-    VkPipeline                                    basePipelineHandle;
-    int32_t                                       basePipelineIndex;
-} VkRayTracingPipelineCreateInfoNV;
-
-typedef struct VkGeometryTrianglesNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBuffer           vertexData;
-    VkDeviceSize       vertexOffset;
-    uint32_t           vertexCount;
-    VkDeviceSize       vertexStride;
-    VkFormat           vertexFormat;
-    VkBuffer           indexData;
-    VkDeviceSize       indexOffset;
-    uint32_t           indexCount;
-    VkIndexType        indexType;
-    VkBuffer           transformData;
-    VkDeviceSize       transformOffset;
-} VkGeometryTrianglesNV;
-
-typedef struct VkGeometryAABBNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBuffer           aabbData;
-    uint32_t           numAABBs;
-    uint32_t           stride;
-    VkDeviceSize       offset;
-} VkGeometryAABBNV;
-
-typedef struct VkGeometryDataNV {
-    VkGeometryTrianglesNV    triangles;
-    VkGeometryAABBNV         aabbs;
-} VkGeometryDataNV;
-
-typedef struct VkGeometryNV {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkGeometryTypeNV     geometryType;
-    VkGeometryDataNV     geometry;
-    VkGeometryFlagsNV    flags;
-} VkGeometryNV;
-
-typedef struct VkAccelerationStructureInfoNV {
-    VkStructureType                        sType;
-    const void*                            pNext;
-    VkAccelerationStructureTypeNV          type;
-    VkBuildAccelerationStructureFlagsNV    flags;
-    uint32_t                               instanceCount;
-    uint32_t                               geometryCount;
-    const VkGeometryNV*                    pGeometries;
-} VkAccelerationStructureInfoNV;
-
-typedef struct VkAccelerationStructureCreateInfoNV {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkDeviceSize                     compactedSize;
-    VkAccelerationStructureInfoNV    info;
-} VkAccelerationStructureCreateInfoNV;
-
-typedef struct VkBindAccelerationStructureMemoryInfoNV {
-    VkStructureType              sType;
-    const void*                  pNext;
-    VkAccelerationStructureNV    accelerationStructure;
-    VkDeviceMemory               memory;
-    VkDeviceSize                 memoryOffset;
-    uint32_t                     deviceIndexCount;
-    const uint32_t*              pDeviceIndices;
-} VkBindAccelerationStructureMemoryInfoNV;
-
-typedef struct VkWriteDescriptorSetAccelerationStructureNV {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    uint32_t                            accelerationStructureCount;
-    const VkAccelerationStructureNV*    pAccelerationStructures;
-} VkWriteDescriptorSetAccelerationStructureNV;
-
-typedef struct VkAccelerationStructureMemoryRequirementsInfoNV {
-    VkStructureType                                    sType;
-    const void*                                        pNext;
-    VkAccelerationStructureMemoryRequirementsTypeNV    type;
-    VkAccelerationStructureNV                          accelerationStructure;
-} VkAccelerationStructureMemoryRequirementsInfoNV;
-
-typedef struct VkPhysicalDeviceRayTracingPropertiesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           shaderGroupHandleSize;
-    uint32_t           maxRecursionDepth;
-    uint32_t           maxShaderGroupStride;
-    uint32_t           shaderGroupBaseAlignment;
-    uint64_t           maxGeometryCount;
-    uint64_t           maxInstanceCount;
-    uint64_t           maxTriangleCount;
-    uint32_t           maxDescriptorSetAccelerationStructures;
-} VkPhysicalDeviceRayTracingPropertiesNV;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure);
-typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
-typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode);
-typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
-typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
-typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
-typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV(
-    VkDevice                                    device,
-    const VkAccelerationStructureCreateInfoNV*  pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkAccelerationStructureNV*                  pAccelerationStructure);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV(
-    VkDevice                                    device,
-    VkAccelerationStructureNV                   accelerationStructure,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV(
-    VkDevice                                    device,
-    const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
-    VkMemoryRequirements2KHR*                   pMemoryRequirements);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV(
-    VkDevice                                    device,
-    uint32_t                                    bindInfoCount,
-    const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV(
-    VkCommandBuffer                             commandBuffer,
-    const VkAccelerationStructureInfoNV*        pInfo,
-    VkBuffer                                    instanceData,
-    VkDeviceSize                                instanceOffset,
-    VkBool32                                    update,
-    VkAccelerationStructureNV                   dst,
-    VkAccelerationStructureNV                   src,
-    VkBuffer                                    scratch,
-    VkDeviceSize                                scratchOffset);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV(
-    VkCommandBuffer                             commandBuffer,
-    VkAccelerationStructureNV                   dst,
-    VkAccelerationStructureNV                   src,
-    VkCopyAccelerationStructureModeNV           mode);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    raygenShaderBindingTableBuffer,
-    VkDeviceSize                                raygenShaderBindingOffset,
-    VkBuffer                                    missShaderBindingTableBuffer,
-    VkDeviceSize                                missShaderBindingOffset,
-    VkDeviceSize                                missShaderBindingStride,
-    VkBuffer                                    hitShaderBindingTableBuffer,
-    VkDeviceSize                                hitShaderBindingOffset,
-    VkDeviceSize                                hitShaderBindingStride,
-    VkBuffer                                    callableShaderBindingTableBuffer,
-    VkDeviceSize                                callableShaderBindingOffset,
-    VkDeviceSize                                callableShaderBindingStride,
-    uint32_t                                    width,
-    uint32_t                                    height,
-    uint32_t                                    depth);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV(
-    VkDevice                                    device,
-    VkPipelineCache                             pipelineCache,
-    uint32_t                                    createInfoCount,
-    const VkRayTracingPipelineCreateInfoNV*     pCreateInfos,
-    const VkAllocationCallbacks*                pAllocator,
-    VkPipeline*                                 pPipelines);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV(
-    VkDevice                                    device,
-    VkPipeline                                  pipeline,
-    uint32_t                                    firstGroup,
-    uint32_t                                    groupCount,
-    size_t                                      dataSize,
-    void*                                       pData);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV(
-    VkDevice                                    device,
-    VkAccelerationStructureNV                   accelerationStructure,
-    size_t                                      dataSize,
-    void*                                       pData);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    accelerationStructureCount,
-    const VkAccelerationStructureNV*            pAccelerationStructures,
-    VkQueryType                                 queryType,
-    VkQueryPool                                 queryPool,
-    uint32_t                                    firstQuery);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV(
-    VkDevice                                    device,
-    VkPipeline                                  pipeline,
-    uint32_t                                    shader);
-#endif
-
-#define VK_NV_representative_fragment_test 1
-#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
-#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
-
-typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           representativeFragmentTest;
-} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV;
-
-typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           representativeFragmentTestEnable;
-} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
-
-
-
-#define VK_EXT_global_priority 1
-#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2
-#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
-
-
-typedef enum VkQueueGlobalPriorityEXT {
-    VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128,
-    VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256,
-    VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512,
-    VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024,
-    VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT,
-    VK_QUEUE_GLOBAL_PRIORITY_END_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT,
-    VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE_EXT = (VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT + 1),
-    VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkQueueGlobalPriorityEXT;
-
-typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT {
-    VkStructureType             sType;
-    const void*                 pNext;
-    VkQueueGlobalPriorityEXT    globalPriority;
-} VkDeviceQueueGlobalPriorityCreateInfoEXT;
-
-
-
-#define VK_EXT_external_memory_host 1
-#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1
-#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host"
-
-typedef struct VkImportMemoryHostPointerInfoEXT {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagBits    handleType;
-    void*                                 pHostPointer;
-} VkImportMemoryHostPointerInfoEXT;
-
-typedef struct VkMemoryHostPointerPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           memoryTypeBits;
-} VkMemoryHostPointerPropertiesEXT;
-
-typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkDeviceSize       minImportedHostPointerAlignment;
-} VkPhysicalDeviceExternalMemoryHostPropertiesEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT(
-    VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBits          handleType,
-    const void*                                 pHostPointer,
-    VkMemoryHostPointerPropertiesEXT*           pMemoryHostPointerProperties);
-#endif
-
-#define VK_AMD_buffer_marker 1
-#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
-#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
-
-typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD(
-    VkCommandBuffer                             commandBuffer,
-    VkPipelineStageFlagBits                     pipelineStage,
-    VkBuffer                                    dstBuffer,
-    VkDeviceSize                                dstOffset,
-    uint32_t                                    marker);
-#endif
-
-#define VK_EXT_calibrated_timestamps 1
-#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 1
-#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps"
-
-
-typedef enum VkTimeDomainEXT {
-    VK_TIME_DOMAIN_DEVICE_EXT = 0,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2,
-    VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3,
-    VK_TIME_DOMAIN_BEGIN_RANGE_EXT = VK_TIME_DOMAIN_DEVICE_EXT,
-    VK_TIME_DOMAIN_END_RANGE_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT,
-    VK_TIME_DOMAIN_RANGE_SIZE_EXT = (VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT - VK_TIME_DOMAIN_DEVICE_EXT + 1),
-    VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkTimeDomainEXT;
-
-typedef struct VkCalibratedTimestampInfoEXT {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkTimeDomainEXT    timeDomain;
-} VkCalibratedTimestampInfoEXT;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains);
-typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(
-    VkPhysicalDevice                            physicalDevice,
-    uint32_t*                                   pTimeDomainCount,
-    VkTimeDomainEXT*                            pTimeDomains);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT(
-    VkDevice                                    device,
-    uint32_t                                    timestampCount,
-    const VkCalibratedTimestampInfoEXT*         pTimestampInfos,
-    uint64_t*                                   pTimestamps,
-    uint64_t*                                   pMaxDeviation);
-#endif
-
-#define VK_AMD_shader_core_properties 1
-#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
-#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
-
-typedef struct VkPhysicalDeviceShaderCorePropertiesAMD {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           shaderEngineCount;
-    uint32_t           shaderArraysPerEngineCount;
-    uint32_t           computeUnitsPerShaderArray;
-    uint32_t           simdPerComputeUnit;
-    uint32_t           wavefrontsPerSimd;
-    uint32_t           wavefrontSize;
-    uint32_t           sgprsPerSimd;
-    uint32_t           minSgprAllocation;
-    uint32_t           maxSgprAllocation;
-    uint32_t           sgprAllocationGranularity;
-    uint32_t           vgprsPerSimd;
-    uint32_t           minVgprAllocation;
-    uint32_t           maxVgprAllocation;
-    uint32_t           vgprAllocationGranularity;
-} VkPhysicalDeviceShaderCorePropertiesAMD;
-
-
-
-#define VK_AMD_memory_overallocation_behavior 1
-#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
-#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
-
-
-typedef enum VkMemoryOverallocationBehaviorAMD {
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_BEGIN_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_END_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_RANGE_SIZE_AMD = (VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD + 1),
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF
-} VkMemoryOverallocationBehaviorAMD;
-
-typedef struct VkDeviceMemoryOverallocationCreateInfoAMD {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkMemoryOverallocationBehaviorAMD    overallocationBehavior;
-} VkDeviceMemoryOverallocationCreateInfoAMD;
-
-
-
-#define VK_EXT_vertex_attribute_divisor 1
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
-
-typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxVertexAttribDivisor;
-} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;
-
-typedef struct VkVertexInputBindingDivisorDescriptionEXT {
-    uint32_t    binding;
-    uint32_t    divisor;
-} VkVertexInputBindingDivisorDescriptionEXT;
-
-typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT {
-    VkStructureType                                     sType;
-    const void*                                         pNext;
-    uint32_t                                            vertexBindingDivisorCount;
-    const VkVertexInputBindingDivisorDescriptionEXT*    pVertexBindingDivisors;
-} VkPipelineVertexInputDivisorStateCreateInfoEXT;
-
-typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           vertexAttributeInstanceRateDivisor;
-    VkBool32           vertexAttributeInstanceRateZeroDivisor;
-} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
-
-
-
-#define VK_NV_shader_subgroup_partitioned 1
-#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
-#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
-
-
-#define VK_NV_compute_shader_derivatives 1
-#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
-#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
-
-typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           computeDerivativeGroupQuads;
-    VkBool32           computeDerivativeGroupLinear;
-} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV;
-
-
-
-#define VK_NV_mesh_shader 1
-#define VK_NV_MESH_SHADER_SPEC_VERSION    1
-#define VK_NV_MESH_SHADER_EXTENSION_NAME  "VK_NV_mesh_shader"
-
-typedef struct VkPhysicalDeviceMeshShaderFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           taskShader;
-    VkBool32           meshShader;
-} VkPhysicalDeviceMeshShaderFeaturesNV;
-
-typedef struct VkPhysicalDeviceMeshShaderPropertiesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           maxDrawMeshTasksCount;
-    uint32_t           maxTaskWorkGroupInvocations;
-    uint32_t           maxTaskWorkGroupSize[3];
-    uint32_t           maxTaskTotalMemorySize;
-    uint32_t           maxTaskOutputCount;
-    uint32_t           maxMeshWorkGroupInvocations;
-    uint32_t           maxMeshWorkGroupSize[3];
-    uint32_t           maxMeshTotalMemorySize;
-    uint32_t           maxMeshOutputVertices;
-    uint32_t           maxMeshOutputPrimitives;
-    uint32_t           maxMeshMultiviewViewCount;
-    uint32_t           meshOutputPerVertexGranularity;
-    uint32_t           meshOutputPerPrimitiveGranularity;
-} VkPhysicalDeviceMeshShaderPropertiesNV;
-
-typedef struct VkDrawMeshTasksIndirectCommandNV {
-    uint32_t    taskCount;
-    uint32_t    firstTask;
-} VkDrawMeshTasksIndirectCommandNV;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    taskCount,
-    uint32_t                                    firstTask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    uint32_t                                    drawCount,
-    uint32_t                                    stride);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    buffer,
-    VkDeviceSize                                offset,
-    VkBuffer                                    countBuffer,
-    VkDeviceSize                                countBufferOffset,
-    uint32_t                                    maxDrawCount,
-    uint32_t                                    stride);
-#endif
-
-#define VK_NV_fragment_shader_barycentric 1
-#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
-#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
-
-typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           fragmentShaderBarycentric;
-} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV;
-
-
-
-#define VK_NV_shader_image_footprint 1
-#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
-#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
-
-typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           imageFootprint;
-} VkPhysicalDeviceShaderImageFootprintFeaturesNV;
-
-
-
-#define VK_NV_scissor_exclusive 1
-#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
-#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
-
-typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           exclusiveScissorCount;
-    const VkRect2D*    pExclusiveScissors;
-} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
-
-typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           exclusiveScissor;
-} VkPhysicalDeviceExclusiveScissorFeaturesNV;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV(
-    VkCommandBuffer                             commandBuffer,
-    uint32_t                                    firstExclusiveScissor,
-    uint32_t                                    exclusiveScissorCount,
-    const VkRect2D*                             pExclusiveScissors);
-#endif
-
-#define VK_NV_device_diagnostic_checkpoints 1
-#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
-#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
-
-typedef struct VkQueueFamilyCheckpointPropertiesNV {
-    VkStructureType         sType;
-    void*                   pNext;
-    VkPipelineStageFlags    checkpointExecutionStageMask;
-} VkQueueFamilyCheckpointPropertiesNV;
-
-typedef struct VkCheckpointDataNV {
-    VkStructureType            sType;
-    void*                      pNext;
-    VkPipelineStageFlagBits    stage;
-    void*                      pCheckpointMarker;
-} VkCheckpointDataNV;
-
-
-typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker);
-typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV(
-    VkCommandBuffer                             commandBuffer,
-    const void*                                 pCheckpointMarker);
-
-VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV(
-    VkQueue                                     queue,
-    uint32_t*                                   pCheckpointDataCount,
-    VkCheckpointDataNV*                         pCheckpointData);
-#endif
-
-#define VK_EXT_pci_bus_info 1
-#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION  2
-#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info"
-
-typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           pciDomain;
-    uint32_t           pciBus;
-    uint32_t           pciDevice;
-    uint32_t           pciFunction;
-} VkPhysicalDevicePCIBusInfoPropertiesEXT;
-
-
-
-#define VK_EXT_fragment_density_map 1
-#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
-#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
-
-typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           fragmentDensityMap;
-    VkBool32           fragmentDensityMapDynamic;
-    VkBool32           fragmentDensityMapNonSubsampledImages;
-} VkPhysicalDeviceFragmentDensityMapFeaturesEXT;
-
-typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkExtent2D         minFragmentDensityTexelSize;
-    VkExtent2D         maxFragmentDensityTexelSize;
-    VkBool32           fragmentDensityInvocations;
-} VkPhysicalDeviceFragmentDensityMapPropertiesEXT;
-
-typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT {
-    VkStructureType          sType;
-    const void*              pNext;
-    VkAttachmentReference    fragmentDensityMapAttachment;
-} VkRenderPassFragmentDensityMapCreateInfoEXT;
-
-
-
-#define VK_EXT_scalar_block_layout 1
-#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
-#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
-
-typedef struct VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
-    VkStructureType    sType;
-    void*              pNext;
-    VkBool32           scalarBlockLayout;
-} VkPhysicalDeviceScalarBlockLayoutFeaturesEXT;
-
-
-
-#define VK_GOOGLE_hlsl_functionality1 1
-#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
-#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
-
-
-#define VK_GOOGLE_decorate_string 1
-#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
-#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
-
-
-#define VK_EXT_separate_stencil_usage 1
-#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
-#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
-
-typedef struct VkImageStencilUsageCreateInfoEXT {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkImageUsageFlags    stencilUsage;
-} VkImageStencilUsageCreateInfoEXT;
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 71a120a..993b751 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Headers module is in frameworks/native/vulkan/Android.bp.
+// Headers module is in external/vulkan-headers/Android.bp.
 ndk_library {
     name: "libvulkan",
     symbol_file: "libvulkan.map.txt",
@@ -20,6 +20,14 @@
     unversioned_until: "current",
 }
 
+llndk_library {
+    name: "libvulkan",
+    symbol_file: "libvulkan.map.txt",
+    export_llndk_headers: [
+        "vulkan_headers_llndk",
+    ],
+}
+
 cc_library_shared {
     name: "libvulkan",
     clang: true,
@@ -65,10 +73,11 @@
         "swapchain.cpp",
     ],
 
-    export_header_lib_headers: ["vulkan_headers"],
     header_libs: [
+        "hwvulkan_headers",
         "vulkan_headers",
     ],
+    export_header_lib_headers: ["vulkan_headers"],
     shared_libs: [
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 71048db..368130d 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -664,6 +664,12 @@
         return VK_ERROR_LAYER_NOT_PRESENT;
     }
 
+    if (!layer.ref.GetGetInstanceProcAddr()) {
+        ALOGW("Failed to locate vkGetInstanceProcAddr in layer %s", name);
+        layer.ref.~LayerRef();
+        return VK_ERROR_LAYER_NOT_PRESENT;
+    }
+
     ALOGI("Loaded layer %s", name);
 
     return VK_SUCCESS;
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index df86af0..37b5368 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
 #include "api.h"
@@ -55,6 +54,11 @@
 
 // clang-format off
 
+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;
+}
+
 VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR, const VkAllocationCallbacks*) {
     driver::Logger(instance).Err(instance, "VK_KHR_surface not enabled. Exported vkDestroySurfaceKHR not executed.");
 }
@@ -113,18 +117,13 @@
     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.");
+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;
 }
 
@@ -162,7 +161,12 @@
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
     INIT_PROC(true, instance, GetPhysicalDeviceSparseImageFormatProperties);
-    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+    INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
+    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(false, instance, GetPhysicalDeviceFeatures2);
     INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC(false, instance, GetPhysicalDeviceFormatProperties2);
@@ -171,15 +175,10 @@
     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(false, instance, GetPhysicalDeviceExternalFenceProperties);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
     INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR);
-    INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
     // clang-format on
 
     return success;
@@ -314,32 +313,32 @@
     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(false, dev, TrimCommandPool);
+    INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
+    INIT_PROC(false, dev, BindBufferMemory2);
+    INIT_PROC(false, dev, BindImageMemory2);
+    INIT_PROC(false, dev, CmdSetDeviceMask);
     INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR);
     INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR);
     INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR);
-    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, false, dev, GetAndroidHardwareBufferPropertiesANDROID);
-    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, false, dev, GetMemoryAndroidHardwareBufferANDROID);
+    INIT_PROC(false, dev, CmdDispatchBase);
+    INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
+    INIT_PROC(false, dev, GetBufferMemoryRequirements2);
+    INIT_PROC(false, dev, GetImageMemoryRequirements2);
+    INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
+    INIT_PROC(false, dev, CreateSamplerYcbcrConversion);
+    INIT_PROC(false, dev, DestroySamplerYcbcrConversion);
+    INIT_PROC(false, dev, GetDeviceQueue2);
+    INIT_PROC(false, dev, GetDescriptorSetLayoutSupport);
+    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, true, dev, GetAndroidHardwareBufferPropertiesANDROID);
+    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, true, dev, GetMemoryAndroidHardwareBufferANDROID);
     // clang-format on
 
     return success;
@@ -479,33 +478,7 @@
 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 VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
 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);
@@ -516,11 +489,37 @@
 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 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 GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+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 CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
 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 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 GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+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 GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+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 void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
 VKAPI_ATTR VkResult GetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
 VKAPI_ATTR VkResult GetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
 
@@ -622,9 +621,9 @@
     // global functions
     if (instance == VK_NULL_HANDLE) {
         if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+        if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
         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;
@@ -1313,112 +1312,8 @@
     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 VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+    return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
 
 VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
@@ -1461,6 +1356,70 @@
     return GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
 }
 
+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 GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return GetData(instance).dispatch.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+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 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 CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    GetData(commandBuffer).dispatch.CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
 VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     return GetData(device).dispatch.GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
 }
@@ -1469,16 +1428,56 @@
     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);
+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 GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return GetData(physicalDevice).dispatch.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+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 GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetImageMemoryRequirements2(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 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 void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    GetData(device).dispatch.GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    GetData(device).dispatch.GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
 }
 
 VKAPI_ATTR VkResult GetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
@@ -1565,6 +1564,11 @@
 }
 
 __attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
+    return vulkan::api::EnumerateInstanceVersion(pApiVersion);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
     return vulkan::api::EnumerateInstanceLayerProperties(pPropertyCount, pProperties);
 }
@@ -2185,143 +2189,8 @@
 }
 
 __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);
+VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+    return vulkan::api::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
 
 __attribute__((visibility("default")))
@@ -2375,6 +2244,86 @@
 }
 
 __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 vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    vulkan::api::GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+__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 vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    vulkan::api::GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+__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 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 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 vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    vulkan::api::CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     return vulkan::api::GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
 }
@@ -2385,18 +2334,68 @@
 }
 
 __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);
+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 vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return vulkan::api::GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+__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 vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__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 vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+    vulkan::api::GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__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 void vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    vulkan::api::GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    vulkan::api::GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
 }
 
 __attribute__((visibility("default")))
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 4bedbeb..2195845 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -20,7 +20,9 @@
 #define LIBVULKAN_API_GEN_H
 
 #include <vulkan/vulkan.h>
+
 #include <bitset>
+
 #include "driver_gen.h"
 
 namespace vulkan {
@@ -40,7 +42,12 @@
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
-    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+    PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+    PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+    PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
     PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
     PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
@@ -49,15 +56,10 @@
     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_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
     PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
-    PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
     // clang-format on
 };
 
@@ -184,30 +186,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_vkTrimCommandPool TrimCommandPool;
+    PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
+    PFN_vkBindBufferMemory2 BindBufferMemory2;
+    PFN_vkBindImageMemory2 BindImageMemory2;
+    PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
     PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR;
     PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
     PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR;
+    PFN_vkCmdDispatchBase CmdDispatchBase;
+    PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
+    PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
+    PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+    PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
+    PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
+    PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
+    PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
+    PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
+    PFN_vkGetDeviceQueue2 GetDeviceQueue2;
+    PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
     PFN_vkGetAndroidHardwareBufferPropertiesANDROID GetAndroidHardwareBufferPropertiesANDROID;
     PFN_vkGetMemoryAndroidHardwareBufferANDROID GetMemoryAndroidHardwareBufferANDROID;
     // clang-format on
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
deleted file mode 100644
index f04eb03..0000000
--- a/vulkan/libvulkan/code-generator.tmpl
+++ /dev/null
@@ -1,1188 +0,0 @@
-{{define "Copyright"}}
-/*
-•* Copyright 2016 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•*      http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/
-¶{{end}}
-
-{{Include "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "api_gen.h"   | Format (Global "clang-format") | Write "api_gen.h"  }}
-{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
-{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
-{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
-
-{{/*
--------------------------------------------------------------------------------
-  api_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "api_gen.h"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef LIBVULKAN_API_GEN_H
-#define LIBVULKAN_API_GEN_H

-#include <bitset>
-#include <vulkan/vulkan.h>
-#include "driver_gen.h"

-namespace vulkan {«
-namespace api {«

-struct InstanceDispatchTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-struct DeviceDispatchTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-bool InitDispatchTable(
-    VkInstance instance,
-    PFN_vkGetInstanceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
-bool InitDispatchTable(
-    VkDevice dev,
-    PFN_vkGetDeviceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);

-»} // namespace api
-»} // namespace vulkan

-#endif // LIBVULKAN_API_GEN_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  api_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "api_gen.cpp"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#include <string.h>

-#include <algorithm>

-#include <log/log.h>

-// to catch mismatches between vulkan.h and this file
-#undef VK_NO_PROTOTYPES
-#include "api.h"

-namespace vulkan {«
-namespace api {«

-{{Macro "C++.DefineInitProcMacro" "dispatch"}}

-{{Macro "api.C++.DefineInitProcExtMacro"}}

-namespace {«

-// clang-format off

-{{range $f := AllCommands $}}
-  {{Macro "api.C++.DefineExtensionStub" $f}}
-{{end}}
-// clang-format on

-»} // anonymous

-bool InitDispatchTable(
-    VkInstance instance,
-    PFN_vkGetInstanceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
-    auto& data = GetData(instance);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-bool InitDispatchTable(
-    VkDevice dev,
-    PFN_vkGetDeviceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
-    auto& data = GetData(dev);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-// clang-format off

-namespace {«

-// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
-{{range $f := AllCommands $}}
-  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
-    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
-  {{end}}
-{{end}}

-{{range $f := AllCommands $}}
-  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
-    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}}) {
-      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
-        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
-      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
-        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
-      {{end}}
-
-      {{Macro "api.C++.Dispatch" $f}}
-    }
-    ¶
-  {{end}}
-{{end}}

-»}  // anonymous namespace

-// clang-format on

-»} // namespace api
-»} // namespace vulkan

-// clang-format off

-{{range $f := AllCommands $}}
-  {{if (Macro "IsFunctionExported" $f)}}
-    __attribute__((visibility("default")))
-    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
-      {{if not (IsVoid $f.Return.Type)}}return §{{end}}
-      vulkan::api::{{Macro "BaseName" $f}}({{Macro "Arguments" $f}});
-    }
-    ¶
-  {{end}}
-{{end}}

-// clang-format on
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  driver_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "driver_gen.h"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef LIBVULKAN_DRIVER_GEN_H
-#define LIBVULKAN_DRIVER_GEN_H

-#include <bitset>
-#include <vulkan/vulkan.h>
-#include <vulkan/vk_android_native_buffer.h>

-namespace vulkan {«
-namespace driver {«

-{{Macro "driver.C++.DefineProcHookType"}}

-struct InstanceDriverTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-struct DeviceDriverTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-const ProcHook* GetProcHook(const char* name);
-ProcHook::Extension GetProcHookExtension(const char* name);

-bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
-bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);

-»} // namespace driver
-»} // namespace vulkan

-#endif // LIBVULKAN_DRIVER_TABLE_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  driver_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "driver_gen.cpp"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#include <string.h>

-#include <algorithm>

-#include <log/log.h>

-#include "driver.h"

-namespace vulkan {«
-namespace driver {«

-namespace {«

-// clang-format off

-{{range $f := AllCommands $}}
-  {{Macro "driver.C++.DefineProcHookStub" $f}}
-{{end}}
-// clang-format on

-const ProcHook g_proc_hooks[] = {
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if (Macro "driver.IsIntercepted" $f)}}
-      {{     if (Macro "IsGloballyDispatched" $f)}}
-        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
-      {{else if (Macro "IsInstanceDispatched" $f)}}
-        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
-      {{else if (Macro "IsDeviceDispatched" $f)}}
-        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
-      {{end}}
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-»} // anonymous

-const ProcHook* GetProcHook(const char* name) {
-    const auto& begin = g_proc_hooks;
-    const auto& end = g_proc_hooks +
-      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
-    const auto hook = std::lower_bound(begin, end, name,
-        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
-    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
-}

-ProcHook::Extension GetProcHookExtension(const char* name) {
-  {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
-  // clang-format off
-  {{range $e := $exts}}
-    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
-  {{end}}
-  // clang-format on
-  return ProcHook::EXTENSION_UNKNOWN;
-}

-{{Macro "C++.DefineInitProcMacro" "driver"}}

-{{Macro "driver.C++.DefineInitProcExtMacro"}}

-bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
-{
-    auto& data = GetData(instance);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
-{
-    auto& data = GetData(dev);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-»} // namespace driver
-»} // namespace vulkan

-// clang-format on
-¶{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a declaration of a dispatch/driver table entry.
-------------------------------------------------------------------------------
-*/}}
-{{define "C++.DeclareTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC macro.
--------------------------------------------------------------------------------
-*/}}
-{{define "C++.DefineInitProcMacro"}}
-  #define UNLIKELY(expr) __builtin_expect((expr), 0)
-  ¶
-  #define INIT_PROC(required, obj, proc) do {                   \
-      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
-              get_proc(obj, "vk" # proc));                      \
-      if (UNLIKELY(required && !data.{{$}}.proc)) {             \
-          ALOGE("missing " # obj " proc: vk" # proc);           \
-          success = false;                                      \
-      }                                                         \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
--------------------------------------------------------------------------------
-*/}}
-{{define "C++.InitProc"}}
-  {{AssertType $ "Function"}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if $ext}}
-    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
-  {{else}}
-    INIT_PROC(§
-  {{end}}
-
-  {{if GetAnnotation $ "optional"}}false{{else if GetAnnotation $ "vulkan1_1"}}false{{else}}true{{end}}, §
-
-  {{if (Macro "IsInstanceDispatched" $)}}
-    instance, §
-  {{else}}
-    dev, §
-  {{end}}
-
-  {{Macro "BaseName" $}});
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is exported and instance-dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.IsInstanceDispatchTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
-    {{/* deprecated and unused internally */}}
-    {{if not (eq $.Name "vkEnumerateDeviceLayerProperties")}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is exported and device-dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.IsDeviceDispatchTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is intercepted by vulkan::api.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.IsIntercepted"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* Global functions cannot be dispatched at all */}}
-    {{     if (Macro "IsGloballyDispatched" $)}}true
-
-    {{/* VkPhysicalDevice functions that manage device layers */}}
-    {{else if eq $.Name "vkCreateDevice"}}true
-    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{/* Destroy functions of dispatchable objects */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC_EXT macro for vulkan::api.
--------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.DefineInitProcExtMacro"}}
-  // Exported extension functions may be invoked even when their extensions
-  // are disabled.  Dispatch to stubs when that happens.
-  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
-      if (extensions[driver::ProcHook::ext])                    \
-        INIT_PROC(required, obj, proc);                         \
-      else                                                      \
-        data.dispatch.proc = disabled ## proc;                  \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a stub for an exported extension function.
--------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.DefineExtensionStub"}}
-  {{AssertType $ "Function"}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if and $ext (Macro "IsFunctionExported" $)}}
-    {{$ext_name := index $ext.Arguments 0}}
-
-    {{$base := (Macro "BaseName" $)}}
-
-    {{$p0 := (index $.CallParameters 0)}}
-    {{$ptail := (Tail 1 $.CallParameters)}}
-
-    {{$first_type := (Macro "Parameter" $p0)}}
-    {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}}
-
-    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) {
-      driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, §
-        "{{$ext_name}} not enabled. Exported {{$.Name}} not executed.");
-      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
-    }
-    ¶
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits code for vkGetInstanceProcAddr for function interception.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.InterceptInstanceProcAddr"}}
-  {{AssertType $ "API"}}
-
-  // global functions
-  if (instance == VK_NULL_HANDLE) {
-    {{range $f := AllCommands $}}
-      {{if (Macro "IsGloballyDispatched" $f)}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}});
-      {{end}}
-    {{end}}
-    ¶
-    ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
-    return nullptr;
-  }
-  ¶
-  static const struct Hook {
-    const char* name;
-    PFN_vkVoidFunction proc;
-  } hooks[] = {
-    {{range $f := SortBy (AllCommands $) "FunctionName"}}
-      {{if (Macro "IsFunctionExported" $f)}}
-        {{/* hide global functions */}}
-        {{if (Macro "IsGloballyDispatched" $f)}}
-          { "{{$f.Name}}", nullptr },
-
-        {{/* redirect intercepted functions */}}
-        {{else if (Macro "api.IsIntercepted" $f)}}
-          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
-            {{Macro "BaseName" $f}}) },
-
-        {{/* redirect vkGetInstanceProcAddr to itself */}}
-        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
-          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
-
-        {{/* redirect device functions to themselves as a workaround for
-             layers that do not intercept in their vkGetInstanceProcAddr */}}
-        {{else if (Macro "IsDeviceDispatched" $f)}}
-          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
-
-        {{end}}
-      {{end}}
-    {{end}}
-  };
-  // clang-format on
-  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
-  auto hook = std::lower_bound(
-    hooks, hooks + count, pName,
-    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
-  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
-    if (!hook->proc) {
-      vulkan::driver::Logger(instance).Err(
-        instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call",
-        instance, pName);
-    }
-    return hook->proc;
-  }
-  // clang-format off
-  ¶
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits code for vkGetDeviceProcAddr for function interception.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.InterceptDeviceProcAddr"}}
-  {{AssertType $ "API"}}
-
-  if (device == VK_NULL_HANDLE) {
-    ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
-    return nullptr;
-  }
-  ¶
-  static const char* const known_non_device_names[] = {
-    {{range $f := SortBy (AllCommands $) "FunctionName"}}
-      {{if (Macro "IsFunctionSupported" $f)}}
-        {{if not (Macro "IsDeviceDispatched" $f)}}
-          "{{$f.Name}}",
-        {{end}}
-      {{end}}
-    {{end}}
-  };
-  // clang-format on
-  constexpr size_t count = sizeof(known_non_device_names) /
-    sizeof(known_non_device_names[0]);
-  if (!pName ||
-      std::binary_search(
-        known_non_device_names, known_non_device_names + count, pName,
-        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
-    vulkan::driver::Logger(device).Err(§
-      device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,§
-      (pName) ? pName : "(null)");
-    return nullptr;
-  }
-  // clang-format off
-  ¶
-  {{range $f := AllCommands $}}
-    {{if (Macro "IsDeviceDispatched" $f)}}
-      {{     if (Macro "api.IsIntercepted" $f)}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>(§
-            {{Macro "BaseName" $f}});
-      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>(§
-            {{Macro "BaseName" $f}});
-      {{end}}
-    {{end}}
-  {{end}}
-  ¶
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits code to dispatch a function.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.Dispatch"}}
-  {{AssertType $ "Function"}}
-  {{if (Macro "api.IsIntercepted" $)}}
-    {{Error "$.Name should not be generated"}}
-  {{end}}
-
-  {{if not (IsVoid $.Return.Type)}}return §{{end}}
-
-  {{$p0 := index $.CallParameters 0}}
-  GetData({{$p0.Name}}).dispatch.§
-  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a list of extensions intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.InterceptedExtensions"}}
-VK_ANDROID_native_buffer
-VK_EXT_debug_report
-VK_EXT_hdr_metadata
-VK_EXT_swapchain_colorspace
-VK_GOOGLE_display_timing
-VK_KHR_android_surface
-VK_KHR_incremental_present
-VK_KHR_shared_presentable_image
-VK_KHR_surface
-VK_KHR_swapchain
-VK_KHR_get_surface_capabilities2
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a list of extensions known to vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.KnownExtensions"}}
-{{Macro "driver.InterceptedExtensions"}}
-VK_KHR_get_physical_device_properties2
-VK_ANDROID_external_memory_android_hardware_buffer
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if an extension is intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsExtensionIntercepted"}}
-  {{$ext_name := index $.Arguments 0}}
-  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
-
-  {{range $f := $filters}}
-    {{if eq $ext_name $f}}true{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsIntercepted"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* Create functions of dispatchable objects */}}
-    {{     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 */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{/* Enumeration of extensions */}}
-    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
-    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
-
-    {{end}}
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "driver.IsExtensionIntercepted" $ext}}
-    {{end}}
-
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function needs a ProcHook stub.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.NeedProcHookStub"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of struct ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineProcHookType"}}
-  struct ProcHook {
-      enum Type {
-        GLOBAL,
-        INSTANCE,
-        DEVICE,
-      };
-
-      enum Extension {
-        {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
-        {{range $e := $exts}}
-          {{TrimPrefix "VK_" $e}},
-        {{end}}
-        ¶
-        EXTENSION_CORE, // valid bit
-        EXTENSION_COUNT,
-        EXTENSION_UNKNOWN,
-      };
-      ¶
-      const char* name;
-      Type type;
-      Extension extension;
-      ¶
-      PFN_vkVoidFunction proc;
-      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
-  };
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC_EXT macro for vulkan::driver.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineInitProcExtMacro"}}
-  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
-      if (extensions[ProcHook::ext])                            \
-        INIT_PROC(required, obj, proc);                         \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a stub for ProcHook::checked_proc.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineProcHookStub"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "driver.NeedProcHookStub" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{$ext_name := index $ext.Arguments 0}}
-
-    {{$base := (Macro "BaseName" $)}}
-
-    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
-      {{$p0 := index $.CallParameters 0}}
-      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
-
-      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
-        {{if not (IsVoid $.Return.Type)}}return §{{end}}
-        {{$base}}({{Macro "Arguments" $}});
-      } else {
-        Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
-        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
-      }
-    }
-    ¶
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of a global ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineGlobalProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if $ext}}
-    {{Error "invalid global extension"}}
-  {{end}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::GLOBAL,
-    ProcHook::EXTENSION_CORE,
-    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-    nullptr,
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of an instance ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineInstanceProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::INSTANCE,
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      ProcHook::{{Macro "BaseName" $ext}},
-
-      {{if (Macro "IsExtensionInternal" $ext)}}
-        nullptr,
-        nullptr,
-      {{else}}
-        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-        nullptr,
-      {{end}}
-    {{else}}
-      ProcHook::EXTENSION_CORE,
-      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-      nullptr,
-    {{end}}
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of a device ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineDeviceProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::DEVICE,
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      ProcHook::{{Macro "BaseName" $ext}},
-
-      {{if (Macro "IsExtensionInternal" $ext)}}
-        nullptr,
-        nullptr,
-      {{else}}
-        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
-      {{end}}
-    {{else}}
-      ProcHook::EXTENSION_CORE,
-      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-      nullptr,
-    {{end}}
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits true if a function is needed by vulkan::driver.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* 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 */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{/* Enumeration of extensions */}}
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{/* 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
-
-    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
-    {{else if eq $.Name "vkCreateImage"}}true
-    {{else if eq $.Name "vkDestroyImage"}}true
-
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties2"}}true
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
-    {{end}}
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{$ext_name := index $ext.Arguments 0}}
-      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
-      {{else if eq $ext_name "VK_EXT_debug_report"}}true
-      {{end}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if an instance-dispatched function is needed by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsInstanceDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a device-dispatched function is needed by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsDeviceDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a function/extension name without the "vk"/"VK_" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
-  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
-  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
-  {{else}}{{Error "invalid use of BaseName"}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C parameter names for the given command.
--------------------------------------------------------------------------------
-*/}}
-{{define "Arguments"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-*/}}
-{{define "IsGloballyDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" for supported functions that undergo table dispatch. Only global
-  functions and functions handled in the loader top without calling into
-  lower layers are not dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsInstanceDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" for supported functions that can have device-specific dispatch.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDeviceDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" if a function is core or from a supportable extension.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionSupported"}}
-  {{AssertType $ "Function"}}
-  {{if not (GetAnnotation $ "pfn")}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if not $ext}}true
-    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Decides whether a function should be exported from the Android Vulkan
-  library. Functions in the core API and in loader extensions are exported.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionExported"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "IsExtensionExported" $ext}}
-    {{else}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" if an extension is unsupportable on Android.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionBlacklisted"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_KHR_display"}}true
-  {{else if eq $ext "VK_KHR_display_swapchain"}}true
-  {{else if eq $ext "VK_KHR_mir_surface"}}true
-  {{else if eq $ext "VK_KHR_xcb_surface"}}true
-  {{else if eq $ext "VK_KHR_xlib_surface"}}true
-  {{else if eq $ext "VK_KHR_wayland_surface"}}true
-  {{else if eq $ext "VK_KHR_win32_surface"}}true
-  {{else if eq $ext "VK_KHR_external_memory_win32"}}true
-  {{else if eq $ext "VK_KHR_win32_keyed_mutex"}}true
-  {{else if eq $ext "VK_KHR_external_semaphore_win32"}}true
-  {{else if eq $ext "VK_KHR_external_fence_win32"}}true
-  {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
-  {{else if eq $ext "VK_EXT_direct_mode_display"}}true
-  {{else if eq $ext "VK_EXT_display_surface_counter"}}true
-  {{else if eq $ext "VK_EXT_display_control"}}true
-  {{else if eq $ext "VK_FUCHSIA_imagepipe_surface"}}true
-  {{else if eq $ext "VK_MVK_ios_surface"}}true
-  {{else if eq $ext "VK_MVK_macos_surface"}}true
-  {{else if eq $ext "VK_NN_vi_surface"}}true
-  {{else if eq $ext "VK_NV_external_memory_win32"}}true
-  {{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension has functions exported by the loader.
-  E.g. applications can directly link to an extension function.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionExported"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_KHR_surface"}}true
-  {{else if eq $ext "VK_KHR_swapchain"}}true
-  {{else if eq $ext "VK_KHR_android_surface"}}true
-  {{else if eq $ext "VK_ANDROID_external_memory_android_hardware_buffer"}}true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension is internal to the loader and drivers,
-  so the loader should not enumerate it.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionInternal"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
-  {{end}}
-{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b3259de..f596086 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -16,30 +16,29 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include "driver.h"
+
+#include <dlfcn.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/prctl.h>
-
-#include <dlfcn.h>
-#include <algorithm>
-#include <array>
-#include <new>
-
-#include <log/log.h>
 
 #include <android/dlext.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android-base/properties.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
+#include <log/log.h>
+#include <sys/prctl.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
-#include "android-base/properties.h"
+#include <algorithm>
+#include <array>
+#include <new>
+#include <vector>
 
-#include "driver.h"
 #include "stubhal.h"
 
 using namespace android::hardware::configstore;
@@ -212,7 +211,7 @@
     if (!ns)
         return -ENOENT;
     android::GraphicsEnv::getInstance().setDriverToLoad(
-        android::GraphicsEnv::Driver::VULKAN);
+        android::GpuStatsInfo::Driver::VULKAN);
     return LoadDriver(ns, module);
 }
 
@@ -223,7 +222,7 @@
     if (!ns)
         return -ENOENT;
     android::GraphicsEnv::getInstance().setDriverToLoad(
-        android::GraphicsEnv::Driver::VULKAN_UPDATED);
+        android::GpuStatsInfo::Driver::VULKAN_UPDATED);
     return LoadDriver(ns, module);
 }
 
@@ -258,7 +257,7 @@
     }
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
-            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
+            android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
@@ -272,7 +271,7 @@
     ATRACE_END();
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
-            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
+            android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
         // Any device with a Vulkan HAL should be able to open the device.
         ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
               result);
@@ -284,7 +283,7 @@
     hal_.InitDebugReportIndex();
 
     android::GraphicsEnv::getInstance().setDriverLoaded(
-        android::GraphicsEnv::Api::API_VK, true, systemTime() - openTime);
+        android::GpuStatsInfo::Api::API_VK, true, systemTime() - openTime);
 
     return true;
 }
@@ -537,6 +536,7 @@
                 // Extensions we don't need to do anything about at this level
                 break;
 
+            case ProcHook::KHR_bind_memory2:
             case ProcHook::KHR_incremental_present:
             case ProcHook::KHR_shared_presentable_image:
             case ProcHook::KHR_swapchain:
@@ -577,6 +577,7 @@
                 // return now as these extensions do not require HAL support
                 return;
             case ProcHook::EXT_hdr_metadata:
+            case ProcHook::KHR_bind_memory2:
                 hook_extensions_.set(ext_bit);
                 break;
             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
@@ -807,8 +808,7 @@
     const char* pLayerName,
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
-
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_SURFACE_EXTENSION_NAME,
         VK_KHR_SURFACE_SPEC_VERSION});
@@ -831,7 +831,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -877,8 +877,7 @@
 
 bool QueryPresentationProperties(
     VkPhysicalDevice physicalDevice,
-    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
-{
+    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) {
     const InstanceData& data = GetData(physicalDevice);
 
     // GPDP2 must be present and enabled on the instance.
@@ -918,7 +917,7 @@
     VkExtensionProperties* pProperties) {
     const InstanceData& data = GetData(physicalDevice);
     // extensions that are unconditionally exposed by the loader
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
@@ -954,7 +953,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -981,7 +980,12 @@
 
             memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
                    sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
-            prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+
+            if (prop.specVersion >= 8) {
+                prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+            } else {
+                prop.specVersion = 68;
+            }
         }
     }
 
@@ -1167,6 +1171,12 @@
                                                      &properties);
     ATRACE_END();
 
+    if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
+        // Log that the app is hitting software Vulkan implementation
+        android::GraphicsEnv::getInstance().setTargetStats(
+            android::GpuStatsInfo::Stats::CPU_VULKAN_IN_USE);
+    }
+
     data->driver_device = dev;
     data->driver_version = properties.driverVersion;
 
@@ -1233,11 +1243,10 @@
         if (!device_count)
             return VK_INCOMPLETE;
 
-        android::Vector<VkPhysicalDevice> devices;
-        devices.resize(device_count);
+        std::vector<VkPhysicalDevice> devices(device_count);
         *pPhysicalDeviceGroupCount = device_count;
-        result = EnumeratePhysicalDevices(instance, &device_count,
-                                          devices.editArray());
+        result =
+            EnumeratePhysicalDevices(instance, &device_count, devices.data());
         if (result < 0)
             return result;
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index ec98b9f..3495861 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 #include "driver.h"
 
 namespace vulkan {
@@ -75,6 +74,15 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
+        return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
+    } else {
+        Logger(device).Err(device, "VK_KHR_bind_memory2 not enabled. vkBindImageMemory2KHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 VKAPI_ATTR VkResult checkedGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
         return GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
@@ -102,6 +110,23 @@
     }
 }
 
+VKAPI_ATTR void checkedSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) {
+    if (GetData(device).hook_extensions[ProcHook::EXT_hdr_metadata]) {
+        SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata);
+    } else {
+        Logger(device).Err(device, "VK_EXT_hdr_metadata not enabled. vkSetHdrMetadataEXT not executed.");
+    }
+}
+
+VKAPI_ATTR VkResult checkedGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_shared_presentable_image]) {
+        return GetSwapchainStatusKHR(device, swapchain);
+    } else {
+        Logger(device).Err(device, "VK_KHR_shared_presentable_image not enabled. vkGetSwapchainStatusKHR 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);
@@ -120,23 +145,6 @@
     }
 }
 
-VKAPI_ATTR void checkedSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) {
-    if (GetData(device).hook_extensions[ProcHook::EXT_hdr_metadata]) {
-        SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata);
-    } else {
-        Logger(device).Err(device, "VK_EXT_hdr_metadata not enabled. vkSetHdrMetadataEXT not executed.");
-    }
-}
-
-VKAPI_ATTR VkResult checkedGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) {
-    if (GetData(device).hook_extensions[ProcHook::KHR_shared_presentable_image]) {
-        return GetSwapchainStatusKHR(device, swapchain);
-    } else {
-        Logger(device).Err(device, "VK_KHR_shared_presentable_image not enabled. vkGetSwapchainStatusKHR not executed.");
-        return VK_SUCCESS;
-    }
-}
-
 // clang-format on
 
 const ProcHook g_proc_hooks[] = {
@@ -170,6 +178,20 @@
         nullptr,
     },
     {
+        "vkBindImageMemory2",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
+        nullptr,
+    },
+    {
+        "vkBindImageMemory2KHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_bind_memory2,
+        reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2KHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2KHR),
+    },
+    {
         "vkCreateAndroidSurfaceKHR",
         ProcHook::INSTANCE,
         ProcHook::KHR_android_surface,
@@ -458,6 +480,7 @@
     if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
     if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
     if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
+    if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
     // clang-format on
     return ProcHook::EXTENSION_UNKNOWN;
 }
@@ -493,12 +516,12 @@
     INIT_PROC(true, instance, GetPhysicalDeviceProperties);
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
-    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
-    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     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);
+    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceProperties2KHR);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
     // clang-format on
 
     return success;
@@ -517,11 +540,13 @@
     INIT_PROC(true, dev, CreateImage);
     INIT_PROC(true, dev, DestroyImage);
     INIT_PROC(true, dev, AllocateCommandBuffers);
+    INIT_PROC(false, dev, BindImageMemory2);
+    INIT_PROC_EXT(KHR_bind_memory2, true, dev, BindImageMemory2KHR);
     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);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, QueueSignalReleaseImageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
     // clang-format on
 
     return success;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 14c3aba..79f070c 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -21,6 +21,7 @@
 
 #include <vulkan/vk_android_native_buffer.h>
 #include <vulkan/vulkan.h>
+
 #include <bitset>
 
 namespace vulkan {
@@ -46,6 +47,7 @@
         KHR_get_surface_capabilities2,
         KHR_get_physical_device_properties2,
         ANDROID_external_memory_android_hardware_buffer,
+        KHR_bind_memory2,
 
         EXTENSION_CORE,  // valid bit
         EXTENSION_COUNT,
@@ -68,12 +70,12 @@
     PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
-    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
-    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
     PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
     PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
     // clang-format on
 };
 
@@ -85,11 +87,13 @@
     PFN_vkCreateImage CreateImage;
     PFN_vkDestroyImage DestroyImage;
     PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+    PFN_vkBindImageMemory2 BindImageMemory2;
+    PFN_vkBindImageMemory2KHR BindImageMemory2KHR;
     PFN_vkGetDeviceQueue2 GetDeviceQueue2;
     PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
-    PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     PFN_vkAcquireImageANDROID AcquireImageANDROID;
     PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
+    PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     // clang-format on
 };
 
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index af1adcf..5679412 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -388,9 +388,8 @@
         return;
     }
     std::string prefix(dir_in_zip + "/");
-    const ZipString prefix_str(prefix.c_str());
     void* iter_cookie = nullptr;
-    if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
+    if ((err = StartIteration(zip, &iter_cookie, prefix, "")) != 0) {
         ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
               err);
         CloseArchive(zip);
@@ -399,11 +398,9 @@
     ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
           dir_in_zip.c_str());
     ZipEntry entry;
-    ZipString name;
+    std::string name;
     while (Next(iter_cookie, &entry, &name) == 0) {
-        std::string filename(
-            reinterpret_cast<const char*>(name.name) + prefix.length(),
-            name.name_length - prefix.length());
+        std::string filename(name.substr(prefix.length()));
         // only enumerate direct entries of the directory, not subdirectories
         if (filename.find('/') != filename.npos)
             continue;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 73fc7b2..d60eaa7 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -16,26 +16,24 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <algorithm>
-
+#include <android/hardware/graphics/common/1.0/types.h>
 #include <grallocusage/GrallocUsageConversion.h>
+#include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
-#include <ui/BufferQueueDefs.h>
 #include <sync/sync.h>
+#include <system/window.h>
+#include <ui/BufferQueueDefs.h>
 #include <utils/StrongPointer.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
-#include <system/window.h>
-#include <android/hardware/graphics/common/1.0/types.h>
+
+#include <algorithm>
+#include <unordered_set>
+#include <vector>
 
 #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.
-// When updating to that version, audit all error returns.
 namespace vulkan {
 namespace driver {
 
@@ -46,11 +44,10 @@
     VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
-    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
     VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
 
 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
@@ -60,27 +57,22 @@
     // transforms are built up from a horizontal flip, vertical flip, and
     // 90-degree rotation, all optional but always in that order.
 
-    // TODO(jessehall): For now, only support pure rotations, not
-    // flip or flip-and-rotate, until I have more time to test them and build
-    // sample code. As far as I know we never actually use anything besides
-    // pure rotations anyway.
-
     switch (native) {
-        case 0:  // 0x0
+        case 0:
             return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:
             return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:
             return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:
             return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
         case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
         default:
@@ -88,6 +80,31 @@
     }
 }
 
+int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
+    switch (transform) {
+        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_180;
+        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_270;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+        default:
+            return 0;
+    }
+}
+
 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
     switch (transform) {
         case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
@@ -96,17 +113,16 @@
             return NATIVE_WINDOW_TRANSFORM_ROT_180;
         case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
             return NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
         case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
         case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
         default:
@@ -116,7 +132,6 @@
 
 class TimingInfo {
    public:
-    TimingInfo() = default;
     TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
@@ -183,8 +198,6 @@
             { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
-// ----------------------------------------------------------------------------
-
 struct Surface {
     android::sp<ANativeWindow> window;
     VkSwapchainKHR swapchain_handle;
@@ -208,10 +221,12 @@
 struct Swapchain {
     Swapchain(Surface& surface_,
               uint32_t num_images_,
-              VkPresentModeKHR present_mode)
+              VkPresentModeKHR present_mode,
+              int pre_transform_)
         : surface(surface_),
           num_images(num_images_),
           mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
+          pre_transform(pre_transform_),
           frame_timestamps_enabled(false),
           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
@@ -220,10 +235,20 @@
             window,
             &refresh_duration);
     }
+    uint64_t get_refresh_duration()
+    {
+        ANativeWindow* window = surface.window.get();
+        native_window_get_refresh_cycle_duration(
+            window,
+            &refresh_duration);
+        return static_cast<uint64_t>(refresh_duration);
+
+    }
 
     Surface& surface;
     uint32_t num_images;
     bool mailbox_mode;
+    int pre_transform;
     bool frame_timestamps_enabled;
     int64_t refresh_duration;
     bool shared;
@@ -240,7 +265,7 @@
         bool dequeued;
     } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
 
-    android::Vector<TimingInfo> timing;
+    std::vector<TimingInfo> timing;
 };
 
 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
@@ -255,6 +280,8 @@
                            ANativeWindow* window,
                            int release_fence,
                            Swapchain::Image& image) {
+    ATRACE_CALL();
+
     ALOG_ASSERT(release_fence == -1 || image.dequeued,
                 "ReleaseSwapchainImage: can't provide a release fence for "
                 "non-dequeued images");
@@ -293,7 +320,9 @@
     }
 
     if (image.image) {
+        ATRACE_BEGIN("DestroyImage");
         GetData(device).driver.DestroyImage(device, image.image, nullptr);
+        ATRACE_END();
         image.image = VK_NULL_HANDLE;
     }
 
@@ -319,7 +348,7 @@
     uint32_t num_ready = 0;
     const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
     for (uint32_t i = 0; i < num_timings; i++) {
-        TimingInfo& ti = swapchain.timing.editItemAt(i);
+        TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
             // This TimingInfo is ready to be reported to the user.  Add it
             // to the num_ready.
@@ -341,9 +370,6 @@
             nullptr,  //&first_composition_start_time,
             nullptr,  //&last_composition_start_time,
             nullptr,  //&composition_finish_time,
-            // TODO(ianelliott): Maybe ask if this one is
-            // supported, at startup time (since it may not be
-            // supported):
             &actual_present_time,
             nullptr,  //&dequeue_ready_time,
             nullptr /*&reads_done_time*/);
@@ -370,7 +396,6 @@
     return num_ready;
 }
 
-// TODO(ianelliott): DEAL WITH RETURN VALUE (e.g. VK_INCOMPLETE)!!!
 void copy_ready_timings(Swapchain& swapchain,
                         uint32_t* count,
                         VkPastPresentationTimingGOOGLE* timings) {
@@ -389,7 +414,7 @@
     }
 
     uint32_t num_copied = 0;
-    size_t num_to_remove = 0;
+    int32_t num_to_remove = 0;
     for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
         const TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
@@ -401,7 +426,8 @@
 
     // Discard old frames that aren't ready if newer frames are ready.
     // We don't expect to get the timing info for those old frames.
-    swapchain.timing.removeItemsAt(0, num_to_remove);
+    swapchain.timing.erase(swapchain.timing.begin(),
+                           swapchain.timing.begin() + num_to_remove);
 
     *count = num_copied;
 }
@@ -509,15 +535,12 @@
               strerror(-err), err);
         surface->~Surface();
         allocator->pfnFree(allocator->pUserData, surface);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
     err =
         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
               err);
         surface->~Surface();
@@ -626,7 +649,6 @@
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Figure out what the min/max values should be.
     int max_buffer_count;
     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
     if (err != 0) {
@@ -640,8 +662,7 @@
     capabilities->currentExtent =
         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
 
-    // TODO(jessehall): Figure out what the max extent should be. Maximum
-    // texture dimension maybe?
+    // TODO(http://b/134182502): Figure out what the max extent should be.
     capabilities->minImageExtent = VkExtent2D{1, 1};
     capabilities->maxImageExtent = VkExtent2D{4096, 4096};
 
@@ -655,11 +676,6 @@
     // associated with the bufferqueue. It can't be changed from here.
     capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
 
-    // TODO(jessehall): I think these are right, but haven't thought hard about
-    // it. Do we need to query the driver for support of any of these?
-    // Currently not included:
-    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
-    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
     capabilities->supportedUsageFlags =
         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
@@ -699,8 +715,7 @@
     int err = native_window_get_wide_color_support(surface.window.get(),
                                                    &wide_color_support);
     if (err) {
-        // Not allowed to return a more sensible error code, so do this
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     ALOGV("wide_color_support is: %d", wide_color_support);
     wide_color_support =
@@ -798,11 +813,10 @@
     } else {
         // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
         // after the call.
-        android::Vector<VkSurfaceFormatKHR> surface_formats;
-        surface_formats.resize(*pSurfaceFormatCount);
+        std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
         VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
             physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
-            &surface_formats.editItemAt(0));
+            surface_formats.data());
 
         if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
             // marshal results individually due to stride difference.
@@ -844,7 +858,7 @@
     }
     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
 
-    android::Vector<VkPresentModeKHR> present_modes;
+    std::vector<VkPresentModeKHR> present_modes;
     if (min_undequeued_buffers + 1 < max_buffer_count)
         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
@@ -864,7 +878,7 @@
         if (*count < num_modes)
             result = VK_INCOMPLETE;
         *count = std::min(*count, num_modes);
-        std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
+        std::copy_n(present_modes.data(), *count, modes);
     } else {
         *count = num_modes;
     }
@@ -948,6 +962,40 @@
     return VK_SUCCESS;
 }
 
+static void DestroySwapchainInternal(VkDevice device,
+                                     VkSwapchainKHR swapchain_handle,
+                                     const VkAllocationCallbacks* allocator) {
+    ATRACE_CALL();
+
+    const auto& dispatch = GetData(device).driver;
+    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+    if (!swapchain) {
+        return;
+    }
+
+    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
+    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
+
+    if (window && swapchain->frame_timestamps_enabled) {
+        native_window_enable_frame_timestamps(window, false);
+    }
+
+    for (uint32_t i = 0; i < swapchain->num_images; i++) {
+        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
+    }
+
+    if (active) {
+        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
+    }
+
+    if (!allocator) {
+        allocator = &GetData(device).allocator;
+    }
+
+    swapchain->~Swapchain();
+    allocator->pfnFree(allocator->pUserData, swapchain);
+}
+
 VKAPI_ATTR
 VkResult CreateSwapchainKHR(VkDevice device,
                             const VkSwapchainCreateInfoKHR* create_info,
@@ -1022,6 +1070,8 @@
     // non-FREE state at any given time. Disconnecting and re-connecting
     // orphans the previous buffers, getting us back to the state where we can
     // dequeue all buffers.
+    //
+    // TODO(http://b/134186185) recycle swapchain images more efficiently
     err = native_window_api_disconnect(surface.window.get(),
                                        NATIVE_WINDOW_API_EGL);
     ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
@@ -1042,8 +1092,6 @@
         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
     err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1070,8 +1118,6 @@
     err = native_window_set_buffers_format(surface.window.get(),
                                            native_pixel_format);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
               native_pixel_format, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1079,8 +1125,6 @@
     err = native_window_set_buffers_data_space(surface.window.get(),
                                                native_dataspace);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
               native_dataspace, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1090,8 +1134,6 @@
         surface.window.get(), static_cast<int>(create_info->imageExtent.width),
         static_cast<int>(create_info->imageExtent.height));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
               create_info->imageExtent.width, create_info->imageExtent.height,
               strerror(-err), err);
@@ -1110,8 +1152,6 @@
         surface.window.get(),
         InvertTransformToNative(create_info->preTransform));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
               InvertTransformToNative(create_info->preTransform),
               strerror(-err), err);
@@ -1121,8 +1161,6 @@
     err = native_window_set_scaling_mode(
         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1152,15 +1190,15 @@
                                 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
                                 &query_value);
     if (err != 0 || query_value < 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
               query_value);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
     uint32_t num_images =
-        (create_info->minImageCount - 1) + min_undequeued_buffers;
+        (swap_interval ? create_info->minImageCount
+                       : std::max(3u, create_info->minImageCount)) -
+        1 + min_undequeued_buffers;
 
     // Lower layer insists that we have at least two buffers. This is wasteful
     // and we'd like to relax it in the shared case, but not all the pieces are
@@ -1169,8 +1207,6 @@
     // can't actually use!).
     err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1179,7 +1215,7 @@
     int32_t legacy_usage = 0;
     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
         uint64_t consumer_usage, producer_usage;
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID");
         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             swapchain_image_usage, &consumer_usage, &producer_usage);
@@ -1191,7 +1227,7 @@
         legacy_usage =
             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID");
         result = dispatch.GetSwapchainGrallocUsageANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             &legacy_usage);
@@ -1210,12 +1246,19 @@
     }
     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?
         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
+    int transform_hint;
+    err = surface.window->query(surface.window.get(),
+                                NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
+    if (err != 0) {
+        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
     // -- Allocate our Swapchain object --
     // After this point, we must deallocate the swapchain on error.
 
@@ -1224,9 +1267,9 @@
                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (!mem)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
-    Swapchain* swapchain =
-        new (mem) Swapchain(surface, num_images, create_info->presentMode);
-
+    Swapchain* swapchain = new (mem)
+        Swapchain(surface, num_images, create_info->presentMode,
+                  TranslateVulkanToNativeTransform(create_info->preTransform));
     // -- Dequeue all buffers and create a VkImage for each --
     // Any failures during or after this must cancel the dequeued buffers.
 
@@ -1269,8 +1312,6 @@
         err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
                                             &img.dequeue_fence);
         if (err != 0) {
-            // TODO(jessehall): Improve error reporting. Can we enumerate
-            // possible errors and translate them to valid Vulkan result codes?
             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
             result = VK_ERROR_SURFACE_LOST_KHR;
             break;
@@ -1290,7 +1331,7 @@
             &image_native_buffer.usage2.producer,
             &image_native_buffer.usage2.consumer);
 
-        ATRACE_BEGIN("dispatch.CreateImage");
+        ATRACE_BEGIN("CreateImage");
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
         ATRACE_END();
@@ -1303,9 +1344,6 @@
     // -- Cancel all buffers, returning them to the queue --
     // If an error occurred before, also destroy the VkImage and release the
     // buffer reference. Otherwise, we retain a strong reference to the buffer.
-    //
-    // TODO(jessehall): The error path here is the same as DestroySwapchain,
-    // but not the non-error path. Should refactor/unify.
     for (uint32_t i = 0; i < num_images; i++) {
         Swapchain::Image& img = swapchain->images[i];
         if (img.dequeued) {
@@ -1316,21 +1354,20 @@
                 img.dequeued = false;
             }
         }
-        if (result != VK_SUCCESS) {
-            if (img.image) {
-                ATRACE_BEGIN("dispatch.DestroyImage");
-                dispatch.DestroyImage(device, img.image, nullptr);
-                ATRACE_END();
-            }
-        }
     }
 
     if (result != VK_SUCCESS) {
-        swapchain->~Swapchain();
-        allocator->pfnFree(allocator->pUserData, swapchain);
+        DestroySwapchainInternal(device, HandleFromSwapchain(swapchain),
+                                 allocator);
         return result;
     }
 
+    if (transform_hint != swapchain->pre_transform) {
+        // Log that the app is not doing pre-rotation.
+        android::GraphicsEnv::getInstance().setTargetStats(
+            android::GpuStatsInfo::Stats::FALSE_PREROTATION);
+    }
+
     surface.swapchain_handle = HandleFromSwapchain(swapchain);
     *swapchain_handle = surface.swapchain_handle;
     return VK_SUCCESS;
@@ -1342,24 +1379,7 @@
                          const VkAllocationCallbacks* allocator) {
     ATRACE_CALL();
 
-    const auto& dispatch = GetData(device).driver;
-    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
-    if (!swapchain)
-        return;
-    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
-    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
-
-    if (swapchain->frame_timestamps_enabled) {
-        native_window_enable_frame_timestamps(window, false);
-    }
-    for (uint32_t i = 0; i < swapchain->num_images; i++)
-        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
-    if (active)
-        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
-    if (!allocator)
-        allocator = &GetData(device).allocator;
-    swapchain->~Swapchain();
-    allocator->pfnFree(allocator->pUserData, swapchain);
+    DestroySwapchainInternal(device, swapchain_handle, allocator);
 }
 
 VKAPI_ATTR
@@ -1425,8 +1445,6 @@
     int fence_fd;
     err = window->dequeueBuffer(window, &buffer, &fence_fd);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
@@ -1481,8 +1499,6 @@
                               uint32_t* pImageIndex) {
     ATRACE_CALL();
 
-    // 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);
@@ -1641,9 +1657,9 @@
 
                     // Add a new timing record with the user's presentID and
                     // the nativeFrameId.
-                    swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
+                    swapchain.timing.emplace_back(time, nativeFrameId);
                     while (swapchain.timing.size() > MAX_TIMING_INFOS) {
-                        swapchain.timing.removeAt(0);
+                        swapchain.timing.erase(swapchain.timing.begin());
                     }
                     if (time->desiredPresentTime) {
                         // Set the desiredPresentTime:
@@ -1660,17 +1676,16 @@
                 err = window->queueBuffer(window, img.buffer.get(), fence);
                 // queueBuffer always closes fence, even on error
                 if (err != 0) {
-                    // TODO(jessehall): What now? We should probably cancel the
-                    // buffer, I guess?
                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
                     swapchain_result = WorstPresentResult(
                         swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
+                } else {
+                    if (img.dequeue_fence >= 0) {
+                        close(img.dequeue_fence);
+                        img.dequeue_fence = -1;
+                    }
+                    img.dequeued = false;
                 }
-                if (img.dequeue_fence >= 0) {
-                    close(img.dequeue_fence);
-                    img.dequeue_fence = -1;
-                }
-                img.dequeued = false;
 
                 // If the swapchain is in shared mode, immediately dequeue the
                 // buffer so it can be presented again without an intervening
@@ -1697,9 +1712,21 @@
                 }
             }
             if (swapchain_result != VK_SUCCESS) {
-                ReleaseSwapchainImage(device, window, fence, img);
                 OrphanSwapchain(device, &swapchain);
             }
+            int window_transform_hint;
+            err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
+                                &window_transform_hint);
+            if (err != 0) {
+                ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+                      strerror(-err), err);
+                swapchain_result = WorstPresentResult(
+                    swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
+            }
+            if (swapchain.pre_transform != window_transform_hint) {
+                swapchain_result =
+                    WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
+            }
         } else {
             ReleaseSwapchainImage(device, nullptr, fence, img);
             swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
@@ -1728,8 +1755,7 @@
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
     VkResult result = VK_SUCCESS;
 
-    pDisplayTimingProperties->refreshDuration =
-            static_cast<uint64_t>(swapchain.refresh_duration);
+    pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration();
 
     return result;
 }
@@ -1743,6 +1769,10 @@
     ATRACE_CALL();
 
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+    if (swapchain.surface.swapchain_handle != swapchain_handle) {
+        return VK_ERROR_OUT_OF_DATE_KHR;
+    }
+
     ANativeWindow* window = swapchain.surface.window.get();
     VkResult result = VK_SUCCESS;
 
@@ -1753,8 +1783,15 @@
     }
 
     if (timings) {
-        // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE)
+        // Get the latest ready timing count before copying, since the copied
+        // timing info will be erased in copy_ready_timings function.
+        uint32_t n = get_num_ready_timings(swapchain);
         copy_ready_timings(swapchain, count, timings);
+        // Check the *count here against the recorded ready timing count, since
+        // *count can be overwritten per spec describes.
+        if (*count < n) {
+            result = VK_INCOMPLETE;
+        }
     } else {
         *count = get_num_ready_timings(swapchain);
     }
@@ -1818,5 +1855,106 @@
     return;
 }
 
+static void InterceptBindImageMemory2(
+    uint32_t bind_info_count,
+    const VkBindImageMemoryInfo* bind_infos,
+    std::vector<VkNativeBufferANDROID>* out_native_buffers,
+    std::vector<VkBindImageMemoryInfo>* out_bind_infos) {
+    out_native_buffers->clear();
+    out_bind_infos->clear();
+
+    if (!bind_info_count)
+        return;
+
+    std::unordered_set<uint32_t> intercepted_indexes;
+
+    for (uint32_t idx = 0; idx < bind_info_count; idx++) {
+        auto info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
+            bind_infos[idx].pNext);
+        while (info &&
+               info->sType !=
+                   VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) {
+            info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
+                info->pNext);
+        }
+
+        if (!info)
+            continue;
+
+        ALOG_ASSERT(info->swapchain != VK_NULL_HANDLE,
+                    "swapchain handle must not be NULL");
+        const Swapchain* swapchain = SwapchainFromHandle(info->swapchain);
+        ALOG_ASSERT(
+            info->imageIndex < swapchain->num_images,
+            "imageIndex must be less than the number of images in swapchain");
+
+        ANativeWindowBuffer* buffer =
+            swapchain->images[info->imageIndex].buffer.get();
+        VkNativeBufferANDROID native_buffer = {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+            .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
+#pragma clang diagnostic pop
+            .pNext = bind_infos[idx].pNext,
+            .handle = buffer->handle,
+            .stride = buffer->stride,
+            .format = buffer->format,
+            .usage = int(buffer->usage),
+        };
+        // Reserve enough space to avoid letting re-allocation invalidate the
+        // addresses of the elements inside.
+        out_native_buffers->reserve(bind_info_count);
+        out_native_buffers->emplace_back(native_buffer);
+
+        // Reserve the space now since we know how much is needed now.
+        out_bind_infos->reserve(bind_info_count);
+        out_bind_infos->emplace_back(bind_infos[idx]);
+        out_bind_infos->back().pNext = &out_native_buffers->back();
+
+        intercepted_indexes.insert(idx);
+    }
+
+    if (intercepted_indexes.empty())
+        return;
+
+    for (uint32_t idx = 0; idx < bind_info_count; idx++) {
+        if (intercepted_indexes.count(idx))
+            continue;
+        out_bind_infos->emplace_back(bind_infos[idx]);
+    }
+}
+
+VKAPI_ATTR
+VkResult BindImageMemory2(VkDevice device,
+                          uint32_t bindInfoCount,
+                          const VkBindImageMemoryInfo* pBindInfos) {
+    ATRACE_CALL();
+
+    // out_native_buffers is for maintaining the lifecycle of the constructed
+    // VkNativeBufferANDROID objects inside InterceptBindImageMemory2.
+    std::vector<VkNativeBufferANDROID> out_native_buffers;
+    std::vector<VkBindImageMemoryInfo> out_bind_infos;
+    InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
+                              &out_bind_infos);
+    return GetData(device).driver.BindImageMemory2(
+        device, bindInfoCount,
+        out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
+}
+
+VKAPI_ATTR
+VkResult BindImageMemory2KHR(VkDevice device,
+                             uint32_t bindInfoCount,
+                             const VkBindImageMemoryInfo* pBindInfos) {
+    ATRACE_CALL();
+
+    std::vector<VkNativeBufferANDROID> out_native_buffers;
+    std::vector<VkBindImageMemoryInfo> out_bind_infos;
+    InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
+                              &out_bind_infos);
+    return GetData(device).driver.BindImageMemory2KHR(
+        device, bindInfoCount,
+        out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
+}
+
 }  // namespace driver
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index ed5718c..4912ef1 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -44,6 +44,8 @@
 VKAPI_ATTR void SetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pHdrMetadataEXTs);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
 // clang-format on
 
 }  // namespace driver
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index 7be9c66..dedf419 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -41,6 +41,9 @@
         "null_driver_gen.cpp",
     ],
 
-    header_libs: ["vulkan_headers"],
+    header_libs: [
+        "hwvulkan_headers",
+        "vulkan_headers",
+    ],
     shared_libs: ["liblog"],
 }
diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl
deleted file mode 100644
index ce15517..0000000
--- a/vulkan/nulldrv/null_driver.tmpl
+++ /dev/null
@@ -1,210 +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 "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "null_driver_gen.h"   | Format (Global "clang-format") | Write "null_driver_gen.h"  }}
-{{$ | Macro "null_driver_gen.cpp" | Format (Global "clang-format") | Write "null_driver_gen.cpp"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  null_driver_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "null_driver_gen.h"}}
-/*
-•* 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.
-•*/

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef NULLDRV_NULL_DRIVER_H
-#define NULLDRV_NULL_DRIVER_H 1

-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>

-namespace null_driver {«

-PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
-PFN_vkVoidFunction GetInstanceProcAddr(const char* name);

-// clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "IsDriverFunction" $f)}}
-VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
-    {{end}}
-  {{end}}
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
-// clang-format on

-»}  // namespace null_driver

-#endif  // NULLDRV_NULL_DRIVER_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  null_driver_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "null_driver_gen.cpp"}}
-/*
-•* 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.
-•*/

-// WARNING: This file is generated. See ../README.md for instructions.

-#include "null_driver_gen.h"
-#include <algorithm>

-using namespace null_driver;

-namespace {

-struct NameProc {
-    const char* name;
-    PFN_vkVoidFunction proc;
-};

-PFN_vkVoidFunction Lookup(const char* name,
-                          const NameProc* begin,
-                          const NameProc* end) {
-    const auto& entry = std::lower_bound(
-        begin, end, name,
-        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
-    if (entry == end || strcmp(entry->name, name) != 0)
-        return nullptr;
-    return entry->proc;
-}

-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
-    return Lookup(name, procs, procs + N);
-}

-const NameProc kGlobalProcs[] = {«
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if and (Macro "IsDriverFunction" $f) (eq (Macro "Vtbl" $f) "Global")}}
-      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
-        static_cast<{{Macro "FunctionPtrName" $f}}>(§
-          {{Macro "BaseName" $f}}))},
-    {{end}}
-  {{end}}
-  // clang-format on
-»};

-const NameProc kInstanceProcs[] = {«
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if (Macro "IsDriverFunction" $f)}}
-      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
-        static_cast<{{Macro "FunctionPtrName" $f}}>(§
-          {{Macro "BaseName" $f}}))},
-    {{end}}
-  {{end}}
-  // clang-format on
-»};

-} // namespace

-namespace null_driver {

-PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
-    return Lookup(name, kGlobalProcs);
-}

-PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {«
-    return Lookup(name, kInstanceProcs);
-»}

-} // namespace null_driver

-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a function name without the "vk" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
-  {{AssertType $ "Function"}}
-  {{TrimPrefix "vk" $.Name}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits 'true' if the API function is implemented by the driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDriverFunction"}}
-  {{AssertType $ "Function"}}
-
-  {{if not (GetAnnotation $ "pfn")}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "IsDriverExtension" $ext}}
-    {{else}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension is implemented by the driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDriverExtension"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
-  {{else if eq $ext "VK_EXT_debug_report"}}true
-  {{else if eq $ext "VK_KHR_get_physical_device_properties2"}}true
-  {{end}}
-{{end}}
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 92b7468..7c9b0c0 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -16,9 +16,10 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
-#include <algorithm>
 #include "null_driver_gen.h"
 
+#include <algorithm>
+
 using namespace null_driver;
 
 namespace {
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index c6ad537..70ef340 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -41,6 +41,7 @@
 VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
 VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
 VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
 VKAPI_ATTR VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
 VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
 VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
@@ -165,48 +166,47 @@
 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);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
 VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
 VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
-VKAPI_ATTR void GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
-VKAPI_ATTR void GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+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 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 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 GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+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 void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
new file mode 100644
index 0000000..a0c648c
--- /dev/null
+++ b/vulkan/scripts/api_generator.py
@@ -0,0 +1,346 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 script provides the functions required for generating the
+# vulkan api framework directly from the vulkan registry (vk.xml)
+
+import os
+import generator_common as gencom
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
+    return True
+  return False
+
+def api_genh():
+
+  header = """#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+#include "driver_gen.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+
+  tail = """
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_API_GEN_H
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
+  with open(genfile, 'w') as f:
+    instanceDispatchTableEntries = []
+    deviceDispatchTableEntries = []
+    for commands in gencom.allCommandsList:
+      if commands not in gencom.aliasDict:
+        if gencom.isInstanceDispatchTableEntry(commands):
+          instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+        elif gencom.isDeviceDispatchTableEntry(commands):
+          deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    f.write ('struct InstanceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in instanceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+
+    f.write ('struct DeviceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in deviceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n')
+
+    f.write (tail)
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def defineInitProc(name, f):
+  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
+  f.write ('\n')
+  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.""" + name + """.proc =                                           \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.""" + name + """.proc)) {               \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)\n\n""")
+
+def defineInitProcExt(f):
+  f.write ('// Exported extension functions may be invoked even when their extensions\n')
+  f.write ('// are disabled.  Dispatch to stubs when that happens.\n')
+  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc)  \\
+    do {                                         \\
+        if (extensions[driver::ProcHook::ext])   \\
+            INIT_PROC(required, obj, proc);      \\
+        else                                     \\
+            data.dispatch.proc = disabled##proc; \\
+    } while (0)\n\n""")
+
+def defineExtensionStub(functionName, f):
+  if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
+    extname = gencom.extensionsDict[functionName]
+    base_name = functionName[2:]
+    pList = gencom.paramDict[functionName]
+    firstParam = pList[0][0] + pList[0][1]
+    tailParams = [x[0][:-1] for x in pList[1:]]
+    tailP = ', '.join(tailParams)
+    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
+    f.write (gencom.clang_off_spaces)
+    f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
+    f.write ('}\n\n')
+
+def isIntercepted(functionName):
+  if gencom.isFunctionSupported(functionName):
+    if gencom.isGloballyDispatched(functionName):
+      return True
+    elif functionName == 'vkCreateDevice':
+      return True
+    elif functionName == 'vkEnumerateDeviceLayerProperties':
+      return True
+    elif functionName == 'vkEnumerateDeviceExtensionProperties':
+      return True
+    elif functionName == 'vkDestroyInstance':
+      return True
+    elif functionName == 'vkDestroyDevice':
+      return True
+  return False
+
+def interceptInstanceProcAddr(functionName, f):
+  indent = 1
+  f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
+  indent = indent + 1
+  for cmds in gencom.allCommandsList:
+    if gencom.isGloballyDispatched(cmds):
+      f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+
+  f.write ('\n')
+  f.write ("""        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+        return nullptr;
+    }
+
+    static const struct Hook {
+        const char* name;
+        PFN_vkVoidFunction proc;
+    } hooks[] = {\n""")
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionExported(cmds):
+      if gencom.isGloballyDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
+      elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
+  f.write (gencom.clang_off_spaces + """};
+    // clang-format on
+    constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+    auto hook = std::lower_bound(
+        hooks, hooks + count, pName,
+        [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+    if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
+        if (!hook->proc) {
+            vulkan::driver::Logger(instance).Err(
+                instance, "invalid vkGetInstanceProcAddr(%p, \\\"%s\\\") call",
+                instance, pName);
+        }
+        return hook->proc;
+    }
+    // clang-format off\n\n""")
+
+def interceptDeviceProcAddr(functionName, f):
+  f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+        ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
+        return nullptr;
+    }\n\n""")
+  f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionSupported(cmds):
+      if not gencom.isDeviceDispatched(cmds):
+        f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
+  f.write(gencom.clang_off_spaces + '};\n')
+  f.write(gencom.clang_off_spaces + """// clang-format on
+    constexpr size_t count =
+        sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
+    if (!pName ||
+        std::binary_search(
+            known_non_device_names, known_non_device_names + count, pName,
+            [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+        vulkan::driver::Logger(device).Err(
+            device, "invalid vkGetDeviceProcAddr(%p, \\\"%s\\\") call", device,
+            (pName) ? pName : "(null)");
+        return nullptr;
+    }
+    // clang-format off\n\n""")
+  for cmds in gencom.allCommandsList:
+    if gencom.isDeviceDispatched(cmds):
+      if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
+        f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+  f.write ('\n')
+
+def apiDispatch(functionName, f):
+  assert not isIntercepted(functionName)
+
+  f.write (gencom.clang_off_spaces)
+  if gencom.returnTypeDict[functionName] != 'void':
+    f.write ('return ')
+
+  paramList = gencom.paramDict[functionName]
+  p0 = paramList[0][1]
+  f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+
+
+def api_gencpp():
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
+  header = """#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write ("""#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {\n\n""")
+    defineInitProc('dispatch',f)
+    defineInitProcExt(f)
+    f.write ('namespace {\n\n')
+    gencom.clang_off(f,0)
+    f.write ('\n')
+    for cmds in gencom.allCommandsList:
+      defineExtensionStub(cmds,f)
+    gencom.clang_on(f,0)
+    f.write ('\n}  // namespace\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;\n\n""")
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isInstanceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;\n\n""")
+
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isDeviceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+
+    gencom.clang_off(f,0)
+
+    f.write ('\nnamespace {\n\n')
+    f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+
+    f.write ('\n')
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
+        if cmds == 'vkGetInstanceProcAddr':
+          interceptInstanceProcAddr(cmds, f)
+        elif cmds == 'vkGetDeviceProcAddr':
+          interceptDeviceProcAddr(cmds, f)
+        apiDispatch(cmds, f)
+        f.write('}\n\n')
+    f.write ("""\n}  // anonymous namespace
+
+// clang-format on
+
+}  // namespace api
+}  // namespace vulkan
+
+// clang-format off\n\n""")
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('__attribute__((visibility("default")))\n')
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
+        f.write (gencom.clang_off_spaces)
+        if gencom.returnTypeDict[cmds] != 'void':
+          f.write ('return ')
+        paramList = gencom.paramDict[cmds]
+        f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+        f.write ('}\n\n')
+
+    gencom.clang_on(f, 0)
+    f.close()
+  gencom.runClangFormat(genfile)
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
new file mode 100755
index 0000000..39fedf4
--- /dev/null
+++ b/vulkan/scripts/code_generator.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 script provides the main function for generating
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import api_generator as apigen
+import driver_generator as drivergen
+import null_generator as nullgen
+
+if __name__ == '__main__':
+  gencom.parseVulkanRegistry()
+  apigen.api_genh()
+  apigen.api_gencpp()
+  drivergen.driver_genh()
+  drivergen.driver_gencpp()
+  nullgen.null_driver_genh()
+  nullgen.null_driver_gencpp()
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
new file mode 100644
index 0000000..04d9f23
--- /dev/null
+++ b/vulkan/scripts/driver_generator.py
@@ -0,0 +1,396 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 script provides the functions for generating the
+# vulkan driver framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import os
+
+interceptedExtensions = [
+  'VK_ANDROID_native_buffer',
+  'VK_EXT_debug_report',
+  'VK_EXT_hdr_metadata',
+  'VK_EXT_swapchain_colorspace',
+  'VK_GOOGLE_display_timing',
+  'VK_KHR_android_surface',
+  'VK_KHR_incremental_present',
+  'VK_KHR_shared_presentable_image',
+  'VK_KHR_surface',
+  'VK_KHR_swapchain',
+  'VK_KHR_get_surface_capabilities2'
+]
+
+knownExtensions = interceptedExtensions + [
+  'VK_KHR_get_physical_device_properties2',
+  'VK_ANDROID_external_memory_android_hardware_buffer',
+  'VK_KHR_bind_memory2'
+]
+
+def defineProcHookType(f):
+  f.write ("""struct ProcHook {
+    enum Type {
+        GLOBAL,
+        INSTANCE,
+        DEVICE,
+    };
+    enum Extension {\n""")
+  for exts in knownExtensions:
+    f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
+  f.write ('\n')
+  f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE,  // valid bit
+        EXTENSION_COUNT,
+        EXTENSION_UNKNOWN,
+    };
+
+    const char* name;
+    Type type;
+    Extension extension;
+
+    PFN_vkVoidFunction proc;
+    PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
+};\n\n""")
+
+def isExtensionIntercepted(extensionName):
+  if extensionName in interceptedExtensions:
+    return True
+  return False
+
+def isDriverTableEntry(functionName):
+  switchCase = {
+    # Create functions of dispatchable objects
+    'vkCreateDevice' : True,
+    'vkGetDeviceQueue' : True,
+    'vkGetDeviceQueue2' : True,
+    'vkAllocateCommandBuffers' : True,
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance' : True,
+    'vkDestroyDevice' : True,
+
+    # Enumeration of extensions
+    'vkEnumerateDeviceExtensionProperties' : True,
+
+    # We cache physical devices in loader.cpp
+    'vkEnumeratePhysicalDevices' : True,
+    'vkEnumeratePhysicalDeviceGroups' : True,
+
+    'vkGetInstanceProcAddr' : True,
+    'vkGetDeviceProcAddr' : True,
+
+    # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
+    'vkCreateImage' : True,
+    'vkDestroyImage' : True,
+
+    'vkGetPhysicalDeviceProperties' : True,
+    'vkGetPhysicalDeviceProperties2' : True,
+    'vkGetPhysicalDeviceProperties2KHR' : True,
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2' : True,
+    'vkBindImageMemory2KHR' : True
+  }
+  if gencom.isFunctionSupported(functionName):
+    if functionName in switchCase:
+      return True
+    if functionName in gencom.extensionsDict:
+      if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
+        return True
+  return False
+
+def isInstanceDriverTableEntry(functionName):
+  if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDriverTableEntry(functionName):
+  if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
+    return True
+  return False
+
+def driver_genh():
+  header = """#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+namespace vulkan {
+namespace driver {\n\n"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    defineProcHookType(f)
+    f.write ('struct InstanceDriverTable {\n')
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isInstanceDriverTableEntry(cmds):
+        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
+    gencom.clang_on(f, 1)
+    f.write ('};\n\n')
+    f.write ('struct DeviceDriverTable {\n')
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if isDeviceDriverTableEntry(cmds):
+        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+    f.write ("""const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+
+bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DRIVER_TABLE_H\n""")
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def isIntercepted(functionName):
+  switchCase = {
+    # Create functions of dispatchable objects
+    'vkCreateInstance' : True,
+    'vkCreateDevice' : True,
+    'vkEnumeratePhysicalDevices' : True,
+    'vkEnumeratePhysicalDeviceGroups' : True,
+    'vkGetDeviceQueue' : True,
+    'vkGetDeviceQueue2' : True,
+    'vkAllocateCommandBuffers' : True,
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance' : True,
+    'vkDestroyDevice' : True,
+
+    # Enumeration of extensions
+    'vkEnumerateInstanceExtensionProperties' : True,
+    'vkEnumerateDeviceExtensionProperties' : True,
+
+    'vkGetInstanceProcAddr' : True,
+    'vkGetDeviceProcAddr' : True,
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2' : True,
+    'vkBindImageMemory2KHR' : True
+  }
+  if gencom.isFunctionSupported(functionName):
+    if functionName in switchCase:
+      return switchCase[functionName]
+
+    if functionName in gencom.extensionsDict:
+      return isExtensionIntercepted(gencom.extensionsDict[functionName])
+  return False
+
+def needProcHookStub(functionName):
+  if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
+    if functionName in gencom.extensionsDict:
+      if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
+        return True
+  return False
+
+def defineInitProc(name, f):
+  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
+  f.write ('\n')
+  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.""" + name + """.proc =                                             \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.""" + name + """.proc)) {                 \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)\n\n""")
+
+def defineInitProcExt(f):
+  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
+    do {                                        \\
+        if (extensions[ProcHook::ext])          \\
+            INIT_PROC(required, obj, proc);     \\
+    } while (0)\n\n""")
+
+def defineProcHookStub(functionName, f):
+  if needProcHookStub(functionName):
+    ext_name = gencom.extensionsDict[functionName]
+    base_name = functionName[2:]
+    paramList = [''.join(i) for i in gencom.paramDict[functionName]]
+    p0 = gencom.paramDict[functionName][0][1]
+    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
+    ext_hook = 'ProcHook::' + ext_name[3:]
+
+    f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
+    f.write (gencom.clang_off_spaces *2)
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write ('return ')
+    paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
+    f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
+    f.write (gencom.clang_off_spaces + '} else {\n')
+    f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
+    f.write (gencom.clang_off_spaces + '}\n')
+    f.write ('}\n\n')
+
+def defineGlobalProcHook(functionName, f):
+  base_name = functionName[2:]
+  assert (functionName not in gencom.extensionsDict)
+  f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
+  f.write ("""ProcHook::GLOBAL,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name  + """),
+        nullptr,
+    },\n""")
+
+def defineInstanceProcHook(functionName, f):
+  base_name = functionName[2:]
+  f.write (gencom.clang_off_spaces + '{\n')
+  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
+  f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
+
+  if functionName in gencom.extensionsDict:
+    ext_name = gencom.extensionsDict[functionName]
+    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
+    if gencom.isExtensionInternal(ext_name):
+      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+    else:
+      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+
+  else:
+    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+        nullptr,\n""")
+
+  f.write (gencom.clang_off_spaces + '},\n')
+
+def defineDeviceProcHook(functionName, f):
+  base_name = functionName[2:]
+  f.write (gencom.clang_off_spaces + '{\n')
+  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
+  f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
+
+  if functionName in gencom.extensionsDict:
+    ext_name = gencom.extensionsDict[functionName]
+    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
+    if gencom.isExtensionInternal(ext_name):
+      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+    else:
+      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
+
+  else:
+    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+        nullptr,\n""")
+
+  f.write (gencom.clang_off_spaces + '},\n')
+
+def driver_gencpp():
+  header = """#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "driver.h"
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+// clang-format off\n\n"""
+
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
+
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+
+    for cmds in gencom.allCommandsList:
+      defineProcHookStub(cmds, f)
+    gencom.clang_on(f, 0)
+    f.write ('\n')
+
+    f.write ('const ProcHook g_proc_hooks[] = {\n')
+    gencom.clang_off(f, 1)
+    sortedCommandsList = sorted(gencom.allCommandsList)
+    for cmds in sortedCommandsList:
+      if isIntercepted(cmds):
+        if gencom.isGloballyDispatched(cmds):
+          defineGlobalProcHook(cmds, f)
+        elif gencom.isInstanceDispatched(cmds):
+          defineInstanceProcHook(cmds, f)
+        elif gencom.isDeviceDispatched(cmds):
+          defineDeviceProcHook(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('};\n\n}  // namespace\n\n')
+
+    f.write ("""const ProcHook* GetProcHook(const char* name) {
+    const auto& begin = g_proc_hooks;
+    const auto& end =
+        g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+    const auto hook = std::lower_bound(
+        begin, end, name,
+        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+    return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}\n\n""")
+
+    f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
+    gencom.clang_off(f, 1)
+    for exts in knownExtensions:
+      f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
+    gencom.clang_on(f, 1)
+    f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
+    f.write ('}\n\n')
+
+    defineInitProc('driver', f)
+    defineInitProcExt(f)
+
+    f.write ("""bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;\n\n""")
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isInstanceDriverTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
+    f.write ('}\n\n')
+
+    f.write ("""bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;\n\n""")
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isDeviceDriverTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
+    f.write ('}\n\n}  // namespace driver\n}  // namespace vulkan\n\n')
+    gencom.clang_on(f, 0)
+    f.close()
+  gencom.runClangFormat(genfile)
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
new file mode 100644
index 0000000..d9f97e1
--- /dev/null
+++ b/vulkan/scripts/generator_common.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 script provides the common functions for generating the
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+from subprocess import check_call
+
+copyright = """/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+"""
+
+warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
+
+blacklistedExtensions = [
+    'VK_KHR_display',
+    'VK_KHR_display_swapchain',
+    'VK_KHR_mir_surface',
+    'VK_KHR_xcb_surface',
+    'VK_KHR_xlib_surface',
+    'VK_KHR_wayland_surface',
+    'VK_KHR_win32_surface',
+    'VK_KHR_external_memory_win32',
+    'VK_KHR_win32_keyed_mutex',
+    'VK_KHR_external_semaphore_win32',
+    'VK_KHR_external_fence_win32',
+    'VK_EXT_acquire_xlib_display',
+    'VK_EXT_direct_mode_display',
+    'VK_EXT_display_surface_counter',
+    'VK_EXT_display_control',
+    'VK_FUCHSIA_imagepipe_surface',
+    'VK_MVK_ios_surface',
+    'VK_MVK_macos_surface',
+    'VK_NN_vi_surface',
+    'VK_NV_external_memory_win32',
+    'VK_NV_win32_keyed_mutex',
+    'VK_EXT_metal_surface', #not present in vulkan.api
+    'VK_NVX_image_view_handle', #not present in vulkan.api
+    'VK_NV_cooperative_matrix', #not present in vulkan.api
+    'VK_EXT_headless_surface', #not present in vulkan.api
+    'VK_GGP_stream_descriptor_surface', #not present in vulkan.api
+    'VK_NV_coverage_reduction_mode', #not present in vulkan.api
+    'VK_EXT_full_screen_exclusive' #not present in vulkan.api
+]
+
+exportedExtensions = [
+    'VK_KHR_surface',
+    'VK_KHR_swapchain',
+    'VK_KHR_android_surface',
+    'VK_ANDROID_external_memory_android_hardware_buffer'
+]
+
+def runClangFormat(args):
+  clang_call = ["clang-format", "--style", "file", "-i", args]
+  check_call (clang_call)
+
+def isExtensionInternal(extensionName):
+  if extensionName == 'VK_ANDROID_native_buffer':
+    return True
+  return False
+
+def isFunctionSupported(functionName):
+  if functionName not in extensionsDict:
+    return True
+  else:
+    if extensionsDict[functionName] not in blacklistedExtensions:
+      return True
+  return False
+
+def isInstanceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
+
+def isDeviceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
+
+def isGloballyDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
+
+def isExtensionExported(extensionName):
+  if extensionName in exportedExtensions:
+    return True
+  return False
+
+def isFunctionExported(functionName):
+  if isFunctionSupported(functionName):
+    if functionName in extensionsDict:
+      return isExtensionExported(extensionsDict[functionName])
+    return True
+  return False
+
+def getDispatchTableType(functionName):
+  if functionName not in paramDict:
+    return None
+
+  switchCase = {
+      'VkInstance ' : 'Instance',
+      'VkPhysicalDevice ' : 'Instance',
+      'VkDevice ' : 'Device',
+      'VkQueue ' : 'Device',
+      'VkCommandBuffer ' : 'Device'
+  }
+
+  if len(paramDict[functionName])>0:
+    return switchCase.get(paramDict[functionName][0][0], 'Global')
+  return 'Global'
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if isFunctionExported(functionName) and isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if isFunctionExported(functionName) and isDeviceDispatched(functionName):
+    return True
+  return False
+
+
+def clang_on(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format on\n')
+
+def clang_off(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format off\n')
+
+clang_off_spaces = ' '*4
+
+parametersList = []
+paramDict = {}
+allCommandsList = []
+extensionsDict = {}
+returnTypeDict = {}
+versionDict = {}
+aliasDict = {}
+
+def parseVulkanRegistry():
+  import xml.etree.ElementTree as ET
+  import os
+  vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
+  tree = ET.parse(vulkan_registry)
+  root = tree.getroot()
+  protoset = False
+  fnName = ""
+  fnType = ""
+  for commands in root.iter('commands'):
+    for command in commands:
+      if command.tag == 'command':
+        if protoset == True:
+          paramDict[fnName] = parametersList.copy()
+        parametersList.clear()
+        protoset = False
+        if command.get('alias') != None:
+          alias = command.get('alias')
+          fnName = command.get('name')
+          aliasDict[fnName] = alias
+          allCommandsList.append(fnName)
+          paramDict[fnName] = paramDict[alias].copy()
+          returnTypeDict[fnName] = returnTypeDict[alias]
+        for params in command:
+          if(params.tag == 'param'):
+            paramtype = ""
+            if params.text!=None:
+              paramtype = params.text
+            typeval = params.find('type')
+            paramtype = paramtype + typeval.text
+            if typeval.tail!=None:
+              paramtype = paramtype + typeval.tail
+            pname = params.find('name')
+            paramname = pname.text
+            if pname.tail != None:
+              parametersList.append((paramtype,paramname,pname.tail))
+            else:
+              parametersList.append((paramtype,paramname))
+          if params.tag == 'proto':
+            for c in params:
+              if c.tag == 'type':
+                fnType = c.text
+              if c.tag == 'name':
+                fnName = c.text
+                protoset = True
+                allCommandsList.append(fnName)
+                returnTypeDict[fnName] = fnType
+
+  for exts in root.iter('extensions'):
+    for extension in exts:
+      apiversion = ""
+      if extension.tag == 'extension':
+        extname = extension.get('name')
+        for req in extension:
+          if req.get('feature')!=None:
+            apiversion = req.get('feature')
+          for commands in req:
+            if commands.tag == 'command':
+              commandname = commands.get('name')
+              if commandname not in extensionsDict:
+                extensionsDict[commandname] = extname
+                if apiversion != "":
+                  versionDict[commandname] = apiversion
+
+  # TODO(adsrini): http://b/136570819
+  extensionsDict['vkGetSwapchainGrallocUsage2ANDROID'] = 'VK_ANDROID_native_buffer'
+  allCommandsList.append('vkGetSwapchainGrallocUsage2ANDROID')
+  returnTypeDict['vkGetSwapchainGrallocUsage2ANDROID'] = 'VkResult'
+  paramDict['vkGetSwapchainGrallocUsage2ANDROID'] = [
+    ('VkDevice ', 'device'),
+    ('VkFormat ', 'format'),
+    ('VkImageUsageFlags ', 'imageUsage'),
+    ('VkSwapchainImageUsageFlagsANDROID ', 'swapchainImageUsage'),
+    ('uint64_t* ', 'grallocConsumerUsage'),
+    ('uint64_t* ', 'grallocProducerUsage')
+  ]
+
+  for feature in root.iter('feature'):
+    apiversion = feature.get('name')
+    for req in feature:
+      for command in req:
+        if command.tag == 'command':
+          cmdName = command.get('name')
+          if cmdName in allCommandsList:
+            versionDict[cmdName] = apiversion
+
+
+def initProc(name, f):
+  if name in extensionsDict:
+    f.write ('    INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
+  else:
+    f.write ('    INIT_PROC(')
+
+  if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
+    f.write('false, ')
+  elif name == 'vkGetSwapchainGrallocUsageANDROID' or name == 'vkGetSwapchainGrallocUsage2ANDROID': # optional in vulkan.api
+    f.write('false, ')
+  else:
+    f.write('true, ')
+
+  if isInstanceDispatched(name):
+    f.write('instance, ')
+  else:
+    f.write('dev, ')
+
+  f.write(name[2:] + ');\n')
+
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
new file mode 100644
index 0000000..ee8762e
--- /dev/null
+++ b/vulkan/scripts/null_generator.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 script provides the functions for generating the null driver
+# framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import os
+
+copyright = """/*
+ * 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.
+ */
+
+"""
+
+def isDriverExtension(extensionName):
+  switchCase = {
+    'VK_ANDROID_native_buffer' : True,
+    'VK_EXT_debug_report' : True,
+    'VK_KHR_get_physical_device_properties2' : True
+  }
+
+  if extensionName in switchCase:
+    return switchCase[extensionName]
+  return False
+
+def isDriverFunction(functionName):
+  if functionName in gencom.extensionsDict:
+    return isDriverExtension(gencom.extensionsDict[functionName])
+  return True
+
+def null_driver_genh():
+  header = """#ifndef NULLDRV_NULL_DRIVER_H
+#define NULLDRV_NULL_DRIVER_H 1
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
+
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h')
+  with open(genfile, 'w') as f:
+    f.write (copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    gencom.clang_off(f,0)
+
+    for cmds in gencom.allCommandsList:
+      if isDriverFunction(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n')
+    f.write ("""VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);\n""")
+    gencom.clang_on(f,0)
+
+    f.write ('\n}  // namespace null_driver\n')
+    f.write ('\n#endif  // NULLDRV_NULL_DRIVER_H\n')
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def null_driver_gencpp():
+  header = """#include <algorithm>
+
+#include "null_driver_gen.h"
+
+using namespace null_driver;
+
+namespace {
+
+struct NameProc {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};
+
+PFN_vkVoidFunction Lookup(const char* name,
+                          const NameProc* begin,
+                          const NameProc* end) {
+    const auto& entry = std::lower_bound(
+        begin, end, name,
+        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry == end || strcmp(entry->name, name) != 0)
+        return nullptr;
+    return entry->proc;
+}
+
+template <size_t N>
+PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
+    return Lookup(name, procs, procs + N);
+}
+
+const NameProc kGlobalProcs[] = {
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp')
+  with open(genfile, 'w') as f:
+    f.write (copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    gencom.clang_off(f,1)
+
+    sortedCommandsList = sorted(gencom.allCommandsList)
+    for cmds in sortedCommandsList:
+      if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global':
+        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+
+    f.write ('const NameProc kInstanceProcs[] = {\n')
+    gencom.clang_off(f,1)
+    for cmds in sortedCommandsList:
+      if isDriverFunction(cmds):
+        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n}  // namespace\n\n')
+
+    f.write ("""namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
+    return Lookup(name, kGlobalProcs);
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {
+    return Lookup(name, kInstanceProcs);
+}
+
+}  // namespace null_driver\n""")
+    f.close()
+  gencom.runClangFormat(genfile)
+
diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp
index 78d6694..a626e48 100644
--- a/vulkan/vkjson/Android.bp
+++ b/vulkan/vkjson/Android.bp
@@ -45,7 +45,7 @@
         "libjsoncpp_ndk",
     ],
     header_libs: [
-        "vulkan_headers_ndk",
+        "vulkan_headers",
     ],
     sdk_version: "24",
     stl: "libc++_static",